• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "binder_filter.h"
16 #include "measure_filter.h"
17 #include "process_filter.h"
18 #include "slice_filter.h"
19 #include "stat_filter.h"
20 #include "string_to_numerical.h"
21 namespace SysTuning {
22 namespace TraceStreamer {
BinderFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)23 BinderFilter::BinderFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter)
24     : FilterBase(dataCache, filter)
25 {
26     binderFlagDescs_ = {{noReturnMsgFlag_, " this is a one-way call: async, no return; "},
27                         {rootObjectMsgFlag_, " contents are the components root object; "},
28                         {statusCodeMsgFlag_, " contents are a 32-bit status code; "},
29                         {acceptFdsMsgFlag_, " allow replies with file descriptors; "},
30                         {noFlagsMsgFlag_, " No Flags Set"}};
31 }
32 BinderFilter::~BinderFilter() = default;
33 
GetBinderFlagsDesc(uint32_t flag)34 std::string BinderFilter::GetBinderFlagsDesc(uint32_t flag)
35 {
36     std::string str;
37     if (flag & noReturnMsgFlag_) {
38         str += binderFlagDescs_.at(noReturnMsgFlag_);
39     }
40     if (flag & rootObjectMsgFlag_) {
41         str += binderFlagDescs_.at(rootObjectMsgFlag_);
42     }
43     if (flag & statusCodeMsgFlag_) {
44         str += binderFlagDescs_.at(statusCodeMsgFlag_);
45     }
46     if (flag & acceptFdsMsgFlag_) {
47         str += binderFlagDescs_.at(acceptFdsMsgFlag_);
48     }
49     if (flag == noFlagsMsgFlag_) {
50         str += binderFlagDescs_.at(noFlagsMsgFlag_);
51     }
52     return str;
53 }
SendTraction(int64_t ts,uint32_t tid,uint64_t transactionId,int32_t destNode,int32_t destTgid,int32_t destTid,bool isReply,int32_t flags,int32_t code)54 void BinderFilter::SendTraction(int64_t ts,
55                                 uint32_t tid,
56                                 uint64_t transactionId,
57                                 int32_t destNode,
58                                 int32_t destTgid,
59                                 int32_t destTid,
60                                 bool isReply,
61                                 int32_t flags,
62                                 int32_t code)
63 {
64     auto flagsStr = traceDataCache_->GetDataIndex("0x" + base::number(flags, base::INTEGER_RADIX_TYPE_HEX) +
65                                                   GetBinderFlagsDesc(flags));
66     DataIndex codeStr = traceDataCache_->GetDataIndex("0x" + base::number(code, base::INTEGER_RADIX_TYPE_HEX) +
67                                                       " Java Layer Dependent");
68     ArgsSet argsSend;
69     argsSend.AppendArg(transId_, BASE_DATA_TYPE_INT, transactionId);
70     argsSend.AppendArg(destNodeId_, BASE_DATA_TYPE_INT, destNode);
71     argsSend.AppendArg(destProcessId_, BASE_DATA_TYPE_INT, destTgid);
72     argsSend.AppendArg(isReplayId_, BASE_DATA_TYPE_BOOLEAN, isReply);
73     argsSend.AppendArg(flagsId_, BASE_DATA_TYPE_STRING, flagsStr);
74     argsSend.AppendArg(codeId_, BASE_DATA_TYPE_STRING, codeStr);
75     argsSend.AppendArg(callingTid_, BASE_DATA_TYPE_INT, tid);
76 
77     if (isReply) {
78         // sometime a reply-binder from a tid appear repeated to different dest, we only chose the right one
79         if (transReplyFilter_.count(tid) && transReplyFilter_[tid] == destTid) {
80             // Add dest information to Reply slices, the Begin msg is from TAG-2
81             InternalTid dstItid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, destTid);
82             const auto destThreadName = traceDataCache_->GetConstThreadData(dstItid).nameIndex_;
83             ArgsSet destArgs;
84             destArgs.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, destTid);
85             destArgs.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, destThreadName);
86             streamFilters_->sliceFilter_->AddArgs(tid, binderCatalogId_, replyId_, destArgs);
87             transReplyFilter_.erase(tid);
88         }
89         // the flowing code should be under the ubove conditions, but this will bring a big impact to the UI-SHOW
90         streamFilters_->sliceFilter_->EndBinder(ts, tid, INVALID_UINT64, INVALID_UINT64, argsSend);
91         transReplyWaitingReply_.insert(transactionId);
92         return;
93     } else {
94         bool needReply = !isReply && !(flags & noReturnMsgFlag_);
95         if (needReply) {
96             // transaction needs reply TAG-1
97             streamFilters_->sliceFilter_->BeginBinder(ts, tid, binderCatalogId_, transSliceId_, argsSend);
98             transNeedReply_[transactionId] = tid;
99         } else {
100             // transaction do not need reply
101             // tid calling id
102             // a binder event only care the transactionId and the callint tid
103             streamFilters_->sliceFilter_->AsyncBinder(ts, tid, binderCatalogId_, transAsyncId_, argsSend);
104             asyncBinderEvents_[transactionId] = argsSend;
105         }
106     }
107 }
ReceiveTraction(int64_t ts,uint32_t pid,uint64_t transactionId)108 void BinderFilter::ReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId)
109 {
110     InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, pid);
111     const auto threadName = traceDataCache_->GetConstThreadData(internalTid).nameIndex_;
112     if (transReplyWaitingReply_.count(transactionId)) {
113         streamFilters_->sliceFilter_->EndBinder(ts, pid);
114         transReplyWaitingReply_.erase(transactionId);
115         return;
116     }
117 
118     if (transNeedReply_.count(transactionId)) {
119         // First, begin the reply, the reply will be end in "SendTraction" func, and the isReply will be true, TAG-2
120         auto replySliceid = streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, replyId_);
121         transReplyFilter_[pid] = transNeedReply_[transactionId];
122         // Add dest info to the reply
123         ArgsSet args;
124         args.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, pid);
125         args.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, threadName);
126         if (IsValidUint32(static_cast<uint32_t>(replySliceid))) {
127             args.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, replySliceid);
128         }
129         // Add dest args
130         uint64_t transSliceId = INVALID_UINT64;
131         uint32_t argSetId = INVALID_UINT32;
132         std::tie(transSliceId, argSetId) = streamFilters_->sliceFilter_->AddArgs(transNeedReply_[transactionId],
133                                                                                  binderCatalogId_, transSliceId_, args);
134 
135         // remeber dest slice-id to the argset from "SendTraction" TAG-1
136         ArgsSet replyDestInserter;
137         if (IsValidUint32(transSliceId)) {
138             replyDestInserter.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, transSliceId);
139         }
140         std::tie(transSliceId, argSetId) = streamFilters_->sliceFilter_->
141         AddArgs(pid, binderCatalogId_, replyId_, replyDestInserter);
142         traceDataCache_->GetInternalSlicesData()->SetArgSetId(transSliceId, argSetId);
143         transNeedReply_.erase(transactionId);
144         return;
145     }
146     // the code below can be hard to understand, may be a EndBinder will be better
147     // this problem can be test after the IDE is finished
148     if (asyncBinderEvents_.count(transactionId)) {
149         auto args = asyncBinderEvents_[transactionId];
150         streamFilters_->sliceFilter_->AsyncBinder(ts, pid, binderCatalogId_, asyncRcvId_, args);
151         // maybe you can use the flowing code: streamFilters_->sliceFilter_->EndBinder(ts, pid);
152         asyncBinderEvents_.erase(transactionId);
153         return;
154     }
155 }
TransactionAllocBuf(int64_t ts,uint32_t pid,uint64_t dataSize,uint64_t offsetsSize)156 void BinderFilter::TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize)
157 {
158     ArgsSet args;
159     args.AppendArg(dataSizeId_, BASE_DATA_TYPE_INT, dataSize);
160     args.AppendArg(dataOffsetSizeId_, BASE_DATA_TYPE_INT, offsetsSize);
161     streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, transSliceId_, args);
162     UNUSED(ts);
163 }
TractionLock(int64_t ts,uint32_t pid,const std::string & tag)164 void BinderFilter::TractionLock(int64_t ts, uint32_t pid, const std::string& tag)
165 {
166     UNUSED(tag);
167     lastEventTs_[pid] = ts;
168     streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockTryId_);
169 }
TractionLocked(int64_t ts,uint32_t pid,const std::string & tag)170 void BinderFilter::TractionLocked(int64_t ts, uint32_t pid, const std::string& tag)
171 {
172     UNUSED(tag);
173     if (!lastEventTs_.count(pid)) {
174         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_NOTMATCH);
175         return;
176     }
177     streamFilters_->sliceFilter_->EndBinder(ts, pid);
178     streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockHoldId_);
179     lastEventTs_.erase(pid);
180     lastEventTs_[pid] = ts;
181 }
TractionUnlock(int64_t ts,uint32_t pid,const std::string & tag)182 void BinderFilter::TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag)
183 {
184     UNUSED(tag);
185     if (!lastEventTs_.count(pid)) {
186         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, STAT_EVENT_NOTMATCH);
187         return;
188     }
189     streamFilters_->sliceFilter_->EndBinder(ts, pid, binderCatalogId_, lockHoldId_);
190     lastEventTs_.erase(pid);
191     lastEventTs_[pid] = ts;
192 }
Clear()193 void BinderFilter::Clear()
194 {
195     lastEventTs_.clear();
196     transReplyWaitingReply_.clear();
197     transNeedReply_.clear();
198     asyncBinderEvents_.clear();
199     binderFlagDescs_.clear();
200 }
201 } // namespace TraceStreamer
202 } // namespace SysTuning
203