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