• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "dsched_collab_manager.h"
17 
18 #include <chrono>
19 #include <random>
20 #include <ctime>
21 #include <sys/prctl.h>
22 
23 #include "cJSON.h"
24 
25 #include "distributed_sched_utils.h"
26 #include "dsched_transport_softbus_adapter.h"
27 #include "dtbschedmgr_device_info_storage.h"
28 #include "dtbschedmgr_log.h"
29 #include "dtbcollabmgr_log.h"
30 #include "ipc_skeleton.h"
31 #include "mission/distributed_bm_storage.h"
32 #include "mission/wifi_state_adapter.h"
33 #include "multi_user_manager.h"
34 #include "string_wrapper.h"
35 
36 namespace OHOS {
37 namespace DistributedSchedule {
38 namespace {
39 const std::string TAG = "DSchedCollabManager";
40 const std::string DSCHED_COLLAB_MANAGER = "dsched_collab_manager";
41 constexpr static int32_t NO_NEED_TO_CHECK_ID = -1;
42 const int32_t RANDOM_STRING_LENGTH = 20;
43 std::map<int32_t, std::string> CMDDATA = {
44     {MIN_CMD, "MIN_CMD"},
45     {SINK_GET_VERSION_CMD, "SINK_GET_VERSION_CMD"},
46     {SOURCE_GET_VERSION_CMD, "SOURCE_GET_VERSION_CMD"},
47     {SINK_START_CMD, "SINK_START_CMD"},
48     {NOTIFY_RESULT_CMD, "NOTIFY_RESULT_CMD"},
49     {DISCONNECT_CMD, "DISCONNECT_CMD"},
50     {MAX_CMD, "MAX_CMD"},
51 };
52 }
53 
54 IMPLEMENT_SINGLE_INSTANCE(DSchedCollabManager);
55 
DSchedCollabManager()56 DSchedCollabManager::DSchedCollabManager()
57 {
58 }
59 
~DSchedCollabManager()60 DSchedCollabManager::~DSchedCollabManager()
61 {
62     HILOGI("DSchedCollabManager delete");
63     UnInit();
64 }
65 
CheckSynergisticRelation(const CollabInfo * sourceInfo,const CollabInfo * sinkInfo)66 static int32_t CheckSynergisticRelation(const CollabInfo *sourceInfo, const CollabInfo *sinkInfo)
67 {
68     if (sourceInfo == nullptr || sinkInfo == nullptr) {
69         HILOGE("Invalid parameters.");
70         return INVALID_PARAMETERS_ERR;
71     }
72     return DSchedCollabManager::GetInstance().CheckCollabRelation(sourceInfo, sinkInfo);
73 }
74 
75 IFeatureAbilityRelationChecker iAbilityRelationChecker = {
76     .CheckCollabRelation = CheckSynergisticRelation
77 };
78 
Init()79 void DSchedCollabManager::Init()
80 {
81     HILOGI("Init DSchedCollabManager start");
82     if (eventHandler_ != nullptr) {
83         HILOGI("DSchedCollabManager already inited, end.");
84         return;
85     }
86     DSchedTransportSoftbusAdapter::GetInstance().InitChannel();
87     softbusListener_ = std::make_shared<DSchedCollabManager::SoftbusListener>();
88     DSchedTransportSoftbusAdapter::GetInstance().RegisterListener(SERVICE_TYPE_COLLAB, softbusListener_);
89     int32_t ret =  RegisterRelationChecker(&iAbilityRelationChecker);
90     if (ret != ERR_OK) {
91         HILOGE("RegisterRelationChecker failed, ret: %{public}d", ret);
92         return;
93     }
94     eventThread_ = std::thread(&DSchedCollabManager::StartEvent, this);
95     std::unique_lock<std::mutex> lock(eventMutex_);
96     eventCon_.wait(lock, [this] {
97         return eventHandler_ != nullptr;
98     });
99     HILOGI("Init DSchedCollabManager end");
100 }
101 
CheckCollabRelation(const CollabInfo * sourceInfo,const CollabInfo * sinkInfo)102 int32_t DSchedCollabManager::CheckCollabRelation(const CollabInfo *sourceInfo, const CollabInfo *sinkInfo)
103 {
104     HILOGI("called");
105     if (collabs_.empty()) {
106         HILOGE("No collab in progress.");
107         return INVALID_PARAMETERS_ERR;
108     }
109     DSchedCollabInfo collabInfo;
110     for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
111         if (iter->second == nullptr) {
112             HILOGE("collab is nullptr");
113             continue;
114         }
115         collabInfo = iter->second->GetCollabInfo();
116         HILOGI("collabInfo: %{public}s", collabInfo.ToString().c_str());
117         if (CheckSrcCollabRelation(sourceInfo, &collabInfo) == ERR_OK &&
118             (sinkInfo->pid == NO_NEED_TO_CHECK_ID || CheckSinkCollabRelation(sinkInfo, &collabInfo) == ERR_OK)) {
119             HILOGI("the collaboration relationship is matched successfully.");
120             return ERR_OK;
121         }
122     }
123     HILOGE("failed to match the collaboration relationship.");
124     return INVALID_PARAMETERS_ERR;
125 }
126 
CheckSrcCollabRelation(const CollabInfo * sourceInfo,const DSchedCollabInfo * collabInfo)127 int32_t DSchedCollabManager::CheckSrcCollabRelation(const CollabInfo *sourceInfo, const DSchedCollabInfo *collabInfo)
128 {
129     HILOGI("called");
130     if (sourceInfo == nullptr) {
131         HILOGE("Invalid sourceInfo.");
132         return INVALID_PARAMETERS_ERR;
133     }
134     if (collabInfo == nullptr) {
135         HILOGE("collab is nullptr");
136         return INVALID_PARAMETERS_ERR;
137     }
138     if (std::string(sourceInfo->deviceId) == collabInfo->srcUdid_ &&
139         sourceInfo->pid == collabInfo->srcInfo_.pid_ &&
140         static_cast<int32_t>(sourceInfo->tokenId) == collabInfo->srcInfo_.accessToken_ &&
141         sourceInfo->userId == collabInfo->srcAccountInfo_.userId) {
142         HILOGI("the collaboration relationship is matched successfully.");
143         return ERR_OK;
144     }
145     HILOGI("Try to verify the info on the other side.");
146     if (std::string(sourceInfo->deviceId) == collabInfo->sinkUdid_ &&
147         sourceInfo->pid == collabInfo->sinkInfo_.pid_ &&
148         static_cast<int32_t>(sourceInfo->tokenId) == collabInfo->sinkInfo_.accessToken_ &&
149         sourceInfo->userId == collabInfo->sinkUserId_) {
150         HILOGI("the collaboration relationship is matched successfully.");
151         return ERR_OK;
152     }
153     HILOGW("deviceId: %{public}s, pid: %{public}d, tokenId: %{public}s, userId: %{public}d, srcUdid: %{public}s",
154         GetAnonymStr(std::string(sourceInfo->deviceId)).c_str(),
155         sourceInfo->pid, GetAnonymStr(std::to_string(sourceInfo->tokenId)).c_str(),
156         sourceInfo->userId, GetAnonymStr(collabInfo->srcUdid_).c_str());
157     return INVALID_PARAMETERS_ERR;
158 }
159 
CheckSinkCollabRelation(const CollabInfo * sinkInfo,const DSchedCollabInfo * collabInfo)160 int32_t DSchedCollabManager::CheckSinkCollabRelation(const CollabInfo *sinkInfo, const DSchedCollabInfo *collabInfo)
161 {
162     HILOGI("called");
163     if (sinkInfo == nullptr) {
164         HILOGE("Invalid sinkInfo.");
165         return INVALID_PARAMETERS_ERR;
166     }
167     if (collabInfo == nullptr) {
168         HILOGE("collab is nullptr");
169         return INVALID_PARAMETERS_ERR;
170     }
171     if (std::string(sinkInfo->deviceId) == collabInfo->sinkUdid_ &&
172         sinkInfo->pid == collabInfo->sinkInfo_.pid_ &&
173         static_cast<int32_t>(sinkInfo->tokenId) == collabInfo->sinkInfo_.accessToken_ &&
174         sinkInfo->userId == collabInfo->sinkUserId_) {
175         HILOGI("the collaboration relationship is matched successfully.");
176         return ERR_OK;
177     }
178     HILOGI("Try to verify the info on the other side.");
179     if (std::string(sinkInfo->deviceId) == collabInfo->srcUdid_ &&
180         sinkInfo->pid == collabInfo->srcInfo_.pid_ &&
181         static_cast<int32_t>(sinkInfo->tokenId) == collabInfo->srcInfo_.accessToken_ &&
182         sinkInfo->userId == collabInfo->srcAccountInfo_.userId) {
183         HILOGI("the collaboration relationship is matched successfully.");
184         return ERR_OK;
185     }
186     HILOGW("deviceId: %{public}s, pid: %{public}d, tokenId: %{public}s, userId: %{public}d, sinkUdid: %{public}s",
187         GetAnonymStr(std::string(sinkInfo->deviceId)).c_str(),
188         sinkInfo->pid, GetAnonymStr(std::to_string(sinkInfo->tokenId)).c_str(),
189         sinkInfo->userId, GetAnonymStr(collabInfo->sinkUdid_).c_str());
190     return INVALID_PARAMETERS_ERR;
191 }
192 
StartEvent()193 void DSchedCollabManager::StartEvent()
194 {
195     HILOGI("called");
196     prctl(PR_SET_NAME, DSCHED_COLLAB_MANAGER.c_str());
197     auto runner = AppExecFwk::EventRunner::Create(false);
198     {
199         std::lock_guard<std::mutex> lock(eventMutex_);
200         eventHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
201     }
202     eventCon_.notify_one();
203     if (runner == nullptr) {
204         HILOGE("runner is nullptr");
205         return;
206     }
207     runner->Run();
208     HILOGI("StartEvent end");
209 }
210 
UnInit()211 void DSchedCollabManager::UnInit()
212 {
213     HILOGI("UnInit start");
214     DSchedTransportSoftbusAdapter::GetInstance().UnregisterListener(SERVICE_TYPE_COLLAB, softbusListener_);
215     DSchedTransportSoftbusAdapter::GetInstance().ReleaseChannel();
216     collabs_.clear();
217 
218     if (eventHandler_ != nullptr) {
219         eventHandler_->GetEventRunner()->Stop();
220         eventThread_.join();
221         eventHandler_ = nullptr;
222     } else {
223         HILOGE("eventHandler is nullptr");
224     }
225     HILOGI("UnInit end");
226 }
227 
GetSinkCollabVersion(DSchedCollabInfo & info)228 int32_t DSchedCollabManager::GetSinkCollabVersion(DSchedCollabInfo &info)
229 {
230     HILOGI("called, sessionId is: %{public}s", info.ToString().c_str());
231     if (info.srcCollabSessionId_ < 0 || info.sinkInfo_.deviceId_.empty() || info.srcClientCB_ == nullptr) {
232         HILOGE("invalid parameters.");
233         return INVALID_PARAMETERS_ERR;
234     }
235     if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(info.srcInfo_.deviceId_)) {
236         HILOGE("get local deviceId failed!");
237         return FIND_LOCAL_DEVICEID_ERR;
238     }
239     if (DtbschedmgrDeviceInfoStorage::GetInstance().GetDeviceInfoById(info.sinkInfo_.deviceId_) == nullptr) {
240         HILOGW("subsequent queries on application level binding relationships");
241     }
242     auto func = [this, info]() {
243         HandleGetSinkCollabVersion(info);
244     };
245     if (eventHandler_ == nullptr) {
246         HILOGE("eventHandler is nullptr");
247         return INVALID_PARAMETERS_ERR;
248     }
249     eventHandler_->PostTask(func);
250     return ERR_OK;
251 }
252 
HandleGetSinkCollabVersion(const DSchedCollabInfo & info)253 void DSchedCollabManager::HandleGetSinkCollabVersion(const DSchedCollabInfo &info)
254 {
255     HILOGI("called");
256     const std::string collabToken = info.collabToken_;
257     auto newCollab = std::make_shared<DSchedCollab>(collabToken, info);
258     newCollab->Init();
259     newCollab->UpdateState(SOURCE_GET_PEER_VERSION_STATE);
260     collabs_.insert(std::make_pair(collabToken, newCollab));
261     newCollab->PostSrcGetPeerVersionTask();
262     SetTimeOut(collabToken, COLLAB_TIMEOUT);
263 
264 #ifdef COLLAB_ALL_CONNECT_DECISIONS
265     if (!DSchedTransportSoftbusAdapter::GetInstance().IsNeedAllConnect(SERVICE_TYPE_COLLAB)) {
266         HILOGW("don't need wait all connect decision");
267         return;
268     }
269     const std::string sinkDeviceId = info.sinkInfo_.deviceId_;
270     if (peerConnectDecision_.find(sinkDeviceId) != peerConnectDecision_.end()) {
271         peerConnectDecision_.erase(sinkDeviceId);
272     }
273     WaitAllConnectDecision(sinkDeviceId, newCollab);
274 #endif
275     HILOGI("end");
276 }
277 
CollabMission(DSchedCollabInfo & info)278 int32_t DSchedCollabManager::CollabMission(DSchedCollabInfo &info)
279 {
280     HILOGI("called, collabInfo is: %{public}s", info.ToString().c_str());
281     if (!MultiUserManager::GetInstance().IsCallerForeground(info.srcInfo_.uid_)) {
282         HILOGE("The current user is not foreground. callingUid: %{public}d .", info.srcInfo_.uid_);
283         return DMS_NOT_FOREGROUND_USER;
284     }
285     if (!IsStartForeground(info) &&
286         !Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) {
287         HILOGE("Non-system applications are prohibited from launching peer ability to the background.");
288         return DMS_START_CONTROL_PERMISSION_DENIED;
289     }
290     if (info.srcInfo_.bundleName_.empty() || info.sinkInfo_.bundleName_.empty() ||
291         info.srcInfo_.moduleName_.empty() || info.sinkInfo_.moduleName_.empty() ||
292         info.srcInfo_.abilityName_.empty() || info.sinkInfo_.abilityName_.empty()) {
293         HILOGE("input parameter validation error!");
294         return INVALID_PARAMETERS_ERR;
295     }
296     if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(info.srcInfo_.deviceId_)) {
297         HILOGE("get local deviceId failed!");
298         return FIND_LOCAL_DEVICEID_ERR;
299     }
300     if (DtbschedmgrDeviceInfoStorage::GetInstance().GetDeviceInfoById(info.sinkInfo_.deviceId_) == nullptr &&
301         !DtbschedmgrDeviceInfoStorage::GetInstance().CheckNetworkIdByBundleName(info.sinkInfo_.bundleName_,
302         info.sinkInfo_.deviceId_)) {
303         HILOGE("failed to find sinkDeviceId.");
304         return FIND_REMOTE_DEVICEID_ERR;
305     }
306     auto dCollab = GetDSchedCollabByTokenId(info.collabToken_);
307     if (dCollab == nullptr) {
308         HILOGE("can't find collab");
309         return INVALID_PARAMETERS_ERR;
310     }
311     dCollab->SetSrcCollabInfo(info);
312     dCollab->UpdateState(SOURCE_START_STATE);
313     dCollab->PostSrcStartTask();
314     return ERR_OK;
315 }
316 
IsStartForeground(DSchedCollabInfo & info)317 bool DSchedCollabManager::IsStartForeground(DSchedCollabInfo &info)
318 {
319     HILOGI("called");
320     auto value = info.srcOpt_.startParams_.GetParam(KEY_START_OPTION);
321     AAFwk::IString *ao = AAFwk::IString::Query(value);
322     if (ao != nullptr) {
323         std::string startOpt = AAFwk::String::Unbox(ao);
324         HILOGI("startOpt : %{public}s", startOpt.c_str());
325         return (startOpt == VALUE_START_OPTION_BACKGROUND) ? false : true;
326     }
327     return true;
328 }
329 
IsSessionExists(const DSchedCollabInfo & info)330 bool DSchedCollabManager::IsSessionExists(const DSchedCollabInfo &info)
331 {
332     HILOGI("called");
333     for (const auto& pair : collabs_) {
334         if (pair.second == nullptr) {
335             continue;
336         }
337         DSchedCollabInfo existCollabInfo = pair.second->GetCollabInfo();
338         if (existCollabInfo.srcInfo_.pid_ == info.srcInfo_.pid_ &&
339             existCollabInfo.srcCollabSessionId_ == info.srcCollabSessionId_) {
340             return true;
341         }
342     }
343     return false;
344 }
345 
GenerateCollabToken(const std::string & srcDeviceId)346 std::string DSchedCollabManager::GenerateCollabToken(const std::string &srcDeviceId)
347 {
348     HILOGI("called");
349     std::string characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
350     std::default_random_engine gen;
351     std::random_device rd;
352     gen.seed(rd());
353     std::uniform_int_distribution<> dis(0, characters.size() - 1);
354     std::string randomValue;
355     randomValue.resize(RANDOM_STRING_LENGTH);
356     size_t index = 0;
357     bool isUnique = false;
358     while (!isUnique) {
359         for (int32_t i = 0; i < RANDOM_STRING_LENGTH; ++i) {
360             index = static_cast<size_t>(dis(gen));
361             randomValue[i] = characters[index];
362         }
363         randomValue = srcDeviceId + randomValue;
364         if (collabs_.count(randomValue) == 0) {
365             isUnique = true;
366         }
367     }
368     HILOGI("end");
369     return randomValue;
370 }
371 
SetTimeOut(const std::string & collabToken,int32_t timeout)372 void DSchedCollabManager::SetTimeOut(const std::string &collabToken, int32_t timeout)
373 {
374     HILOGI("called, collabToken: %{public}s", GetAnonymStr(collabToken).c_str());
375     auto func = [this, collabToken]() {
376         if (collabs_.count(collabToken) == 0) {
377             HILOGW("collab not exist.");
378             return;
379         }
380         HILOGE("collab timeout! info: %{public}s", GetAnonymStr(collabToken).c_str());
381         auto dCollab = collabs_[collabToken];
382         if (dCollab != nullptr) {
383             dCollab->PostErrEndTask(COLLAB_ABILITY_TIMEOUT_ERR);
384         }
385     };
386     if (eventHandler_ == nullptr) {
387         HILOGE("eventHandler is nullptr");
388         return;
389     }
390     timeout > 0 ? eventHandler_->PostTask(func, collabToken, timeout) :
391         eventHandler_->PostTask(func);
392 }
393 
RemoveTimeout(const std::string & collabToken)394 void DSchedCollabManager::RemoveTimeout(const std::string &collabToken)
395 {
396     HILOGI("called, collabToken: %{public}s", GetAnonymStr(collabToken).c_str());
397     if (eventHandler_ == nullptr) {
398         HILOGE("eventHandler is nullptr");
399         return;
400     }
401     eventHandler_->RemoveTask(collabToken);
402 }
403 
WaitAllConnectDecision(const std::string & peerDeviceId,const std::shared_ptr<DSchedCollab> & dCollab)404 void DSchedCollabManager::WaitAllConnectDecision(const std::string &peerDeviceId,
405     const std::shared_ptr<DSchedCollab> &dCollab)
406 {
407 #ifdef DMSFWK_ALL_CONNECT_MGR
408     {
409         HILOGI("called");
410         std::unique_lock<std::mutex> decisionLock(connectDecisionMutex_);
411         connectDecisionCond_.wait_for(decisionLock, std::chrono::seconds(CONNECT_DECISION_TIME_OUT),
412             [this, peerDeviceId]() {
413                 return peerConnectDecision_.find(peerDeviceId) != peerConnectDecision_.end() &&
414                     peerConnectDecision_.at(peerDeviceId).load();
415             });
416 
417         if (peerConnectDecision_.find(peerDeviceId) == peerConnectDecision_.end()) {
418             HILOGE("Not find peerDeviceId %{public}s in peerConnectDecision.", GetAnonymStr(peerDeviceId).c_str());
419             if (dCollab != nullptr) {
420                 dCollab->PostErrEndTask(COLLAB_ABILITY_TIMEOUT_ERR);
421             }
422             return;
423         }
424         if (!peerConnectDecision_.at(peerDeviceId).load()) {
425             HILOGE("All connect manager refuse bind to PeerDeviceId %{public}s.", GetAnonymStr(peerDeviceId).c_str());
426             peerConnectDecision_.erase(peerDeviceId);
427             if (dCollab != nullptr) {
428                 dCollab->PostErrEndTask(COLLAB_ABILITY_TIMEOUT_ERR);
429             }
430             return;
431         }
432         peerConnectDecision_.erase(peerDeviceId);
433         HILOGI("end");
434     }
435 #endif
436 }
437 
NotifyAllConnectDecision(std::string peerDeviceId,bool isSupport)438 void DSchedCollabManager::NotifyAllConnectDecision(std::string peerDeviceId, bool isSupport)
439 {
440     HILOGI("Notify all connect decision, peerDeviceId %{public}s, isSupport %{public}d.",
441         GetAnonymStr(peerDeviceId).c_str(), isSupport);
442 #ifdef DMSFWK_ALL_CONNECT_MGR
443     std::lock_guard<std::mutex> decisionLock(connectDecisionMutex_);
444     peerConnectDecision_[peerDeviceId] = isSupport;
445     connectDecisionCond_.notify_all();
446 #endif
447 }
448 
NotifyStartAbilityResult(const std::string & collabToken,const int32_t & result,const int32_t & sinkPid,const int32_t & sinkUid,const int32_t & sinkAccessTokenId)449 int32_t DSchedCollabManager::NotifyStartAbilityResult(const std::string& collabToken, const int32_t &result,
450     const int32_t &sinkPid, const int32_t &sinkUid, const int32_t &sinkAccessTokenId)
451 {
452     HILOGI("called, result %{public}d", result);
453     auto dCollab = GetDSchedCollabByTokenId(collabToken);
454     if (dCollab == nullptr) {
455         HILOGE("can't find collab");
456         return INVALID_PARAMETERS_ERR;
457     }
458     if (result != ACCEPT) {
459         HILOGE("start ability failed");
460         return dCollab->PostErrEndTask(ConvertCollaborateResult(result));
461     }
462     dCollab->SaveSinkAbilityData(collabToken, result, sinkPid, sinkUid, sinkAccessTokenId);
463     HILOGI("end, info: %{public}s.", dCollab->GetCollabInfo().ToString().c_str());
464     return ERR_OK;
465 }
466 
ConvertCollaborateResult(int32_t result)467 int32_t DSchedCollabManager::ConvertCollaborateResult(int32_t result)
468 {
469     HILOGI("collaborate result is %{public}d.", result);
470     switch (result) {
471         case REJECT:
472             return DistributedCollab::PEER_APP_REJECTED;
473         case ON_COLLABORATE_ERR:
474             return DistributedCollab::PEER_ABILITY_NO_ONCOLLABORATE;
475         default:
476             return INVALID_PARAMETERS_ERR;
477     }
478 }
479 
NotifySinkPrepareResult(const DSchedCollabInfo & dSchedCollabInfo,const int32_t & result)480 int32_t DSchedCollabManager::NotifySinkPrepareResult(const DSchedCollabInfo &dSchedCollabInfo, const int32_t &result)
481 {
482     HILOGI("end, dSchedCollabInfo: %{public}s.", dSchedCollabInfo.ToString().c_str());
483     if (GetDSchedCollabByTokenId(dSchedCollabInfo.collabToken_) == nullptr) {
484         HILOGE("not find dCollab");
485         return INVALID_PARAMETERS_ERR;
486     }
487     auto func = [this, dSchedCollabInfo, result]() {
488         HandleCollabPrepareResult(dSchedCollabInfo, result);
489     };
490     if (eventHandler_ == nullptr) {
491         HILOGE("eventHandler is nullptr");
492         return INVALID_PARAMETERS_ERR;
493     }
494     eventHandler_->PostTask(func);
495     return ERR_OK;
496 }
497 
HandleCollabPrepareResult(const DSchedCollabInfo & dSchedCollabInfo,const int32_t & result)498 void DSchedCollabManager::HandleCollabPrepareResult(const DSchedCollabInfo &dSchedCollabInfo, const int32_t &result)
499 {
500     HILOGI("called");
501     auto dCollab = GetDSchedCollabByTokenId(dSchedCollabInfo.collabToken_);
502     if (dCollab == nullptr) {
503         HILOGE("not find dCollab");
504         return;
505     }
506     dCollab->PostSinkPrepareResultTask(result, dSchedCollabInfo);
507     RemoveTimeout(dSchedCollabInfo.collabToken_);
508     HILOGI("end, info: %{public}s.", dCollab->GetCollabInfo().ToString().c_str());
509     return;
510 }
511 
NotifySinkRejectReason(const std::string & collabToken,const std::string & reason)512 int32_t DSchedCollabManager::NotifySinkRejectReason(const std::string& collabToken, const std::string& reason)
513 {
514     HILOGI("called, resion: %{public}s", reason.c_str());
515     auto dCollab = GetDSchedCollabByTokenId(collabToken);
516     if (dCollab == nullptr) {
517         HILOGE("not find dCollab");
518         return INVALID_PARAMETERS_ERR;
519     }
520     return dCollab->PostAbilityRejectTask(reason);
521 }
522 
NotifyAbilityDied(const std::string & bundleName,const int32_t & pid)523 int32_t DSchedCollabManager::NotifyAbilityDied(const std::string &bundleName, const int32_t &pid)
524 {
525     HILOGI("called");
526     auto func = [this, bundleName, pid]() {
527         HandleCloseSessions(bundleName, pid);
528     };
529     if (eventHandler_ == nullptr) {
530         HILOGE("eventHandler is nullptr");
531         return INVALID_PARAMETERS_ERR;
532     }
533     eventHandler_->PostTask(func);
534     return ERR_OK;
535 }
536 
HandleCloseSessions(const std::string & bundleName,const int32_t & pid)537 int32_t DSchedCollabManager::HandleCloseSessions(const std::string &bundleName, const int32_t &pid)
538 {
539     HILOGI("called");
540     DSchedCollabInfo dSchedCollabInfo;
541     for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
542         if (iter->second == nullptr) {
543             continue;
544         }
545         dSchedCollabInfo = iter->second->GetCollabInfo();
546         if ((bundleName == dSchedCollabInfo.srcInfo_.bundleName_ && pid == dSchedCollabInfo.srcInfo_.pid_) ||
547             (bundleName == dSchedCollabInfo.sinkInfo_.bundleName_ && pid == dSchedCollabInfo.sinkInfo_.pid_)) {
548             HILOGI("find collab, need be clear, collabInfo: %{public}s", dSchedCollabInfo.ToString().c_str());
549             return iter->second->PostEndTask();
550         }
551     }
552     return ERR_OK;
553 }
554 
ReleaseAbilityLink(const std::string & bundleName,const int32_t & pid)555 int32_t DSchedCollabManager::ReleaseAbilityLink(const std::string &bundleName, const int32_t &pid)
556 {
557     HILOGW("called");
558     DSchedCollabInfo dSchedCollabInfo;
559     std::string collabToken;
560     {
561         std::shared_lock<std::shared_mutex> readLock(collabReadMutex_);
562         for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
563             if (iter->second == nullptr) {
564                 continue;
565             }
566             dSchedCollabInfo = iter->second->GetCollabInfo();
567             if (bundleName == dSchedCollabInfo.srcInfo_.bundleName_ && pid == dSchedCollabInfo.srcInfo_.pid_) {
568                 collabToken = dSchedCollabInfo.collabToken_;
569             }
570             if (bundleName == dSchedCollabInfo.srcInfo_.bundleName_ && pid == dSchedCollabInfo.sinkInfo_.pid_) {
571                 collabToken = dSchedCollabInfo.collabToken_;
572             }
573         }
574     }
575     if (collabToken.empty()) {
576         HILOGE("can't find collab");
577         return INVALID_PARAMETERS_ERR;
578     }
579 
580     auto func = [this, bundleName, pid, collabToken]() {
581         HandleReleaseAbilityLink(bundleName, pid, collabToken);
582     };
583     const std::string taskName = bundleName + std::to_string(pid);
584     HILOGW("disconnect the existing link after 5S");
585     if (eventHandler_ == nullptr) {
586         HILOGE("eventHandler is nullptr");
587         return INVALID_PARAMETERS_ERR;
588     }
589     eventHandler_->PostTask(func, taskName, BACKGROUND_TIMEOUT);
590     return ERR_OK;
591 }
592 
HandleReleaseAbilityLink(const std::string & bundleName,const int32_t & pid,const std::string & collabToken)593 void DSchedCollabManager::HandleReleaseAbilityLink(const std::string &bundleName, const int32_t &pid,
594     const std::string &collabToken)
595 {
596     HILOGI("called");
597     auto dCollab = GetDSchedCollabByTokenId(collabToken);
598     if (dCollab == nullptr) {
599         HILOGE("can't find collab");
600         return;
601     }
602     DSchedCollabInfo dSchedCollabInfo = dCollab->GetCollabInfo();
603     if (pid == dSchedCollabInfo.srcInfo_.pid_) {
604         HILOGI("source ability been background, collabInfo: %{public}s", dSchedCollabInfo.ToString().c_str());
605         PrivilegeShutdown(static_cast<uint64_t>(dSchedCollabInfo.srcInfo_.accessToken_),
606             pid, dSchedCollabInfo.sinkInfo_.deviceId_.c_str());
607             dCollab->PostEndTask();
608     }
609     if (pid == dSchedCollabInfo.sinkInfo_.pid_) {
610         HILOGI("sink ability been background, collabInfo: %{public}s", dSchedCollabInfo.ToString().c_str());
611         dCollab->PostEndTask();
612     }
613     return;
614 }
615 
CancleReleaseAbilityLink(const std::string & bundleName,const int32_t & pid)616 int32_t DSchedCollabManager::CancleReleaseAbilityLink(const std::string &bundleName, const int32_t &pid)
617 {
618     HILOGW("called");
619     if (eventHandler_ == nullptr) {
620         HILOGE("eventHandler is nullptr");
621         return INVALID_PARAMETERS_ERR;
622     }
623     const std::string taskName = bundleName + std::to_string(pid);
624     eventHandler_->RemoveTask(taskName);
625     return ERR_OK;
626 }
627 
NotifyWifiOpen()628 void DSchedCollabManager::NotifyWifiOpen()
629 {
630     HILOGI("called");
631     for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
632         if (iter->second != nullptr) {
633             iter->second->NotifyWifiOpen();
634         }
635     }
636 }
637 
GetWifiStatus()638 bool DSchedCollabManager::GetWifiStatus()
639 {
640     return DistributedSchedule::WifiStateAdapter::GetInstance().IsWifiActive();
641 }
642 
NotifySessionClose(const std::string & collabToken)643 int32_t DSchedCollabManager::NotifySessionClose(const std::string &collabToken)
644 {
645     HILOGI("called, collabToken: %{public}s", GetAnonymStr(collabToken).c_str());
646     auto dCollab = GetDSchedCollabByTokenId(collabToken);
647     if (dCollab == nullptr) {
648         HILOGE("can't find collab");
649         return INVALID_PARAMETERS_ERR;
650     }
651     dCollab->PostEndTask();
652     HILOGI("end.");
653     return ERR_OK;
654 }
655 
CleanUpSession(const std::string & collabToken)656 int32_t DSchedCollabManager::CleanUpSession(const std::string &collabToken)
657 {
658     HILOGI("called, collabToken: %{public}s", GetAnonymStr(collabToken).c_str());
659     auto func = [this, collabToken]() {
660         HILOGI("called, collabToken: %{public}s", GetAnonymStr(collabToken).c_str());
661         auto dCollab = GetDSchedCollabByTokenId(collabToken);
662         if (dCollab == nullptr) {
663             HILOGE("can't find collab");
664             return;
665         }
666         dCollab->UnInit();
667         RemoveTimeout(collabToken);
668         {
669             std::lock_guard<std::mutex> collabLock(collabMutex_);
670             collabs_.erase(collabToken);
671         }
672     };
673     if (eventHandler_ == nullptr) {
674         HILOGE("eventHandler is nullptr");
675         return INVALID_PARAMETERS_ERR;
676     }
677     eventHandler_->PostTask(func);
678     HILOGI("end.");
679     return ERR_OK;
680 }
681 
GetDSchedCollabByTokenId(const std::string & tokenId)682 std::shared_ptr<DSchedCollab> DSchedCollabManager::GetDSchedCollabByTokenId(const std::string &tokenId)
683 {
684     HILOGI("called, tokenId: %{public}s", tokenId.c_str());
685     std::lock_guard<std::mutex> collabLock(collabMutex_);
686     if (tokenId.empty() || collabs_.count(tokenId) == 0) {
687         HILOGE("no such collaboration in progress.");
688         return nullptr;
689     }
690     return collabs_[tokenId];
691 }
692 
OnDataRecv(int32_t softbusSessionId,std::shared_ptr<DSchedDataBuffer> dataBuffer)693 void DSchedCollabManager::OnDataRecv(int32_t softbusSessionId, std::shared_ptr<DSchedDataBuffer> dataBuffer)
694 {
695     auto func = [this, softbusSessionId, dataBuffer]() {
696         HandleDataRecv(softbusSessionId, dataBuffer);
697     };
698     if (eventHandler_ == nullptr) {
699         HILOGE("eventHandler is nullptr");
700         return;
701     }
702     eventHandler_->PostTask(func);
703 }
704 
HandleDataRecv(const int32_t & softbusSessionId,std::shared_ptr<DSchedDataBuffer> dataBuffer)705 void DSchedCollabManager::HandleDataRecv(const int32_t &softbusSessionId, std::shared_ptr<DSchedDataBuffer> dataBuffer)
706 {
707     HILOGI("called, softbusSessionId: %{public}d.", softbusSessionId);
708     if (dataBuffer == nullptr) {
709         HILOGE("dataBuffer is null.");
710         return;
711     }
712     uint8_t *data = dataBuffer->Data();
713     std::string jsonStr(reinterpret_cast<const char *>(data), dataBuffer->Capacity());
714     cJSON *rootValue = cJSON_Parse(jsonStr.c_str());
715     if (rootValue == nullptr) {
716         HILOGE("Parse jsonStr error.");
717         return;
718     }
719     cJSON *baseCmd = cJSON_GetObjectItemCaseSensitive(rootValue, "BaseCmd");
720     if (baseCmd == nullptr || !cJSON_IsString(baseCmd) || (baseCmd->valuestring == nullptr)) {
721         cJSON_Delete(rootValue);
722         HILOGE("Parse base cmd error.");
723         return;
724     }
725 
726     cJSON *cmdValue = cJSON_Parse(baseCmd->valuestring);
727     cJSON_Delete(rootValue);
728     if (cmdValue == nullptr) {
729         HILOGE("Parse cmd value error.");
730         return;
731     }
732 
733     cJSON *comvalue = cJSON_GetObjectItemCaseSensitive(cmdValue, "Command");
734     if (comvalue == nullptr || !cJSON_IsNumber(comvalue)) {
735         cJSON_Delete(cmdValue);
736         HILOGE("parse command failed");
737         return;
738     }
739     int32_t command = comvalue->valueint;
740     cJSON *collabTokenvalue = cJSON_GetObjectItemCaseSensitive(cmdValue, "CollabToken");
741     if (collabTokenvalue == nullptr || !cJSON_IsString(collabTokenvalue)) {
742         cJSON_Delete(cmdValue);
743         HILOGE("parse collabToken failed");
744         return;
745     }
746     const std::string collabToken = collabTokenvalue->valuestring;
747     cJSON_Delete(cmdValue);
748     NotifyDataRecv(softbusSessionId, command, jsonStr, dataBuffer, collabToken);
749     HILOGI("end");
750 }
751 
NotifyDataRecv(const int32_t & softbusSessionId,int32_t command,const std::string & jsonStr,std::shared_ptr<DSchedDataBuffer> dataBuffer,const std::string & collabToken)752 void DSchedCollabManager::NotifyDataRecv(const int32_t &softbusSessionId, int32_t command, const std::string& jsonStr,
753     std::shared_ptr<DSchedDataBuffer> dataBuffer, const std::string& collabToken)
754 {
755     HILOGI("called, parsed cmd %{public}s", CMDDATA[command].c_str());
756     for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
757         if (iter->second != nullptr && softbusSessionId == iter->second->GetSoftbusSessionId() &&
758             collabToken == iter->second->GetCollabInfo().collabToken_) {
759             HILOGI("softbusSessionId exist.");
760             const std::string peerDeviceId =
761                 DSchedTransportSoftbusAdapter::GetInstance().GetPeerDeviceIdBySocket(softbusSessionId);
762             iter->second->OnDataRecv(peerDeviceId, command, dataBuffer);
763             if (command == NOTIFY_RESULT_CMD) {
764                 RemoveTimeout(iter->first);
765             }
766             return;
767         }
768     }
769     if (command == SINK_GET_VERSION_CMD) {
770         auto getVersionCmd = std::make_shared<GetSinkCollabVersionCmd>();
771         int32_t ret = getVersionCmd->Unmarshal(jsonStr);
772         if (ret != ERR_OK) {
773             HILOGE("Unmarshal cmd failed, ret: %{public}d", ret);
774             return;
775         }
776         std::string localDevId;
777         if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(localDevId)) {
778             HILOGE("get local deviceId failed!");
779             return;
780         }
781         if (getVersionCmd->sinkDeviceId_ != localDevId) {
782             HILOGE("Irrecognized deviceId: %{public}s", GetAnonymStr(getVersionCmd->sinkDeviceId_).c_str());
783             return;
784         }
785         auto newCollab = std::make_shared<DSchedCollab>(getVersionCmd, softbusSessionId);
786         newCollab->Init();
787         newCollab->UpdateState(SINK_GET_VERSION_STATE);
788         collabs_.insert(std::make_pair(getVersionCmd->collabToken_, newCollab));
789         newCollab->PostSinkGetVersionTask();
790         SetTimeOut(getVersionCmd->collabToken_, COLLAB_TIMEOUT);
791         HILOGI("end");
792         return;
793     }
794     HILOGE("No matching session to handle cmd!");
795     return;
796 }
797 
OnShutdown(int32_t socket,bool isSelfCalled)798 void DSchedCollabManager::OnShutdown(int32_t socket, bool isSelfCalled)
799 {
800     HILOGW("called,softbusSessionId: %{public}d, isSelfCalled: %{public}d", socket, isSelfCalled);
801     if (isSelfCalled) {
802         HILOGW("called, shutdown by local");
803         return;
804     }
805     auto func = [this, socket]() {
806         std::lock_guard<std::mutex> collabLock(collabMutex_);
807         if (collabs_.empty()) {
808             return;
809         }
810         for (auto iter = collabs_.begin(); iter != collabs_.end(); iter++) {
811             if (iter->second != nullptr && socket == iter->second->GetSoftbusSessionId()) {
812                 HILOGE("collab: %{public}s", iter->second->GetCollabInfo().ToString().c_str());
813                 iter->second->PostErrEndTask(COLLAB_SESSION_SHUTDOWN);
814             }
815         }
816     };
817     if (eventHandler_ == nullptr) {
818         HILOGE("eventHandler is nullptr");
819         return;
820     }
821     eventHandler_->PostTask(func);
822     return;
823 }
824 
OnBind(int32_t socket,PeerSocketInfo info)825 void DSchedCollabManager::SoftbusListener::OnBind(int32_t socket, PeerSocketInfo info)
826 {
827 }
828 
OnShutdown(int32_t socket,bool isSelfCalled)829 void DSchedCollabManager::SoftbusListener::OnShutdown(int32_t socket, bool isSelfCalled)
830 {
831     DSchedCollabManager::GetInstance().OnShutdown(socket, isSelfCalled);
832 }
833 
OnDataRecv(int32_t socket,std::shared_ptr<DSchedDataBuffer> dataBuffer)834 void DSchedCollabManager::SoftbusListener::OnDataRecv(int32_t socket, std::shared_ptr<DSchedDataBuffer> dataBuffer)
835 {
836     DSchedCollabManager::GetInstance().OnDataRecv(socket, dataBuffer);
837 }
838 }  // namespace DistributedSchedule
839 }  // namespace OHOS
840