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