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