• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "perfetto/base/logging.h"
20 #include "src/trace_processor/importers/common/args_tracker.h"
21 #include "src/trace_processor/importers/common/args_translation_table.h"
22 #include "src/trace_processor/importers/common/event_tracker.h"
23 #include "src/trace_processor/importers/common/flow_tracker.h"
24 #include "src/trace_processor/importers/common/process_tracker.h"
25 #include "src/trace_processor/importers/common/slice_tracker.h"
26 #include "src/trace_processor/importers/common/slice_translation_table.h"
27 #include "src/trace_processor/importers/common/track_tracker.h"
28 #include "src/trace_processor/storage/trace_storage.h"
29 #include "test/gtest_and_gmock.h"
30 
31 namespace perfetto {
32 namespace trace_processor {
33 namespace {
34 constexpr int kOneWay = 0x01;
35 
36 class BinderTrackerTest : public ::testing::Test {
37  public:
BinderTrackerTest()38   BinderTrackerTest() {
39     context.storage.reset(new TraceStorage());
40     context.global_args_tracker.reset(
41         new GlobalArgsTracker(context.storage.get()));
42     context.args_tracker.reset(new ArgsTracker(&context));
43     context.args_translation_table.reset(
44         new ArgsTranslationTable(context.storage.get()));
45     context.slice_tracker.reset(new SliceTracker(&context));
46     context.slice_translation_table.reset(
47         new SliceTranslationTable(context.storage.get()));
48     context.process_tracker.reset(new ProcessTracker(&context));
49     context.track_tracker.reset(new TrackTracker(&context));
50     context.flow_tracker.reset(new FlowTracker(&context));
51     binder_tracker = BinderTracker::GetOrCreate(&context);
52   }
53 
54  protected:
55   TraceProcessorContext context;
56   BinderTracker* binder_tracker;
57 };
58 
TEST_F(BinderTrackerTest,RequestReply)59 TEST_F(BinderTrackerTest, RequestReply) {
60   int64_t req_ts = 100;
61   int64_t req_recv_ts = 105;
62   int64_t rep_ts = 150;
63   int64_t rep_recv_ts = 155;
64 
65   uint32_t req_tid = 5;
66   uint32_t rep_tid = 10;
67 
68   int32_t req_transaction_id = 1234;
69   int32_t rep_transaction_id = 5678;
70 
71   binder_tracker->Transaction(req_ts, req_tid, req_transaction_id, 9, rep_tid,
72                               rep_tid, false, 0, kNullStringId);
73   binder_tracker->TransactionReceived(req_recv_ts, rep_tid, req_transaction_id);
74 
75   binder_tracker->Transaction(rep_ts, rep_tid, rep_transaction_id, 99, req_tid,
76                               req_tid, true, 0, kNullStringId);
77   binder_tracker->TransactionReceived(rep_recv_ts, req_tid, rep_transaction_id);
78 
79   const auto& thread = context.storage->thread_table();
80   const auto& track = context.storage->thread_track_table();
81   const auto& slice = context.storage->slice_table();
82   const auto& flow = context.storage->flow_table();
83   ASSERT_EQ(slice.row_count(), 2u);
84 
85   auto tid_for_slice = [&](uint32_t row) {
86     TrackId track_id = slice.track_id()[row];
87     UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
88     return thread.tid()[utid];
89   };
90 
91   ASSERT_EQ(slice.ts()[0], req_ts);
92   ASSERT_EQ(slice.dur()[0], rep_recv_ts - req_ts);
93   ASSERT_EQ(tid_for_slice(0), req_tid);
94 
95   ASSERT_EQ(slice.ts()[1], req_recv_ts);
96   ASSERT_EQ(slice.dur()[1], 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.slice_out()[0], slice.id()[0]);
101   ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
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.track_id()[row];
127     UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
128     return thread.tid()[utid];
129   };
130 
131   ASSERT_EQ(slice.ts()[0], sen_ts);
132   ASSERT_EQ(slice.dur()[0], 0);
133   ASSERT_EQ(tid_for_slice(0), sen_tid);
134 
135   ASSERT_EQ(slice.ts()[1], rec_ts);
136   ASSERT_EQ(slice.dur()[1], 0);
137   ASSERT_EQ(tid_for_slice(1), rec_tid);
138 
139   ASSERT_EQ(flow.row_count(), 1u);
140   ASSERT_EQ(flow.slice_out()[0], slice.id()[0]);
141   ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
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.dur()[0], -1);
174   EXPECT_NE(slice.dur()[1], -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.dur()[0], -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.dur()[0], -1);
240   EXPECT_NE(slice.dur()[1], -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.dur()[0], -1);
273   EXPECT_NE(slice.dur()[1], -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.dur()[0], 0);
298   EXPECT_EQ(slice.dur()[1], 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.dur()[0], 0);
335 
336   EXPECT_TRUE(binder_tracker->utid_stacks_empty());
337 }
338 
339 }  // namespace
340 }  // namespace trace_processor
341 }  // namespace perfetto
342