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