1 /*
2 * Copyright (c) 2022-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 "distributed_ability_manager_service.h"
17
18 #include <chrono>
19 #include <thread>
20
21 #include "ability_manager_client.h"
22 #include "accesstoken_kit.h"
23 #include "base/continuationmgr_log.h"
24 #include "base/parcel_helper.h"
25 #include "bundlemgr/bundle_mgr_interface.h"
26 #include "bundlemgr/bundle_mgr_proxy.h"
27 #include "continuation_manager/app_connection_stub.h"
28 #include "continuation_manager/app_device_callback_stub.h"
29 #include "continuation_manager/device_selection_notifier_proxy.h"
30 #include "continuation_manager/notifier_death_recipient.h"
31 #include "distributed_ability_manager_dumper.h"
32 #include "file_ex.h"
33 #include "ipc_skeleton.h"
34 #include "iservice_registry.h"
35 #include "os_account_manager.h"
36 #include "parameters.h"
37 #include "system_ability_definition.h"
38
39 namespace OHOS {
40 namespace DistributedSchedule {
41 namespace {
42 const std::string TAG = "ContinuationManagerService";
43 const std::u16string HIPLAY_PANEL_INTERFACE_TOKEN = u"ohos.hiplay.panel";
44 const std::string TOKEN_KEY = "distributedsched.continuationmanager.token";
45 const std::string DEFAULT_TOKEN_VALUE = "0";
46 const std::string DMS_HIPLAY_ACTION = "ohos.ability.action.deviceSelect";
47 const std::string PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC";
48 constexpr int32_t MAX_TOKEN_NUM = 100000000;
49 constexpr int32_t MAX_REGISTER_NUM = 600;
50 constexpr int32_t START_DEVICE_MANAGER_CODE = 1;
51 constexpr int32_t UPDATE_CONNECT_STATUS_CODE = 2;
52 constexpr int32_t VALUE_NULL = -1; // no object in parcel
53 constexpr int32_t VALUE_OBJECT = 1; // object exist in parcel
54 }
55
56 IMPLEMENT_SINGLE_INSTANCE(DistributedAbilityManagerService);
57 const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(&DistributedAbilityManagerService::GetInstance());
58
DistributedAbilityManagerService()59 DistributedAbilityManagerService::DistributedAbilityManagerService() : SystemAbility(CONTINUATION_MANAGER_SA_ID, true)
60 {
61 }
62
OnStart()63 void DistributedAbilityManagerService::OnStart()
64 {
65 HILOGI("begin");
66 {
67 std::lock_guard<std::mutex> tokenLock(tokenMutex_);
68 std::string tokenStr = system::GetParameter(TOKEN_KEY, DEFAULT_TOKEN_VALUE);
69 if (!tokenStr.empty()) {
70 token_.store(std::atoi(tokenStr.c_str()));
71 }
72 }
73 notifierDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new NotifierDeathRecipient());
74 if (continuationHandler_ == nullptr) {
75 continuationHandler_ = std::make_shared<ffrt::queue>("ContinuationMgr");
76 }
77 Publish(this);
78 }
79
OnStop()80 void DistributedAbilityManagerService::OnStop()
81 {
82 HILOGI("begin");
83 }
84
Dump(int32_t fd,const std::vector<std::u16string> & args)85 int32_t DistributedAbilityManagerService::Dump(int32_t fd, const std::vector<std::u16string>& args)
86 {
87 std::vector<std::string> argsInStr8;
88 for (const auto& arg : args) {
89 argsInStr8.emplace_back(Str16ToStr8(arg));
90 }
91 std::string result;
92 DistributedAbilityManagerDumper::Dump(argsInStr8, result);
93 if (!SaveStringToFd(fd, result)) {
94 HILOGE("save to fd failed");
95 return DMS_WRITE_FILE_FAILED_ERR;
96 }
97 return ERR_OK;
98 }
99
DumpAppRegisterInfo(std::string & info)100 void DistributedAbilityManagerService::DumpAppRegisterInfo(std::string& info)
101 {
102 std::lock_guard<std::mutex> autoLock(tokenMapMutex_);
103 info += "application register infos:\n";
104 info += " ";
105 if (!tokenMap_.empty()) {
106 for (const auto& tokenMap : tokenMap_) {
107 info += "accessToken: ";
108 info += std::to_string(tokenMap.first);
109 std::vector<int32_t> tokenVec = tokenMap.second;
110 DumpNotifierLocked(tokenVec, info);
111 info += "\n";
112 info += " ";
113 }
114 } else {
115 info += " <none info>\n";
116 }
117 }
118
DumpNotifierLocked(const std::vector<int32_t> & tokenVec,std::string & info)119 void DistributedAbilityManagerService::DumpNotifierLocked(const std::vector<int32_t>& tokenVec, std::string& info)
120 {
121 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
122 for (const auto& token : tokenVec) {
123 info += ", ";
124 info += "token: ";
125 info += std::to_string(token);
126 if (callbackMap_.find(token) == callbackMap_.end()) {
127 continue;
128 }
129 if (callbackMap_[token] == nullptr) {
130 HILOGE("this ptr is null");
131 return;
132 }
133 if (!callbackMap_[token]->IsNotifierMapEmpty()) {
134 info += ", ";
135 info += "cbType: ";
136 if (callbackMap_[token]->GetNotifier(EVENT_CONNECT) != nullptr) {
137 info += " ";
138 info += EVENT_CONNECT;
139 }
140 if (callbackMap_[token]->GetNotifier(EVENT_DISCONNECT) != nullptr) {
141 info += " ";
142 info += EVENT_DISCONNECT;
143 }
144 }
145 }
146 }
147
VerifyPermission(uint32_t accessToken,const std::string & permissionName) const148 bool DistributedAbilityManagerService::VerifyPermission(uint32_t accessToken, const std::string& permissionName) const
149 {
150 int32_t result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, permissionName);
151 if (result == Security::AccessToken::PermissionState::PERMISSION_DENIED) {
152 HILOGE("permission denied, permissionName:%{public}s", permissionName.c_str());
153 return false;
154 }
155 HILOGD("permission matched.");
156 return true;
157 }
158
Register(const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams,int32_t & token)159 int32_t DistributedAbilityManagerService::Register(
160 const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams, int32_t& token)
161 {
162 HILOGD("called");
163 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
164 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
165 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
166 return DMS_PERMISSION_DENIED;
167 }
168 if (continuationExtraParams != nullptr) {
169 ContinuationMode continuationMode = continuationExtraParams->GetContinuationMode();
170 if (!IsContinuationModeValid(continuationMode)) {
171 return INVALID_CONTINUATION_MODE;
172 }
173 }
174 int32_t ret = RegisterWithoutExtraParam(token);
175 return ret;
176 }
177
Unregister(int32_t token)178 int32_t DistributedAbilityManagerService::Unregister(int32_t token)
179 {
180 HILOGD("called");
181 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
182 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
183 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
184 return DMS_PERMISSION_DENIED;
185 }
186 if (!IsTokenRegistered(accessToken, token)) {
187 return TOKEN_HAS_NOT_REGISTERED;
188 }
189 // remove death recipient and update callbackMap_ by token
190 {
191 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
192 if (IsNotifierRegistered(token)) {
193 callbackMap_[token]->RemoveDeathRecipient(notifierDeathRecipient_);
194 callbackMap_.erase(token);
195 }
196 }
197 // update tokenMap_ by token
198 {
199 std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
200 for (auto iter = tokenMap_.begin(); iter != tokenMap_.end();) {
201 iter->second.erase(std::remove_if(iter->second.begin(), iter->second.end(),
202 [token](int32_t n) { return n == token; }), iter->second.end());
203 if (iter->second.empty()) {
204 tokenMap_.erase(iter++);
205 break;
206 } else {
207 iter++;
208 }
209 }
210 }
211 // disconnect to app when third-party app called unregister
212 (void)HandleDisconnectAbility();
213 return ERR_OK;
214 }
215
RegisterDeviceSelectionCallback(int32_t token,const std::string & cbType,const sptr<IRemoteObject> & notifier)216 int32_t DistributedAbilityManagerService::RegisterDeviceSelectionCallback(
217 int32_t token, const std::string& cbType, const sptr<IRemoteObject>& notifier)
218 {
219 HILOGD("called");
220 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
221 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
222 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
223 return DMS_PERMISSION_DENIED;
224 }
225 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
226 HILOGE("type: %{public}s not support!", cbType.c_str());
227 return UNKNOWN_CALLBACK_TYPE;
228 }
229 if (!IsTokenRegistered(accessToken, token)) {
230 return TOKEN_HAS_NOT_REGISTERED;
231 }
232 if (IsNotifierRegisteredLocked(token, cbType)) {
233 return CALLBACK_HAS_REGISTERED;
234 }
235 {
236 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
237 auto iter = callbackMap_.find(token);
238 if (iter != callbackMap_.end()) { // registered at least once
239 if (iter->second == nullptr) {
240 return ERR_NULL_OBJECT;
241 }
242 iter->second->SetNotifier(cbType, notifier);
243 } else { // never registered
244 std::unique_ptr<NotifierInfo> notifierInfo = std::make_unique<NotifierInfo>();
245 notifierInfo->SetNotifier(cbType, notifier);
246 callbackMap_[token] = std::move(notifierInfo);
247 notifier->AddDeathRecipient(notifierDeathRecipient_);
248 }
249 HILOGD("token register success");
250 }
251 return ERR_OK;
252 }
253
UnregisterDeviceSelectionCallback(int32_t token,const std::string & cbType)254 int32_t DistributedAbilityManagerService::UnregisterDeviceSelectionCallback(int32_t token, const std::string& cbType)
255 {
256 HILOGD("called");
257 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
258 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
259 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
260 return DMS_PERMISSION_DENIED;
261 }
262 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
263 HILOGE("type: %{public}s not support!", cbType.c_str());
264 return UNKNOWN_CALLBACK_TYPE;
265 }
266 if (!IsTokenRegistered(accessToken, token)) {
267 return TOKEN_HAS_NOT_REGISTERED;
268 }
269 if (!IsNotifierRegisteredLocked(token, cbType)) {
270 return CALLBACK_HAS_NOT_REGISTERED;
271 }
272 {
273 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
274 auto iter = callbackMap_.find(token);
275 if (iter != callbackMap_.end()) {
276 iter->second->RemoveDeathRecipient(notifierDeathRecipient_, cbType);
277 iter->second->DeleteNotifier(cbType);
278 if (iter->second->IsNotifierMapEmpty()) {
279 callbackMap_.erase(iter);
280 }
281 }
282 }
283 HILOGD("token unregister success");
284 return ERR_OK;
285 }
286
UpdateConnectStatus(int32_t token,const std::string & deviceId,DeviceConnectStatus deviceConnectStatus)287 int32_t DistributedAbilityManagerService::UpdateConnectStatus(int32_t token, const std::string& deviceId,
288 DeviceConnectStatus deviceConnectStatus)
289 {
290 HILOGD("called");
291 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
292 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
293 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
294 return DMS_PERMISSION_DENIED;
295 }
296 if (deviceId.empty()) {
297 HILOGE("deviceId is empty");
298 return ERR_NULL_OBJECT;
299 }
300 if (!IsConnectStatusValid(deviceConnectStatus)) {
301 return INVALID_CONNECT_STATUS;
302 }
303 if (!IsTokenRegistered(accessToken, token)) {
304 return TOKEN_HAS_NOT_REGISTERED;
305 }
306 {
307 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
308 if (!IsNotifierRegistered(token)) {
309 return CALLBACK_HAS_NOT_REGISTERED;
310 }
311 std::shared_ptr<ConnectStatusInfo> connectStatusInfo =
312 std::make_shared<ConnectStatusInfo>(deviceId, deviceConnectStatus);
313 callbackMap_[token]->SetConnectStatusInfo(connectStatusInfo);
314 }
315 // sendRequest status(token, connectStatusInfo) to app by app proxy when appProxy_ is not null.
316 {
317 std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
318 if (appProxy_ != nullptr) {
319 HandleUpdateConnectStatus(token, deviceId, deviceConnectStatus);
320 }
321 }
322 return ERR_OK;
323 }
324
StartDeviceManager(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)325 int32_t DistributedAbilityManagerService::StartDeviceManager(
326 int32_t token, const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
327 {
328 HILOGD("called");
329 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
330 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
331 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
332 return DMS_PERMISSION_DENIED;
333 }
334 if (continuationExtraParams != nullptr) {
335 ContinuationMode continuationMode = continuationExtraParams->GetContinuationMode();
336 if (!IsContinuationModeValid(continuationMode)) {
337 return INVALID_CONTINUATION_MODE;
338 }
339 }
340 if (!IsTokenRegistered(accessToken, token)) {
341 return TOKEN_HAS_NOT_REGISTERED;
342 }
343 {
344 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
345 if (!IsNotifierRegistered(token)) {
346 return CALLBACK_HAS_NOT_REGISTERED;
347 }
348 }
349 // 1. connect to app and get the app proxy if appProxy_ is null, otherwise start device manager directly.
350 {
351 std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
352 if (appProxy_ != nullptr) {
353 HandleStartDeviceManager(token, continuationExtraParams);
354 return ERR_OK;
355 }
356 }
357 int32_t errCode = ConnectAbility(token, continuationExtraParams);
358 if (errCode != ERR_OK) {
359 HILOGE("token connect to app failed");
360 return CONNECT_ABILITY_FAILED;
361 }
362 // 2. sendRequest data(token, filter, dmsStub, connectStatusInfo) to app by app proxy when connect callback.
363 return ERR_OK;
364 }
365
RegisterWithoutExtraParam(int32_t & token)366 int32_t DistributedAbilityManagerService::RegisterWithoutExtraParam(int32_t& token)
367 {
368 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
369 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
370 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
371 return DMS_PERMISSION_DENIED;
372 }
373 if (IsExceededRegisterMaxNum(accessToken)) {
374 return REGISTER_EXCEED_MAX_TIMES;
375 }
376 int32_t tToken = -1;
377 {
378 std::lock_guard<std::mutex> tokenLock(tokenMutex_);
379 tToken = token_.load();
380 if (++tToken > MAX_TOKEN_NUM) {
381 tToken = 1;
382 }
383 token_.store(tToken);
384 // save at parameters
385 system::SetParameter(TOKEN_KEY, std::to_string(tToken));
386 }
387 // update tokenMap_
388 {
389 std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
390 tokenMap_[accessToken].emplace_back(tToken);
391 }
392 token = tToken;
393 return ERR_OK;
394 }
395
StartDeviceManagerWithoutExtraParam(int32_t token)396 int32_t DistributedAbilityManagerService::StartDeviceManagerWithoutExtraParam(int32_t token)
397 {
398 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
399 if (!VerifyPermission(accessToken, PERMISSION_DISTRIBUTED_DATASYNC)) {
400 HILOGE("DISTRIBUTED_DATASYNC permission check failed!");
401 return DMS_PERMISSION_DENIED;
402 }
403 if (!IsTokenRegistered(accessToken, token)) {
404 return TOKEN_HAS_NOT_REGISTERED;
405 }
406 {
407 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
408 if (!IsNotifierRegistered(token)) {
409 return CALLBACK_HAS_NOT_REGISTERED;
410 }
411 }
412 // 1. connect to app and get the app proxy if appProxy_ is null, otherwise start device manager directly.
413 {
414 std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
415 if (appProxy_ != nullptr) {
416 HandleStartDeviceManager(token, nullptr);
417 return ERR_OK;
418 }
419 }
420 int32_t errCode = ConnectAbility(token, nullptr);
421 if (errCode != ERR_OK) {
422 HILOGE("token connect to app failed");
423 return CONNECT_ABILITY_FAILED;
424 }
425 // 2. sendRequest data(token, filter, dmsStub, connectStatusInfo) to app by app proxy when connect callback.
426 return ERR_OK;
427 }
428
ConnectAbility(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)429 int32_t DistributedAbilityManagerService::ConnectAbility(int32_t token,
430 const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
431 {
432 AAFwk::Want want;
433 want.SetAction(DMS_HIPLAY_ACTION);
434 int32_t activeAccountId = -1;
435 #ifdef OS_ACCOUNT_PART
436 std::vector<int32_t> ids;
437 int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
438 if (ret != ERR_OK || ids.empty()) {
439 return INVALID_PARAMETERS_ERR;
440 }
441 activeAccountId = ids[0];
442 #endif
443 AppExecFwk::ExtensionAbilityInfo extensionInfo;
444 if (!QueryExtensionAbilityInfo(activeAccountId, want, extensionInfo)) {
445 HILOGE("QueryExtensionAbilityInfo failed");
446 return CONNECT_ABILITY_FAILED;
447 }
448 if (connect_ == nullptr) {
449 connect_ = new AppConnectionStub(token, continuationExtraParams);
450 }
451 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
452 if (errCode != ERR_OK) {
453 HILOGE("connect ability manager server failed, errCode=%{public}d", errCode);
454 return errCode;
455 }
456 errCode = AAFwk::AbilityManagerClient::GetInstance()->ConnectAbility(want,
457 iface_cast<AAFwk::IAbilityConnection>(connect_), this, activeAccountId);
458 if (errCode != ERR_OK) {
459 HILOGE("ConnectAbility failed");
460 connect_ = nullptr;
461 return CONNECT_ABILITY_FAILED;
462 }
463 return ERR_OK;
464 }
465
QueryExtensionAbilityInfo(const int32_t & activeAccountId,const AAFwk::Want & want,AppExecFwk::ExtensionAbilityInfo & extensionInfo)466 bool DistributedAbilityManagerService::QueryExtensionAbilityInfo(const int32_t& activeAccountId,
467 const AAFwk::Want& want, AppExecFwk::ExtensionAbilityInfo& extensionInfo)
468 {
469 auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
470 if (samgrProxy == nullptr) {
471 HILOGE("get samgr failed");
472 return false;
473 }
474 sptr<IRemoteObject> bmsProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
475 if (bmsProxy == nullptr) {
476 HILOGE("get bms from samgr failed");
477 return false;
478 }
479 auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bmsProxy);
480 if (bundleMgr == nullptr) {
481 HILOGE("bms iface_cast failed");
482 return false;
483 }
484 std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
485 std::string identity = IPCSkeleton::ResetCallingIdentity();
486 bundleMgr->QueryExtensionAbilityInfos(want, AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
487 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_PERMISSION, activeAccountId, extensionInfos);
488 IPCSkeleton::SetCallingIdentity(identity);
489 if (extensionInfos.empty()) {
490 HILOGE("QueryExtensionAbilityInfo failed");
491 return false;
492 }
493 extensionInfo = extensionInfos.front();
494 if (extensionInfo.bundleName.empty() || extensionInfo.name.empty()) {
495 HILOGE("ExtensionAbilityInfo is empty.");
496 return false;
497 }
498 HILOGD("ExtensionAbilityInfo found, name=%{public}s.", extensionInfo.name.c_str());
499 return true;
500 }
501
DisconnectAbility()502 int32_t DistributedAbilityManagerService::DisconnectAbility()
503 {
504 if (connect_ == nullptr) {
505 return ERR_NULL_OBJECT;
506 }
507 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->Connect();
508 if (errCode != ERR_OK) {
509 HILOGE("connect ability manager server failed, errCode=%{public}d", errCode);
510 return errCode;
511 }
512 errCode = AAFwk::AbilityManagerClient::GetInstance()->DisconnectAbility(
513 iface_cast<AAFwk::IAbilityConnection>(connect_));
514 connect_ = nullptr;
515 if (errCode != ERR_OK) {
516 HILOGE("DisconnectAbility failed");
517 return DISCONNECT_ABILITY_FAILED;
518 }
519 return ERR_OK;
520 }
521
OnDeviceConnect(int32_t token,const std::vector<ContinuationResult> & continuationResults)522 int32_t DistributedAbilityManagerService::OnDeviceConnect(int32_t token,
523 const std::vector<ContinuationResult>& continuationResults)
524 {
525 // device connect callback to napi
526 if (!HandleDisconnectAbility()) {
527 return DISCONNECT_ABILITY_FAILED;
528 }
529 if (!IsNotifierRegisteredLocked(token, EVENT_CONNECT)) {
530 return CALLBACK_HAS_NOT_REGISTERED;
531 }
532 {
533 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
534 auto notifier = callbackMap_[token]->GetNotifier(EVENT_CONNECT);
535 if (!HandleDeviceConnect(notifier, continuationResults)) {
536 return INVALID_PARAMETERS_ERR;
537 }
538 }
539 return ERR_OK;
540 }
541
OnDeviceDisconnect(int32_t token,const std::vector<ContinuationResult> & continuationResults)542 int32_t DistributedAbilityManagerService::OnDeviceDisconnect(int32_t token,
543 const std::vector<ContinuationResult>& continuationResults)
544 {
545 // device disconnect callback to napi
546 if (!HandleDisconnectAbility()) {
547 return DISCONNECT_ABILITY_FAILED;
548 }
549 if (!IsNotifierRegisteredLocked(token, EVENT_DISCONNECT)) {
550 return CALLBACK_HAS_NOT_REGISTERED;
551 }
552 {
553 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
554 auto notifier = callbackMap_[token]->GetNotifier(EVENT_DISCONNECT);
555 if (!HandleDeviceDisconnect(notifier, continuationResults)) {
556 return INVALID_PARAMETERS_ERR;
557 }
558 }
559 return ERR_OK;
560 }
561
OnDeviceCancel()562 int32_t DistributedAbilityManagerService::OnDeviceCancel()
563 {
564 // disconnect to app when app close the window.
565 if (!HandleDisconnectAbility()) {
566 return DISCONNECT_ABILITY_FAILED;
567 }
568 return ERR_OK;
569 }
570
HandleDisconnectAbility()571 bool DistributedAbilityManagerService::HandleDisconnectAbility()
572 {
573 if (continuationHandler_ == nullptr) {
574 HILOGE("continuationHandler is null.");
575 return false;
576 }
577 auto func = [this]() {
578 HILOGD("HandleDisconnectAbility called.");
579 int32_t errCode = DisconnectAbility();
580 if (errCode != ERR_OK) {
581 HILOGE("DisconnectAbility errCode: %{public}d.", errCode);
582 return;
583 }
584 };
585 continuationHandler_->submit(func);
586 return true;
587 }
588
IsExceededRegisterMaxNum(uint32_t accessToken)589 bool DistributedAbilityManagerService::IsExceededRegisterMaxNum(uint32_t accessToken)
590 {
591 std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
592 auto iter = tokenMap_.find(accessToken);
593 if (iter != tokenMap_.end() && iter->second.size() >= MAX_REGISTER_NUM) {
594 HILOGE("accessToken registered too much times");
595 return true;
596 }
597 return false;
598 }
599
IsContinuationModeValid(ContinuationMode continuationMode)600 bool DistributedAbilityManagerService::IsContinuationModeValid(ContinuationMode continuationMode)
601 {
602 if (static_cast<int32_t>(continuationMode) < static_cast<int32_t>(ContinuationMode::COLLABORATION_SINGLE) ||
603 static_cast<int32_t>(continuationMode) > static_cast<int32_t>(ContinuationMode::COLLABORATION_MUTIPLE)) {
604 HILOGE("continuationMode is invalid");
605 return false;
606 }
607 return true;
608 }
609
IsConnectStatusValid(DeviceConnectStatus deviceConnectStatus)610 bool DistributedAbilityManagerService::IsConnectStatusValid(DeviceConnectStatus deviceConnectStatus)
611 {
612 if (static_cast<int32_t>(deviceConnectStatus) < static_cast<int32_t>(DeviceConnectStatus::IDLE) ||
613 static_cast<int32_t>(deviceConnectStatus) > static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)) {
614 HILOGE("deviceConnectStatus is invalid");
615 return false;
616 }
617 return true;
618 }
619
IsTokenRegistered(uint32_t accessToken,int32_t token)620 bool DistributedAbilityManagerService::IsTokenRegistered(uint32_t accessToken, int32_t token)
621 {
622 std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
623 auto iter = tokenMap_.find(accessToken);
624 if (iter == tokenMap_.end()) {
625 HILOGE("accessToken has not registered in token map.");
626 return false;
627 }
628 for (auto it = iter->second.begin(); it != iter->second.end(); it++) {
629 if (*it == token) {
630 return true;
631 }
632 }
633 HILOGE("token has not registered");
634 return false;
635 }
636
IsNotifierRegistered(int32_t token)637 bool DistributedAbilityManagerService::IsNotifierRegistered(int32_t token)
638 {
639 // must be in callbackMapLock scope
640 auto iter = callbackMap_.find(token);
641 if (iter == callbackMap_.end()) {
642 HILOGE("accessToken has not registered in callback map.");
643 return false;
644 }
645 if (iter->second == nullptr) {
646 HILOGE("notifierInfo is nullptr");
647 return false;
648 }
649 return true;
650 }
651
IsNotifierRegisteredLocked(int32_t token,const std::string & cbType)652 bool DistributedAbilityManagerService::IsNotifierRegisteredLocked(int32_t token, const std::string& cbType)
653 {
654 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
655 if (!IsNotifierRegistered(token)) {
656 return false;
657 }
658 if (callbackMap_[token]->GetNotifier(cbType) != nullptr) {
659 HILOGD("token and cbType:%{public}s has already registered", cbType.c_str());
660 return true;
661 }
662 HILOGE("token and cbType:%{public}s has not registered", cbType.c_str());
663 return false;
664 }
665
HandleDeviceConnect(const sptr<IRemoteObject> & notifier,const std::vector<ContinuationResult> & continuationResults)666 bool DistributedAbilityManagerService::HandleDeviceConnect(const sptr<IRemoteObject>& notifier,
667 const std::vector<ContinuationResult>& continuationResults)
668 {
669 if (continuationHandler_ == nullptr) {
670 HILOGE("continuationHandler_ is nullptr");
671 return false;
672 }
673 if (notifier == nullptr) {
674 HILOGE("notifier is nullptr");
675 return false;
676 }
677 auto func = [notifier, continuationResults]() {
678 HILOGD("HandleDeviceConnect called.");
679 auto proxy = std::make_unique<DeviceSelectionNotifierProxy>(notifier);
680 proxy->OnDeviceConnect(continuationResults);
681 };
682 continuationHandler_->submit(func);
683 return true;
684 }
685
HandleDeviceDisconnect(const sptr<IRemoteObject> & notifier,const std::vector<ContinuationResult> & continuationResults)686 bool DistributedAbilityManagerService::HandleDeviceDisconnect(const sptr<IRemoteObject>& notifier,
687 const std::vector<ContinuationResult>& continuationResults)
688 {
689 if (continuationHandler_ == nullptr) {
690 HILOGE("continuationHandler_ is nullptr");
691 return false;
692 }
693 if (notifier == nullptr) {
694 HILOGE("notifier is nullptr");
695 return false;
696 }
697 auto func = [notifier, continuationResults]() {
698 HILOGD("HandleDeviceDisconnect called.");
699 auto proxy = std::make_unique<DeviceSelectionNotifierProxy>(notifier);
700 proxy->OnDeviceDisconnect(continuationResults);
701 };
702 continuationHandler_->submit(func);
703 return true;
704 }
705
ScheduleStartDeviceManager(const sptr<IRemoteObject> & appProxy,int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)706 void DistributedAbilityManagerService::ScheduleStartDeviceManager(const sptr<IRemoteObject>& appProxy, int32_t token,
707 const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
708 {
709 std::lock_guard<std::mutex> appProxyLock(appProxyMutex_);
710 appProxy_ = appProxy;
711 if (appProxy_ == nullptr) {
712 return;
713 }
714 HandleStartDeviceManager(token, continuationExtraParams);
715 }
716
HandleStartDeviceManager(int32_t token,const std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)717 void DistributedAbilityManagerService::HandleStartDeviceManager(int32_t token,
718 const std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
719 {
720 if (continuationHandler_ == nullptr) {
721 HILOGE("continuationHandler_ is nullptr");
722 return;
723 }
724 auto func = [this, token, continuationExtraParams, appProxy = appProxy_]() {
725 HILOGD("HandleStartDeviceManager called.");
726 MessageParcel data;
727 if (!data.WriteInterfaceToken(HIPLAY_PANEL_INTERFACE_TOKEN)) {
728 HILOGE("WriteInterfaceToken failed");
729 return;
730 }
731 PARCEL_WRITE_HELPER_NORET(data, Int32, token);
732 if (continuationExtraParams == nullptr) {
733 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
734 } else {
735 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_OBJECT);
736 PARCEL_WRITE_HELPER_NORET(data, Parcelable, continuationExtraParams.get());
737 }
738 sptr<AppDeviceCallbackStub> callback(new AppDeviceCallbackStub());
739 PARCEL_WRITE_HELPER_NORET(data, RemoteObject, callback);
740 // query whether the connect status needs to be send
741 {
742 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
743 if (IsNotifierRegistered(token)) {
744 std::shared_ptr<ConnectStatusInfo> connectStatusInfo = callbackMap_[token]->GetConnectStatusInfo();
745 if (connectStatusInfo == nullptr) {
746 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
747 } else {
748 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_OBJECT);
749 // use u16string, because send to app
750 PARCEL_WRITE_HELPER_NORET(data, String16, Str8ToStr16(connectStatusInfo->GetDeviceId()));
751 PARCEL_WRITE_HELPER_NORET(data, Int32,
752 static_cast<int32_t>(connectStatusInfo->GetDeviceConnectStatus()));
753 }
754 } else {
755 PARCEL_WRITE_HELPER_NORET(data, Int32, VALUE_NULL);
756 }
757 }
758 MessageParcel reply;
759 MessageOption option;
760 if (appProxy == nullptr) {
761 HILOGE("appProxy is nullptr");
762 return;
763 }
764 int32_t result = appProxy->SendRequest(START_DEVICE_MANAGER_CODE, data, reply, option);
765 HILOGD("result is %{public}d", result);
766 };
767 continuationHandler_->submit(func);
768 }
769
HandleUpdateConnectStatus(int32_t token,std::string deviceId,const DeviceConnectStatus & deviceConnectStatus)770 void DistributedAbilityManagerService::HandleUpdateConnectStatus(int32_t token, std::string deviceId,
771 const DeviceConnectStatus& deviceConnectStatus)
772 {
773 if (continuationHandler_ == nullptr) {
774 HILOGE("continuationHandler_ is nullptr");
775 return;
776 }
777 auto func = [this, token, deviceId, deviceConnectStatus, appProxy = appProxy_]() {
778 HILOGD("HandleUpdateConnectStatus called.");
779 MessageParcel data;
780 if (!data.WriteInterfaceToken(HIPLAY_PANEL_INTERFACE_TOKEN)) {
781 HILOGE("WriteInterfaceToken failed");
782 return;
783 }
784 PARCEL_WRITE_HELPER_NORET(data, Int32, token);
785 // use u16string, because send to app
786 PARCEL_WRITE_HELPER_NORET(data, String16, Str8ToStr16(deviceId));
787 PARCEL_WRITE_HELPER_NORET(data, Int32, static_cast<int32_t>(deviceConnectStatus));
788 MessageParcel reply;
789 MessageOption option;
790 if (appProxy == nullptr) {
791 HILOGE("appProxy is nullptr");
792 return;
793 }
794 int32_t result = appProxy->SendRequest(UPDATE_CONNECT_STATUS_CODE, data, reply, option);
795 HILOGD("result is %{public}d", result);
796 };
797 continuationHandler_->submit(func);
798 }
799
QueryTokenByNotifier(const sptr<IRemoteObject> & notifier,int32_t & token)800 bool DistributedAbilityManagerService::QueryTokenByNotifier(const sptr<IRemoteObject>& notifier, int32_t& token)
801 {
802 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
803 for (auto iter = callbackMap_.begin(); iter != callbackMap_.end(); iter++) {
804 if (iter->second == nullptr) {
805 return false;
806 }
807 if (iter->second->QueryNotifier(notifier)) {
808 token = iter->first;
809 return true;
810 }
811 }
812 return false;
813 }
814
ProcessNotifierDied(const sptr<IRemoteObject> & notifier)815 void DistributedAbilityManagerService::ProcessNotifierDied(const sptr<IRemoteObject>& notifier)
816 {
817 // update cache when third-party app died
818 if (notifier == nullptr) {
819 return;
820 }
821 HandleNotifierDied(notifier);
822 }
823
HandleNotifierDied(const sptr<IRemoteObject> & notifier)824 void DistributedAbilityManagerService::HandleNotifierDied(const sptr<IRemoteObject>& notifier)
825 {
826 if (continuationHandler_ == nullptr) {
827 HILOGE("continuationHandler_ is nullptr");
828 return;
829 }
830 auto func = [this, notifier] () {
831 HILOGD("HandleNotifierDied called.");
832 // query token in callbackMap_ by notifier
833 int32_t token = -1;
834 if (!QueryTokenByNotifier(notifier, token)) {
835 HILOGE("QueryTokenByNotifier failed");
836 return;
837 }
838 // remove death recipient and update callbackMap_ by token
839 {
840 std::lock_guard<std::mutex> callbackMapLock(callbackMapMutex_);
841 if (IsNotifierRegistered(token)) {
842 callbackMap_[token]->RemoveDeathRecipient(notifierDeathRecipient_);
843 callbackMap_.erase(token);
844 }
845 }
846 // update tokenMap_ by token
847 {
848 std::lock_guard<std::mutex> tokenMapLock(tokenMapMutex_);
849 for (auto iter = tokenMap_.begin(); iter != tokenMap_.end();) {
850 iter->second.erase(std::remove_if(iter->second.begin(), iter->second.end(),
851 [token](int32_t n) { return n == token; }), iter->second.end());
852 if (iter->second.empty()) {
853 tokenMap_.erase(iter++);
854 break;
855 } else {
856 iter++;
857 }
858 }
859 }
860 // disconnect to app when third-party app died
861 (void)HandleDisconnectAbility();
862 };
863 continuationHandler_->submit(func);
864 }
865 } // namespace DistributedSchedule
866 } // namespace OHOS
867