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