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