1 /*
2 * Copyright (c) 2023-2024 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
16 #include "cooperate_client.h"
17
18 #ifdef ENABLE_PERFORMANCE_CHECK
19 #include <algorithm>
20 #include <numeric>
21 #endif // ENABLE_PERFORMANCE_CHECK
22
23 #include "cooperate_params.h"
24 #include "default_params.h"
25 #include "devicestatus_define.h"
26 #include "utility.h"
27
28 #undef LOG_TAG
29 #define LOG_TAG "CooperateClient"
30
31 namespace OHOS {
32 namespace Msdp {
33 namespace DeviceStatus {
34 namespace {
35 #ifdef ENABLE_PERFORMANCE_CHECK
36 constexpr int32_t PERCENTAGE { 100 };
37 constexpr int32_t FAILURE_DURATION { -100 };
38 constexpr int32_t INVALID_INDEX { -1 };
39 #endif // ENABLE_PERFORMANCE_CHECK
40 } // namespace
41
RegisterListener(ITunnelClient & tunnel,CooperateListenerPtr listener,bool isCheckPermission)42 int32_t CooperateClient::RegisterListener(ITunnelClient &tunnel,
43 CooperateListenerPtr listener, bool isCheckPermission)
44 {
45 CALL_DEBUG_ENTER;
46 CHKPR(listener, RET_ERR);
47 std::lock_guard<std::mutex> guard(mtx_);
48 for (const auto &item : devCooperateListener_) {
49 if (item == listener) {
50 FI_HILOGE("The listener already exists");
51 return RET_ERR;
52 }
53 }
54 if (!isListeningProcess_) {
55 FI_HILOGI("Start monitoring");
56 DefaultParam param;
57 DefaultReply reply;
58
59 int32_t ret = tunnel.AddWatch(Intention::COOPERATE, CooperateRequestID::REGISTER_LISTENER, param, reply);
60 if (ret != RET_OK) {
61 FI_HILOGE("Failed to register, ret:%{public}d", ret);
62 return ret;
63 }
64 isListeningProcess_ = true;
65 }
66 devCooperateListener_.push_back(listener);
67 return RET_OK;
68 }
69
UnregisterListener(ITunnelClient & tunnel,CooperateListenerPtr listener,bool isCheckPermission)70 int32_t CooperateClient::UnregisterListener(ITunnelClient &tunnel,
71 CooperateListenerPtr listener, bool isCheckPermission)
72 {
73 CALL_DEBUG_ENTER;
74 std::lock_guard<std::mutex> guard(mtx_);
75 if (listener == nullptr) {
76 devCooperateListener_.clear();
77 goto listenerLabel;
78 }
79 for (auto it = devCooperateListener_.begin(); it != devCooperateListener_.end(); ++it) {
80 if (*it == listener) {
81 devCooperateListener_.erase(it);
82 goto listenerLabel;
83 }
84 }
85
86 listenerLabel:
87 if (isListeningProcess_ && devCooperateListener_.empty()) {
88 isListeningProcess_ = false;
89 DefaultParam param;
90 DefaultReply reply;
91 return tunnel.RemoveWatch(Intention::COOPERATE, CooperateRequestID::UNREGISTER_LISTENER, param, reply);
92 }
93 return RET_OK;
94 }
95
Enable(ITunnelClient & tunnel,CooperateMessageCallback callback,bool isCheckPermission)96 int32_t CooperateClient::Enable(ITunnelClient &tunnel,
97 CooperateMessageCallback callback, bool isCheckPermission)
98 {
99 CALL_DEBUG_ENTER;
100 std::lock_guard<std::mutex> guard(mtx_);
101 CooperateEvent event { callback };
102 DefaultParam param { GenerateRequestID() };
103 DefaultReply reply;
104
105 int32_t ret = tunnel.Enable(Intention::COOPERATE, param, reply);
106 if (ret != RET_OK) {
107 FI_HILOGE("Prepare cooperate failed");
108 return ret;
109 }
110 devCooperateEvent_.insert_or_assign(param.userData, event);
111 return RET_OK;
112 }
113
Disable(ITunnelClient & tunnel,CooperateMessageCallback callback,bool isCheckPermission)114 int32_t CooperateClient::Disable(ITunnelClient &tunnel,
115 CooperateMessageCallback callback, bool isCheckPermission)
116 {
117 CALL_DEBUG_ENTER;
118 std::lock_guard<std::mutex> guard(mtx_);
119 CooperateEvent event { callback };
120 DefaultParam param { GenerateRequestID() };
121 DefaultReply reply;
122
123 int32_t ret = tunnel.Disable(Intention::COOPERATE, param, reply);
124 if (ret != RET_OK) {
125 FI_HILOGE("Unprepare cooperate failed");
126 return ret;
127 }
128 devCooperateEvent_.insert_or_assign(param.userData, event);
129 #ifdef ENABLE_PERFORMANCE_CHECK
130 DumpPerformanceInfo();
131 #endif // ENABLE_PERFORMANCE_CHECK
132 return RET_OK;
133 }
134
Start(ITunnelClient & tunnel,const std::string & remoteNetworkId,int32_t startDeviceId,CooperateMessageCallback callback,bool isCheckPermission)135 int32_t CooperateClient::Start(ITunnelClient &tunnel, const std::string &remoteNetworkId,
136 int32_t startDeviceId, CooperateMessageCallback callback, bool isCheckPermission)
137 {
138 CALL_DEBUG_ENTER;
139 std::lock_guard<std::mutex> guard(mtx_);
140 CooperateEvent event { callback };
141 auto userData = GenerateRequestID();
142 #ifdef ENABLE_PERFORMANCE_CHECK
143 StartTrace(userData);
144 #endif // ENABLE_PERFORMANCE_CHECK
145 StartCooperateParam param { userData, remoteNetworkId, startDeviceId, isCheckPermission };
146 DefaultReply reply;
147
148 int32_t ret = tunnel.Start(Intention::COOPERATE, param, reply);
149 if (ret != RET_OK) {
150 FI_HILOGE("Activate cooperate failed");
151 return ret;
152 }
153 devCooperateEvent_.insert_or_assign(param.userData, event);
154 return RET_OK;
155 }
156
Stop(ITunnelClient & tunnel,bool isUnchained,CooperateMessageCallback callback,bool isCheckPermission)157 int32_t CooperateClient::Stop(ITunnelClient &tunnel,
158 bool isUnchained, CooperateMessageCallback callback, bool isCheckPermission)
159 {
160 CALL_DEBUG_ENTER;
161 std::lock_guard<std::mutex> guard(mtx_);
162 CooperateEvent event { callback };
163 StopCooperateParam param { GenerateRequestID(), isUnchained, isCheckPermission };
164 DefaultReply reply;
165
166 int32_t ret = tunnel.Stop(Intention::COOPERATE, param, reply);
167 if (ret != RET_OK) {
168 FI_HILOGE("Deactivate cooperate failed");
169 return ret;
170 }
171 devCooperateEvent_.insert_or_assign(param.userData, event);
172 return RET_OK;
173 }
174
GetCooperateState(ITunnelClient & tunnel,const std::string & networkId,CooperateStateCallback callback,bool isCheckPermission)175 int32_t CooperateClient::GetCooperateState(ITunnelClient &tunnel,
176 const std::string &networkId, CooperateStateCallback callback, bool isCheckPermission)
177 {
178 CALL_DEBUG_ENTER;
179 std::lock_guard<std::mutex> guard(mtx_);
180 CooperateEvent event { callback };
181 GetCooperateStateParam param { GenerateRequestID(), networkId, isCheckPermission };
182 DefaultReply reply;
183
184 int32_t ret = tunnel.GetParam(Intention::COOPERATE, CooperateRequestID::GET_COOPERATE_STATE, param, reply);
185 if (ret != RET_OK) {
186 FI_HILOGE("Get cooperate state failed");
187 return ret;
188 }
189 devCooperateEvent_.insert_or_assign(param.userData, event);
190 return RET_OK;
191 }
192
GetCooperateState(ITunnelClient & tunnel,const std::string & udId,bool & state)193 int32_t CooperateClient::GetCooperateState(ITunnelClient &tunnel, const std::string &udId, bool &state)
194 {
195 CALL_DEBUG_ENTER;
196 std::lock_guard<std::mutex> guard(mtx_);
197 GetCooperateStateSyncParam param { udId };
198 BooleanReply reply;
199 if (tunnel.GetParam(Intention::COOPERATE, CooperateRequestID::GET_COOPERATE_STATE_SYNC, param, reply) != RET_OK) {
200 FI_HILOGE("Get cooperate state failed udId: %{public}s", Utility::Anonymize(udId).c_str());
201 return RET_ERR;
202 }
203 FI_HILOGI("GetCooperateState for udId: %{public}s successfully,state: %{public}s",
204 Utility::Anonymize(udId).c_str(), reply.state ? "true" : "false");
205 state = reply.state;
206 return RET_OK;
207 }
208
RegisterEventListener(ITunnelClient & tunnel,const std::string & networkId,MouseLocationListenerPtr listener)209 int32_t CooperateClient::RegisterEventListener(ITunnelClient &tunnel,
210 const std::string &networkId, MouseLocationListenerPtr listener)
211 {
212 CALL_DEBUG_ENTER;
213 CHKPR(listener, COMMON_PARAMETER_ERROR);
214 std::lock_guard<std::mutex> guard(mtx_);
215 if (eventListener_.find(networkId) != eventListener_.end() &&
216 eventListener_[networkId].find(listener) != eventListener_[networkId].end()) {
217 FI_HILOGE("This listener for networkId:%{public}s already exists", Utility::Anonymize(networkId).c_str());
218 return RET_ERR;
219 }
220 RegisterEventListenerParam param { networkId };
221 DefaultReply reply;
222 if (int32_t ret = tunnel.AddWatch(Intention::COOPERATE, CooperateRequestID::REGISTER_EVENT_LISTENER, param, reply);
223 ret != RET_OK) {
224 FI_HILOGE("RegisterEventListener failed, ret:%{public}d", ret);
225 return ret;
226 }
227 eventListener_[networkId].insert(listener);
228 FI_HILOGI("Add listener for networkId:%{public}s successfully", Utility::Anonymize(networkId).c_str());
229 return RET_OK;
230 }
231
UnregisterEventListener(ITunnelClient & tunnel,const std::string & networkId,MouseLocationListenerPtr listener)232 int32_t CooperateClient::UnregisterEventListener(ITunnelClient &tunnel,
233 const std::string &networkId, MouseLocationListenerPtr listener)
234 {
235 CALL_DEBUG_ENTER;
236 std::lock_guard<std::mutex> guard(mtx_);
237 if (eventListener_.find(networkId) == eventListener_.end()) {
238 FI_HILOGE("No listener for networkId:%{public}s is registered", Utility::Anonymize(networkId).c_str());
239 return RET_ERR;
240 }
241 if (eventListener_.find(networkId) != eventListener_.end() && listener != nullptr &&
242 eventListener_[networkId].find(listener) == eventListener_[networkId].end()) {
243 FI_HILOGE("Current listener for networkId:%{public}s is not registered", Utility::Anonymize(networkId).c_str());
244 return RET_ERR;
245 }
246 if (listener == nullptr) {
247 eventListener_.erase(networkId);
248 FI_HILOGI("Remove all listener for networkId:%{public}s", Utility::Anonymize(networkId).c_str());
249 } else {
250 eventListener_[networkId].erase(listener);
251 FI_HILOGI("Remove listener for networkId:%{public}s", Utility::Anonymize(networkId).c_str());
252 if (eventListener_[networkId].empty()) {
253 eventListener_.erase(networkId);
254 FI_HILOGD("No listener for networkId:%{public}s, clean current networkId",
255 Utility::Anonymize(networkId).c_str());
256 }
257 }
258 if (eventListener_.find(networkId) != eventListener_.end()) {
259 FI_HILOGD("UnregisterEventListener for networkId:%{public}s successfully",
260 Utility::Anonymize(networkId).c_str());
261 return RET_OK;
262 }
263 UnregisterEventListenerParam param { networkId };
264 DefaultReply reply;
265 if (int32_t ret = tunnel.RemoveWatch(Intention::COOPERATE,
266 CooperateRequestID::UNREGISTER_EVENT_LISTENER, param, reply); ret != RET_OK) {
267 FI_HILOGE("UnregisterEventListener failed, ret:%{public}d", ret);
268 return ret;
269 }
270 FI_HILOGD("Unregister all Listener for networkId:%{public}s successfully", Utility::Anonymize(networkId).c_str());
271 return RET_OK;
272 }
273
AddHotAreaListener(ITunnelClient & tunnel,HotAreaListenerPtr listener)274 int32_t CooperateClient::AddHotAreaListener(ITunnelClient &tunnel, HotAreaListenerPtr listener)
275 {
276 CALL_DEBUG_ENTER;
277 CHKPR(listener, RET_ERR);
278 std::lock_guard<std::mutex> guard(mtx_);
279 if (std::find(devHotAreaListener_.begin(), devHotAreaListener_.end(), listener) != devHotAreaListener_.end()) {
280 FI_HILOGD("Current listener is registered already");
281 return RET_ERR;
282 }
283 RegisterHotAreaListenerParam param { GenerateRequestID(), false };
284 DefaultReply reply;
285 if (int32_t ret = tunnel.AddWatch(Intention::COOPERATE,
286 CooperateRequestID::REGISTER_HOTAREA_LISTENER, param, reply); ret != RET_OK) {
287 FI_HILOGE("AddHotAreaListener failed, ret:%{public}d", ret);
288 return ret;
289 }
290 devHotAreaListener_.push_back(listener);
291 return RET_OK;
292 }
293
RemoveHotAreaListener(ITunnelClient & tunnel,HotAreaListenerPtr listener)294 int32_t CooperateClient::RemoveHotAreaListener(ITunnelClient &tunnel, HotAreaListenerPtr listener)
295 {
296 CALL_DEBUG_ENTER;
297 {
298 std::lock_guard<std::mutex> guard(mtx_);
299 if (listener != nullptr &&
300 std::find(devHotAreaListener_.begin(), devHotAreaListener_.end(), listener) == devHotAreaListener_.end()) {
301 FI_HILOGD("Current listener is not registered");
302 return RET_ERR;
303 }
304 if (listener == nullptr) {
305 devHotAreaListener_.clear();
306 } else {
307 for (auto it = devHotAreaListener_.begin(); it != devHotAreaListener_.end(); ++it) {
308 if (*it == listener) {
309 devHotAreaListener_.erase(it);
310 }
311 }
312 }
313 if (!devHotAreaListener_.empty()) {
314 FI_HILOGI("RemoveHotAreaListener successfully");
315 return RET_OK;
316 }
317 }
318 UnregisterHotAreaListenerParam param { GenerateRequestID(), false };
319 DefaultReply reply;
320 if (int32_t ret = tunnel.RemoveWatch(Intention::COOPERATE,
321 CooperateRequestID::UNREGISTER_HOTAREA_LISTENER, param, reply); ret != RET_OK) {
322 FI_HILOGE("RemoveHotAreaListener failed, ret:%{public}d", ret);
323 return ret;
324 }
325 FI_HILOGI("Remove all hot area listener successfully");
326 return RET_OK;
327 }
328
GenerateRequestID()329 int32_t CooperateClient::GenerateRequestID()
330 {
331 static int32_t requestId { 0 };
332
333 if (requestId == std::numeric_limits<int32_t>::max()) {
334 FI_HILOGE("Request ID exceeds the maximum");
335 requestId = 0;
336 }
337 return requestId++;
338 }
339
OnCoordinationListener(const StreamClient & client,NetPacket & pkt)340 int32_t CooperateClient::OnCoordinationListener(const StreamClient &client, NetPacket &pkt)
341 {
342 CALL_INFO_TRACE;
343 int32_t userData = 0;
344 std::string networkId;
345 int32_t nType = 0;
346 pkt >> userData >> networkId >> nType;
347 if (pkt.ChkRWError()) {
348 FI_HILOGE("Packet read type failed");
349 return RET_ERR;
350 }
351 FI_HILOGI("NetworkId:%{public}s, nType:%{public}d", Utility::Anonymize(networkId).c_str(), nType);
352 OnDevCooperateListener(networkId, CoordinationMessage(nType));
353 return RET_OK;
354 }
355
OnDevCooperateListener(const std::string & networkId,CoordinationMessage msg)356 void CooperateClient::OnDevCooperateListener(const std::string &networkId, CoordinationMessage msg)
357 {
358 CALL_INFO_TRACE;
359 std::lock_guard<std::mutex> guard(mtx_);
360 for (const auto &item : devCooperateListener_) {
361 item->OnCoordinationMessage(networkId, msg);
362 }
363 }
364
OnCoordinationMessage(const StreamClient & client,NetPacket & pkt)365 int32_t CooperateClient::OnCoordinationMessage(const StreamClient &client, NetPacket &pkt)
366 {
367 CALL_INFO_TRACE;
368 int32_t userData = 0;
369 std::string networkId;
370 int32_t nType = 0;
371 int32_t errCode = -1;
372 pkt >> userData >> networkId >> nType >> errCode;
373 if (pkt.ChkRWError()) {
374 FI_HILOGE("Packet read coordination msg failed");
375 return RET_ERR;
376 }
377 #ifdef ENABLE_PERFORMANCE_CHECK
378 FinishTrace(userData, CoordinationMessage(nType));
379 #endif // ENABLE_PERFORMANCE_CHECK
380 FI_HILOGI("NetworkId:%{public}s, nType:%{public}d", Utility::Anonymize(networkId).c_str(), nType);
381 CoordinationMsgInfo msgInfo {
382 .msg = static_cast<CoordinationMessage> (nType),
383 .errCode = errCode
384 };
385 OnCooperateMessageEvent(userData, networkId, msgInfo);
386 return RET_OK;
387 }
388
OnCooperateMessageEvent(int32_t userData,const std::string & networkId,const CoordinationMsgInfo & msgInfo)389 void CooperateClient::OnCooperateMessageEvent(int32_t userData,
390 const std::string &networkId, const CoordinationMsgInfo &msgInfo)
391 {
392 CALL_INFO_TRACE;
393 CHK_PID_AND_TID();
394 std::lock_guard<std::mutex> guard(mtx_);
395 auto iter = devCooperateEvent_.find(userData);
396 if (iter == devCooperateEvent_.end()) {
397 return;
398 }
399 CooperateMessageCallback callback = iter->second.msgCb;
400 CHKPV(callback);
401 callback(networkId, msgInfo);
402 devCooperateEvent_.erase(iter);
403 }
404
OnCoordinationState(const StreamClient & client,NetPacket & pkt)405 int32_t CooperateClient::OnCoordinationState(const StreamClient &client, NetPacket &pkt)
406 {
407 CALL_INFO_TRACE;
408 int32_t userData = 0;
409 bool state = false;
410 int32_t errCode = -1;
411 pkt >> userData >> state >> errCode;
412 if (pkt.ChkRWError()) {
413 FI_HILOGE("Packet read coordination msg failed");
414 return RET_ERR;
415 }
416 FI_HILOGI("State%{public}s", state ? "true" : "false");
417 OnCooperateStateEvent(userData, state);
418 return RET_OK;
419 }
420
OnCooperateStateEvent(int32_t userData,bool state)421 void CooperateClient::OnCooperateStateEvent(int32_t userData, bool state)
422 {
423 CALL_INFO_TRACE;
424 CHK_PID_AND_TID();
425 std::lock_guard<std::mutex> guard(mtx_);
426 auto iter = devCooperateEvent_.find(userData);
427 if (iter == devCooperateEvent_.end()) {
428 return;
429 }
430 CooperateStateCallback event = iter->second.stateCb;
431 CHKPV(event);
432 event(state);
433 devCooperateEvent_.erase(iter);
434 FI_HILOGD("Coordination state event callback, userData:%{public}d, state:(%{public}d)", userData, state);
435 }
436
OnHotAreaListener(const StreamClient & client,NetPacket & pkt)437 int32_t CooperateClient::OnHotAreaListener(const StreamClient &client, NetPacket &pkt)
438 {
439 CALL_DEBUG_ENTER;
440 int32_t positionX = 0;
441 int32_t positionY = 0;
442 int32_t type = 0;
443 bool isEdge = false;
444 pkt >> positionX >> positionY >> type >> isEdge;
445 if (pkt.ChkRWError()) {
446 FI_HILOGE("Packet read type failed");
447 return RET_ERR;
448 }
449 OnDevHotAreaListener(positionX, positionY, HotAreaType(type), isEdge);
450 return RET_OK;
451 }
452
OnMouseLocationListener(const StreamClient & client,NetPacket & pkt)453 int32_t CooperateClient::OnMouseLocationListener(const StreamClient &client, NetPacket &pkt)
454 {
455 CALL_DEBUG_ENTER;
456 std::string networkId;
457 Event event;
458 pkt >> networkId >> event.displayX >> event.displayY >> event.displayWidth >> event.displayHeight;
459 if (pkt.ChkRWError()) {
460 FI_HILOGE("Packet read type failed");
461 return RET_ERR;
462 }
463 OnDevMouseLocationListener(networkId, event);
464 return RET_OK;
465 }
466
OnDevHotAreaListener(int32_t displayX,int32_t displayY,HotAreaType type,bool isEdge)467 void CooperateClient::OnDevHotAreaListener(int32_t displayX,
468 int32_t displayY, HotAreaType type, bool isEdge)
469 {
470 CALL_DEBUG_ENTER;
471 std::lock_guard<std::mutex> guard(mtx_);
472 for (const auto &item : devHotAreaListener_) {
473 item->OnHotAreaMessage(displayX, displayY, type, isEdge);
474 }
475 }
476
OnDevMouseLocationListener(const std::string & networkId,const Event & event)477 void CooperateClient::OnDevMouseLocationListener(const std::string &networkId, const Event &event)
478 {
479 CALL_DEBUG_ENTER;
480 std::lock_guard<std::mutex> guard(mtx_);
481 if (eventListener_.find(networkId) == eventListener_.end()) {
482 FI_HILOGI("No listener for networkId:%{public}s is registered", Utility::Anonymize(networkId).c_str());
483 return;
484 }
485 for (const auto &listener : eventListener_[networkId]) {
486 CHKPC(listener);
487 listener->OnMouseLocationEvent(networkId, event);
488 FI_HILOGD("Trigger listener for networkId:%{public}s,"
489 "displayX:%{private}d, displayY:%{private}d, displayWidth:%{public}d, displayHeight:%{public}d",
490 Utility::Anonymize(networkId).c_str(), event.displayX, event.displayY,
491 event.displayWidth, event.displayHeight);
492 }
493 }
494
495 #ifdef ENABLE_PERFORMANCE_CHECK
GetFirstSuccessIndex()496 int32_t CooperateClient::GetFirstSuccessIndex()
497 {
498 CALL_DEBUG_ENTER;
499 size_t durationLen = performanceInfo_.durationList.size();
500 for (size_t i = 0; i < durationLen; ++i) {
501 if (performanceInfo_.durationList[i] != FAILURE_DURATION) {
502 performanceInfo_.successNum = 1;
503 FI_HILOGI("[PERF] First success index:%{public}zu", i);
504 return static_cast<int32_t>(i);
505 }
506 }
507 return INVALID_INDEX;
508 }
StartTrace(int32_t userData)509 void CooperateClient::StartTrace(int32_t userData)
510 {
511 CALL_DEBUG_ENTER;
512 std::lock_guard guard { performanceLock_ };
513 performanceInfo_.traces_.emplace(userData, std::chrono::steady_clock::now());
514 performanceInfo_.activateNum += 1;
515 FI_HILOGI("[PERF] Start tracing \'%{public}d\'", userData);
516 }
517
FinishTrace(int32_t userData,CoordinationMessage msg)518 void CooperateClient::FinishTrace(int32_t userData, CoordinationMessage msg)
519 {
520 CALL_DEBUG_ENTER;
521 std::lock_guard guard { performanceLock_ };
522 if (msg == CoordinationMessage::ACTIVATE_SUCCESS) {
523 if (auto iter = performanceInfo_.traces_.find(userData); iter != performanceInfo_.traces_.end()) {
524 auto curDuration = std::chrono::duration_cast<std::chrono::milliseconds>(
525 std::chrono::steady_clock::now() - iter->second).count();
526 FI_HILOGI("[PERF] Finish tracing \'%{public}d\', elapsed: %{public}lld ms", userData, curDuration);
527 performanceInfo_.traces_.erase(iter);
528 performanceInfo_.durationList.push_back(curDuration);
529 } else {
530 FI_HILOGW("[PERF] FinishTrace with something wrong");
531 }
532 } else if (msg == CoordinationMessage::ACTIVATE_FAIL) {
533 FI_HILOGW("[PERF] Activate coordination failed");
534 performanceInfo_.traces_.erase(userData);
535 performanceInfo_.durationList.push_back(FAILURE_DURATION);
536 }
537 }
538
DumpPerformanceInfo()539 void CooperateClient::DumpPerformanceInfo()
540 {
541 CALL_DEBUG_ENTER;
542 std::lock_guard guard { performanceLock_ };
543 int32_t firstSuccessIndex = GetFirstSuccessIndex();
544 int32_t durationLen = static_cast<int32_t>(performanceInfo_.durationList.size());
545 if (firstSuccessIndex < 0 || firstSuccessIndex >= durationLen) {
546 FI_HILOGE("[PERF] DumpPerformanceInfo failed, invalid first success index");
547 return;
548 }
549 performanceInfo_.failNum = firstSuccessIndex;
550 performanceInfo_.failBeforeSuccess = firstSuccessIndex;
551 performanceInfo_.firstSuccessDuration = performanceInfo_.durationList[firstSuccessIndex];
552 int32_t successDurationSumWithoutFirst { 0 };
553 for (int32_t i = firstSuccessIndex + 1; i < durationLen; i++) {
554 if (performanceInfo_.durationList[i] != FAILURE_DURATION) {
555 successDurationSumWithoutFirst += performanceInfo_.durationList[i];
556 performanceInfo_.minDuration = std::min(performanceInfo_.durationList[i], performanceInfo_.minDuration);
557 performanceInfo_.maxDuration = std::max(performanceInfo_.durationList[i], performanceInfo_.maxDuration);
558 performanceInfo_.successNum += 1;
559 } else {
560 performanceInfo_.failNum += 1;
561 }
562 }
563 int32_t validActivateNum = performanceInfo_.activateNum - performanceInfo_.failBeforeSuccess;
564 if (validActivateNum > 0) {
565 performanceInfo_.successRate = (static_cast<float>(performanceInfo_.successNum) * PERCENTAGE) /
566 validActivateNum;
567 }
568 if (int32_t successNumWithoutFirst = performanceInfo_.successNum - 1; successNumWithoutFirst > 0) {
569 performanceInfo_.averageDuration = successDurationSumWithoutFirst / successNumWithoutFirst;
570 }
571 FI_HILOGI("[PERF] performanceInfo:"
572 "activateNum:%{public}d successNum:%{public}d failNum:%{public}d successRate:%{public}.2f "
573 "averageDuration:%{public}d ms maxDuration:%{public}d ms minDuration:%{public}d ms failBeforeSucc:%{public}d "
574 "firstSuccessDuration:%{public}d ms",
575 performanceInfo_.activateNum, performanceInfo_.successNum, performanceInfo_.failNum,
576 performanceInfo_.successRate, performanceInfo_.averageDuration, performanceInfo_.maxDuration,
577 performanceInfo_.minDuration, performanceInfo_.failBeforeSuccess, performanceInfo_.firstSuccessDuration);
578 std::string durationStr;
579 for (auto duration : performanceInfo_.durationList) {
580 durationStr += std::to_string(duration) + ", ";
581 }
582 FI_HILOGI("[PERF] Duration: %{public}s", durationStr.c_str());
583 performanceInfo_ = PerformanceInfo();
584 }
585 #endif // ENABLE_PERFORMANCE_CHECK
586 } // namespace DeviceStatus
587 } // namespace Msdp
588 } // namespace OHOS
589