1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
18
19 #include <cstdint>
20 #include <optional>
21
22 #include "src/trace_processor/importers/common/args_tracker.h"
23 #include "src/trace_processor/importers/common/args_translation_table.h"
24 #include "src/trace_processor/importers/common/event_tracker.h"
25 #include "src/trace_processor/importers/common/flow_tracker.h"
26 #include "src/trace_processor/importers/common/global_args_tracker.h"
27 #include "src/trace_processor/importers/common/process_tracker.h"
28 #include "src/trace_processor/importers/common/slice_tracker.h"
29 #include "src/trace_processor/importers/common/slice_translation_table.h"
30 #include "src/trace_processor/importers/common/track_tracker.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "test/gtest_and_gmock.h"
33
34 namespace perfetto::trace_processor {
35 namespace {
36 constexpr int kOneWay = 0x01;
37
38 class BinderTrackerTest : public ::testing::Test {
39 public:
BinderTrackerTest()40 BinderTrackerTest() {
41 context.storage.reset(new TraceStorage());
42 context.global_args_tracker.reset(
43 new GlobalArgsTracker(context.storage.get()));
44 context.args_tracker.reset(new ArgsTracker(&context));
45 context.args_translation_table.reset(
46 new ArgsTranslationTable(context.storage.get()));
47 context.slice_tracker.reset(new SliceTracker(&context));
48 context.slice_translation_table.reset(
49 new SliceTranslationTable(context.storage.get()));
50 context.process_tracker.reset(new ProcessTracker(&context));
51 context.track_tracker.reset(new TrackTracker(&context));
52 context.flow_tracker.reset(new FlowTracker(&context));
53 binder_tracker = BinderTracker::GetOrCreate(&context);
54 }
55
TidForSlice(uint32_t row) const56 uint32_t TidForSlice(uint32_t row) const {
57 const auto& thread = context.storage->thread_table();
58 const auto& track = context.storage->track_table();
59 const auto& slice = context.storage->slice_table();
60 auto rr = track.FindById(slice[row].track_id());
61 return thread[*rr->utid()].tid();
62 }
63
64 protected:
65 TraceProcessorContext context;
66 BinderTracker* binder_tracker;
67 };
68
TEST_F(BinderTrackerTest,RequestReply)69 TEST_F(BinderTrackerTest, RequestReply) {
70 int64_t req_ts = 100;
71 int64_t req_recv_ts = 105;
72 int64_t rep_ts = 150;
73 int64_t rep_recv_ts = 155;
74
75 uint32_t req_tid = 5;
76 uint32_t rep_tid = 10;
77
78 int32_t req_transaction_id = 1234;
79 int32_t rep_transaction_id = 5678;
80
81 binder_tracker->Transaction(req_ts, req_tid, req_transaction_id, 9, rep_tid,
82 rep_tid, false, 0, kNullStringId);
83 binder_tracker->TransactionReceived(req_recv_ts, rep_tid, req_transaction_id);
84
85 binder_tracker->Transaction(rep_ts, rep_tid, rep_transaction_id, 99, req_tid,
86 req_tid, true, 0, kNullStringId);
87 binder_tracker->TransactionReceived(rep_recv_ts, req_tid, rep_transaction_id);
88
89 const auto& slice = context.storage->slice_table();
90 const auto& flow = context.storage->flow_table();
91 ASSERT_EQ(slice.row_count(), 2u);
92
93 ASSERT_EQ(slice[0].ts(), req_ts);
94 ASSERT_EQ(slice[0].dur(), rep_recv_ts - req_ts);
95 ASSERT_EQ(TidForSlice(0), req_tid);
96
97 ASSERT_EQ(slice[1].ts(), req_recv_ts);
98 ASSERT_EQ(slice[1].dur(), rep_ts - req_recv_ts);
99 ASSERT_EQ(TidForSlice(1), rep_tid);
100
101 ASSERT_EQ(flow.row_count(), 1u);
102 ASSERT_EQ(flow[0].slice_out(), slice[0].id());
103 ASSERT_EQ(flow[0].slice_in(), slice[1].id());
104
105 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
106 }
107
TEST_F(BinderTrackerTest,Oneway)108 TEST_F(BinderTrackerTest, Oneway) {
109 int64_t sen_ts = 100;
110 int64_t rec_ts = 150;
111
112 uint32_t sen_tid = 5;
113 uint32_t rec_tid = 10;
114
115 int32_t transaction_id = 1234;
116
117 binder_tracker->Transaction(sen_ts, sen_tid, transaction_id, 9, rec_tid,
118 rec_tid, false, kOneWay, kNullStringId);
119 binder_tracker->TransactionReceived(rec_ts, rec_tid, transaction_id);
120
121 const auto& slice = context.storage->slice_table();
122 const auto& flow = context.storage->flow_table();
123 ASSERT_EQ(slice.row_count(), 2u);
124
125 ASSERT_EQ(slice[0].ts(), sen_ts);
126 ASSERT_EQ(slice[0].dur(), 0);
127 ASSERT_EQ(TidForSlice(0), sen_tid);
128
129 ASSERT_EQ(slice[1].ts(), rec_ts);
130 ASSERT_EQ(slice[1].dur(), 0);
131 ASSERT_EQ(TidForSlice(1), rec_tid);
132
133 ASSERT_EQ(flow.row_count(), 1u);
134 ASSERT_EQ(flow[0].slice_out(), slice[0].id());
135 ASSERT_EQ(flow[0].slice_in(), slice[1].id());
136
137 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
138 }
139
TEST_F(BinderTrackerTest,RequestReplyWithCommands)140 TEST_F(BinderTrackerTest, RequestReplyWithCommands) {
141 constexpr uint32_t kSndTid = 5;
142 constexpr uint32_t kRcvTid = 10;
143
144 constexpr int32_t kTransactionId = 1234;
145 constexpr int32_t kReplyTransactionId = 5678;
146
147 int64_t ts = 1;
148 binder_tracker->CommandToKernel(ts++, kSndTid,
149 BinderTracker::kBC_TRANSACTION);
150 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
151 kRcvTid, false, 0, kNullStringId);
152 binder_tracker->TransactionReceived(ts++, kRcvTid, kTransactionId);
153 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
154 BinderTracker::kBR_TRANSACTION);
155 binder_tracker->CommandToKernel(ts++, kRcvTid, BinderTracker::kBC_REPLY);
156 binder_tracker->Transaction(ts++, kRcvTid, kReplyTransactionId, 99, kSndTid,
157 kSndTid, true, 0, kNullStringId);
158 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
159 BinderTracker::kBR_TRANSACTION_COMPLETE);
160 binder_tracker->ReturnFromKernel(ts++, kSndTid,
161 BinderTracker::kBR_TRANSACTION_COMPLETE);
162 binder_tracker->TransactionReceived(ts++, kSndTid, kReplyTransactionId);
163 binder_tracker->ReturnFromKernel(ts++, kSndTid, BinderTracker::kBR_REPLY);
164
165 const auto& slice = context.storage->slice_table();
166 ASSERT_EQ(slice.row_count(), 2u);
167 EXPECT_NE(slice[0].dur(), -1);
168 EXPECT_NE(slice[1].dur(), -1);
169
170 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
171 }
172
TEST_F(BinderTrackerTest,RequestReplyWithCommandsFailAfterBcTransaction)173 TEST_F(BinderTrackerTest, RequestReplyWithCommandsFailAfterBcTransaction) {
174 constexpr uint32_t kSndTid = 5;
175
176 int64_t ts = 1;
177 binder_tracker->CommandToKernel(ts++, kSndTid,
178 BinderTracker::kBC_TRANSACTION);
179 binder_tracker->ReturnFromKernel(ts++, kSndTid,
180 BinderTracker::kBR_DEAD_REPLY);
181
182 const auto& slice = context.storage->slice_table();
183 EXPECT_EQ(slice.row_count(), 0u);
184
185 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
186 }
187
TEST_F(BinderTrackerTest,RequestReplyWithCommandsFailAfterSendTxn)188 TEST_F(BinderTrackerTest, RequestReplyWithCommandsFailAfterSendTxn) {
189 constexpr uint32_t kSndTid = 5;
190 constexpr uint32_t kRcvTid = 10;
191
192 constexpr int32_t kTransactionId = 1234;
193
194 int64_t ts = 1;
195 binder_tracker->CommandToKernel(ts++, kSndTid,
196 BinderTracker::kBC_TRANSACTION);
197 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
198 kRcvTid, false, 0, kNullStringId);
199 binder_tracker->ReturnFromKernel(ts++, kSndTid,
200 BinderTracker::kBR_FAILED_REPLY);
201
202 const auto& slice = context.storage->slice_table();
203 ASSERT_EQ(slice.row_count(), 1u);
204 EXPECT_NE(slice[0].dur(), -1);
205
206 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
207 }
208
TEST_F(BinderTrackerTest,RequestReplyWithCommandsFailBeforeReplyTxn)209 TEST_F(BinderTrackerTest, RequestReplyWithCommandsFailBeforeReplyTxn) {
210 constexpr uint32_t kSndTid = 5;
211 constexpr uint32_t kRcvTid = 10;
212
213 constexpr int32_t kTransactionId = 1234;
214
215 int64_t ts = 1;
216 binder_tracker->CommandToKernel(ts++, kSndTid,
217 BinderTracker::kBC_TRANSACTION);
218 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
219 kRcvTid, false, 0, kNullStringId);
220 binder_tracker->TransactionReceived(ts++, kRcvTid, kTransactionId);
221 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
222 BinderTracker::kBR_TRANSACTION);
223 binder_tracker->CommandToKernel(ts++, kRcvTid, BinderTracker::kBC_REPLY);
224 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
225 BinderTracker::kBR_FAILED_REPLY);
226 binder_tracker->ReturnFromKernel(ts++, kSndTid,
227 BinderTracker::kBR_TRANSACTION_COMPLETE);
228 binder_tracker->ReturnFromKernel(ts++, kSndTid,
229 BinderTracker::kBR_FAILED_REPLY);
230
231 const auto& slice = context.storage->slice_table();
232 ASSERT_EQ(slice.row_count(), 2u);
233 EXPECT_NE(slice[0].dur(), -1);
234 EXPECT_NE(slice[1].dur(), -1);
235
236 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
237 }
238
TEST_F(BinderTrackerTest,RequestReplyWithCommandsFailAfterReplyTxn)239 TEST_F(BinderTrackerTest, RequestReplyWithCommandsFailAfterReplyTxn) {
240 constexpr uint32_t kSndTid = 5;
241 constexpr uint32_t kRcvTid = 10;
242
243 constexpr int32_t kTransactionId = 1234;
244 constexpr int32_t kReplyTransactionId = 5678;
245
246 int64_t ts = 1;
247 binder_tracker->CommandToKernel(ts++, kSndTid,
248 BinderTracker::kBC_TRANSACTION);
249 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
250 kRcvTid, false, 0, kNullStringId);
251 binder_tracker->TransactionReceived(ts++, kRcvTid, kTransactionId);
252 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
253 BinderTracker::kBR_TRANSACTION);
254 binder_tracker->CommandToKernel(ts++, kRcvTid, BinderTracker::kBC_REPLY);
255 binder_tracker->Transaction(ts++, kRcvTid, kReplyTransactionId, 99, kSndTid,
256 kSndTid, true, 0, kNullStringId);
257 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
258 BinderTracker::kBR_TRANSACTION_COMPLETE);
259 binder_tracker->ReturnFromKernel(ts++, kSndTid,
260 BinderTracker::kBR_TRANSACTION_COMPLETE);
261 binder_tracker->ReturnFromKernel(ts++, kSndTid,
262 BinderTracker::kBR_FAILED_REPLY);
263
264 const auto& slice = context.storage->slice_table();
265 ASSERT_EQ(slice.row_count(), 2u);
266 EXPECT_NE(slice[0].dur(), -1);
267 EXPECT_NE(slice[1].dur(), -1);
268
269 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
270 }
271
TEST_F(BinderTrackerTest,OneWayWithCommands)272 TEST_F(BinderTrackerTest, OneWayWithCommands) {
273 constexpr uint32_t kSndTid = 5;
274 constexpr uint32_t kRcvTid = 10;
275
276 constexpr int32_t kTransactionId = 1234;
277
278 int64_t ts = 1;
279 binder_tracker->CommandToKernel(ts++, kSndTid,
280 BinderTracker::kBC_TRANSACTION);
281 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
282 kRcvTid, false, kOneWay, kNullStringId);
283 binder_tracker->ReturnFromKernel(ts++, kSndTid,
284 BinderTracker::kBR_TRANSACTION_COMPLETE);
285 binder_tracker->TransactionReceived(ts++, kRcvTid, kTransactionId);
286 binder_tracker->ReturnFromKernel(ts++, kRcvTid,
287 BinderTracker::kBR_TRANSACTION);
288
289 const auto& slice = context.storage->slice_table();
290 ASSERT_EQ(slice.row_count(), 2u);
291 EXPECT_EQ(slice[0].dur(), 0);
292 EXPECT_EQ(slice[1].dur(), 0);
293
294 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
295 }
296
TEST_F(BinderTrackerTest,OneWayWithCommandsFailBeforeTxn)297 TEST_F(BinderTrackerTest, OneWayWithCommandsFailBeforeTxn) {
298 constexpr uint32_t kSndTid = 5;
299
300 int64_t ts = 1;
301 binder_tracker->CommandToKernel(ts++, kSndTid,
302 BinderTracker::kBC_TRANSACTION);
303 binder_tracker->ReturnFromKernel(ts++, kSndTid,
304 BinderTracker::kBR_FAILED_REPLY);
305
306 const auto& slice = context.storage->slice_table();
307 EXPECT_EQ(slice.row_count(), 0u);
308
309 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
310 }
311
TEST_F(BinderTrackerTest,OneWayWithCommandsFailAfterTxn)312 TEST_F(BinderTrackerTest, OneWayWithCommandsFailAfterTxn) {
313 constexpr uint32_t kSndTid = 5;
314 constexpr uint32_t kRcvTid = 10;
315
316 constexpr int32_t kTransactionId = 1234;
317
318 int64_t ts = 1;
319 binder_tracker->CommandToKernel(ts++, kSndTid,
320 BinderTracker::kBC_TRANSACTION);
321 binder_tracker->Transaction(ts++, kSndTid, kTransactionId, 9, kRcvTid,
322 kRcvTid, false, kOneWay, kNullStringId);
323 binder_tracker->ReturnFromKernel(ts++, kSndTid,
324 BinderTracker::kBR_FAILED_REPLY);
325
326 const auto& slice = context.storage->slice_table();
327 ASSERT_EQ(slice.row_count(), 1u);
328 EXPECT_EQ(slice[0].dur(), 0);
329
330 EXPECT_TRUE(binder_tracker->utid_stacks_empty());
331 }
332
333 } // namespace
334 } // namespace perfetto::trace_processor
335