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