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