• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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             (void)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         (void)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             (void)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             (void)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         (void)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         } else {
129             TS_LOGD("ReceiveTraction, replySliceid value is INVALID!");
130             return;
131         }
132         // Add dest args
133         uint64_t transSliceId = INVALID_UINT32;
134         uint32_t argSetId = INVALID_UINT32;
135         std::tie(transSliceId, argSetId) = streamFilters_->sliceFilter_->AddArgs(transNeedReply_[transactionId],
136                                                                                  binderCatalogId_, transSliceId_, args);
137 
138         // remeber dest slice-id to the argset from "SendTraction" TAG-1
139         ArgsSet replyDestInserter;
140         if (IsValidUint32(transSliceId)) {
141             replyDestInserter.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, transSliceId);
142         } else {
143             TS_LOGD("ReceiveTraction, transSliceId value is INVALID!");
144             return;
145         }
146         std::tie(transSliceId, argSetId) =
147             streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, replyId_, replyDestInserter);
148         traceDataCache_->GetInternalSlicesData()->SetArgSetId(transSliceId, argSetId);
149         transNeedReply_.erase(transactionId);
150         return;
151     }
152     // the code below can be hard to understand, may be a EndBinder will be better
153     // this problem can be test after the IDE is finished
154     if (asyncBinderEvents_.count(transactionId)) {
155         auto args = asyncBinderEvents_[transactionId];
156         (void)streamFilters_->sliceFilter_->AsyncBinder(ts, pid, binderCatalogId_, asyncRcvId_, args);
157         // maybe you can use the flowing code: streamFilters_->sliceFilter_->EndBinder(ts, pid);
158         asyncBinderEvents_.erase(transactionId);
159         return;
160     }
161 }
TransactionAllocBuf(int64_t ts,uint32_t pid,uint64_t dataSize,uint64_t offsetsSize)162 void BinderFilter::TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize)
163 {
164     ArgsSet args;
165     args.AppendArg(dataSizeId_, BASE_DATA_TYPE_INT, dataSize);
166     args.AppendArg(dataOffsetSizeId_, BASE_DATA_TYPE_INT, offsetsSize);
167     (void)streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, transSliceId_, args);
168     Unused(ts);
169 }
TractionLock(int64_t ts,uint32_t pid,const std::string & tag)170 void BinderFilter::TractionLock(int64_t ts, uint32_t pid, const std::string &tag)
171 {
172     Unused(tag);
173     lastEventTs_[pid] = ts;
174     (void)streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockTryId_);
175 }
TractionLocked(int64_t ts,uint32_t pid,const std::string & tag)176 void BinderFilter::TractionLocked(int64_t ts, uint32_t pid, const std::string &tag)
177 {
178     Unused(tag);
179     if (!lastEventTs_.count(pid)) {
180         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_NOTMATCH);
181         return;
182     }
183     (void)streamFilters_->sliceFilter_->EndBinder(ts, pid);
184     (void)streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockHoldId_);
185     lastEventTs_.erase(pid);
186     lastEventTs_[pid] = ts;
187 }
TractionUnlock(int64_t ts,uint32_t pid,const std::string & tag)188 void BinderFilter::TractionUnlock(int64_t ts, uint32_t pid, const std::string &tag)
189 {
190     Unused(tag);
191     if (!lastEventTs_.count(pid)) {
192         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, STAT_EVENT_NOTMATCH);
193         return;
194     }
195     (void)streamFilters_->sliceFilter_->EndBinder(ts, pid, binderCatalogId_, lockHoldId_);
196     lastEventTs_.erase(pid);
197     lastEventTs_[pid] = ts;
198 }
IsAsync(int32_t flags) const199 bool BinderFilter::IsAsync(int32_t flags) const
200 {
201     return (flags & noReturnMsgFlag_) == noReturnMsgFlag_;
202 }
Clear()203 void BinderFilter::Clear()
204 {
205     lastEventTs_.clear();
206     transReplyWaitingReply_.clear();
207     transNeedReply_.clear();
208     asyncBinderEvents_.clear();
209 }
210 } // namespace TraceStreamer
211 } // namespace SysTuning
212