/* * Copyright (c) 2023-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 "dialog_session_manager.h" #include #include "ability_manager_service.h" #include "ability_util.h" #include "hitrace_meter.h" #include "int_wrapper.h" #include "modal_system_ui_extension.h" #include "start_ability_utils.h" #include "string_wrapper.h" #include "want.h" namespace OHOS { namespace AAFwk { using OHOS::AppExecFwk::BundleInfo; namespace { constexpr const char* UIEXTENSION_MODAL_TYPE = "ability.want.params.modalType"; constexpr int32_t ERMS_ISALLOW_RESULTCODE = 10; constexpr const char* SUPPORT_CLOSE_ON_BLUR = "supportCloseOnBlur"; constexpr const char* DIALOG_SESSION_ID = "dialogSessionId"; } DialogSessionManager &DialogSessionManager::GetInstance() { static DialogSessionManager instance; return instance; } std::string DialogSessionManager::GenerateDialogSessionId() { auto timestamp = std::chrono::system_clock::now().time_since_epoch(); auto time = std::chrono::duration_cast(timestamp).count(); std::random_device seed; std::mt19937 rng(seed()); std::uniform_int_distribution uni(0, INT_MAX); int randomDigit = uni(rng); std::string dialogSessionId = std::to_string(time) + "_" + std::to_string(randomDigit); std::lock_guard guard(dialogSessionRecordLock_); auto iter = dialogSessionInfoMap_.find(dialogSessionId); while (iter != dialogSessionInfoMap_.end()) { dialogSessionId += "_1"; iter = dialogSessionInfoMap_.find(dialogSessionId); } return dialogSessionId; } void DialogSessionManager::SetStartupSessionInfo(const std::string &dialogSessionId, const AbilityRequest &abilityRequest) { std::lock_guard guard(dialogSessionRecordLock_); std::shared_ptr startupSessionInfo = std::make_shared(); startupSessionInfo->abilityRequest = abilityRequest; startupSessionInfoMap_[dialogSessionId] = startupSessionInfo; } void DialogSessionManager::SetDialogSessionInfo(const std::string &dialogSessionId, sptr &dilogSessionInfo, std::shared_ptr &dialogCallerInfo) { std::lock_guard guard(dialogSessionRecordLock_); dialogSessionInfoMap_[dialogSessionId] = dilogSessionInfo; dialogCallerInfoMap_[dialogSessionId] = dialogCallerInfo; } sptr DialogSessionManager::GetDialogSessionInfo(const std::string &dialogSessionId) const { std::lock_guard guard(dialogSessionRecordLock_); auto it = dialogSessionInfoMap_.find(dialogSessionId); if (it != dialogSessionInfoMap_.end()) { return it->second; } TAG_LOGI(AAFwkTag::DIALOG, "not find"); return nullptr; } std::shared_ptr DialogSessionManager::GetDialogCallerInfo(const std::string &dialogSessionId) const { std::lock_guard guard(dialogSessionRecordLock_); auto it = dialogCallerInfoMap_.find(dialogSessionId); if (it != dialogCallerInfoMap_.end()) { return it->second; } TAG_LOGI(AAFwkTag::DIALOG, "not find"); return nullptr; } std::shared_ptr DialogSessionManager::GetStartupSessionInfo( const std::string &dialogSessionId) const { std::lock_guard guard(dialogSessionRecordLock_); auto it = startupSessionInfoMap_.find(dialogSessionId); if (it != startupSessionInfoMap_.end()) { return it->second; } TAG_LOGI(AAFwkTag::DIALOG, "not find"); return nullptr; } void DialogSessionManager::ClearDialogContext(const std::string &dialogSessionId) { std::lock_guard guard(dialogSessionRecordLock_); dialogSessionInfoMap_.erase(dialogSessionId); dialogCallerInfoMap_.erase(dialogSessionId); startupSessionInfoMap_.erase(dialogSessionId); return; } void DialogSessionManager::ClearAllDialogContexts() { std::lock_guard guard(dialogSessionRecordLock_); dialogSessionInfoMap_.clear(); dialogCallerInfoMap_.clear(); startupSessionInfoMap_.clear(); } void DialogSessionManager::GenerateCallerAbilityInfo(AbilityRequest &abilityRequest, DialogAbilityInfo &callerAbilityInfo) { sptr callerToken = abilityRequest.callerToken; if (callerToken != nullptr) { auto callerRecord = Token::GetAbilityRecordByToken(callerToken); CHECK_POINTER(callerRecord); callerAbilityInfo.bundleName = callerRecord->GetAbilityInfo().bundleName; callerAbilityInfo.moduleName = callerRecord->GetAbilityInfo().moduleName; callerAbilityInfo.abilityName = callerRecord->GetAbilityInfo().name; callerAbilityInfo.abilityIconId = callerRecord->GetAbilityInfo().iconId; callerAbilityInfo.abilityLabelId = callerRecord->GetAbilityInfo().labelId; callerAbilityInfo.bundleIconId = callerRecord->GetApplicationInfo().iconId; callerAbilityInfo.bundleLabelId = callerRecord->GetApplicationInfo().labelId; callerAbilityInfo.visible = callerRecord->GetAbilityInfo().visible; callerAbilityInfo.appIndex = callerRecord->GetApplicationInfo().appIndex; callerAbilityInfo.multiAppMode = callerRecord->GetApplicationInfo().multiAppMode; } } void DialogSessionManager::GenerateSelectorTargetAbilityInfos(std::vector &dialogAppInfos, std::vector &targetAbilityInfos) { for (auto &dialogAppInfo : dialogAppInfos) { DialogAbilityInfo targetDialogAbilityInfo; targetDialogAbilityInfo.bundleName = dialogAppInfo.bundleName; targetDialogAbilityInfo.moduleName = dialogAppInfo.moduleName; targetDialogAbilityInfo.abilityName = dialogAppInfo.abilityName; targetDialogAbilityInfo.abilityIconId = dialogAppInfo.abilityIconId; targetDialogAbilityInfo.abilityLabelId = dialogAppInfo.abilityLabelId; targetDialogAbilityInfo.bundleIconId = dialogAppInfo.bundleIconId; targetDialogAbilityInfo.bundleLabelId = dialogAppInfo.bundleLabelId; targetDialogAbilityInfo.visible = dialogAppInfo.visible; targetDialogAbilityInfo.appIndex = dialogAppInfo.appIndex; targetDialogAbilityInfo.multiAppMode = dialogAppInfo.multiAppMode; targetAbilityInfos.emplace_back(targetDialogAbilityInfo); } } void DialogSessionManager::GenerateJumpTargetAbilityInfos(AbilityRequest &abilityRequest, std::vector &targetAbilityInfos) { DialogAbilityInfo targetDialogAbilityInfo; targetDialogAbilityInfo.bundleName = abilityRequest.abilityInfo.bundleName; targetDialogAbilityInfo.moduleName = abilityRequest.abilityInfo.moduleName; targetDialogAbilityInfo.abilityName = abilityRequest.abilityInfo.name; targetDialogAbilityInfo.abilityIconId = abilityRequest.abilityInfo.iconId; targetDialogAbilityInfo.abilityLabelId = abilityRequest.abilityInfo.labelId; targetDialogAbilityInfo.bundleIconId = abilityRequest.abilityInfo.applicationInfo.iconId; targetDialogAbilityInfo.bundleLabelId = abilityRequest.abilityInfo.applicationInfo.labelId; targetDialogAbilityInfo.visible = abilityRequest.abilityInfo.visible; targetDialogAbilityInfo.appIndex = abilityRequest.abilityInfo.applicationInfo.appIndex; targetDialogAbilityInfo.multiAppMode = abilityRequest.abilityInfo.applicationInfo.multiAppMode; targetAbilityInfos.emplace_back(targetDialogAbilityInfo); } void DialogSessionManager::GenerateDialogCallerInfo(AbilityRequest &abilityRequest, int32_t userId, std::shared_ptr dialogCallerInfo, SelectorType type) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); CHECK_POINTER(dialogCallerInfo); dialogCallerInfo->type = type; dialogCallerInfo->callerToken = abilityRequest.callerToken; dialogCallerInfo->requestCode = abilityRequest.requestCode; dialogCallerInfo->targetWant = abilityRequest.want; dialogCallerInfo->userId = userId; } int DialogSessionManager::SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllowed) { if (!isAllowed) { TAG_LOGI(AAFwkTag::ABILITYMGR, "user refuse to jump"); ClearDialogContext(dialogSessionId); return ERR_OK; } std::shared_ptr startupSessionInfo = GetStartupSessionInfo(dialogSessionId); if (startupSessionInfo != nullptr) { return NotifySCBToRecoveryAfterInterception(dialogSessionId, startupSessionInfo->abilityRequest); } std::shared_ptr dialogCallerInfo = GetDialogCallerInfo(dialogSessionId); if (dialogCallerInfo == nullptr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "dialog caller info is nullptr"); ClearDialogContext(dialogSessionId); return ERR_INVALID_VALUE; } auto targetWant = dialogCallerInfo->targetWant; targetWant.SetElement(want.GetElement()); targetWant.SetParam("isSelector", dialogCallerInfo->type != SelectorType::WITHOUT_SELECTOR); targetWant.SetParam(DIALOG_SESSION_ID, dialogSessionId); if (want.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY)) { int32_t appIndex = want.GetIntParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, 0); targetWant.SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, appIndex); } if (!targetWant.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY)) { targetWant.SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, 0); } sptr callerToken = dialogCallerInfo->callerToken; auto abilityMgr = DelayedSingleton::GetInstance(); if (!abilityMgr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityMgr is nullptr."); return INNER_ERR; } int ret = abilityMgr->StartAbilityAsCallerDetails(targetWant, callerToken, callerToken, dialogCallerInfo->userId, dialogCallerInfo->requestCode, false, dialogCallerInfo->type == SelectorType::APP_CLONE_SELECTOR); if (ret == ERR_OK) { ClearDialogContext(dialogSessionId); abilityMgr->RemoveSelectorIdentity(dialogCallerInfo->targetWant.GetIntParam(Want::PARAM_RESV_CALLER_TOKEN, 0)); } return ret; } int32_t DialogSessionManager::NotifySCBToRecoveryAfterInterception(const std::string &dialogSessionId, const AbilityRequest &abilityRequest) { auto abilityMgr = DelayedSingleton::GetInstance(); if (!abilityMgr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityMgr is nullptr."); return INNER_ERR; } int ret = IN_PROCESS_CALL(abilityMgr->NotifySCBToRecoveryAfterInterception(abilityRequest)); if (ret == ERR_OK) { ClearDialogContext(dialogSessionId); } return ret; } std::string DialogSessionManager::GenerateDialogSessionRecordCommon(AbilityRequest &abilityRequest, int32_t userId, const AAFwk::WantParams ¶meters, std::vector &dialogAppInfos, SelectorType type) { auto dialogSessionInfo = sptr::MakeSptr(); CHECK_POINTER_AND_RETURN(dialogSessionInfo, ""); GenerateCallerAbilityInfo(abilityRequest, dialogSessionInfo->callerAbilityInfo); if (type != SelectorType::WITHOUT_SELECTOR) { GenerateSelectorTargetAbilityInfos(dialogAppInfos, dialogSessionInfo->targetAbilityInfos); } else { GenerateJumpTargetAbilityInfos(abilityRequest, dialogSessionInfo->targetAbilityInfos); } dialogSessionInfo->parameters = parameters; std::shared_ptr dialogCallerInfo = std::make_shared(); GenerateDialogCallerInfo(abilityRequest, userId, dialogCallerInfo, type); std::string dialogSessionId = GenerateDialogSessionId(); SetDialogSessionInfo(dialogSessionId, dialogSessionInfo, dialogCallerInfo); return dialogSessionId; } int DialogSessionManager::CreateJumpModalDialog(AbilityRequest &abilityRequest, int32_t userId, const Want &replaceWant) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); AAFwk::WantParams parameters; parameters.SetParam("deviceType", AAFwk::String::Box(OHOS::system::GetDeviceType())); parameters.SetParam("userId", AAFwk::Integer::Box(userId)); std::vector dialogAppInfos; std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, parameters, dialogAppInfos, SelectorType::WITHOUT_SELECTOR); if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); return ERR_INVALID_VALUE; } return CreateModalDialogCommon(replaceWant, abilityRequest.callerToken, dialogSessionId); } int DialogSessionManager::CreateImplicitSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, std::vector &dialogAppInfos) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); AAFwk::Want sessionWant; sessionWant.SetParam("deviceType", OHOS::system::GetDeviceType()); sessionWant.SetParam("userId", userId); sessionWant.SetParam("action", abilityRequest.want.GetAction()); sessionWant.SetParam("wantType", abilityRequest.want.GetType()); sessionWant.SetParam("uri", abilityRequest.want.GetUriString()); sessionWant.SetParam("entities", abilityRequest.want.GetEntities()); sessionWant.SetParam("appselector.selectorType", static_cast(SelectorType::IMPLICIT_START_SELECTOR)); bool showCaller = abilityRequest.want.GetBoolParam("showCaller", false); sessionWant.SetParam("showCaller", showCaller); sessionWant.SetParam("ohos.ability.param.showDefaultPicker", abilityRequest.want.GetBoolParam("ohos.ability.params.showDefaultPicker", false)); std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, sessionWant.GetParams(), dialogAppInfos, SelectorType::IMPLICIT_START_SELECTOR); if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); return ERR_INVALID_VALUE; } return CreateModalDialogCommon(want, abilityRequest.callerToken, dialogSessionId); } int DialogSessionManager::CreateCloneSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, std::vector &dialogAppInfos, const std::string &replaceWant) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); AAFwk::WantParams parameters; parameters.SetParam("deviceType", AAFwk::String::Box(OHOS::system::GetDeviceType())); parameters.SetParam("userId", AAFwk::Integer::Box(userId)); parameters.SetParam("appselector.selectorType", AAFwk::Integer::Box(static_cast(SelectorType::APP_CLONE_SELECTOR))); if (replaceWant != "") { parameters.SetParam("ecological.replaceWant", AAFwk::String::Box(replaceWant)); } std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, parameters, dialogAppInfos, SelectorType::APP_CLONE_SELECTOR); if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); return ERR_INVALID_VALUE; } return CreateModalDialogCommon(want, abilityRequest.callerToken, dialogSessionId); } int DialogSessionManager::CreateModalDialogCommon(const Want &replaceWant, sptr callerToken, const std::string &dialogSessionId) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); (const_cast(replaceWant)).SetParam(DIALOG_SESSION_ID, dialogSessionId); auto connection = std::make_shared(); if (callerToken == nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "create modal ui extension for system"); (const_cast(replaceWant)).SetParam(UIEXTENSION_MODAL_TYPE, 1); (const_cast(replaceWant)).SetParam(SUPPORT_CLOSE_ON_BLUR, true); return IN_PROCESS_CALL(connection->CreateModalUIExtension(replaceWant)) ? ERR_OK : INNER_ERR; } auto callerRecord = Token::GetAbilityRecordByToken(callerToken); if (!callerRecord) { TAG_LOGE(AAFwkTag::ABILITYMGR, "callerRecord is nullptr."); return ERR_INVALID_VALUE; } sptr token; auto abilityMgr = DelayedSingleton::GetInstance(); if (!abilityMgr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityMgr is nullptr."); return INNER_ERR; } int ret = IN_PROCESS_CALL(abilityMgr->GetTopAbility(token)); if (ret != ERR_OK || token == nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "create modal ui extension for system"); (const_cast(replaceWant)).SetParam(UIEXTENSION_MODAL_TYPE, 1); (const_cast(replaceWant)).SetParam(SUPPORT_CLOSE_ON_BLUR, true); return IN_PROCESS_CALL(connection->CreateModalUIExtension(replaceWant)) ? ERR_OK : INNER_ERR; } if (callerRecord->GetAbilityInfo().type == AppExecFwk::AbilityType::PAGE && token == callerToken) { TAG_LOGD(AAFwkTag::ABILITYMGR, "create modal ui extension for application"); return callerRecord->CreateModalUIExtension(replaceWant); } TAG_LOGD(AAFwkTag::ABILITYMGR, "create modal ui extension for system"); (const_cast(replaceWant)).SetParam(UIEXTENSION_MODAL_TYPE, 1); (const_cast(replaceWant)).SetParam(SUPPORT_CLOSE_ON_BLUR, true); return IN_PROCESS_CALL(connection->CreateModalUIExtension(replaceWant)) ? ERR_OK : INNER_ERR; } int DialogSessionManager::HandleErmsResult(AbilityRequest &abilityRequest, int32_t userId, const Want &replaceWant) { std::string bundleName = abilityRequest.abilityInfo.bundleName; if (StartAbilityUtils::ermsResultCode < ERMS_ISALLOW_RESULTCODE || !IsCreateCloneSelectorDialog(bundleName, userId)) { TAG_LOGI(AAFwkTag::ABILITYMGR, "create jump modal dialog"); return CreateJumpModalDialog(abilityRequest, userId, replaceWant); } auto abilityMgr = DelayedSingleton::GetInstance(); if (!abilityMgr) { TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityMgr is nullptr."); return INNER_ERR; } (const_cast(replaceWant)).RemoveParam("ecological_experience_original_target"); return abilityMgr->CreateCloneSelectorDialog(abilityRequest, userId, replaceWant.ToString()); } int32_t DialogSessionManager::HandleErmsResultBySCB(AbilityRequest &abilityRequest, const Want &replaceWant) { auto systemUIExtension = std::make_shared(); (const_cast(replaceWant)).SetParam(UIEXTENSION_MODAL_TYPE, 1); (const_cast(replaceWant)).SetParam(SUPPORT_CLOSE_ON_BLUR, true); std::string dialogSessionId = GenerateDialogSessionId(); if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); return ERR_INVALID_VALUE; } SetStartupSessionInfo(dialogSessionId, abilityRequest); (const_cast(replaceWant)).SetParam(DIALOG_SESSION_ID, dialogSessionId); return IN_PROCESS_CALL(systemUIExtension->CreateModalUIExtension(replaceWant)) ? ERR_ECOLOGICAL_CONTROL_STATUS : INNER_ERR; } bool DialogSessionManager::IsCreateCloneSelectorDialog(const std::string &bundleName, int32_t userId) { if (StartAbilityUtils::isWantWithAppCloneIndex) { TAG_LOGI(AAFwkTag::ABILITYMGR, "want with app clone index."); StartAbilityUtils::isWantWithAppCloneIndex = false; return false; } auto appIndexes = StartAbilityUtils::GetCloneAppIndexes(bundleName, userId); if (appIndexes.empty()) { TAG_LOGI(AAFwkTag::ABILITYMGR, "The application do not create clone index."); return false; } return true; } } // namespace AAFwk } // namespace OHOS