/* * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ability_connect_manager.h" #include #include "ability_manager_service.h" #include "ability_resident_process_rdb.h" #include "appfreeze_manager.h" #include "app_exit_reason_data_manager.h" #include "assert_fault_callback_death_mgr.h" #include "hitrace_meter.h" #include "int_wrapper.h" #include "param.h" #include "res_sched_util.h" #include "session/host/include/zidl/session_interface.h" #include "startup_util.h" #include "ui_extension_utils.h" #include "ui_service_extension_connection_constants.h" #include "cache_extension_utils.h" #include "datetime_ex.h" #include "init_reboot.h" namespace OHOS { namespace AAFwk { namespace { constexpr char EVENT_KEY_UID[] = "UID"; constexpr char EVENT_KEY_PID[] = "PID"; constexpr char EVENT_KEY_MESSAGE[] = "MSG"; constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME"; constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME"; const std::string DEBUG_APP = "debugApp"; const std::string FRS_APP_INDEX = "ohos.extra.param.key.frs_index"; const std::string FRS_BUNDLE_NAME = "com.ohos.formrenderservice"; const std::string UIEXTENSION_ABILITY_ID = "ability.want.params.uiExtensionAbilityId"; const std::string UIEXTENSION_ROOT_HOST_PID = "ability.want.params.uiExtensionRootHostPid"; const std::string MAX_UINT64_VALUE = "18446744073709551615"; const std::string IS_PRELOAD_UIEXTENSION_ABILITY = "ability.want.params.is_preload_uiextension_ability"; const std::string SEPARATOR = ":"; #ifdef SUPPORT_ASAN const int LOAD_TIMEOUT_MULTIPLE = 150; const int CONNECT_TIMEOUT_MULTIPLE = 45; const int COMMAND_TIMEOUT_MULTIPLE = 75; const int COMMAND_WINDOW_TIMEOUT_MULTIPLE = 75; #else const int LOAD_TIMEOUT_MULTIPLE = 10; const int CONNECT_TIMEOUT_MULTIPLE = 10; const int COMMAND_TIMEOUT_MULTIPLE = 5; const int COMMAND_WINDOW_TIMEOUT_MULTIPLE = 5; #endif const int32_t AUTO_DISCONNECT_INFINITY = -1; constexpr const char* FROZEN_WHITE_DIALOG = "com.huawei.hmos.huaweicast"; constexpr char BUNDLE_NAME_DIALOG[] = "com.ohos.amsdialog"; constexpr char ABILITY_NAME_ASSERT_FAULT_DIALOG[] = "AssertFaultDialog"; constexpr const char* WANT_PARAMS_APP_RESTART_FLAG = "ohos.aafwk.app.restart"; const std::string XIAOYI_BUNDLE_NAME = "com.huawei.hmos.vassistant"; bool IsSpecialAbility(const AppExecFwk::AbilityInfo &abilityInfo) { std::vector> trustAbilities{ { AbilityConfig::SCENEBOARD_BUNDLE_NAME, AbilityConfig::SCENEBOARD_ABILITY_NAME }, { AbilityConfig::SYSTEM_UI_BUNDLE_NAME, AbilityConfig::SYSTEM_UI_ABILITY_NAME }, { AbilityConfig::LAUNCHER_BUNDLE_NAME, AbilityConfig::LAUNCHER_ABILITY_NAME } }; for (const auto &pair : trustAbilities) { if (pair.first == abilityInfo.bundleName && pair.second == abilityInfo.name) { return true; } } return false; } } AbilityConnectManager::AbilityConnectManager(int userId) : userId_(userId) { uiExtensionAbilityRecordMgr_ = std::make_unique(userId); } AbilityConnectManager::~AbilityConnectManager() {} int AbilityConnectManager::StartAbility(const AbilityRequest &abilityRequest) { std::lock_guard guard(serialMutex_); return StartAbilityLocked(abilityRequest); } int AbilityConnectManager::TerminateAbility(const sptr &token) { std::lock_guard guard(serialMutex_); return TerminateAbilityInner(token); } int AbilityConnectManager::TerminateAbilityInner(const sptr &token) { auto abilityRecord = GetExtensionByTokenFromServiceMap(token); if (abilityRecord == nullptr) { abilityRecord = GetExtensionByTokenFromAbilityCache(token); } CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate ability, ability is %{public}s.", element.c_str()); if (IsUIExtensionAbility(abilityRecord)) { if (!abilityRecord->IsConnectListEmpty()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist connection, don't terminate."); return ERR_OK; } else if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND) || abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING) || abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "current ability is active"); DoBackgroundAbilityWindow(abilityRecord, abilityRecord->GetSessionInfo()); MoveToTerminatingMap(abilityRecord); return ERR_OK; } } MoveToTerminatingMap(abilityRecord); return TerminateAbilityLocked(token); } int AbilityConnectManager::StopServiceAbility(const AbilityRequest &abilityRequest) { TAG_LOGI(AAFwkTag::ABILITYMGR, "call"); std::lock_guard guard(serialMutex_); return StopServiceAbilityLocked(abilityRequest); } int AbilityConnectManager::StartAbilityLocked(const AbilityRequest &abilityRequest) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::ABILITYMGR, "ability_name:%{public}s", abilityRequest.want.GetElement().GetURI().c_str()); std::shared_ptr targetService; bool isLoadedAbility = false; if (UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) { auto callerAbilityRecord = AAFwk::Token::GetAbilityRecordByToken(abilityRequest.callerToken); if (callerAbilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get callerAbilityRecord."); return ERR_NULL_OBJECT; } std::string hostBundleName = callerAbilityRecord->GetAbilityInfo().bundleName; int32_t ret = GetOrCreateExtensionRecord(abilityRequest, false, hostBundleName, targetService, isLoadedAbility); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get or create extension record, ret: %{public}d", ret); return ret; } } else { GetOrCreateServiceRecord(abilityRequest, false, targetService, isLoadedAbility); } CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE); TAG_LOGI(AAFwkTag::ABILITYMGR, "Start ability: %{public}s", targetService->GetURI().c_str()); targetService->AddCallerRecord(abilityRequest.callerToken, abilityRequest.requestCode, abilityRequest.want); targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_START_EXTENSION); targetService->DoBackgroundAbilityWindowDelayed(false); targetService->SetSessionInfo(abilityRequest.sessionInfo); if (IsUIExtensionAbility(targetService) && abilityRequest.sessionInfo && abilityRequest.sessionInfo->sessionToken) { auto &remoteObj = abilityRequest.sessionInfo->sessionToken; { std::lock_guard guard(uiExtensionMapMutex_); uiExtensionMap_[remoteObj] = UIExtWindowMapValType(targetService, abilityRequest.sessionInfo); } AddUIExtWindowDeathRecipient(remoteObj); } auto &abilityInfo = abilityRequest.abilityInfo; auto ret = ReportXiaoYiToRSSIfNeeded(abilityInfo); if (ret != ERR_OK) { return ret; } if (!isLoadedAbility) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Target service has not been loaded."); SetLastExitReason(abilityRequest, targetService); if (IsUIExtensionAbility(targetService)) { targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_START_ABILITY); } targetService->GrantUriPermissionForServiceExtension(); LoadAbility(targetService); } else if (targetService->IsAbilityState(AbilityState::ACTIVE) && !IsUIExtensionAbility(targetService)) { // It may have been started through connect targetService->SetWant(abilityRequest.want); targetService->GrantUriPermissionForServiceExtension(); CommandAbility(targetService); } else if (IsUIExtensionAbility(targetService)) { DoForegroundUIExtension(targetService, abilityRequest); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service is already activating."); EnqueueStartServiceReq(abilityRequest); return ERR_OK; } sptr token = targetService->GetToken(); sptr preToken = nullptr; if (targetService->GetPreAbilityRecord()) { preToken = targetService->GetPreAbilityRecord()->GetToken(); } DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1); return ERR_OK; } void AbilityConnectManager::SetLastExitReason( const AbilityRequest &abilityRequest, std::shared_ptr &targetRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); if (targetRecord == nullptr || !UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Failed to set UIExtensionAbility last exit reason."); return; } auto appExitReasonDataMgr = DelayedSingleton::GetInstance(); if (appExitReasonDataMgr == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Get app exit reason data mgr instance is nullptr."); return; } ExitReason exitReason = { REASON_UNKNOWN, "" }; const std::string keyEx = targetRecord->GetAbilityInfo().bundleName + SEPARATOR + targetRecord->GetAbilityInfo().moduleName + SEPARATOR + targetRecord->GetAbilityInfo().name; if (!appExitReasonDataMgr->GetUIExtensionAbilityExitReason(keyEx, exitReason)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "There is no record of UIExtensionAbility's last exit reason in the database."); return; } targetRecord->SetLastExitReason(exitReason); } void AbilityConnectManager::DoForegroundUIExtension(std::shared_ptr abilityRecord, const AbilityRequest &abilityRequest) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); CHECK_POINTER(abilityRequest.sessionInfo); auto abilitystateStr = abilityRecord->ConvertAbilityState(abilityRecord->GetAbilityState()); TAG_LOGI(AAFwkTag::ABILITYMGR, "Foreground ability: %{public}s, persistentId: %{public}d, abilityState: %{public}s", abilityRecord->GetURI().c_str(), abilityRequest.sessionInfo->persistentId, abilitystateStr.c_str()); if (abilityRecord->IsReady() && !abilityRecord->IsAbilityState(AbilityState::INACTIVATING) && !abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING) && !abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING) && abilityRecord->IsAbilityWindowReady()) { if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND)) { abilityRecord->SetWant(abilityRequest.want); CommandAbilityWindow(abilityRecord, abilityRequest.sessionInfo, WIN_CMD_FOREGROUND); return; } else { abilityRecord->SetWant(abilityRequest.want); abilityRecord->PostUIExtensionAbilityTimeoutTask(AbilityManagerService::FOREGROUND_TIMEOUT_MSG); DelayedSingleton::GetInstance()->MoveToForeground(abilityRecord->GetToken()); return; } } EnqueueStartServiceReq(abilityRequest, abilityRecord->GetURI()); } void AbilityConnectManager::EnqueueStartServiceReq(const AbilityRequest &abilityRequest, const std::string &serviceUri) { std::lock_guard guard(startServiceReqListLock_); auto abilityUri = abilityRequest.want.GetElement().GetURI(); if (!serviceUri.empty()) { abilityUri = serviceUri; } TAG_LOGI(AAFwkTag::ABILITYMGR, "abilityUri is %{public}s", abilityUri.c_str()); auto reqListIt = startServiceReqList_.find(abilityUri); if (reqListIt != startServiceReqList_.end()) { reqListIt->second->push_back(abilityRequest); } else { auto reqList = std::make_shared>(); reqList->push_back(abilityRequest); startServiceReqList_.emplace(abilityUri, reqList); CHECK_POINTER(taskHandler_); auto callback = [abilityUri, connectManager = shared_from_this()]() { std::lock_guard guard{connectManager->startServiceReqListLock_}; auto exist = connectManager->startServiceReqList_.erase(abilityUri); if (exist) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Target service %{public}s start timeout", abilityUri.c_str()); } }; int connectTimeout = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * CONNECT_TIMEOUT_MULTIPLE; taskHandler_->SubmitTask(callback, std::string("start_service_timeout:") + abilityUri, connectTimeout); } } int AbilityConnectManager::TerminateAbilityLocked(const sptr &token) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); auto abilityRecord = GetExtensionByTokenFromTerminatingMap(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); if (abilityRecord->IsTerminating()) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability is on terminating."); return ERR_OK; } if (!abilityRecord->GetConnectRecordList().empty()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service has been connected. Post disconnect task."); auto connectRecordList = abilityRecord->GetConnectRecordList(); HandleTerminateDisconnectTask(connectRecordList); } auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { TAG_LOGW(AAFwkTag::ABILITYMGR, "Disconnect ability terminate timeout."); connectManager->HandleStopTimeoutTask(abilityRecord); }; abilityRecord->Terminate(timeoutTask); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { AddUIExtensionAbilityRecordToTerminatedList(abilityRecord); } else { RemoveUIExtensionAbilityRecord(abilityRecord); } return ERR_OK; } int AbilityConnectManager::StopServiceAbilityLocked(const AbilityRequest &abilityRequest) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGI(AAFwkTag::ABILITYMGR, "call"); AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, GenerateBundleName(abilityRequest), abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName); std::string serviceKey = element.GetURI(); if (FRS_BUNDLE_NAME == abilityRequest.abilityInfo.bundleName) { serviceKey = serviceKey + std::to_string(abilityRequest.want.GetIntParam(FRS_APP_INDEX, 0)); } auto abilityRecord = GetServiceRecordByElementName(serviceKey); if (abilityRecord == nullptr) { abilityRecord = AbilityCacheManager::GetInstance().Get(abilityRequest); AddToServiceMap(serviceKey, abilityRecord); } CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); if (abilityRecord->IsTerminating()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability is on terminating."); return ERR_OK; } if (!abilityRecord->GetConnectRecordList().empty()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Post disconnect task."); auto connectRecordList = abilityRecord->GetConnectRecordList(); HandleTerminateDisconnectTask(connectRecordList); } TerminateRecord(abilityRecord); EventInfo eventInfo = BuildEventInfo(abilityRecord); EventReport::SendStopServiceEvent(EventName::STOP_SERVICE, eventInfo); return ERR_OK; } int32_t AbilityConnectManager::GetOrCreateExtensionRecord(const AbilityRequest &abilityRequest, bool isCreatedByConnect, const std::string &hostBundleName, std::shared_ptr &extensionRecord, bool &isLoaded) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName); CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); if (uiExtensionAbilityRecordMgr_->IsBelongToManager(abilityRequest.abilityInfo)) { int32_t ret = uiExtensionAbilityRecordMgr_->GetOrCreateExtensionRecord( abilityRequest, hostBundleName, extensionRecord, isLoaded); if (ret != ERR_OK) { return ret; } extensionRecord->SetCreateByConnectMode(isCreatedByConnect); std::string extensionRecordKey = element.GetURI() + std::to_string(extensionRecord->GetUIExtensionAbilityId()); extensionRecord->SetURI(extensionRecordKey); TAG_LOGD(AAFwkTag::ABILITYMGR, "Service map add, hostBundleName:%{public}s, key: %{public}s", hostBundleName.c_str(), extensionRecordKey.c_str()); AddToServiceMap(extensionRecordKey, extensionRecord); if (IsAbilityNeedKeepAlive(extensionRecord)) { extensionRecord->SetRestartTime(abilityRequest.restartTime); extensionRecord->SetRestartCount(abilityRequest.restartCount); } return ERR_OK; } return ERR_INVALID_VALUE; } void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abilityRequest, const bool isCreatedByConnect, std::shared_ptr &targetService, bool &isLoadedAbility) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); // lifecycle is not complete when window extension is reused bool noReuse = UIExtensionUtils::IsWindowExtension(abilityRequest.abilityInfo.extensionAbilityType); AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, GenerateBundleName(abilityRequest), abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName); std::string serviceKey = element.GetURI(); if (FRS_BUNDLE_NAME == abilityRequest.abilityInfo.bundleName) { serviceKey = element.GetURI() + std::to_string(abilityRequest.want.GetIntParam(FRS_APP_INDEX, 0)); } { std::lock_guard lock(serviceMapMutex_); auto serviceMapIter = serviceMap_.find(serviceKey); targetService = serviceMapIter == serviceMap_.end() ? nullptr : serviceMapIter->second; } if (targetService == nullptr && CacheExtensionUtils::IsCacheExtensionType(abilityRequest.abilityInfo.extensionAbilityType)) { targetService = AbilityCacheManager::GetInstance().Get(abilityRequest); if (targetService != nullptr) { AddToServiceMap(serviceKey, targetService); } } if (noReuse && targetService) { if (IsSpecialAbility(abilityRequest.abilityInfo)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Removing ability: %{public}s", element.GetURI().c_str()); } std::lock_guard lock(serviceMapMutex_); serviceMap_.erase(serviceKey); } isLoadedAbility = true; if (noReuse || targetService == nullptr) { targetService = AbilityRecord::CreateAbilityRecord(abilityRequest); CHECK_POINTER(targetService); targetService->SetOwnerMissionUserId(userId_); if (isCreatedByConnect) { targetService->SetCreateByConnectMode(); } if (abilityRequest.abilityInfo.name == AbilityConfig::LAUNCHER_ABILITY_NAME) { targetService->SetLauncherRoot(); targetService->SetRestartTime(abilityRequest.restartTime); targetService->SetRestartCount(abilityRequest.restartCount); } else if (IsAbilityNeedKeepAlive(targetService)) { targetService->SetRestartTime(abilityRequest.restartTime); targetService->SetRestartCount(abilityRequest.restartCount); } AddToServiceMap(serviceKey, targetService); isLoadedAbility = false; } } void AbilityConnectManager::GetConnectRecordListFromMap( const sptr &connect, std::list> &connectRecordList) { std::lock_guard lock(connectMapMutex_); auto connectMapIter = connectMap_.find(connect->AsObject()); if (connectMapIter != connectMap_.end()) { connectRecordList = connectMapIter->second; } } int32_t AbilityConnectManager::GetOrCreateTargetServiceRecord( const AbilityRequest &abilityRequest, const sptr &connectInfo, std::shared_ptr &targetService, bool &isLoadedAbility) { if (UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType) && connectInfo != nullptr) { int32_t ret = GetOrCreateExtensionRecord( abilityRequest, true, connectInfo->hostBundleName, targetService, isLoadedAbility); if (ret != ERR_OK || targetService == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get or create extension record."); return ERR_NULL_OBJECT; } connectInfo->uiExtensionAbilityId = targetService->GetUIExtensionAbilityId(); TAG_LOGD(AAFwkTag::ABILITYMGR, "UIExtensionAbility id %{public}d.", connectInfo->uiExtensionAbilityId); } else { GetOrCreateServiceRecord(abilityRequest, true, targetService, isLoadedAbility); } CHECK_POINTER_AND_RETURN(targetService, ERR_INVALID_VALUE); return ERR_OK; } int AbilityConnectManager::PreloadUIExtensionAbilityLocked(const AbilityRequest &abilityRequest, std::string &hostBundleName) { std::lock_guard guard(serialMutex_); return PreloadUIExtensionAbilityInner(abilityRequest, hostBundleName); } int AbilityConnectManager::PreloadUIExtensionAbilityInner(const AbilityRequest &abilityRequest, std::string &hostBundleName) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); if (!UIExtensionUtils::IsUIExtension(abilityRequest.abilityInfo.extensionAbilityType)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't preload non-uiextension type."); return ERR_WRONG_INTERFACE_CALL; } std::shared_ptr extensionRecord = nullptr; CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); int32_t extensionRecordId = INVALID_EXTENSION_RECORD_ID; int32_t ret = uiExtensionAbilityRecordMgr_->CreateExtensionRecord(abilityRequest, hostBundleName, extensionRecord, extensionRecordId); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "CreateExtensionRecord ERR."); return ret; } CHECK_POINTER_AND_RETURN(extensionRecord, ERR_NULL_OBJECT); std::shared_ptr targetService = extensionRecord->abilityRecord_; AppExecFwk::ElementName element(abilityRequest.abilityInfo.deviceId, abilityRequest.abilityInfo.bundleName, abilityRequest.abilityInfo.name, abilityRequest.abilityInfo.moduleName); std::string extensionRecordKey = element.GetURI() + std::to_string(targetService->GetUIExtensionAbilityId()); targetService->SetURI(extensionRecordKey); AddToServiceMap(extensionRecordKey, targetService); LoadAbility(targetService); return ERR_OK; } int AbilityConnectManager::UnloadUIExtensionAbility(const std::shared_ptr &abilityRecord, std::string &hostBundleName) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); //Get preLoadUIExtensionInfo CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); auto preLoadUIExtensionInfo = std::make_tuple(abilityRecord->GetWant().GetElement().GetAbilityName(), abilityRecord->GetWant().GetElement().GetBundleName(), abilityRecord->GetWant().GetElement().GetModuleName(), hostBundleName); //delete preLoadUIExtensionMap CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); auto extensionRecordId = abilityRecord->GetUIExtensionAbilityId(); uiExtensionAbilityRecordMgr_->RemovePreloadUIExtensionRecordById(preLoadUIExtensionInfo, extensionRecordId); //terminate preload uiextension auto token = abilityRecord->GetToken(); auto result = TerminateAbilityInner(token); if (result != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "terminate error!"); return result; } return ERR_OK; } void AbilityConnectManager::ReportEventToRSS(const AppExecFwk::AbilityInfo &abilityInfo, const std::shared_ptr abilityRecord, sptr callerToken) { if (taskHandler_ == nullptr || abilityRecord == nullptr || abilityRecord->GetPid() <= 0) { return; } std::string reason = ResSchedUtil::GetInstance().GetThawReasonByAbilityType(abilityInfo); const int32_t uid = abilityInfo.applicationInfo.uid; const std::string bundleName = abilityInfo.applicationInfo.bundleName; const int32_t pid = abilityRecord->GetPid(); auto callerAbility = Token::GetAbilityRecordByToken(callerToken); const int32_t callerPid = (callerAbility != nullptr) ? callerAbility->GetPid() : IPCSkeleton::GetCallingPid(); TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}d_%{public}s_%{public}d reason=%{public}s callerPid=%{public}d", uid, bundleName.c_str(), pid, reason.c_str(), callerPid); taskHandler_->SubmitTask([uid, bundleName, reason, pid, callerPid]() { ResSchedUtil::GetInstance().ReportEventToRSS(uid, bundleName, reason, pid, callerPid); }); } int AbilityConnectManager::ConnectAbilityLocked(const AbilityRequest &abilityRequest, const sptr &connect, const sptr &callerToken, sptr sessionInfo, sptr connectInfo) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER_AND_RETURN(connect, ERR_INVALID_VALUE); auto connectObject = connect->AsObject(); std::lock_guard guard(serialMutex_); // 1. get target service ability record, and check whether it has been loaded. std::shared_ptr targetService; bool isLoadedAbility = false; int32_t ret = GetOrCreateTargetServiceRecord(abilityRequest, connectInfo, targetService, isLoadedAbility); if (ret != ERR_OK) { return ret; } if (abilityRequest.abilityInfo.extensionAbilityType == AppExecFwk::ExtensionAbilityType::REMOTE_NOTIFICATION) { ReportEventToRSS(abilityRequest.abilityInfo, targetService, callerToken); } // 2. get target connectRecordList, and check whether this callback has been connected. ConnectListType connectRecordList; GetConnectRecordListFromMap(connect, connectRecordList); bool isCallbackConnected = !connectRecordList.empty(); // 3. If this service ability and callback has been connected, There is no need to connect repeatedly if (isLoadedAbility && (isCallbackConnected) && IsAbilityConnected(targetService, connectRecordList)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Service/callback connected"); return ERR_OK; } // 4. Other cases , need to connect the service ability auto connectRecord = ConnectionRecord::CreateConnectionRecord(callerToken, targetService, connect); CHECK_POINTER_AND_RETURN(connectRecord, ERR_INVALID_VALUE); connectRecord->AttachCallerInfo(); connectRecord->SetConnectState(ConnectionState::CONNECTING); if (targetService->GetAbilityInfo().extensionAbilityType == AppExecFwk::ExtensionAbilityType::UI_SERVICE) { connectRecord->SetConnectWant(abilityRequest.want); } targetService->AddConnectRecordToList(connectRecord); targetService->SetSessionInfo(sessionInfo); connectRecordList.push_back(connectRecord); AddConnectObjectToMap(connectObject, connectRecordList, isCallbackConnected); targetService->SetLaunchReason(LaunchReason::LAUNCHREASON_CONNECT_EXTENSION); if (UIExtensionUtils::IsWindowExtension(targetService->GetAbilityInfo().extensionAbilityType) && abilityRequest.sessionInfo) { std::lock_guard guard(windowExtensionMapMutex_); windowExtensionMap_.emplace(connectObject, WindowExtMapValType(targetService->GetApplicationInfo().accessTokenId, abilityRequest.sessionInfo)); } auto &abilityInfo = abilityRequest.abilityInfo; ret = ReportXiaoYiToRSSIfNeeded(abilityInfo); if (ret != ERR_OK) { return ret; } if (!isLoadedAbility) { LoadAbility(targetService); } else if (targetService->IsAbilityState(AbilityState::ACTIVE)) { targetService->SetWant(abilityRequest.want); HandleActiveAbility(targetService, connectRecord); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "TargetService activing"); targetService->SaveConnectWant(abilityRequest.want); } auto token = targetService->GetToken(); auto preToken = iface_cast(connectRecord->GetToken()); DelayedSingleton::GetInstance()->AbilityBehaviorAnalysis(token, preToken, 0, 1, 1); return ret; } void AbilityConnectManager::HandleActiveAbility(std::shared_ptr &targetService, std::shared_ptr &connectRecord) { TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s called.", __func__); if (targetService == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "null target service"); return; } AppExecFwk::ExtensionAbilityType extType = targetService->GetAbilityInfo().extensionAbilityType; bool isAbilityUIServiceExt = (extType == AppExecFwk::ExtensionAbilityType::UI_SERVICE); if (!isAbilityUIServiceExt) { if (targetService->GetConnectedListSize() >= 1) { TAG_LOGI(AAFwkTag::ABILITYMGR, "connected"); targetService->RemoveSignatureInfo(); CHECK_POINTER(connectRecord); connectRecord->CompleteConnect(); } else if (targetService->GetConnectingListSize() <= 1) { ConnectAbility(targetService); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "connecting"); } } else { CHECK_POINTER(connectRecord); Want want = connectRecord->GetConnectWant(); int connectRecordId = connectRecord->GetRecordId(); ConnectUIServiceExtAbility(targetService, connectRecordId, want); } } int AbilityConnectManager::DisconnectAbilityLocked(const sptr &connect) { std::lock_guard guard(serialMutex_); return DisconnectAbilityLocked(connect, false); } int AbilityConnectManager::DisconnectAbilityLocked(const sptr &connect, bool callerDied) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); // 1. check whether callback was connected. ConnectListType connectRecordList; GetConnectRecordListFromMap(connect, connectRecordList); if (connectRecordList.empty()) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Can't find the connect list from connect map by callback."); return CONNECTION_NOT_EXIST; } // 2. schedule disconnect to target service int result = ERR_OK; ConnectListType list; for (auto &connectRecord : connectRecordList) { if (connectRecord) { auto abilityRecord = connectRecord->GetAbilityRecord(); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); TAG_LOGD(AAFwkTag::ABILITYMGR, "abilityName: %{public}s, bundleName: %{public}s", abilityRecord->GetAbilityInfo().name.c_str(), abilityRecord->GetAbilityInfo().bundleName.c_str()); if (abilityRecord->GetAbilityInfo().type == AbilityType::EXTENSION) { RemoveExtensionDelayDisconnectTask(connectRecord); } if (connectRecord->GetCallerTokenId() != IPCSkeleton::GetCallingTokenID() && static_cast(IPCSkeleton::GetSelfTokenID() != IPCSkeleton::GetCallingTokenID())) { TAG_LOGW( AAFwkTag::ABILITYMGR, "The caller is inconsistent with the caller stored in the connectRecord."); continue; } result = DisconnectRecordNormal(list, connectRecord, callerDied); if (result != ERR_OK && callerDied) { DisconnectRecordForce(list, connectRecord); result = ERR_OK; } if (result != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect ability fail , ret = %{public}d.", result); break; } else { EventInfo eventInfo = BuildEventInfo(abilityRecord); EventReport::SendDisconnectServiceEvent(EventName::DISCONNECT_SERVICE, eventInfo); } } } for (auto&& connectRecord : list) { RemoveConnectionRecordFromMap(connectRecord); } return result; } void AbilityConnectManager::TerminateRecord(std::shared_ptr abilityRecord) { TAG_LOGI(AAFwkTag::ABILITYMGR, "called"); if (!GetExtensionByIdFromServiceMap(abilityRecord->GetRecordId()) && !AbilityCacheManager::GetInstance().FindRecordByToken(abilityRecord->GetToken())) { return; } auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { TAG_LOGW(AAFwkTag::ABILITYMGR, "Disconnect ability terminate timeout."); connectManager->HandleStopTimeoutTask(abilityRecord); }; MoveToTerminatingMap(abilityRecord); abilityRecord->Terminate(timeoutTask); } int AbilityConnectManager::DisconnectRecordNormal(ConnectListType &list, std::shared_ptr connectRecord, bool callerDied) const { auto result = connectRecord->DisconnectAbility(); if (result != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect ability fail , ret = %{public}d.", result); return result; } if (connectRecord->GetConnectState() == ConnectionState::DISCONNECTED) { TAG_LOGW(AAFwkTag::ABILITYMGR, "DisconnectRecordNormal disconnect record:%{public}d", connectRecord->GetRecordId()); connectRecord->CompleteDisconnect(ERR_OK, callerDied); list.emplace_back(connectRecord); } return ERR_OK; } void AbilityConnectManager::DisconnectRecordForce(ConnectListType &list, std::shared_ptr connectRecord) { auto abilityRecord = connectRecord->GetAbilityRecord(); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Disconnect force abilityRecord null"); return; } abilityRecord->RemoveConnectRecordFromList(connectRecord); connectRecord->CompleteDisconnect(ERR_OK, true); list.emplace_back(connectRecord); if (abilityRecord->IsConnectListEmpty() && (IsUIExtensionAbility(abilityRecord) || abilityRecord->IsNeverStarted() == 0)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Force terminate ability record state: %{public}d.", abilityRecord->GetAbilityState()); TerminateRecord(abilityRecord); } } int AbilityConnectManager::AttachAbilityThreadLocked( const sptr &scheduler, const sptr &token) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); auto abilityRecord = GetExtensionByTokenFromServiceMap(token); if (abilityRecord == nullptr) { abilityRecord = GetExtensionByTokenFromTerminatingMap(token); if (abilityRecord != nullptr && !IsUIExtensionAbility(abilityRecord)) { abilityRecord = nullptr; } } CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability: %{public}s", element.c_str()); if (taskHandler_ != nullptr) { int recordId = abilityRecord->GetRecordId(); std::string taskName = std::string("LoadTimeout_") + std::to_string(recordId); taskHandler_->CancelTask(taskName); } if (eventHandler_) { eventHandler_->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId()); } if (abilityRecord->IsSceneBoard()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Attach Ability: %{public}s", element.c_str()); sceneBoardTokenId_ = abilityRecord->GetAbilityInfo().applicationInfo.accessTokenId; } abilityRecord->SetScheduler(scheduler); abilityRecord->RemoveSpecifiedWantParam(UIEXTENSION_ABILITY_ID); abilityRecord->RemoveSpecifiedWantParam(UIEXTENSION_ROOT_HOST_PID); if (IsUIExtensionAbility(abilityRecord) && !abilityRecord->IsCreateByConnect() && !abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) { abilityRecord->PostUIExtensionAbilityTimeoutTask(AbilityManagerService::FOREGROUND_TIMEOUT_MSG); DelayedSingleton::GetInstance()->MoveToForeground(token); } else { TAG_LOGD(AAFwkTag::ABILITYMGR, "Inactivate"); abilityRecord->Inactivate(); } return ERR_OK; } void AbilityConnectManager::OnAbilityRequestDone(const sptr &token, const int32_t state) { TAG_LOGD(AAFwkTag::ABILITYMGR, "state: %{public}d", state); std::lock_guard guard(serialMutex_); AppAbilityState abilityState = DelayedSingleton::GetInstance()->ConvertToAppAbilityState(state); if (abilityState == AppAbilityState::ABILITY_STATE_FOREGROUND) { auto abilityRecord = GetExtensionByTokenFromServiceMap(token); CHECK_POINTER(abilityRecord); if (!IsUIExtensionAbility(abilityRecord)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Not ui extension."); return; } if (abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "abilityRecord is foregrounding."); return; } std::string element = abilityRecord->GetURI(); TAG_LOGD(AAFwkTag::ABILITYMGR, "Ability is %{public}s, start to foreground.", element.c_str()); abilityRecord->GrantUriPermissionForUIExtension(); abilityRecord->ForegroundUIExtensionAbility(); } } void AbilityConnectManager::OnAppStateChanged(const AppInfo &info) { auto serviceMap = GetServiceMap(); std::for_each(serviceMap.begin(), serviceMap.end(), [&info](ServiceMapType::reference service) { if (service.second && (info.processName == service.second->GetAbilityInfo().process || info.processName == service.second->GetApplicationInfo().bundleName)) { auto appName = service.second->GetApplicationInfo().name; auto uid = service.second->GetAbilityInfo().applicationInfo.uid; auto isExist = [&appName, &uid]( const AppData &appData) { return appData.appName == appName && appData.uid == uid; }; auto iter = std::find_if(info.appData.begin(), info.appData.end(), isExist); if (iter != info.appData.end()) { service.second->SetAppState(info.state); } } }); auto cacheAbilityList = AbilityCacheManager::GetInstance().GetAbilityList(); std::for_each(cacheAbilityList.begin(), cacheAbilityList.end(), [&info](std::shared_ptr &service) { if (service && (info.processName == service->GetAbilityInfo().process || info.processName == service->GetApplicationInfo().bundleName)) { auto appName = service->GetApplicationInfo().name; auto uid = service->GetAbilityInfo().applicationInfo.uid; auto isExist = [&appName, &uid](const AppData &appData) { return appData.appName == appName && appData.uid == uid; }; auto iter = std::find_if(info.appData.begin(), info.appData.end(), isExist); if (iter != info.appData.end()) { service->SetAppState(info.state); } } }); } int AbilityConnectManager::AbilityTransitionDone(const sptr &token, int state) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); int targetState = AbilityRecord::ConvertLifeCycleToAbilityState(static_cast(state)); std::string abilityState = AbilityRecord::ConvertAbilityState(static_cast(targetState)); std::shared_ptr abilityRecord; if (targetState == AbilityState::INACTIVE) { abilityRecord = GetExtensionByTokenFromServiceMap(token); } else if (targetState == AbilityState::FOREGROUND || targetState == AbilityState::BACKGROUND) { abilityRecord = GetExtensionByTokenFromServiceMap(token); if (abilityRecord == nullptr) { abilityRecord = GetExtensionByTokenFromTerminatingMap(token); } } else if (targetState == AbilityState::INITIAL) { abilityRecord = GetExtensionByTokenFromTerminatingMap(token); } CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s called, ability:%{public}s, state:%{public}s", __func__, element.c_str(), abilityState.c_str()); switch (targetState) { case AbilityState::INACTIVE: { if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) { DelayedSingleton::GetInstance()->UpdateAbilityState( token, AppExecFwk::AbilityState::ABILITY_STATE_CREATE); } else { DelayedSingleton::GetInstance()->UpdateExtensionState( token, AppExecFwk::ExtensionState::EXTENSION_STATE_CREATE); auto preloadTask = [owner = weak_from_this(), abilityRecord] { auto acm = owner.lock(); if (acm == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "AbilityConnectManager is nullptr."); return; } acm->ProcessPreload(abilityRecord); }; if (taskHandler_ != nullptr) { taskHandler_->SubmitTask(preloadTask); } } return DispatchInactive(abilityRecord, state); } case AbilityState::FOREGROUND: { abilityRecord->RemoveSignatureInfo(); return DispatchForeground(abilityRecord); } case AbilityState::BACKGROUND: { return DispatchBackground(abilityRecord); } case AbilityState::INITIAL: { if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) { DelayedSingleton::GetInstance()->UpdateAbilityState( token, AppExecFwk::AbilityState::ABILITY_STATE_TERMINATED); } else { DelayedSingleton::GetInstance()->UpdateExtensionState( token, AppExecFwk::ExtensionState::EXTENSION_STATE_TERMINATED); } return DispatchTerminate(abilityRecord); } default: { TAG_LOGW(AAFwkTag::ABILITYMGR, "Don't support transiting state: %{public}d", state); return ERR_INVALID_VALUE; } } } int AbilityConnectManager::AbilityWindowConfigTransactionDone(const sptr &token, const WindowConfig &windowConfig) { std::lock_guard guard(serialMutex_); auto abilityRecord = Token::GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); abilityRecord->SaveAbilityWindowConfig(windowConfig); return ERR_OK; } void AbilityConnectManager::ProcessPreload(const std::shared_ptr &record) const { auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper(); CHECK_POINTER(bundleMgrHelper); auto abilityInfo = record->GetAbilityInfo(); Want want; want.SetElementName(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name, abilityInfo.moduleName); auto uid = record->GetUid(); want.SetParam("uid", uid); bundleMgrHelper->ProcessPreload(want); } int AbilityConnectManager::ScheduleConnectAbilityDoneLocked( const sptr &token, const sptr &remoteObject) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); auto abilityRecord = Token::GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s called, Connect ability done, ability: %{public}s.", __func__, element.c_str()); if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) && (!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability record state is not inactive ,state: %{public}d", abilityRecord->GetAbilityState()); return INVALID_CONNECTION_STATE; } abilityRecord->RemoveConnectWant(); abilityRecord->RemoveSignatureInfo(); if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) { DelayedSingleton::GetInstance()->UpdateAbilityState( token, AppExecFwk::AbilityState::ABILITY_STATE_CONNECTED); } else { DelayedSingleton::GetInstance()->UpdateExtensionState( token, AppExecFwk::ExtensionState::EXTENSION_STATE_CONNECTED); } EventInfo eventInfo = BuildEventInfo(abilityRecord); eventInfo.userId = userId_; eventInfo.bundleName = abilityRecord->GetAbilityInfo().bundleName; eventInfo.moduleName = abilityRecord->GetAbilityInfo().moduleName; eventInfo.abilityName = abilityRecord->GetAbilityInfo().name; EventReport::SendConnectServiceEvent(EventName::CONNECT_SERVICE, eventInfo); abilityRecord->SetConnRemoteObject(remoteObject); // There may be multiple callers waiting for the connection result auto connectRecordList = abilityRecord->GetConnectRecordList(); for (auto &connectRecord : connectRecordList) { connectRecord->ScheduleConnectAbilityDone(); if (abilityRecord->GetAbilityInfo().type == AbilityType::EXTENSION && abilityRecord->GetAbilityInfo().extensionAbilityType != AppExecFwk::ExtensionAbilityType::SERVICE) { PostExtensionDelayDisconnectTask(connectRecord); } } CompleteStartServiceReq(abilityRecord->GetURI()); return ERR_OK; } void AbilityConnectManager::ProcessEliminateAbilityRecord(std::shared_ptr eliminateRecord) { CHECK_POINTER(eliminateRecord); std::string eliminateKey = eliminateRecord->GetURI(); if (FRS_BUNDLE_NAME == eliminateRecord->GetAbilityInfo().bundleName) { eliminateKey = eliminateKey + std::to_string(eliminateRecord->GetWant().GetIntParam(FRS_APP_INDEX, 0)); } AddToServiceMap(eliminateKey, eliminateRecord); TerminateRecord(eliminateRecord); } void AbilityConnectManager::TerminateOrCacheAbility(std::shared_ptr abilityRecord) { RemoveUIExtensionAbilityRecord(abilityRecord); if (abilityRecord->IsSceneBoard()) { return; } if (IsCacheExtensionAbilityType(abilityRecord)) { std::string serviceKey = abilityRecord->GetURI(); auto abilityInfo = abilityRecord->GetAbilityInfo(); TAG_LOGD(AAFwkTag::ABILITYMGR, "Cache the ability, service:%{public}s, extension type %{public}d", serviceKey.c_str(), abilityInfo.extensionAbilityType); if (FRS_BUNDLE_NAME == abilityInfo.bundleName) { AppExecFwk::ElementName elementName(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name, abilityInfo.moduleName); serviceKey = elementName.GetURI() + std::to_string(abilityRecord->GetWant().GetIntParam(FRS_APP_INDEX, 0)); } { std::lock_guard lock(serviceMapMutex_); serviceMap_.erase(serviceKey); } auto eliminateRecord = AbilityCacheManager::GetInstance().Put(abilityRecord); if (eliminateRecord != nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate the eliminated ability, service:%{public}s.", eliminateRecord->GetURI().c_str()); ProcessEliminateAbilityRecord(eliminateRecord); } return; } TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate the ability, service:%{public}s, extension type %{public}d", abilityRecord->GetURI().c_str(), abilityRecord->GetAbilityInfo().extensionAbilityType); TerminateRecord(abilityRecord); } int AbilityConnectManager::ScheduleDisconnectAbilityDoneLocked(const sptr &token) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); auto abilityRecord = GetExtensionByTokenFromServiceMap(token); CHECK_POINTER_AND_RETURN(abilityRecord, CONNECTION_NOT_EXIST); auto connect = abilityRecord->GetDisconnectingRecord(); CHECK_POINTER_AND_RETURN(connect, CONNECTION_NOT_EXIST); if (!abilityRecord->IsAbilityState(AbilityState::ACTIVE)) { if (IsUIExtensionAbility(abilityRecord) && (abilityRecord->IsForeground() || abilityRecord->IsAbilityState(AbilityState::BACKGROUND) || abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING))) { // uiextension ability support connect and start, so the ability state maybe others TAG_LOGI( AAFwkTag::ABILITYMGR, "Disconnect when ability state is %{public}d", abilityRecord->GetAbilityState()); } else { TAG_LOGE(AAFwkTag::ABILITYMGR, "The service ability state is not active ,state: %{public}d", abilityRecord->GetAbilityState()); return INVALID_CONNECTION_STATE; } } if (abilityRecord->GetAbilityInfo().type == AbilityType::SERVICE) { DelayedSingleton::GetInstance()->UpdateAbilityState( token, AppExecFwk::AbilityState::ABILITY_STATE_DISCONNECTED); } else { DelayedSingleton::GetInstance()->UpdateExtensionState( token, AppExecFwk::ExtensionState::EXTENSION_STATE_DISCONNECTED); } std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "ScheduleDisconnectAbilityDoneLocked called, service:%{public}s.", element.c_str()); // complete disconnect and remove record from conn map connect->ScheduleDisconnectAbilityDone(); abilityRecord->RemoveConnectRecordFromList(connect); if (abilityRecord->IsConnectListEmpty() && abilityRecord->GetStartId() == 0) { if (IsUIExtensionAbility(abilityRecord) && CheckUIExtensionAbilitySessionExist(abilityRecord)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist ui extension component, don't terminate when disconnect."); } else if (abilityRecord->GetAbilityInfo().extensionAbilityType == AppExecFwk::ExtensionAbilityType::UI_SERVICE) { TAG_LOGI(AAFwkTag::ABILITYMGR, "don't terminate uiservice"); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "Service ability has no any connection, and not started, need terminate or cache."); TerminateOrCacheAbility(abilityRecord); } } RemoveConnectionRecordFromMap(connect); return ERR_OK; } int AbilityConnectManager::ScheduleCommandAbilityDoneLocked(const sptr &token) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); auto abilityRecord = Token::GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s called, Ability: %{public}s", __func__, element.c_str()); if ((!abilityRecord->IsAbilityState(AbilityState::INACTIVE)) && (!abilityRecord->IsAbilityState(AbilityState::ACTIVE))) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability record state is not inactive ,state: %{public}d", abilityRecord->GetAbilityState()); return INVALID_CONNECTION_STATE; } EventInfo eventInfo = BuildEventInfo(abilityRecord); EventReport::SendStartServiceEvent(EventName::START_SERVICE, eventInfo); abilityRecord->RemoveSignatureInfo(); // complete command and pop waiting start ability from queue. CompleteCommandAbility(abilityRecord); return ERR_OK; } int AbilityConnectManager::ScheduleCommandAbilityWindowDone( const sptr &token, const sptr &sessionInfo, WindowCommand winCmd, AbilityCommand abilityCmd) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::lock_guard guard(serialMutex_); CHECK_POINTER_AND_RETURN(token, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(sessionInfo, ERR_INVALID_VALUE); auto abilityRecord = Token::GetAbilityRecordByToken(token); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); std::string element = abilityRecord->GetURI(); TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability: %{public}s, persistentId: %{private}d, winCmd: %{public}d, abilityCmd: %{public}d", element.c_str(), sessionInfo->persistentId, winCmd, abilityCmd); // Only foreground mode need cancel, cause only foreground CommandAbilityWindow post timeout task. if (taskHandler_ && winCmd == WIN_CMD_FOREGROUND) { int recordId = abilityRecord->GetRecordId(); std::string taskName = std::string("CommandWindowTimeout_") + std::to_string(recordId) + std::string("_") + std::to_string(sessionInfo->persistentId) + std::string("_") + std::to_string(winCmd); taskHandler_->CancelTask(taskName); } if (winCmd == WIN_CMD_DESTROY) { HandleCommandDestroy(sessionInfo); } abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, true); CompleteStartServiceReq(element); return ERR_OK; } void AbilityConnectManager::HandleCommandDestroy(const sptr &sessionInfo) { if (sessionInfo == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "null session info."); return; } if (sessionInfo->sessionToken) { RemoveUIExtWindowDeathRecipient(sessionInfo->sessionToken); size_t ret = 0; { std::lock_guard guard(uiExtensionMapMutex_); ret = uiExtensionMap_.erase(sessionInfo->sessionToken); } if (ret > 0) { return; } std::lock_guard guard(windowExtensionMapMutex_); for (auto& item : windowExtensionMap_) { auto sessionInfoVal = item.second.second; if (sessionInfoVal && sessionInfoVal->callerToken == sessionInfo->sessionToken) { windowExtensionMap_.erase(item.first); break; } } } } void AbilityConnectManager::CompleteCommandAbility(std::shared_ptr abilityRecord) { CHECK_POINTER(abilityRecord); if (taskHandler_) { int recordId = abilityRecord->GetRecordId(); std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") + std::to_string(abilityRecord->GetStartId()); taskHandler_->CancelTask(taskName); } abilityRecord->SetAbilityState(AbilityState::ACTIVE); // manage queued request CompleteStartServiceReq(abilityRecord->GetURI()); if (abilityRecord->NeedConnectAfterCommand()) { ConnectAbility(abilityRecord); } } void AbilityConnectManager::CompleteStartServiceReq(const std::string &serviceUri) { std::shared_ptr> reqList; { std::lock_guard guard(startServiceReqListLock_); auto it = startServiceReqList_.find(serviceUri); if (it != startServiceReqList_.end()) { reqList = it->second; startServiceReqList_.erase(it); if (taskHandler_) { taskHandler_->CancelTask(std::string("start_service_timeout:") + serviceUri); } } } if (reqList) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Target service is activating : %{public}zu, uri: %{public}s", reqList->size(), serviceUri.c_str()); for (const auto &req: *reqList) { StartAbilityLocked(req); } } } std::shared_ptr AbilityConnectManager::GetServiceRecordByElementName(const std::string &element) { std::lock_guard guard(serviceMapMutex_); auto mapIter = serviceMap_.find(element); if (mapIter != serviceMap_.end()) { return mapIter->second; } return nullptr; } std::shared_ptr AbilityConnectManager::GetExtensionByTokenFromServiceMap( const sptr &token) { auto IsMatch = [token](auto service) { if (!service.second) { return false; } sptr srcToken = service.second->GetToken(); return srcToken == token; }; std::lock_guard lock(serviceMapMutex_); auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch); if (serviceRecord != serviceMap_.end()) { return serviceRecord->second; } return nullptr; } std::shared_ptr AbilityConnectManager::GetExtensionByTokenFromAbilityCache( const sptr &token) { return AbilityCacheManager::GetInstance().FindRecordByToken(token); } std::shared_ptr AbilityConnectManager::GetExtensionByIdFromServiceMap( const int64_t &abilityRecordId) { auto IsMatch = [abilityRecordId](auto &service) { if (!service.second) { return false; } return service.second->GetAbilityRecordId() == abilityRecordId; }; std::lock_guard lock(serviceMapMutex_); auto serviceRecord = std::find_if(serviceMap_.begin(), serviceMap_.end(), IsMatch); if (serviceRecord != serviceMap_.end()) { return serviceRecord->second; } return nullptr; } std::shared_ptr AbilityConnectManager::GetExtensionByIdFromTerminatingMap( const int64_t &abilityRecordId) { auto IsMatch = [abilityRecordId](auto &extensionRecord) { if (extensionRecord == nullptr) { return false; } return extensionRecord->GetAbilityRecordId() == abilityRecordId; }; std::lock_guard lock(serviceMapMutex_); auto extensionRecord = std::find_if(terminatingExtensionList_.begin(), terminatingExtensionList_.end(), IsMatch); if (extensionRecord != terminatingExtensionList_.end()) { return *extensionRecord; } return nullptr; } std::shared_ptr AbilityConnectManager::GetUIExtensioBySessionInfo( const sptr &sessionInfo) { CHECK_POINTER_AND_RETURN(sessionInfo, nullptr); auto sessionToken = iface_cast(sessionInfo->sessionToken); CHECK_POINTER_AND_RETURN(sessionToken, nullptr); std::string descriptor = Str16ToStr8(sessionToken->GetDescriptor()); if (descriptor != "OHOS.ISession") { TAG_LOGE(AAFwkTag::ABILITYMGR, "Input token is not a sessionToken, token->GetDescriptor(): %{public}s", descriptor.c_str()); return nullptr; } std::lock_guard guard(uiExtensionMapMutex_); auto it = uiExtensionMap_.find(sessionToken->AsObject()); if (it != uiExtensionMap_.end()) { auto abilityRecord = it->second.first.lock(); if (abilityRecord == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr."); RemoveUIExtWindowDeathRecipient(sessionToken->AsObject()); uiExtensionMap_.erase(it); return nullptr; } auto savedSessionInfo = it->second.second; if (!savedSessionInfo || savedSessionInfo->sessionToken != sessionInfo->sessionToken || savedSessionInfo->callerToken != sessionInfo->callerToken) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Inconsistent sessionInfo."); return nullptr; } return abilityRecord; } else { TAG_LOGE(AAFwkTag::ABILITYMGR, "UIExtension not found."); } return nullptr; } std::shared_ptr AbilityConnectManager::GetExtensionByTokenFromTerminatingMap( const sptr &token) { auto IsMatch = [token](auto& extensionRecord) { if (extensionRecord == nullptr) { return false; } auto terminatingToken = extensionRecord->GetToken(); if (terminatingToken != nullptr) { return terminatingToken->AsObject() == token; } return false; }; std::lock_guard lock(serviceMapMutex_); auto terminatingExtensionRecord = std::find_if(terminatingExtensionList_.begin(), terminatingExtensionList_.end(), IsMatch); if (terminatingExtensionRecord != terminatingExtensionList_.end()) { return *terminatingExtensionRecord; } return nullptr; } std::list> AbilityConnectManager::GetConnectRecordListByCallback( sptr callback) { std::lock_guard guard(connectMapMutex_); std::list> connectList; auto connectMapIter = connectMap_.find(callback->AsObject()); if (connectMapIter != connectMap_.end()) { connectList = connectMapIter->second; } return connectList; } void AbilityConnectManager::LoadAbility(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); abilityRecord->SetStartTime(); if (!abilityRecord->CanRestartRootLauncher()) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Root launcher restart is out of max count."); RemoveServiceAbility(abilityRecord); return; } bool isDebug = abilityRecord->GetWant().GetBoolParam(DEBUG_APP, false); if (!isDebug) { TAG_LOGD(AAFwkTag::ABILITYMGR, "IsDebug is false, here is not debug app"); PostTimeOutTask(abilityRecord, AbilityManagerService::LOAD_TIMEOUT_MSG); } sptr token = abilityRecord->GetToken(); sptr perToken = nullptr; if (abilityRecord->IsCreateByConnect()) { perToken = iface_cast(abilityRecord->GetConnectingRecord()->GetToken()); } else { auto callerList = abilityRecord->GetCallerRecordList(); if (!callerList.empty() && callerList.back()) { auto caller = callerList.back()->GetCaller(); if (caller) { perToken = caller->GetToken(); } } } UpdateUIExtensionInfo(abilityRecord); AbilityRuntime::LoadParam loadParam; loadParam.abilityRecordId = abilityRecord->GetRecordId(); loadParam.isShellCall = AAFwk::PermissionVerification::GetInstance()->IsShellCall(); loadParam.token = token; loadParam.preToken = perToken; DelayedSingleton::GetInstance()->LoadAbility( loadParam, abilityRecord->GetAbilityInfo(), abilityRecord->GetApplicationInfo(), abilityRecord->GetWant()); } void AbilityConnectManager::PostRestartResidentTask(const AbilityRequest &abilityRequest) { TAG_LOGI(AAFwkTag::ABILITYMGR, "PostRestartResidentTask start."); CHECK_POINTER(taskHandler_); std::string taskName = std::string("RestartResident_") + std::string(abilityRequest.abilityInfo.name); auto task = [abilityRequest, connectManager = shared_from_this()]() { CHECK_POINTER(connectManager); connectManager->HandleRestartResidentTask(abilityRequest); }; int restartIntervalTime = 0; auto abilityMgr = DelayedSingleton::GetInstance(); if (abilityMgr) { restartIntervalTime = AmsConfigurationParameter::GetInstance().GetRestartIntervalTime(); } TAG_LOGD(AAFwkTag::ABILITYMGR, "PostRestartResidentTask, time:%{public}d", restartIntervalTime); taskHandler_->SubmitTask(task, taskName, restartIntervalTime); TAG_LOGI(AAFwkTag::ABILITYMGR, "PostRestartResidentTask end."); } void AbilityConnectManager::HandleRestartResidentTask(const AbilityRequest &abilityRequest) { TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleRestartResidentTask start."); std::lock_guard guard(serialMutex_); auto findRestartResidentTask = [abilityRequest](const AbilityRequest &requestInfo) { return (requestInfo.want.GetElement().GetBundleName() == abilityRequest.want.GetElement().GetBundleName() && requestInfo.want.GetElement().GetModuleName() == abilityRequest.want.GetElement().GetModuleName() && requestInfo.want.GetElement().GetAbilityName() == abilityRequest.want.GetElement().GetAbilityName()); }; auto findIter = find_if(restartResidentTaskList_.begin(), restartResidentTaskList_.end(), findRestartResidentTask); if (findIter != restartResidentTaskList_.end()) { restartResidentTaskList_.erase(findIter); } StartAbilityLocked(abilityRequest); } void AbilityConnectManager::PostTimeOutTask(const std::shared_ptr &abilityRecord, uint32_t messageId) { int connectRecordId = 0; if (messageId == AbilityConnectManager::CONNECT_TIMEOUT_MSG) { auto connectRecord = abilityRecord->GetConnectingRecord(); CHECK_POINTER(connectRecord); connectRecordId = connectRecord->GetRecordId(); } PostTimeOutTask(abilityRecord, connectRecordId, messageId); } void AbilityConnectManager::PostTimeOutTask(const std::shared_ptr &abilityRecord, int connectRecordId, uint32_t messageId) { CHECK_POINTER(abilityRecord); CHECK_POINTER(taskHandler_); std::string taskName; int32_t delayTime = 0; if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) { if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { return abilityRecord->PostUIExtensionAbilityTimeoutTask(messageId); } // first load ability, There is at most one connect record. int recordId = abilityRecord->GetRecordId(); taskName = std::string("LoadTimeout_") + std::to_string(recordId); delayTime = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * LOAD_TIMEOUT_MULTIPLE; } else if (messageId == AbilityConnectManager::CONNECT_TIMEOUT_MSG) { taskName = std::string("ConnectTimeout_") + std::to_string(connectRecordId); delayTime = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * CONNECT_TIMEOUT_MULTIPLE; } else { TAG_LOGE(AAFwkTag::ABILITYMGR, "Timeout task messageId is error."); return; } // check libc.hook_mode const int bufferLen = 128; char paramOutBuf[bufferLen] = {0}; const char *hook_mode = "startup:"; int ret = GetParameter("libc.hook_mode", "", paramOutBuf, bufferLen - 1); if (ret > 0 && strncmp(paramOutBuf, hook_mode, strlen(hook_mode)) == 0) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Hook_mode: no timeoutTask"); return; } auto timeoutTask = [abilityRecord, connectManager = shared_from_this(), messageId]() { if (messageId == AbilityManagerService::LOAD_TIMEOUT_MSG) { connectManager->HandleStartTimeoutTask(abilityRecord); } else if (messageId == AbilityConnectManager::CONNECT_TIMEOUT_MSG) { connectManager->HandleConnectTimeoutTask(abilityRecord); } }; taskHandler_->SubmitTask(timeoutTask, taskName, delayTime); } void AbilityConnectManager::HandleStartTimeoutTask(const std::shared_ptr &abilityRecord) { TAG_LOGW(AAFwkTag::ABILITYMGR, "load ability timeout."); std::lock_guard guard(serialMutex_); CHECK_POINTER(abilityRecord); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "consume session timeout, Uri: %{public}s", abilityRecord->GetURI().c_str()); if (uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Start load timeout."); uiExtensionAbilityRecordMgr_->LoadTimeout(abilityRecord->GetUIExtensionAbilityId()); } } auto connectingList = abilityRecord->GetConnectingRecordList(); for (auto &connectRecord : connectingList) { if (connectRecord == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "ConnectRecord is nullptr."); continue; } connectRecord->CompleteDisconnect(ERR_OK, false, true); abilityRecord->RemoveConnectRecordFromList(connectRecord); RemoveConnectionRecordFromMap(connectRecord); } if (GetExtensionByTokenFromServiceMap(abilityRecord->GetToken()) == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Timeout ability record is not exist in service map."); return; } MoveToTerminatingMap(abilityRecord); TAG_LOGW(AAFwkTag::ABILITYMGR, "Load time out , remove target service record from services map."); RemoveServiceAbility(abilityRecord); if (abilityRecord->IsSceneBoard()) { auto isAttached = IN_PROCESS_CALL(DelayedSingleton::GetInstance()->IsProcessAttached( abilityRecord->GetToken())); DelayedSingleton::GetInstance()->AttachTimeOut(abilityRecord->GetToken()); if (!isAttached) { RestartAbility(abilityRecord, userId_); } return; } DelayedSingleton::GetInstance()->AttachTimeOut(abilityRecord->GetToken()); if (IsAbilityNeedKeepAlive(abilityRecord)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Load time out, try to restart"); RestartAbility(abilityRecord, userId_); } } void AbilityConnectManager::HandleCommandTimeoutTask(const std::shared_ptr &abilityRecord) { CHECK_POINTER(abilityRecord); if (AppUtils::GetInstance().IsLauncherAbility(abilityRecord->GetAbilityInfo().name)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Handle root launcher command timeout."); // terminate the timeout root launcher. DelayedSingleton::GetInstance()->AttachTimeOut(abilityRecord->GetToken()); } TAG_LOGD(AAFwkTag::ABILITYMGR, "HandleCommandTimeoutTask end"); } void AbilityConnectManager::HandleConnectTimeoutTask(std::shared_ptr abilityRecord) { TAG_LOGW(AAFwkTag::ABILITYMGR, "connect ability timeout."); CHECK_POINTER(abilityRecord); auto connectList = abilityRecord->GetConnectRecordList(); std::lock_guard guard(serialMutex_); for (const auto &connectRecord : connectList) { RemoveExtensionDelayDisconnectTask(connectRecord); connectRecord->CancelConnectTimeoutTask(); connectRecord->CompleteDisconnect(ERR_OK, false, true); abilityRecord->RemoveConnectRecordFromList(connectRecord); RemoveConnectionRecordFromMap(connectRecord); } if (IsSpecialAbility(abilityRecord->GetAbilityInfo()) || abilityRecord->GetStartId() != 0) { TAG_LOGI(AAFwkTag::ABILITYMGR, "no need to terminate."); return; } TerminateRecord(abilityRecord); } void AbilityConnectManager::HandleCommandWindowTimeoutTask(const std::shared_ptr &abilityRecord, const sptr &sessionInfo, WindowCommand winCmd) { TAG_LOGD(AAFwkTag::ABILITYMGR, "start"); std::lock_guard guard(serialMutex_); CHECK_POINTER(abilityRecord); abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, true); // manage queued request CompleteStartServiceReq(abilityRecord->GetURI()); TAG_LOGD(AAFwkTag::ABILITYMGR, "end"); } void AbilityConnectManager::HandleStopTimeoutTask(const std::shared_ptr &abilityRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Complete stop ability timeout start."); std::lock_guard guard(serialMutex_); CHECK_POINTER(abilityRecord); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { if (uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Start terminate timeout"); uiExtensionAbilityRecordMgr_->TerminateTimeout(abilityRecord->GetUIExtensionAbilityId()); } PrintTimeOutLog(abilityRecord, AbilityManagerService::TERMINATE_TIMEOUT_MSG); } TerminateDone(abilityRecord); } void AbilityConnectManager::HandleTerminateDisconnectTask(const ConnectListType& connectlist) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Disconnect ability when terminate."); for (auto& connectRecord : connectlist) { if (!connectRecord) { continue; } auto targetService = connectRecord->GetAbilityRecord(); if (targetService) { TAG_LOGW(AAFwkTag::ABILITYMGR, "This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId()); connectRecord->CompleteDisconnect(ERR_OK, false, true); targetService->RemoveConnectRecordFromList(connectRecord); RemoveConnectionRecordFromMap(connectRecord); }; } } int AbilityConnectManager::DispatchInactive(const std::shared_ptr &abilityRecord, int state) { TAG_LOGD(AAFwkTag::ABILITYMGR, "DispatchInactive call"); CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(eventHandler_, ERR_INVALID_VALUE); if (!abilityRecord->IsAbilityState(AbilityState::INACTIVATING)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability transition life state error. expect %{public}d, actual %{public}d callback %{public}d", AbilityState::INACTIVATING, abilityRecord->GetAbilityState(), state); return ERR_INVALID_VALUE; } eventHandler_->RemoveEvent(AbilityManagerService::INACTIVE_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId()); if (abilityRecord->GetAbilityInfo().extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE) { ResSchedUtil::GetInstance().ReportLoadingEventToRss(LoadingStage::LOAD_END, abilityRecord->GetPid(), abilityRecord->GetUid(), 0, abilityRecord->GetAbilityRecordId()); } // complete inactive abilityRecord->SetAbilityState(AbilityState::INACTIVE); if (abilityRecord->IsCreateByConnect()) { ConnectAbility(abilityRecord); } else if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "IS_PRELOAD_UIEXTENSION_ABILITY"); auto ret = uiExtensionAbilityRecordMgr_->AddPreloadUIExtensionRecord(abilityRecord); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Add preload UI Extension record error!"); return ret; } return ERR_OK; } else { CommandAbility(abilityRecord); if (abilityRecord->GetConnectRecordList().size() > 0) { // It means someone called connectAbility when service was loading abilityRecord->UpdateConnectWant(); ConnectAbility(abilityRecord); } } return ERR_OK; } int AbilityConnectManager::DispatchForeground(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(taskHandler_, ERR_INVALID_VALUE); // remove foreground timeout task. if (eventHandler_) { eventHandler_->RemoveEvent(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId()); } auto self(shared_from_this()); auto task = [self, abilityRecord]() { self->CompleteForeground(abilityRecord); }; taskHandler_->SubmitTask(task, TaskQoS::USER_INTERACTIVE); return ERR_OK; } int AbilityConnectManager::DispatchBackground(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(taskHandler_, ERR_INVALID_VALUE); // remove background timeout task. taskHandler_->CancelTask("background_" + std::to_string(abilityRecord->GetAbilityRecordId())); auto self(shared_from_this()); auto task = [self, abilityRecord]() { self->CompleteBackground(abilityRecord); }; taskHandler_->SubmitTask(task, TaskQoS::USER_INTERACTIVE); return ERR_OK; } int AbilityConnectManager::DispatchTerminate(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, ERR_INVALID_VALUE); // remove terminate timeout task if (taskHandler_ != nullptr) { taskHandler_->CancelTask("terminate_" + std::to_string(abilityRecord->GetAbilityRecordId())); } ResSchedUtil::GetInstance().ReportLoadingEventToRss(LoadingStage::DESTROY_END, abilityRecord->GetPid(), abilityRecord->GetUid(), 0, abilityRecord->GetRecordId()); // complete terminate TerminateDone(abilityRecord); return ERR_OK; } void AbilityConnectManager::ConnectAbility(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); AppExecFwk::ExtensionAbilityType extType = abilityRecord->GetAbilityInfo().extensionAbilityType; if (extType == AppExecFwk::ExtensionAbilityType::UI_SERVICE) { ResumeConnectAbility(abilityRecord); } else { PostTimeOutTask(abilityRecord, AbilityConnectManager::CONNECT_TIMEOUT_MSG); abilityRecord->ConnectAbility(); } } void AbilityConnectManager::ConnectUIServiceExtAbility(const std::shared_ptr &abilityRecord, int connectRecordId, const Want &want) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); PostTimeOutTask(abilityRecord, connectRecordId, AbilityConnectManager::CONNECT_TIMEOUT_MSG); abilityRecord->ConnectAbilityWithWant(want); } void AbilityConnectManager::ResumeConnectAbility(const std::shared_ptr &abilityRecord) { TAG_LOGI(AAFwkTag::ABILITYMGR, "ResumeConnectAbility"); HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); std::list> connectingList = abilityRecord->GetConnectingRecordList(); for (auto &connectRecord : connectingList) { if (connectRecord == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "ConnectRecord is nullptr."); continue; } int connectRecordId = connectRecord->GetRecordId(); PostTimeOutTask(abilityRecord, connectRecordId, AbilityConnectManager::CONNECT_TIMEOUT_MSG); abilityRecord->ConnectAbilityWithWant(connectRecord->GetConnectWant()); } } void AbilityConnectManager::CommandAbility(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (taskHandler_ != nullptr) { // first connect ability, There is at most one connect record. int recordId = abilityRecord->GetRecordId(); abilityRecord->AddStartId(); std::string taskName = std::string("CommandTimeout_") + std::to_string(recordId) + std::string("_") + std::to_string(abilityRecord->GetStartId()); auto timeoutTask = [abilityRecord, connectManager = shared_from_this()]() { TAG_LOGE(AAFwkTag::ABILITYMGR, "Command ability timeout. %{public}s", abilityRecord->GetAbilityInfo().name.c_str()); connectManager->HandleCommandTimeoutTask(abilityRecord); }; int commandTimeout = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * COMMAND_TIMEOUT_MULTIPLE; taskHandler_->SubmitTask(timeoutTask, taskName, commandTimeout); // scheduling command ability abilityRecord->CommandAbility(); } } void AbilityConnectManager::CommandAbilityWindow(const std::shared_ptr &abilityRecord, const sptr &sessionInfo, WindowCommand winCmd) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); CHECK_POINTER(sessionInfo); TAG_LOGD(AAFwkTag::ABILITYMGR, "ability: %{public}s, persistentId: %{private}d, wincmd: %{public}d", abilityRecord->GetURI().c_str(), sessionInfo->persistentId, winCmd); abilityRecord->SetAbilityWindowState(sessionInfo, winCmd, false); if (taskHandler_ != nullptr) { int recordId = abilityRecord->GetRecordId(); std::string taskName = std::string("CommandWindowTimeout_") + std::to_string(recordId) + std::string("_") + std::to_string(sessionInfo->persistentId) + std::string("_") + std::to_string(winCmd); auto timeoutTask = [abilityRecord, sessionInfo, winCmd, connectManager = shared_from_this()]() { TAG_LOGE(AAFwkTag::ABILITYMGR, "Command window timeout. %{public}s", abilityRecord->GetAbilityInfo().name.c_str()); connectManager->HandleCommandWindowTimeoutTask(abilityRecord, sessionInfo, winCmd); }; int commandWindowTimeout = AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * COMMAND_WINDOW_TIMEOUT_MULTIPLE; taskHandler_->SubmitTask(timeoutTask, taskName, commandWindowTimeout); // scheduling command ability abilityRecord->CommandAbilityWindow(sessionInfo, winCmd); } } void AbilityConnectManager::BackgroundAbilityWindowLocked(const std::shared_ptr &abilityRecord, const sptr &sessionInfo) { std::lock_guard guard(serialMutex_); DoBackgroundAbilityWindow(abilityRecord, sessionInfo); } void AbilityConnectManager::DoBackgroundAbilityWindow(const std::shared_ptr &abilityRecord, const sptr &sessionInfo) { CHECK_POINTER(abilityRecord); CHECK_POINTER(sessionInfo); auto abilitystateStr = abilityRecord->ConvertAbilityState(abilityRecord->GetAbilityState()); TAG_LOGI(AAFwkTag::ABILITYMGR, "Background ability: %{public}s, persistentId: %{public}d, abilityState: %{public}s", abilityRecord->GetURI().c_str(), sessionInfo->persistentId, abilitystateStr.c_str()); if (abilityRecord->IsAbilityState(AbilityState::FOREGROUND)) { MoveToBackground(abilityRecord); } else if (abilityRecord->IsAbilityState(AbilityState::INITIAL) || abilityRecord->IsAbilityState(AbilityState::FOREGROUNDING)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "There exist initial or foregrounding task."); abilityRecord->DoBackgroundAbilityWindowDelayed(true); } else if (!abilityRecord->IsAbilityState(AbilityState::BACKGROUNDING)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid ability state when background."); } } void AbilityConnectManager::TerminateAbilityWindowLocked(const std::shared_ptr &abilityRecord, const sptr &sessionInfo) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); CHECK_POINTER(sessionInfo); auto abilitystateStr = abilityRecord->ConvertAbilityState(abilityRecord->GetAbilityState()); TAG_LOGI(AAFwkTag::ABILITYMGR, "Terminate ability: %{public}s, persistentId: %{public}d, abilityState: %{public}s", abilityRecord->GetURI().c_str(), sessionInfo->persistentId, abilitystateStr.c_str()); EventInfo eventInfo; eventInfo.bundleName = abilityRecord->GetAbilityInfo().bundleName; eventInfo.abilityName = abilityRecord->GetAbilityInfo().name; EventReport::SendAbilityEvent(EventName::TERMINATE_ABILITY, HiSysEventType::BEHAVIOR, eventInfo); std::lock_guard guard(serialMutex_); eventInfo.errCode = TerminateAbilityInner(abilityRecord->GetToken()); if (eventInfo.errCode != ERR_OK) { EventReport::SendAbilityEvent(EventName::TERMINATE_ABILITY_ERROR, HiSysEventType::FAULT, eventInfo); } } void AbilityConnectManager::TerminateDone(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(abilityRecord); if (!abilityRecord->IsAbilityState(AbilityState::TERMINATING)) { std::string expect = AbilityRecord::ConvertAbilityState(AbilityState::TERMINATING); std::string actual = AbilityRecord::ConvertAbilityState(abilityRecord->GetAbilityState()); TAG_LOGE(AAFwkTag::ABILITYMGR, "Transition life state error. expect %{public}s, actual %{public}s", expect.c_str(), actual.c_str()); return; } IN_PROCESS_CALL_WITHOUT_RET(abilityRecord->RevokeUriPermission()); abilityRecord->RemoveAbilityDeathRecipient(); if (abilityRecord->IsSceneBoard()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "To kill processes because scb exit."); KillProcessesByUserId(); } DelayedSingleton::GetInstance()->TerminateAbility(abilityRecord->GetToken(), false); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { RemoveUIExtensionAbilityRecord(abilityRecord); } RemoveServiceAbility(abilityRecord); } bool AbilityConnectManager::IsAbilityConnected(const std::shared_ptr &abilityRecord, const std::list> &connectRecordList) { auto isMatch = [abilityRecord](auto connectRecord) -> bool { if (abilityRecord == nullptr || connectRecord == nullptr) { return false; } if (abilityRecord != connectRecord->GetAbilityRecord()) { return false; } return true; }; return std::any_of(connectRecordList.begin(), connectRecordList.end(), isMatch); } void AbilityConnectManager::RemoveConnectionRecordFromMap(std::shared_ptr connection) { std::lock_guard lock(connectMapMutex_); for (auto &connectCallback : connectMap_) { auto &connectList = connectCallback.second; auto connectRecord = std::find(connectList.begin(), connectList.end(), connection); if (connectRecord != connectList.end()) { TAG_LOGD(AAFwkTag::ABILITYMGR, "connrecord(%{public}d)", (*connectRecord)->GetRecordId()); connectList.remove(connection); if (connectList.empty()) { RemoveConnectDeathRecipient(connectCallback.first); connectMap_.erase(connectCallback.first); } return; } } } void AbilityConnectManager::RemoveServiceAbility(const std::shared_ptr &abilityRecord) { CHECK_POINTER(abilityRecord); TAG_LOGD(AAFwkTag::ABILITYMGR, "Remove service(%{public}s) from terminating map.", abilityRecord->GetURI().c_str()); std::lock_guard lock(serviceMapMutex_); terminatingExtensionList_.remove(abilityRecord); } void AbilityConnectManager::AddConnectDeathRecipient(sptr connectObject) { CHECK_POINTER(connectObject); { std::lock_guard guard(recipientMapMutex_); auto it = recipientMap_.find(connectObject); if (it != recipientMap_.end()) { TAG_LOGE(AAFwkTag::ABILITYMGR, "This death recipient has been added."); return; } } std::weak_ptr thisWeakPtr(shared_from_this()); sptr deathRecipient = new AbilityConnectCallbackRecipient([thisWeakPtr](const wptr &remote) { auto abilityConnectManager = thisWeakPtr.lock(); if (abilityConnectManager) { abilityConnectManager->OnCallBackDied(remote); } }); if (!connectObject->AddDeathRecipient(deathRecipient)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "AddDeathRecipient failed."); } std::lock_guard guard(recipientMapMutex_); recipientMap_.emplace(connectObject, deathRecipient); } void AbilityConnectManager::RemoveConnectDeathRecipient(sptr connectObject) { CHECK_POINTER(connectObject); sptr deathRecipient; { std::lock_guard guard(recipientMapMutex_); auto it = recipientMap_.find(connectObject); if (it == recipientMap_.end()) { return; } deathRecipient = it->second; recipientMap_.erase(it); } connectObject->RemoveDeathRecipient(deathRecipient); } void AbilityConnectManager::OnCallBackDied(const wptr &remote) { auto object = remote.promote(); CHECK_POINTER(object); if (taskHandler_) { auto task = [object, connectManager = shared_from_this()]() { connectManager->HandleCallBackDiedTask(object); }; taskHandler_->SubmitTask(task, TASK_ON_CALLBACK_DIED); } } void AbilityConnectManager::HandleCallBackDiedTask(const sptr &connect) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); CHECK_POINTER(connect); { std::lock_guard guard(windowExtensionMapMutex_); auto item = windowExtensionMap_.find(connect); if (item != windowExtensionMap_.end()) { windowExtensionMap_.erase(item); } } { std::lock_guard guard(connectMapMutex_); auto it = connectMap_.find(connect); if (it != connectMap_.end()) { ConnectListType connectRecordList = it->second; for (auto &connRecord : connectRecordList) { connRecord->ClearConnCallBack(); } } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "Died object can't find from conn map."); return; } } sptr object = iface_cast(connect); std::lock_guard guard(serialMutex_); DisconnectAbilityLocked(object, true); } int32_t AbilityConnectManager::GetActiveUIExtensionList( const int32_t pid, std::vector &extensionList) { CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionList(pid, extensionList); } int32_t AbilityConnectManager::GetActiveUIExtensionList( const std::string &bundleName, std::vector &extensionList) { CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); return uiExtensionAbilityRecordMgr_->GetActiveUIExtensionList(bundleName, extensionList); } void AbilityConnectManager::OnAbilityDied(const std::shared_ptr &abilityRecord, int32_t currentUserId) { CHECK_POINTER(abilityRecord); TAG_LOGI(AAFwkTag::ABILITYMGR, "On ability died: %{public}s.", abilityRecord->GetURI().c_str()); if (abilityRecord->GetAbilityInfo().type != AbilityType::SERVICE && abilityRecord->GetAbilityInfo().type != AbilityType::EXTENSION) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Ability type is not service."); return; } if (eventHandler_ && abilityRecord->GetAbilityState() == AbilityState::INITIAL) { eventHandler_->RemoveEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId()); } if (eventHandler_ && abilityRecord->GetAbilityState() == AbilityState::FOREGROUNDING) { eventHandler_->RemoveEvent(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecord->GetAbilityRecordId()); } if (taskHandler_ && abilityRecord->GetAbilityState() == AbilityState::BACKGROUNDING) { taskHandler_->CancelTask("background_" + std::to_string(abilityRecord->GetAbilityRecordId())); } if (taskHandler_ && abilityRecord->GetAbilityState() == AbilityState::TERMINATING) { taskHandler_->CancelTask("terminate_" + std::to_string(abilityRecord->GetAbilityRecordId())); } if (taskHandler_) { auto task = [abilityRecord, connectManager = shared_from_this(), currentUserId]() { connectManager->HandleAbilityDiedTask(abilityRecord, currentUserId); }; taskHandler_->SubmitTask(task, TASK_ON_ABILITY_DIED); } } void AbilityConnectManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId, bool isHalf) { auto abilityRecord = GetExtensionByIdFromServiceMap(abilityRecordId); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "ability record nullptr"); return; } PrintTimeOutLog(abilityRecord, msgId, isHalf); if (isHalf) { return; } switch (msgId) { case AbilityManagerService::LOAD_TIMEOUT_MSG: HandleStartTimeoutTask(abilityRecord); break; case AbilityManagerService::INACTIVE_TIMEOUT_MSG: HandleInactiveTimeout(abilityRecord); break; case AbilityManagerService::FOREGROUND_TIMEOUT_MSG: HandleForegroundTimeoutTask(abilityRecord); break; default: break; } } void AbilityConnectManager::HandleInactiveTimeout(const std::shared_ptr &ability) { TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleInactiveTimeout start"); CHECK_POINTER(ability); if (AppUtils::GetInstance().IsLauncherAbility(ability->GetAbilityInfo().name)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Handle root launcher inactive timeout."); // terminate the timeout root launcher. DelayedSingleton::GetInstance()->AttachTimeOut(ability->GetToken()); } if (ability->GetAbilityInfo().name == AbilityConfig::CALLUI_ABILITY_NAME && ability->GetStartId() == 0) { HandleConnectTimeoutTask(ability); EventInfo eventInfo; eventInfo.userId = userId_; eventInfo.bundleName = ability->GetAbilityInfo().bundleName; eventInfo.moduleName = ability->GetAbilityInfo().moduleName; eventInfo.abilityName = ability->GetAbilityInfo().name; eventInfo.abilityName = ability->GetAbilityInfo().name; eventInfo.errCode = CONNECTION_TIMEOUT; EventReport::SendExtensionEvent(EventName::CONNECT_SERVICE_ERROR, HiSysEventType::FAULT, eventInfo); } TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleInactiveTimeout end"); } bool AbilityConnectManager::IsAbilityNeedKeepAlive(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER_AND_RETURN(abilityRecord, false); const auto &abilityInfo = abilityRecord->GetAbilityInfo(); if (IsSpecialAbility(abilityInfo)) { return true; } return abilityRecord->IsKeepAliveBundle(); } void AbilityConnectManager::ClearPreloadUIExtensionRecord(const std::shared_ptr &abilityRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); CHECK_POINTER(abilityRecord); auto extensionRecordId = abilityRecord->GetUIExtensionAbilityId(); std::string hostBundleName; auto ret = uiExtensionAbilityRecordMgr_->GetHostBundleNameForExtensionId(extensionRecordId, hostBundleName); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "cannot get hostbundlename for this extension id."); return; } auto extensionRecordMapKey = std::make_tuple(abilityRecord->GetWant().GetElement().GetAbilityName(), abilityRecord->GetWant().GetElement().GetBundleName(), abilityRecord->GetWant().GetElement().GetModuleName(), hostBundleName); uiExtensionAbilityRecordMgr_->RemovePreloadUIExtensionRecordById(extensionRecordMapKey, extensionRecordId); } void AbilityConnectManager::KeepAbilityAlive(const std::shared_ptr &abilityRecord, int32_t currentUserId) { CHECK_POINTER(abilityRecord); auto abilityInfo = abilityRecord->GetAbilityInfo(); TAG_LOGI(AAFwkTag::ABILITYMGR, "restart ability, bundleName: %{public}s, abilityName: %{public}s", abilityInfo.bundleName.c_str(), abilityInfo.name.c_str()); auto token = abilityRecord->GetToken(); if ((IsLauncher(abilityRecord) || abilityRecord->IsSceneBoard()) && token != nullptr) { IN_PROCESS_CALL_WITHOUT_RET(DelayedSingleton::GetInstance()->ClearProcessByToken( token->AsObject())); if (abilityRecord->IsSceneBoard() && currentUserId != userId_) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Not the current user's SCB, clear the user and do not restart"); KillProcessesByUserId(); return; } } if (userId_ != USER_ID_NO_HEAD && userId_ != currentUserId) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Not current user's ability"); return; } if (abilityRecord->IsSceneBoard() && AmsConfigurationParameter::GetInstance().IsSupportSCBCrashReboot()) { static int sceneBoardCrashCount = 0; static int64_t tickCount = GetTickCount(); int64_t tickNow = GetTickCount(); const int64_t maxTime = 240000; // 240000 4min const int maxCount = 4; // 4: crash happened 4 times during 4 mins if (tickNow - tickCount > maxTime) { sceneBoardCrashCount = 0; tickCount = tickNow; } ++sceneBoardCrashCount; if (sceneBoardCrashCount >= maxCount) { std::string reason = "SceneBoard exits " + std::to_string(sceneBoardCrashCount) + "times in " + std::to_string(maxTime) + "ms"; DoRebootExt("panic", reason.c_str()); } } if (DelayedSingleton::GetInstance()->IsKilledForUpgradeWeb(abilityInfo.bundleName)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "bundle is killed for upgrade web"); return; } if (DelayedSingleton::GetInstance()->IsMemorySizeSufficent() || IsLauncher(abilityRecord) || abilityRecord->IsSceneBoard() || AppUtils::GetInstance().IsAllowResidentInExtremeMemory(abilityInfo.bundleName, abilityInfo.name)) { RestartAbility(abilityRecord, currentUserId); } } void AbilityConnectManager::HandleAbilityDiedTask( const std::shared_ptr &abilityRecord, int32_t currentUserId) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); std::lock_guard guard(serialMutex_); CHECK_POINTER(abilityRecord); TAG_LOGI(AAFwkTag::ABILITYMGR, "Ability died: %{public}s", abilityRecord->GetURI().c_str()); abilityRecord->SetConnRemoteObject(nullptr); ConnectListType connlist = abilityRecord->GetConnectRecordList(); for (auto &connectRecord : connlist) { TAG_LOGW(AAFwkTag::ABILITYMGR, "This record complete disconnect directly. recordId:%{public}d", connectRecord->GetRecordId()); RemoveExtensionDelayDisconnectTask(connectRecord); connectRecord->CompleteDisconnect(ERR_OK, false, true); abilityRecord->RemoveConnectRecordFromList(connectRecord); RemoveConnectionRecordFromMap(connectRecord); } if (IsUIExtensionAbility(abilityRecord)) { HandleUIExtensionDied(abilityRecord); } bool isRemove = false; if (IsCacheExtensionAbilityType(abilityRecord) && AbilityCacheManager::GetInstance().FindRecordByToken(abilityRecord->GetToken()) != nullptr) { AbilityCacheManager::GetInstance().Remove(abilityRecord); MoveToTerminatingMap(abilityRecord); RemoveServiceAbility(abilityRecord); isRemove = true; } else if (GetExtensionByIdFromServiceMap(abilityRecord->GetAbilityRecordId()) != nullptr) { MoveToTerminatingMap(abilityRecord); RemoveServiceAbility(abilityRecord); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { RemoveUIExtensionAbilityRecord(abilityRecord); } isRemove = true; } if (IsAbilityNeedKeepAlive(abilityRecord)) { KeepAbilityAlive(abilityRecord, currentUserId); } else { if (isRemove) { HandleNotifyAssertFaultDialogDied(abilityRecord); } } } static bool CheckIsNumString(const std::string &numStr) { const std::regex regexJsperf(R"(^\d*)"); std::match_results matchResults; if (numStr.empty() || !std::regex_match(numStr, matchResults, regexJsperf)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Number parsing error, %{public}s.", numStr.c_str()); return false; } if (MAX_UINT64_VALUE.length() < numStr.length() || (MAX_UINT64_VALUE.length() == numStr.length() && MAX_UINT64_VALUE.compare(numStr) < 0)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Number parsing error, %{public}s.", numStr.c_str()); return false; } return true; } void AbilityConnectManager::HandleNotifyAssertFaultDialogDied(const std::shared_ptr &abilityRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); CHECK_POINTER(abilityRecord); if (abilityRecord->GetAbilityInfo().name != ABILITY_NAME_ASSERT_FAULT_DIALOG || abilityRecord->GetAbilityInfo().bundleName != BUNDLE_NAME_DIALOG) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Is not assert fault dialog."); return; } auto want = abilityRecord->GetWant(); auto assertSessionStr = want.GetStringParam(Want::PARAM_ASSERT_FAULT_SESSION_ID); if (!CheckIsNumString(assertSessionStr)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Check assert session str is number failed."); return; } auto callbackDeathMgr = DelayedSingleton::GetInstance(); if (callbackDeathMgr == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Get callback death manager instance is nullptr."); return; } callbackDeathMgr->CallAssertFaultCallback(std::stoull(assertSessionStr)); } void AbilityConnectManager::CloseAssertDialog(const std::string &assertSessionId) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Called"); std::shared_ptr abilityRecord = nullptr; { std::lock_guard lock(serviceMapMutex_); for (const auto &item : serviceMap_) { if (item.second == nullptr) { continue; } auto assertSessionStr = item.second->GetWant().GetStringParam(Want::PARAM_ASSERT_FAULT_SESSION_ID); if (assertSessionStr == assertSessionId) { abilityRecord = item.second; serviceMap_.erase(item.first); break; } } } if (abilityRecord == nullptr) { abilityRecord = AbilityCacheManager::GetInstance().FindRecordBySessionId(assertSessionId); AbilityCacheManager::GetInstance().Remove(abilityRecord); } if (abilityRecord == nullptr) { return; } TAG_LOGD(AAFwkTag::ABILITYMGR, "Terminate assert fault dialog"); terminatingExtensionList_.push_back(abilityRecord); sptr token = abilityRecord->GetToken(); if (token != nullptr) { std::lock_guard lock(serialMutex_); TerminateAbilityLocked(token); } } void AbilityConnectManager::HandleUIExtensionDied(const std::shared_ptr &abilityRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called"); CHECK_POINTER(abilityRecord); std::lock_guard guard(uiExtensionMapMutex_); for (auto it = uiExtensionMap_.begin(); it != uiExtensionMap_.end();) { std::shared_ptr uiExtAbility = it->second.first.lock(); if (uiExtAbility == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "uiExtAbility is nullptr"); RemoveUIExtWindowDeathRecipient(it->first); it = uiExtensionMap_.erase(it); continue; } if (abilityRecord == uiExtAbility) { sptr sessionProxy = iface_cast(it->first); if (sessionProxy) { TAG_LOGD(AAFwkTag::ABILITYMGR, "start NotifyExtensionDied"); sessionProxy->NotifyExtensionDied(); } TAG_LOGW(AAFwkTag::UI_EXT, "uiExtAbility caller died"); RemoveUIExtWindowDeathRecipient(it->first); it = uiExtensionMap_.erase(it); continue; } ++it; } } void AbilityConnectManager::RestartAbility(const std::shared_ptr &abilityRecord, int32_t currentUserId) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Restart ability: %{public}s.", abilityRecord->GetURI().c_str()); AbilityRequest requestInfo; requestInfo.want = abilityRecord->GetWant(); requestInfo.abilityInfo = abilityRecord->GetAbilityInfo(); requestInfo.appInfo = abilityRecord->GetApplicationInfo(); requestInfo.restartTime = abilityRecord->GetRestartTime(); requestInfo.restart = true; requestInfo.uid = abilityRecord->GetUid(); abilityRecord->SetRestarting(true); ResidentAbilityInfoGuard residentAbilityInfoGuard; if (abilityRecord->IsKeepAliveBundle()) { residentAbilityInfoGuard.SetResidentAbilityInfo(requestInfo.abilityInfo.bundleName, requestInfo.abilityInfo.name, userId_); } if (AppUtils::GetInstance().IsLauncherAbility(abilityRecord->GetAbilityInfo().name)) { if (currentUserId != userId_) { TAG_LOGW(AAFwkTag::ABILITYMGR, "delay restart root launcher until switch user."); return; } if (abilityRecord->IsSceneBoard()) { requestInfo.want.SetParam("ohos.app.recovery", true); DelayedSingleton::GetInstance()->EnableListForSCBRecovery(userId_); } requestInfo.restartCount = abilityRecord->GetRestartCount(); TAG_LOGD(AAFwkTag::ABILITYMGR, "restart root launcher, number:%{public}d", requestInfo.restartCount); StartAbilityLocked(requestInfo); return; } requestInfo.want.SetParam(WANT_PARAMS_APP_RESTART_FLAG, true); // restart other resident ability if (abilityRecord->CanRestartResident()) { requestInfo.restartCount = abilityRecord->GetRestartCount(); requestInfo.restartTime = AbilityUtil::SystemTimeMillis(); StartAbilityLocked(requestInfo); } else { auto findRestartResidentTask = [requestInfo](const AbilityRequest &abilityRequest) { return (requestInfo.want.GetElement().GetBundleName() == abilityRequest.want.GetElement().GetBundleName() && requestInfo.want.GetElement().GetModuleName() == abilityRequest.want.GetElement().GetModuleName() && requestInfo.want.GetElement().GetAbilityName() == abilityRequest.want.GetElement().GetAbilityName()); }; auto findIter = find_if(restartResidentTaskList_.begin(), restartResidentTaskList_.end(), findRestartResidentTask); if (findIter != restartResidentTaskList_.end()) { TAG_LOGW(AAFwkTag::ABILITYMGR, "The restart task has been registered."); return; } restartResidentTaskList_.emplace_back(requestInfo); PostRestartResidentTask(requestInfo); } } std::string AbilityConnectManager::GetServiceKey(const std::shared_ptr &service) { std::string serviceKey = service->GetURI(); if (FRS_BUNDLE_NAME == service->GetAbilityInfo().bundleName) { serviceKey = serviceKey + std::to_string(service->GetWant().GetIntParam(FRS_APP_INDEX, 0)); } return serviceKey; } void AbilityConnectManager::DumpState(std::vector &info, bool isClient, const std::string &args) { TAG_LOGI(AAFwkTag::ABILITYMGR, "args:%{public}s.", args.c_str()); auto serviceMapBack = GetServiceMap(); auto cacheList = AbilityCacheManager::GetInstance().GetAbilityList(); if (!args.empty()) { auto it = std::find_if(serviceMapBack.begin(), serviceMapBack.end(), [&args](const auto &service) { return service.first.compare(args) == 0; }); if (it != serviceMapBack.end()) { info.emplace_back("uri [ " + it->first + " ]"); if (it->second != nullptr) { it->second->DumpService(info, isClient); } } else { info.emplace_back(args + ": Nothing to dump from serviceMap."); } std::string serviceKey; auto iter = std::find_if(cacheList.begin(), cacheList.end(), [&args, &serviceKey, this](const auto &service) { serviceKey = GetServiceKey(service); return serviceKey.compare(args) == 0; }); if (iter != cacheList.end()) { info.emplace_back("uri [ " + serviceKey + " ]"); if (*iter != nullptr) { (*iter)->DumpService(info, isClient); } } else { info.emplace_back(args + ": Nothing to dump from lru cache."); } } else { info.emplace_back(" ExtensionRecords:"); for (auto &&service : serviceMapBack) { info.emplace_back(" uri [" + service.first + "]"); if (service.second != nullptr) { service.second->DumpService(info, isClient); } } for (auto &&service : cacheList) { std::string serviceKey = GetServiceKey(service); info.emplace_back(" uri [" + serviceKey + "]"); if (service != nullptr) { service->DumpService(info, isClient); } } } } void AbilityConnectManager::DumpStateByUri(std::vector &info, bool isClient, const std::string &args, std::vector ¶ms) { TAG_LOGI(AAFwkTag::ABILITYMGR, "args:%{public}s, params size: %{public}zu", args.c_str(), params.size()); std::shared_ptr extensionAbilityRecord = nullptr; { std::lock_guard lock(serviceMapMutex_); auto it = std::find_if(serviceMap_.begin(), serviceMap_.end(), [&args](const auto &service) { return service.first.compare(args) == 0; }); if (it != serviceMap_.end()) { info.emplace_back("uri [ " + it->first + " ]"); extensionAbilityRecord = it->second; } else { info.emplace_back(args + ": Nothing to dump from serviceMap."); } } if (extensionAbilityRecord != nullptr) { extensionAbilityRecord->DumpService(info, params, isClient); return; } extensionAbilityRecord = AbilityCacheManager::GetInstance().FindRecordByServiceKey(args); if (extensionAbilityRecord != nullptr) { info.emplace_back("uri [ " + args + " ]"); extensionAbilityRecord->DumpService(info, params, isClient); } else { info.emplace_back(args + ": Nothing to dump from lru cache."); } } void AbilityConnectManager::GetExtensionRunningInfos(int upperLimit, std::vector &info, const int32_t userId, bool isPerm) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); auto serviceMapBack = GetServiceMap(); auto queryInfo = [&](ServiceMapType::reference service) { if (static_cast(info.size()) >= upperLimit) { return; } auto abilityRecord = service.second; CHECK_POINTER(abilityRecord); if (isPerm) { GetExtensionRunningInfo(abilityRecord, userId, info); } else { auto callingTokenId = IPCSkeleton::GetCallingTokenID(); auto tokenID = abilityRecord->GetApplicationInfo().accessTokenId; if (callingTokenId == tokenID) { GetExtensionRunningInfo(abilityRecord, userId, info); } } }; std::for_each(serviceMapBack.begin(), serviceMapBack.end(), queryInfo); auto cacheAbilityList = AbilityCacheManager::GetInstance().GetAbilityList(); auto queryInfoForCache = [&](std::shared_ptr &service) { if (static_cast(info.size()) >= upperLimit) { return; } CHECK_POINTER(service); if (isPerm) { GetExtensionRunningInfo(service, userId, info); } else { auto callingTokenId = IPCSkeleton::GetCallingTokenID(); auto tokenID = service->GetApplicationInfo().accessTokenId; if (callingTokenId == tokenID) { GetExtensionRunningInfo(service, userId, info); } } }; std::for_each(cacheAbilityList.begin(), cacheAbilityList.end(), queryInfoForCache); } void AbilityConnectManager::GetAbilityRunningInfos(std::vector &info, bool isPerm) { auto serviceMapBack = GetServiceMap(); auto queryInfo = [&info, isPerm](ServiceMapType::reference service) { auto abilityRecord = service.second; CHECK_POINTER(abilityRecord); if (isPerm) { DelayedSingleton::GetInstance()->GetAbilityRunningInfo(info, abilityRecord); } else { auto callingTokenId = IPCSkeleton::GetCallingTokenID(); auto tokenID = abilityRecord->GetApplicationInfo().accessTokenId; if (callingTokenId == tokenID) { DelayedSingleton::GetInstance()->GetAbilityRunningInfo(info, abilityRecord); } } }; std::for_each(serviceMapBack.begin(), serviceMapBack.end(), queryInfo); } void AbilityConnectManager::GetExtensionRunningInfo(std::shared_ptr &abilityRecord, const int32_t userId, std::vector &info) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); ExtensionRunningInfo extensionInfo; AppExecFwk::RunningProcessInfo processInfo; extensionInfo.extension = abilityRecord->GetElementName(); extensionInfo.type = abilityRecord->GetAbilityInfo().extensionAbilityType; DelayedSingleton::GetInstance()-> GetRunningProcessInfoByToken(abilityRecord->GetToken(), processInfo); extensionInfo.pid = processInfo.pid_; extensionInfo.uid = processInfo.uid_; extensionInfo.processName = processInfo.processName_; extensionInfo.startTime = abilityRecord->GetStartTime(); ConnectListType connectRecordList = abilityRecord->GetConnectRecordList(); for (auto &connectRecord : connectRecordList) { if (connectRecord == nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "connectRecord is nullptr."); continue; } auto callerAbilityRecord = Token::GetAbilityRecordByToken(connectRecord->GetToken()); if (callerAbilityRecord == nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "callerAbilityRecord is nullptr."); continue; } std::string package = callerAbilityRecord->GetAbilityInfo().bundleName; extensionInfo.clientPackage.emplace_back(package); } info.emplace_back(extensionInfo); } void AbilityConnectManager::PauseExtensions() { TAG_LOGD(AAFwkTag::ABILITYMGR, "begin."); std::vector> needTerminatedTokens; { std::lock_guard lock(serviceMapMutex_); for (auto it = serviceMap_.begin(); it != serviceMap_.end();) { auto targetExtension = it->second; if (targetExtension != nullptr && targetExtension->GetAbilityInfo().type == AbilityType::EXTENSION && (IsLauncher(targetExtension) || targetExtension->IsSceneBoard() || (targetExtension->GetKeepAlive() && userId_ != USER_ID_NO_HEAD))) { terminatingExtensionList_.push_back(it->second); it = serviceMap_.erase(it); TAG_LOGI(AAFwkTag::ABILITYMGR, "terminate ability:%{public}s.", targetExtension->GetAbilityInfo().name.c_str()); needTerminatedTokens.push_back(targetExtension->GetToken()); } else { ++it; } } } for (const auto &token : needTerminatedTokens) { std::lock_guard lock(serialMutex_); TerminateAbilityLocked(token); } } void AbilityConnectManager::RemoveLauncherDeathRecipient() { TAG_LOGI(AAFwkTag::ABILITYMGR, "Call."); { std::lock_guard lock(serviceMapMutex_); for (auto it = serviceMap_.begin(); it != serviceMap_.end(); ++it) { auto targetExtension = it->second; if (targetExtension != nullptr && targetExtension->GetAbilityInfo().type == AbilityType::EXTENSION && (IsLauncher(targetExtension) || targetExtension->IsSceneBoard())) { targetExtension->RemoveAbilityDeathRecipient(); return; } } } AbilityCacheManager::GetInstance().RemoveLauncherDeathRecipient(); } bool AbilityConnectManager::IsLauncher(std::shared_ptr serviceExtension) const { if (serviceExtension == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "param is nullptr"); return false; } return serviceExtension->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME && serviceExtension->GetAbilityInfo().bundleName == AbilityConfig::LAUNCHER_BUNDLE_NAME; } void AbilityConnectManager::KillProcessesByUserId() const { auto appScheduler = DelayedSingleton::GetInstance(); if (appScheduler == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "appScheduler is nullptr"); return; } IN_PROCESS_CALL_WITHOUT_RET(appScheduler->KillProcessesByUserId(userId_)); } void AbilityConnectManager::MoveToBackground(const std::shared_ptr &abilityRecord) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Move the ui extension ability to background fail, ability record is null."); return; } TAG_LOGD(AAFwkTag::ABILITYMGR, "Move the ui extension ability to background, ability:%{public}s.", abilityRecord->GetAbilityInfo().name.c_str()); abilityRecord->SetIsNewWant(false); auto self(weak_from_this()); auto task = [abilityRecord, self]() { auto selfObj = self.lock(); if (selfObj == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "mgr is invalid."); return; } CHECK_POINTER(abilityRecord); if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType) && selfObj->uiExtensionAbilityRecordMgr_ != nullptr && selfObj->IsCallerValid(abilityRecord)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Start background timeout."); selfObj->uiExtensionAbilityRecordMgr_->BackgroundTimeout(abilityRecord->GetUIExtensionAbilityId()); } TAG_LOGE(AAFwkTag::ABILITYMGR, "move to background timeout."); selfObj->PrintTimeOutLog(abilityRecord, AbilityManagerService::BACKGROUND_TIMEOUT_MSG); selfObj->CompleteBackground(abilityRecord); }; abilityRecord->BackgroundAbility(task); } void AbilityConnectManager::CompleteForeground(const std::shared_ptr &abilityRecord) { std::lock_guard guard(serialMutex_); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr"); return; } if (abilityRecord->GetAbilityState() != AbilityState::FOREGROUNDING) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability state is %{public}d, it can't complete foreground.", abilityRecord->GetAbilityState()); return; } abilityRecord->SetAbilityState(AbilityState::FOREGROUND); if (abilityRecord->BackgroundAbilityWindowDelayed()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Response background request."); abilityRecord->DoBackgroundAbilityWindowDelayed(false); DoBackgroundAbilityWindow(abilityRecord, abilityRecord->GetSessionInfo()); } CompleteStartServiceReq(abilityRecord->GetURI()); } void AbilityConnectManager::HandleForegroundTimeoutTask(const std::shared_ptr &abilityRecord) { std::lock_guard guard(serialMutex_); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr"); return; } if (UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType) && uiExtensionAbilityRecordMgr_ != nullptr && IsCallerValid(abilityRecord)) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Start foreground timeout."); uiExtensionAbilityRecordMgr_->ForegroundTimeout(abilityRecord->GetUIExtensionAbilityId()); } abilityRecord->SetAbilityState(AbilityState::BACKGROUND); abilityRecord->DoBackgroundAbilityWindowDelayed(false); CompleteStartServiceReq(abilityRecord->GetURI()); } void AbilityConnectManager::CompleteBackground(const std::shared_ptr &abilityRecord) { std::lock_guard lock(serialMutex_); if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr"); return; } if (abilityRecord->GetAbilityState() != AbilityState::BACKGROUNDING) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Ability state is %{public}d, it can't complete background.", abilityRecord->GetAbilityState()); return; } abilityRecord->SetAbilityState(AbilityState::BACKGROUND); // send application state to AppMS. // notify AppMS to update application state. DelayedSingleton::GetInstance()->MoveToBackground(abilityRecord->GetToken()); CompleteStartServiceReq(abilityRecord->GetURI()); // Abilities ahead of the one started were put in terminate list, we need to terminate them. TerminateAbilityLocked(abilityRecord->GetToken()); } void AbilityConnectManager::PrintTimeOutLog(const std::shared_ptr &ability, uint32_t msgId, bool isHalf) { CHECK_POINTER(ability); AppExecFwk::RunningProcessInfo processInfo = {}; DelayedSingleton::GetInstance()->GetRunningProcessInfoByToken(ability->GetToken(), processInfo); if (processInfo.pid_ == 0) { TAG_LOGE(AAFwkTag::ABILITYMGR, "ability %{public}s pid invalid", ability->GetURI().c_str()); return; } int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT; std::string msgContent = "ability:" + ability->GetAbilityInfo().name + " "; switch (msgId) { case AbilityManagerService::LOAD_TIMEOUT_MSG: msgContent += "load timeout"; typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT; break; case AbilityManagerService::ACTIVE_TIMEOUT_MSG: msgContent += "active timeout"; break; case AbilityManagerService::INACTIVE_TIMEOUT_MSG: msgContent += "inactive timeout"; break; case AbilityManagerService::FOREGROUND_TIMEOUT_MSG: msgContent += "foreground timeout"; typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT; break; case AbilityManagerService::BACKGROUND_TIMEOUT_MSG: msgContent += "background timeout"; break; case AbilityManagerService::TERMINATE_TIMEOUT_MSG: msgContent += "terminate timeout"; break; default: return; } TAG_LOGW(AAFwkTag::ABILITYMGR, "LIFECYCLE_TIMEOUT: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s," "msg: %{public}s", processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(), ability->GetAbilityInfo().name.c_str(), msgContent.c_str()); std::string eventName = isHalf ? AppExecFwk::AppFreezeType::LIFECYCLE_HALF_TIMEOUT : AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT; AppExecFwk::AppfreezeManager::ParamInfo info = { .typeId = typeId, .pid = processInfo.pid_, .eventName = eventName, .bundleName = ability->GetAbilityInfo().bundleName, .msg = msgContent }; AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(info); } void AbilityConnectManager::MoveToTerminatingMap(const std::shared_ptr& abilityRecord) { CHECK_POINTER(abilityRecord); auto& abilityInfo = abilityRecord->GetAbilityInfo(); std::lock_guard lock(serviceMapMutex_); terminatingExtensionList_.push_back(abilityRecord); std::string serviceKey = abilityRecord->GetURI(); if (FRS_BUNDLE_NAME == abilityInfo.bundleName) { AppExecFwk::ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name, abilityInfo.moduleName); serviceKey = element.GetURI() + std::to_string(abilityRecord->GetWant().GetIntParam(FRS_APP_INDEX, 0)); } serviceMap_.erase(serviceKey); AbilityCacheManager::GetInstance().Remove(abilityRecord); if (IsSpecialAbility(abilityRecord->GetAbilityInfo())) { TAG_LOGI(AAFwkTag::ABILITYMGR, "Moving ability: %{public}s", abilityRecord->GetURI().c_str()); } } void AbilityConnectManager::AddUIExtWindowDeathRecipient(const sptr &session) { CHECK_POINTER(session); std::lock_guard lock(uiExtRecipientMapMutex_); auto it = uiExtRecipientMap_.find(session); if (it != uiExtRecipientMap_.end()) { TAG_LOGE(AAFwkTag::ABILITYMGR, "This death recipient has been added."); return; } else { std::weak_ptr thisWeakPtr(shared_from_this()); sptr deathRecipient = new AbilityConnectCallbackRecipient([thisWeakPtr](const wptr &remote) { auto abilityConnectManager = thisWeakPtr.lock(); if (abilityConnectManager) { abilityConnectManager->OnUIExtWindowDied(remote); } }); if (!session->AddDeathRecipient(deathRecipient)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "AddDeathRecipient failed."); } uiExtRecipientMap_.emplace(session, deathRecipient); } } void AbilityConnectManager::RemoveUIExtWindowDeathRecipient(const sptr &session) { CHECK_POINTER(session); std::lock_guard lock(uiExtRecipientMapMutex_); auto it = uiExtRecipientMap_.find(session); if (it != uiExtRecipientMap_.end() && it->first != nullptr) { it->first->RemoveDeathRecipient(it->second); uiExtRecipientMap_.erase(it); return; } } void AbilityConnectManager::OnUIExtWindowDied(const wptr &remote) { auto object = remote.promote(); CHECK_POINTER(object); if (taskHandler_) { auto task = [object, connectManager = shared_from_this()]() { connectManager->HandleUIExtWindowDiedTask(object); }; taskHandler_->SubmitTask(task); } } void AbilityConnectManager::HandleUIExtWindowDiedTask(const sptr &remote) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call."); CHECK_POINTER(remote); std::shared_ptr abilityRecord; sptr sessionInfo; { std::lock_guard guard(uiExtensionMapMutex_); auto it = uiExtensionMap_.find(remote); if (it != uiExtensionMap_.end()) { abilityRecord = it->second.first.lock(); sessionInfo = it->second.second; TAG_LOGW(AAFwkTag::UI_EXT, "uiExtAbility caller died"); uiExtensionMap_.erase(it); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "Died object can't find from map."); return; } } if (abilityRecord) { TerminateAbilityWindowLocked(abilityRecord, sessionInfo); } else { TAG_LOGI(AAFwkTag::ABILITYMGR, "abilityRecord is nullptr"); } RemoveUIExtWindowDeathRecipient(remote); } bool AbilityConnectManager::IsUIExtensionFocused(uint32_t uiExtensionTokenId, const sptr& focusToken) { TAG_LOGD(AAFwkTag::ABILITYMGR, "called, id: %{public}u", uiExtensionTokenId); CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, false); std::lock_guard guard(uiExtensionMapMutex_); for (auto& item: uiExtensionMap_) { auto uiExtension = item.second.first.lock(); auto sessionInfo = item.second.second; if (uiExtension && uiExtension->GetApplicationInfo().accessTokenId == uiExtensionTokenId) { if (sessionInfo && uiExtensionAbilityRecordMgr_->IsFocused( uiExtension->GetUIExtensionAbilityId(), sessionInfo->callerToken, focusToken)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Focused"); return true; } if (sessionInfo && sessionInfo->callerToken == focusToken) { return true; } } } return false; } sptr AbilityConnectManager::GetUIExtensionSourceToken(const sptr &token) { TAG_LOGD(AAFwkTag::ABILITYMGR, "Called"); std::lock_guard guard(uiExtensionMapMutex_); for (auto &item : uiExtensionMap_) { auto sessionInfo = item.second.second; auto uiExtension = item.second.first.lock(); if (sessionInfo != nullptr && uiExtension != nullptr && uiExtension->GetToken() != nullptr && uiExtension->GetToken()->AsObject() == token) { TAG_LOGD(AAFwkTag::ABILITYMGR, "The source token found."); return sessionInfo->callerToken; } } return nullptr; } void AbilityConnectManager::GetUIExtensionCallerTokenList(const std::shared_ptr &abilityRecord, std::list> &callerList) { CHECK_POINTER(uiExtensionAbilityRecordMgr_); uiExtensionAbilityRecordMgr_->GetCallerTokenList(abilityRecord, callerList); } bool AbilityConnectManager::IsWindowExtensionFocused(uint32_t extensionTokenId, const sptr& focusToken) { std::lock_guard guard(windowExtensionMapMutex_); for (auto& item: windowExtensionMap_) { uint32_t windowExtTokenId = item.second.first; auto sessionInfo = item.second.second; if (windowExtTokenId == extensionTokenId && sessionInfo && sessionInfo->callerToken == focusToken) { return true; } } return false; } void AbilityConnectManager::HandleProcessFrozen(const std::vector &pidList, int32_t uid) { auto taskHandler = taskHandler_; if (!taskHandler) { TAG_LOGE(AAFwkTag::ABILITYMGR, "taskHandler null"); return; } TAG_LOGI(AAFwkTag::ABILITYMGR, "HandleProcessFrozen: %{public}d", uid); std::unordered_set pidSet(pidList.begin(), pidList.end()); std::lock_guard lock(serviceMapMutex_); auto weakThis = weak_from_this(); for (auto [key, abilityRecord] : serviceMap_) { if (abilityRecord && abilityRecord->GetUid() == uid && abilityRecord->GetAbilityInfo().extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE && pidSet.count(abilityRecord->GetPid()) > 0 && abilityRecord->GetAbilityInfo().bundleName != FROZEN_WHITE_DIALOG && abilityRecord->IsConnectListEmpty() && !abilityRecord->GetKeepAlive()) { taskHandler->SubmitTask([weakThis, record = abilityRecord]() { auto connectManager = weakThis.lock(); if (record && connectManager) { TAG_LOGI(AAFwkTag::ABILITYMGR, "TerminateRecord: %{public}s", record->GetAbilityInfo().bundleName.c_str()); connectManager->TerminateRecord(record); } else { TAG_LOGE(AAFwkTag::ABILITYMGR, "connectManager null"); } }); } } } void AbilityConnectManager::PostExtensionDelayDisconnectTask(const std::shared_ptr &connectRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); CHECK_POINTER(taskHandler_); CHECK_POINTER(connectRecord); int32_t recordId = connectRecord->GetRecordId(); std::string taskName = std::string("DelayDisconnectTask_") + std::to_string(recordId); auto abilityRecord = connectRecord->GetAbilityRecord(); CHECK_POINTER(abilityRecord); auto typeName = abilityRecord->GetAbilityInfo().extensionTypeName; int32_t delayTime = DelayedSingleton::GetInstance()->GetExtensionAutoDisconnectTime(typeName); if (delayTime == AUTO_DISCONNECT_INFINITY) { TAG_LOGD(AAFwkTag::ABILITYMGR, "This extension needn't auto disconnect."); return; } auto task = [connectRecord, self = weak_from_this()]() { auto selfObj = self.lock(); if (selfObj == nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "mgr is invalid."); return; } TAG_LOGW(AAFwkTag::ABILITYMGR, "Auto disconnect the Extension's connection."); selfObj->HandleExtensionDisconnectTask(connectRecord); }; taskHandler_->SubmitTask(task, taskName, delayTime); } void AbilityConnectManager::RemoveExtensionDelayDisconnectTask(const std::shared_ptr &connectRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); CHECK_POINTER(taskHandler_); CHECK_POINTER(connectRecord); int32_t recordId = connectRecord->GetRecordId(); std::string taskName = std::string("DelayDisconnectTask_") + std::to_string(recordId); taskHandler_->CancelTask(taskName); } void AbilityConnectManager::HandleExtensionDisconnectTask(const std::shared_ptr &connectRecord) { TAG_LOGD(AAFwkTag::ABILITYMGR, "call"); std::lock_guard guard(serialMutex_); CHECK_POINTER(connectRecord); int result = connectRecord->DisconnectAbility(); if (result != ERR_OK) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Auto disconnect extension error, ret: %{public}d.", result); } if (connectRecord->GetConnectState() == ConnectionState::DISCONNECTED) { connectRecord->CompleteDisconnect(ERR_OK, false); RemoveConnectionRecordFromMap(connectRecord); } } bool AbilityConnectManager::IsUIExtensionAbility(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, false); return UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType); } bool AbilityConnectManager::IsCacheExtensionAbilityType(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, false); return CacheExtensionUtils::IsCacheExtensionType(abilityRecord->GetAbilityInfo().extensionAbilityType); } bool AbilityConnectManager::CheckUIExtensionAbilitySessionExist( const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN(abilityRecord, false); std::lock_guard guard(uiExtensionMapMutex_); for (auto it = uiExtensionMap_.begin(); it != uiExtensionMap_.end(); ++it) { std::shared_ptr uiExtAbility = it->second.first.lock(); if (abilityRecord == uiExtAbility) { return true; } } return false; } void AbilityConnectManager::RemoveUIExtensionAbilityRecord(const std::shared_ptr &abilityRecord) { CHECK_POINTER(abilityRecord); CHECK_POINTER(uiExtensionAbilityRecordMgr_); if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) { ClearPreloadUIExtensionRecord(abilityRecord); } uiExtensionAbilityRecordMgr_->RemoveExtensionRecord(abilityRecord->GetUIExtensionAbilityId()); } void AbilityConnectManager::AddUIExtensionAbilityRecordToTerminatedList( const std::shared_ptr &abilityRecord) { CHECK_POINTER(abilityRecord); CHECK_POINTER(uiExtensionAbilityRecordMgr_); uiExtensionAbilityRecordMgr_->AddExtensionRecordToTerminatedList(abilityRecord->GetUIExtensionAbilityId()); } bool AbilityConnectManager::IsCallerValid(const std::shared_ptr &abilityRecord) { CHECK_POINTER_AND_RETURN_LOG(abilityRecord, false, "Invalid caller for UIExtension"); auto sessionInfo = abilityRecord->GetSessionInfo(); CHECK_POINTER_AND_RETURN_LOG(sessionInfo, false, "Invalid caller for UIExtension"); CHECK_POINTER_AND_RETURN_LOG(sessionInfo->sessionToken, false, "Invalid caller for UIExtension"); std::lock_guard lock(uiExtRecipientMapMutex_); if (uiExtRecipientMap_.find(sessionInfo->sessionToken) == uiExtRecipientMap_.end()) { TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid caller for UIExtension."); return false; } TAG_LOGD(AAFwkTag::ABILITYMGR, "The caller survival."); return true; } int32_t AbilityConnectManager::GetUIExtensionSessionInfo(const sptr token, UIExtensionSessionInfo &uiExtensionSessionInfo) { CHECK_POINTER_AND_RETURN(token, ERR_NULL_OBJECT); CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, ERR_NULL_OBJECT); return uiExtensionAbilityRecordMgr_->GetUIExtensionSessionInfo(token, uiExtensionSessionInfo); } void AbilityConnectManager::SignRestartAppFlag(int32_t uid) { { std::lock_guard lock(serviceMapMutex_); for (auto &[key, abilityRecord] : serviceMap_) { if (abilityRecord == nullptr || abilityRecord->GetUid() != uid) { continue; } abilityRecord->SetRestartAppFlag(true); } } AbilityCacheManager::GetInstance().SignRestartAppFlag(uid); } std::shared_ptr AbilityConnectManager::GetUIExtensionRootHostInfo(const sptr token) { CHECK_POINTER_AND_RETURN(token, nullptr); CHECK_POINTER_AND_RETURN(uiExtensionAbilityRecordMgr_, nullptr); return uiExtensionAbilityRecordMgr_->GetUIExtensionRootHostInfo(token); } bool AbilityConnectManager::AddToServiceMap(const std::string &key, std::shared_ptr abilityRecord) { std::lock_guard lock(serviceMapMutex_); if (abilityRecord == nullptr) { return false; } auto insert = serviceMap_.emplace(key, abilityRecord); if (!insert.second) { TAG_LOGW(AAFwkTag::ABILITYMGR, "record exist: %{public}s", key.c_str()); } return insert.second; } AbilityConnectManager::ServiceMapType AbilityConnectManager::GetServiceMap() { std::lock_guard lock(serviceMapMutex_); return serviceMap_; } void AbilityConnectManager::AddConnectObjectToMap(sptr connectObject, const ConnectListType &connectRecordList, bool updateOnly) { if (!updateOnly) { AddConnectDeathRecipient(connectObject); } std::lock_guard guard(connectMapMutex_); connectMap_[connectObject] = connectRecordList; } EventInfo AbilityConnectManager::BuildEventInfo(const std::shared_ptr &abilityRecord) { EventInfo eventInfo; if (abilityRecord == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "build eventInfo failed, abilityRecord is nullptr"); return eventInfo; } AppExecFwk::RunningProcessInfo processInfo; DelayedSingleton::GetInstance()->GetRunningProcessInfoByToken(abilityRecord->GetToken(), processInfo); eventInfo.pid = processInfo.pid_; eventInfo.processName = processInfo.processName_; eventInfo.time = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); auto callerPid = abilityRecord->GetWant().GetIntParam(Want::PARAM_RESV_CALLER_PID, -1); eventInfo.callerPid = callerPid == -1 ? IPCSkeleton::GetCallingPid() : callerPid; DelayedSingleton::GetInstance()->GetRunningProcessInfoByPid(eventInfo.callerPid, processInfo); eventInfo.callerPid = processInfo.pid_; eventInfo.callerProcessName = processInfo.processName_; if (!abilityRecord->IsCreateByConnect()) { auto abilityInfo = abilityRecord->GetAbilityInfo(); eventInfo.extensionType = static_cast(abilityInfo.extensionAbilityType); eventInfo.userId = userId_; eventInfo.bundleName = abilityInfo.bundleName; eventInfo.moduleName = abilityInfo.moduleName; eventInfo.abilityName = abilityInfo.name; } return eventInfo; } void AbilityConnectManager::UpdateUIExtensionInfo(const std::shared_ptr &abilityRecord) { if (abilityRecord == nullptr || !UIExtensionUtils::IsUIExtension(abilityRecord->GetAbilityInfo().extensionAbilityType)) { return; } WantParams wantParams; auto uiExtensionAbilityId = abilityRecord->GetUIExtensionAbilityId(); wantParams.SetParam(UIEXTENSION_ABILITY_ID, AAFwk::Integer::Box(uiExtensionAbilityId)); auto rootHostRecord = GetUIExtensionRootHostInfo(abilityRecord->GetToken()); if (rootHostRecord != nullptr) { auto rootHostPid = rootHostRecord->GetPid(); wantParams.SetParam(UIEXTENSION_ROOT_HOST_PID, AAFwk::Integer::Box(rootHostPid)); } if (abilityRecord->GetWant().GetBoolParam(IS_PRELOAD_UIEXTENSION_ABILITY, false)) { // Applicable only to preloadUIExtension scenarios auto rootHostPid = IPCSkeleton::GetCallingPid(); wantParams.SetParam(UIEXTENSION_ROOT_HOST_PID, AAFwk::Integer::Box(rootHostPid)); } abilityRecord->UpdateUIExtensionInfo(wantParams); } std::string AbilityConnectManager::GenerateBundleName(const AbilityRequest &abilityRequest) const { auto bundleName = abilityRequest.abilityInfo.bundleName; if (AbilityRuntime::StartupUtil::IsSupportAppClone(abilityRequest.abilityInfo.extensionAbilityType)) { auto appCloneIndex = abilityRequest.want.GetIntParam(Want::PARAM_APP_CLONE_INDEX_KEY, 0); if (appCloneIndex > 0) { bundleName = std::to_string(appCloneIndex) + bundleName; } } return bundleName; } int32_t AbilityConnectManager::ReportXiaoYiToRSSIfNeeded(const AppExecFwk::AbilityInfo &abilityInfo) { if (abilityInfo.type != AppExecFwk::AbilityType::EXTENSION || abilityInfo.bundleName != XIAOYI_BUNDLE_NAME) { return ERR_OK; } TAG_LOGI(AAFwkTag::ABILITYMGR, "bundleName is com.huawei.hmos.vassistant extension, abilityName:%{public}s, report to rss.", abilityInfo.name.c_str()); auto ret = ReportAbilityStartInfoToRSS(abilityInfo); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::ABILITYMGR, "ReportAbilitStartInfoToRSS failed, ret:%{public}d", ret); return ret; } return ERR_OK; } int32_t AbilityConnectManager::ReportAbilityStartInfoToRSS(const AppExecFwk::AbilityInfo &abilityInfo) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::vector runningProcessInfos; auto ret = IN_PROCESS_CALL(DelayedSingleton::GetInstance()->GetProcessRunningInfos( runningProcessInfos)); if (ret != ERR_OK) { return ret; } bool isColdStart = true; int32_t pid = 0; for (auto const &info : runningProcessInfos) { if (info.uid_ == abilityInfo.applicationInfo.uid) { isColdStart = false; pid = info.pid_; break; } } TAG_LOGI(AAFwkTag::ABILITYMGR, "ReportAbilityStartInfoToRSS, abilityName:%{public}s", abilityInfo.name.c_str()); ResSchedUtil::GetInstance().ReportAbilityStartInfoToRSS(abilityInfo, pid, isColdStart); return ERR_OK; } void AbilityConnectManager::UninstallApp(const std::string &bundleName, int32_t uid) { std::lock_guard lock(serviceMapMutex_); for (const auto &[key, abilityRecord]: serviceMap_) { if (abilityRecord && abilityRecord->GetAbilityInfo().bundleName == bundleName && abilityRecord->GetUid() == uid) { abilityRecord->SetKeepAliveBundle(false); } } } int32_t AbilityConnectManager::UpdateKeepAliveEnableState(const std::string &bundleName, const std::string &moduleName, const std::string &mainElement, bool updateEnable) { std::lock_guard lock(serviceMapMutex_); for (const auto &[key, abilityRecord]: serviceMap_) { CHECK_POINTER_AND_RETURN(abilityRecord, ERR_NULL_OBJECT); if (abilityRecord->GetAbilityInfo().bundleName == bundleName && abilityRecord->GetAbilityInfo().name == mainElement && abilityRecord->GetAbilityInfo().moduleName == moduleName) { TAG_LOGI(AAFwkTag::ABILITYMGR, "update keepAlive,bundle:%{public}s,module:%{public}s,ability:%{public}s,enable:%{public}d", bundleName.c_str(), moduleName.c_str(), mainElement.c_str(), updateEnable); abilityRecord->SetKeepAliveBundle(updateEnable); return ERR_OK; } } return ERR_OK; } } // namespace AAFwk } // namespace OHOS