diff --git a/frameworks/js/napi/ability_manager/BUILD.gn b/frameworks/js/napi/ability_manager/BUILD.gn index 12c739c399..fabcc40f67 100644 --- a/frameworks/js/napi/ability_manager/BUILD.gn +++ b/frameworks/js/napi/ability_manager/BUILD.gn @@ -38,8 +38,10 @@ template("abilitymanager") { deps = [ "${ability_runtime_innerkits_path}/ability_manager:ability_manager", "${ability_runtime_innerkits_path}/app_manager:app_manager", + "${ability_runtime_innerkits_path}/napi_base_context:napi_base_context", "${ability_runtime_innerkits_path}/runtime:runtime", "${ability_runtime_napi_path}/inner/napi_common:napi_common", + "${ability_runtime_native_path}/ability:ability_context_native", "${ability_runtime_native_path}/ability/native:ability_business_error", "${ability_runtime_native_path}/ability/native:abilitykit_native", ] diff --git a/frameworks/js/napi/ability_manager/js_ability_manager.cpp b/frameworks/js/napi/ability_manager/js_ability_manager.cpp index ad0b3515c5..2fe65802f5 100644 --- a/frameworks/js/napi/ability_manager/js_ability_manager.cpp +++ b/frameworks/js/napi/ability_manager/js_ability_manager.cpp @@ -34,6 +34,7 @@ #include "js_runtime.h" #include "js_runtime_utils.h" #include "napi/native_api.h" +#include "napi_base_context.h" #include "napi_common_configuration.h" #include "napi_common_util.h" #include "napi_common_want.h" @@ -115,6 +116,11 @@ public: GET_CB_INFO_AND_CALL(env, info, JsAbilityManager, OnOff); } + static napi_value IsEmbeddedOpenAllowed(napi_env env, napi_callback_info info) + { + GET_NAPI_INFO_AND_CALL(env, info, JsAbilityManager, OnIsEmbeddedOpenAllowed); + } + private: sptr observerForeground_ = nullptr; sptr appManager_ = nullptr; @@ -481,6 +487,56 @@ private: CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result)); return result; } + + napi_value OnIsEmbeddedOpenAllowed(napi_env env, NapiCallbackInfo& info) + { + HILOG_DEBUG("Called."); + if (info.argc < ARGC_TWO) { + HILOG_ERROR("Not enough params"); + ThrowTooFewParametersError(env); + return CreateJsUndefined(env); + } + + bool stageMode = false; + napi_status status = OHOS::AbilityRuntime::IsStageContext(env, info.argv[0], stageMode); + if (status != napi_ok || !stageMode) { + HILOG_ERROR("it is not a stage mode"); + ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return CreateJsUndefined(env); + } + auto context = OHOS::AbilityRuntime::GetStageModeContext(env, info.argv[0]); + if (context == nullptr) { + HILOG_ERROR("get context failed"); + ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return CreateJsUndefined(env); + } + auto uiAbilityContext = AbilityRuntime::Context::ConvertTo(context); + if (uiAbilityContext == nullptr) { + HILOG_ERROR("convert to UIAbility context failed"); + ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return CreateJsUndefined(env); + } + + std::string appId; + if (!ConvertFromJsValue(env, info.argv[1], appId)) { + HILOG_ERROR("OnOpenAtomicService, parse appId failed."); + ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_PARAM); + return CreateJsUndefined(env); + } + + auto token = uiAbilityContext->GetToken(); + + NapiAsyncTask::CompleteCallback complete = [token, appId](napi_env env, NapiAsyncTask &task, int32_t status) { + auto isAllowed = AbilityManagerClient::GetInstance()->IsEmbeddedOpenAllowed(token, appId); + task.Resolve(env, CreateJsValue(env, isAllowed)); + }; + + napi_value lastParam = (info.argc > ARGC_TWO) ?info. argv[ARGC_TWO] : nullptr; + napi_value result = nullptr; + NapiAsyncTask::Schedule("JsAbilityManager::OnIsEmbeddedOpenAllowed", env, + CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result)); + return result; + } }; } // namespace @@ -506,6 +562,7 @@ napi_value JsAbilityManagerInit(napi_env env, napi_value exportObj) env, exportObj, "getForegroundUIAbilities", moduleName, JsAbilityManager::GetForegroundUIAbilities); BindNativeFunction(env, exportObj, "on", moduleName, JsAbilityManager::On); BindNativeFunction(env, exportObj, "off", moduleName, JsAbilityManager::Off); + BindNativeFunction(env, exportObj, "isEmbeddedOpenAllowed", moduleName, JsAbilityManager::IsEmbeddedOpenAllowed); HILOG_DEBUG("end"); return CreateJsUndefined(env); } diff --git a/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp b/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp index 5f37b38f9a..46f56ad433 100644 --- a/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp +++ b/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp @@ -66,6 +66,7 @@ constexpr const char* ERROR_MSG_NO_MISSION_LISTENER = "Input error. The specifie constexpr const char* ERROR_MSG_START_ABILITY_WAITTING = "The previous ability is starting, wait start later."; constexpr const char* ERROR_MSG_NOT_SELF_APPLICATION = "The target application is not self application."; +// follow ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST of appexecfwk_errors.h in bundle_framework constexpr int32_t ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST = 8521220; static std::unordered_map ERR_CODE_MAP = { diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_client.h b/interfaces/inner_api/ability_manager/include/ability_manager_client.h index 1477a03142..49571083f0 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -1376,6 +1376,15 @@ public: int32_t OpenAtomicService(Want& want, sptr callerToken, int32_t requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE); + /** + * @brief Querying whether to allow embedded startup of atomic service. + * + * @param token The caller UIAbility token. + * @param appId The ID of the application to which this bundle belongs. + * @return Returns true to allow ability to start, or false to reject. + */ + bool IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId); + private: AbilityManagerClient(); DISALLOW_COPY_AND_MOVE(AbilityManagerClient); diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h index 6c0bda4096..69e409262a 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -1410,6 +1410,18 @@ public: { return 0; } + + /** + * @brief Querying whether to allow embedded startup of atomic service. + * + * @param token The caller UIAbility token. + * @param appId The ID of the application to which this bundle belongs. + * @return Returns true to allow ability to start, or false to reject. + */ + virtual bool IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) + { + return true; + } }; } // namespace AAFwk } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h index 059a76fe1c..952ce9e25f 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h @@ -238,6 +238,9 @@ enum class AbilityManagerInterfaceCode { // Pop-up launch of full-screen atomic service(77) OPEN_ATOMIC_SERVICE = 77, + // Querying whether to allow embedded startup of atomic service. + IS_EMBEDDED_OPEN_ALLOWED = 78, + // ipc id 1001-2000 for DMS // ipc id for starting ability (1001) START_ABILITY = 1001, diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index 40b19c2cec..63093a794c 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -1135,6 +1135,15 @@ public: */ virtual int32_t OpenAtomicService(Want& want, sptr callerToken, int32_t requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; + + /** + * @brief Querying whether to allow embedded startup of atomic service. + * + * @param token The caller UIAbility token. + * @param appId The ID of the application to which this bundle belongs. + * @return Returns true to allow ability to start, or false to reject. + */ + virtual bool IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) override; private: template int GetParcelableInfos(MessageParcel &reply, std::vector &parcelableInfos); diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 50e0991206..9bddb2d3ee 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -281,6 +281,15 @@ public: virtual int32_t OpenAtomicService(Want& want, sptr callerToken, int32_t requestCode = DEFAULT_INVAL_VALUE, int32_t userId = DEFAULT_INVAL_VALUE) override; + /** + * @brief Querying whether to allow embedded startup of atomic service. + * + * @param token The caller UIAbility token. + * @param appId The ID of the application to which this bundle belongs. + * @return Returns true to allow ability to start, or false to reject. + */ + virtual bool IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) override; + /** * Start extension ability with want, send want to ability manager service. * @@ -1903,6 +1912,9 @@ private: int32_t SignRestartAppFlag(int32_t userId, const std::string &bundleName); int32_t CheckRestartAppWant(const AAFwk::Want &want); + bool IsEmbeddedOpenAllowedInner(sptr callerToken, const std::string &appId, + std::shared_ptr callerAbility); + constexpr static int REPOLL_TIME_MICRO_SECONDS = 1000000; constexpr static int WAITING_BOOT_ANIMATION_TIMER = 5; diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index 9459765620..8296225468 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -273,6 +273,7 @@ private: int32_t GetElementNameByAppIdInner(MessageParcel &data, MessageParcel &reply); int32_t OpenAtomicServiceInner(MessageParcel &data, MessageParcel &reply); + int32_t IsEmbeddedOpenAllowedInner(MessageParcel &data, MessageParcel &reply); //insight intent related int32_t StartAbilityByInsightIntentInner(MessageParcel &data, MessageParcel &reply); diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index 4f765c302d..c19b7393f4 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -1716,5 +1716,16 @@ int32_t AbilityManagerClient::OpenAtomicService(Want& want, sptr CHECK_POINTER_RETURN_INVALID_VALUE(abms); return abms->OpenAtomicService(want, callerToken, requestCode, userId); } + +bool AbilityManagerClient::IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) +{ + HILOG_DEBUG("Get ui extension host info."); + auto abms = GetAbilityManager(); + if (abms == nullptr) { + HILOG_ERROR("abms is nullptr."); + return false; + } + return abms->IsEmbeddedOpenAllowed(callerToken, appId); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index 5b476c5acf..66dce3d364 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -4781,5 +4781,38 @@ int32_t AbilityManagerProxy::OpenAtomicService(Want& want, sptr c } return reply.ReadInt32(); } + +bool AbilityManagerProxy::IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) +{ + if (callerToken == nullptr) { + HILOG_ERROR("Input param invalid."); + return false; + } + + MessageParcel data; + if (!WriteInterfaceToken (data)) { + HILOG_ERROR("Write remote object failed."); + return false; + } + + if (!data.WriteBool(true) || !data.WriteRemoteObject(callerToken)) { + HILOG_ERROR("Write flag and callerToken failed."); + return false; + } + + if (!data.WriteString(appId)) { + HILOG_ERROR("Write userId failed."); + return false; + } + + MessageParcel reply; + MessageOption option; + auto error = SendRequest(AbilityManagerInterfaceCode::IS_EMBEDDED_OPEN_ALLOWED, data, reply, option); + if (error != NO_ERROR) { + HILOG_ERROR("Send request error: %{public}d", error); + return false; + } + return reply.ReadBool(); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index d90f80999e..bff2ed139d 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -5256,7 +5256,8 @@ int AbilityManagerService::GenerateAbilityRequest( return RESOLVE_APP_ERR; } if (request.want.GetIntParam(AAFwk::SCREEN_MODE_KEY, AAFwk::ScreenMode::IDLE_SCREEN_MODE) == 0 && - request.abilityInfo.applicationInfo.bundleType != AppExecFwk::BundleType::ATOMIC_SERVICE) { + (request.abilityInfo.applicationInfo.bundleType != AppExecFwk::BundleType::ATOMIC_SERVICE || + request.abilityInfo.launchMode != AppExecFwk::LaunchMode::SINGLETON)) { HILOG_ERROR("The interface of starting atomicService can start only atomicService."); return TARGET_ABILITY_NOT_SERVICE; } @@ -9609,6 +9610,82 @@ int32_t AbilityManagerService::SignRestartAppFlag(int32_t userId, const std::str missionListManager->SignRestartAppFlag(bundleName); return ERR_OK; } + +bool AbilityManagerService::IsEmbeddedOpenAllowed(sptr callerToken, const std::string &appId) +{ + auto deviceType = OHOS::system::GetDeviceType(); + if (deviceType != "phone") { + HILOG_ERROR("device type is not allowd."); + return false; + } + auto accessTokenId = IPCSkeleton::GetCallingTokenID(); + auto type = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(accessTokenId); + if (type != Security::AccessToken::TypeATokenTypeEnum::TOKEN_HAP) { + HILOG_ERROR("The caller is not hap."); + return false; + } + if (uiAbilityLifecycleManager_ == nullptr) { + HILOG_ERROR("The SceneBoard not enabled."); + return false; + } + auto isUIAbility = uiAbilityLifecycleManager_->IsContainsAbility(callerToken); + if (!isUIAbility) { + HILOG_ERROR("The caller is not UIAbility."); + return false; + } + auto callerAbility = Token::GetAbilityRecordByToken(callerToken); + if (callerAbility == nullptr) { + HILOG_ERROR("The caller is invalid."); + return false; + } + if (!callerAbility->IsForeground() && !callerAbility->GetAbilityForegroundingFlag()) { + HILOG_ERROR("The caller not foreground."); + return false; + } + return IsEmbeddedOpenAllowedInner(callerToken, appId, callerAbility); +} + +bool AbilityManagerService::IsEmbeddedOpenAllowedInner(sptr callerToken, const std::string &appId, + std::shared_ptr callerAbility) +{ + auto bms = GetBundleManager(); + if (bms == nullptr) { + HILOG_ERROR("bms is invalid."); + return false; + } + auto bundleName = bms->ParseBundleNameByAppId(appId); + HILOG_INFO("bundleName is %{public}s.", bundleName.c_str()); + Want launchWant; + auto queryRet = IN_PROCESS_CALL(bms->GetLaunchWantForBundle(bundleName, launchWant, GetUserId())); + if (queryRet != ERR_OK) { + HILOG_ERROR("The method returns err:%{public}d.", queryRet); + return false; + } + std::string abilityName = launchWant.GetElement().GetAbilityName(); + if (bundleName.empty() || abilityName.empty()) { + HILOG_ERROR("bundleName: %{public}s, abilityName: %{public}s", bundleName.c_str(), abilityName.c_str()); + return false; + } + AppExecFwk::ApplicationInfo appInfo; + bool ans = IN_PROCESS_CALL(bms->GetApplicationInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, + GetUserId(), appInfo)); + if (!ans) { + HILOG_ERROR("Fail to get application info."); + return false; + } + if (appInfo.bundleType != AppExecFwk::BundleType::ATOMIC_SERVICE) { + HILOG_ERROR("The target is not atomic service."); + return false; + } + launchWant.SetParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME, callerAbility->GetElementName().GetBundleName()); + auto erms = std::make_shared(); + queryRet = erms->DoProcess(launchWant, 0, GetUserId(), true, callerToken); + if (queryRet == ERR_OK) { + return true; + } + HILOG_ERROR("The erms returns err:%{public}d.", queryRet); + return false; +} } // namespace AAFwk } // namespace OHOS \ No newline at end of file diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index bd1de8b76b..cbc309fd69 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -401,6 +401,8 @@ void AbilityManagerStub::FourthStepInit() &AbilityManagerStub::GetElementNameByAppIdInner; requestFuncMap_[static_cast(AbilityManagerInterfaceCode::OPEN_ATOMIC_SERVICE)] = &AbilityManagerStub::OpenAtomicServiceInner; + requestFuncMap_[static_cast(AbilityManagerInterfaceCode::IS_EMBEDDED_OPEN_ALLOWED)] = + &AbilityManagerStub::IsEmbeddedOpenAllowedInner; } int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -3086,5 +3088,27 @@ int32_t AbilityManagerStub::OpenAtomicServiceInner(MessageParcel &data, MessageP } return ERR_OK; } + +int32_t AbilityManagerStub::IsEmbeddedOpenAllowedInner(MessageParcel &data, MessageParcel &reply) +{ + sptr callerToken = nullptr; + if (data.ReadBool()) { + callerToken = data.ReadRemoteObject(); + if (callerToken == nullptr) { + HILOG_ERROR("caller token is nullptr."); + return ERR_INVALID_VALUE; + } + } + + std::string appId = data.ReadString(); + auto result = IsEmbeddedOpenAllowed(callerToken, appId); + + if (!reply.WriteInt32(result)) { + HILOG_ERROR("Write result failed."); + return ERR_INVALID_VALUE; + } + + return NO_ERROR; +} } // namespace AAFwk } // namespace OHOS \ No newline at end of file