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