diff --git a/cli_tool_framework/services/climgr/src/tool_util.cpp b/cli_tool_framework/services/climgr/src/tool_util.cpp index 43773da195..8bebe8f7df 100644 --- a/cli_tool_framework/services/climgr/src/tool_util.cpp +++ b/cli_tool_framework/services/climgr/src/tool_util.cpp @@ -190,6 +190,12 @@ bool ToolUtil::GenerateSandboxConfig(const ExecToolParam ¶m, AccessToken::Ac config["cliName"] = param.toolName; config["subCliName"] = param.subcommand; config["type"] = "cli"; + nlohmann::json envConfig; + envConfig["ohos_cli_callerBundleName"] = bundleInfo.name; + envConfig["ohos_cli_callerUid"] = std::to_string(IPCSkeleton::GetCallingUid()); + envConfig["ohos_cli_callerTokenId"] = std::to_string(IPCSkeleton::GetCallingTokenID()); + config["env"] = envConfig; + sandboxConfig = config.dump(); bundleName = bundleInfo.name; TAG_LOGI(AAFwkTag::CLI_TOOL, "bundleName:%{public}s, gid:%{public}d, cliName:%{public}s, subCliName:%{public}s", diff --git a/frameworks/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp b/frameworks/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp index da9c2e26c8..351957d227 100644 --- a/frameworks/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp +++ b/frameworks/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.cpp @@ -678,7 +678,8 @@ bool BundleMgrHelper::GetApplicationInfoWithAppIndex( if (bundleMgr->GetApplicationInfo(appName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, userId, appInfo)) { return true; } - } else if (appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + } else if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { if (bundleMgr->GetCloneBundleInfo(appName, static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION), appIndex, bundleInfo, userId) == ERR_OK) { @@ -987,6 +988,25 @@ ErrCode BundleMgrHelper::QueryCloneAbilityInfo(const ElementName &element, int32 return ret; } +ErrCode BundleMgrHelper::QuerySandboxCloneAbilityInfo(const std::string &creatorBundleName, + const ElementName &element, int32_t flags, int32_t sandBoxCloneIndex, + AbilityInfo &abilityInfo, int32_t userId) +{ + TAG_LOGD(AAFwkTag::BUNDLEMGRHELPER, "called"); + auto bundleMgr = Connect(); + if (bundleMgr == nullptr) { + TAG_LOGE(AAFwkTag::BUNDLEMGRHELPER, "null bundleMgr"); + return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR; + } + + RecordCostTimeUtil timeRecord("QuerySandboxCloneAbilityInfo"); + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto ret = bundleMgr->QuerySandboxCloneAbilityInfo(creatorBundleName, element, flags, + sandBoxCloneIndex, abilityInfo, userId); + SetAbilityProcessEmpty(abilityInfo); + return ret; +} + ErrCode BundleMgrHelper::GetCloneBundleInfo(const std::string &bundleName, int32_t flags, int32_t appCloneIndex, BundleInfo &bundleInfo, int32_t userId) { diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index df97be100c..1ff1c32104 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -1404,7 +1404,7 @@ bool GetBundleForLaunchApplication(std::shared_ptr bundleMgrHel int32_t appIndex, BundleInfo &bundleInfo) { bool queryResult; - if (appIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsDlpIndex(appIndex)) { TAG_LOGD(AAFwkTag::APPKIT, "The bundleName = %{public}s", bundleName.c_str()); queryResult = (bundleMgrHelper->GetSandboxBundleInfo(bundleName, appIndex, UNSPECIFIED_USERID, bundleInfo) == 0); diff --git a/interfaces/inner_api/ability_manager/BUILD.gn b/interfaces/inner_api/ability_manager/BUILD.gn index 28e1e43bba..9c74375c1f 100644 --- a/interfaces/inner_api/ability_manager/BUILD.gn +++ b/interfaces/inner_api/ability_manager/BUILD.gn @@ -115,6 +115,7 @@ ohos_shared_library("ability_manager") { "${ability_runtime_services_path}/abilitymgr/src/skill/skill_execute_result.cpp", "${ability_runtime_services_path}/abilitymgr/src/start_params_by_SCB.cpp", "${ability_runtime_services_path}/abilitymgr/src/start_specified_ability_params.cpp", + "${ability_runtime_services_path}/abilitymgr/src/sandbox_clone_params.cpp", "${ability_runtime_services_path}/abilitymgr/src/system_ability_token_callback_stub.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_ui_extension_execute_callback_proxy.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_ui_extension_execute_callback_stub.cpp", 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 c25939492f..0179490f7f 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -1131,6 +1131,15 @@ public: * @return Returns ERR_OK on success, others on failure. */ ErrCode StartAbilityForPrelaunch(const Want &want, const int32_t frameNum = 0); + + /** + * StartSandboxCloneAbility - Start sandbox clone ability. + * @param want The want of the ability to start. + * @param params Parameters containing caller information. + * @return Returns ERR_OK on success, others on failure. + */ + ErrCode StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms); + /** * CallRequestDone, after invoke callRequest, ability will call this interface to return callee. * diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h index 1c5ea27ef5..6bb202594c 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h @@ -1436,6 +1436,11 @@ enum NativeFreeInstallError { * Result (29360227) The current application is not in a game preloading state. */ ERR_NOT_GAME_PRELOAD_STATE = 29360227, + + /** + * Result(29360228) for sandbox clone index is invalid. + */ + ERR_SANDBOX_CLONE_INDEX_INVALID = 29360228, /* codes 29360270 - 29360280 are reserved for StartSelfUIAbility by delayed process exit */ /* 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 e0c24ad21b..6bc822d47e 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -81,6 +81,7 @@ #endif #include "ihidden_start_observer.h" #include "kiosk_status.h" +#include "sandbox_clone_params.h" namespace OHOS { namespace AbilityRuntime { @@ -2630,6 +2631,17 @@ public: return 0; } + /** + * StartSandboxCloneAbility - Start sandbox clone ability. + * @param want The want of the ability to start. + * @param params Parameters containing caller information. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) + { + return 0; + } + virtual int32_t UpdateKioskApplicationList(const std::vector &appList) { return 0; 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 a2b7684713..19dbecd0a6 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 @@ -773,6 +773,9 @@ enum class AbilityManagerInterfaceCode { // start self uiability by application context in current process START_SELF_UI_ABILITY_BY_APP_CONTEXT = 6175, + + // start sandbox clone ability with sandBoxCloneIndex for CLI tool + START_SANDBOX_CLONE_ABILITY = 6176, }; } // namespace AAFwk } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/sandbox_clone_params.h b/interfaces/inner_api/ability_manager/include/sandbox_clone_params.h new file mode 100644 index 0000000000..46969052e5 --- /dev/null +++ b/interfaces/inner_api/ability_manager/include/sandbox_clone_params.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2026 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. + */ + +#ifndef OHOS_ABILITY_RUNTIME_SANDBOX_CLONE_PARAMS_H +#define OHOS_ABILITY_RUNTIME_SANDBOX_CLONE_PARAMS_H + +#include +#include + +namespace OHOS { +namespace AAFwk { +/** + * @struct SandboxCloneParams + * SandboxCloneParams is used to pass parameters for starting sandbox clone ability. + * Contains caller information needed for sandbox clone application launch. + */ +struct SandboxCloneParams : public Parcelable { + std::string callerBundleName; + int32_t callerUid = -1; + uint32_t callerTokenId = 0; + + /** + * @brief Constructor + */ + SandboxCloneParams() = default; + + /** + * @brief Destructor + */ + ~SandboxCloneParams() override = default; + + /** + * @brief Read data from parcel + * @param parcel The parcel object to read from + * @return Returns true on success, false on failure + */ + bool ReadFromParcel(Parcel &parcel); + + /** + * @brief Write data to parcel + * @param parcel The parcel object to write to + * @return Returns true on success, false on failure + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * @brief Create SandboxCloneParams from parcel + * @param parcel The parcel object to read from + * @return Returns pointer to SandboxCloneParams, or nullptr on failure + */ + static SandboxCloneParams *Unmarshalling(Parcel &parcel); +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_SANDBOX_CLONE_PARAMS_H diff --git a/interfaces/kits/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.h b/interfaces/kits/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.h index 399556ba43..41e5ef191c 100644 --- a/interfaces/kits/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.h +++ b/interfaces/kits/native/appkit/ability_bundle_manager_helper/bundle_mgr_helper.h @@ -109,6 +109,9 @@ public: ErrCode GetLaunchWantForBundle(const std::string &bundleName, Want &want, int32_t userId); ErrCode QueryCloneAbilityInfo(const ElementName &element, int32_t flags, int32_t appCloneIndex, AbilityInfo &abilityInfo, int32_t userId); + ErrCode QuerySandboxCloneAbilityInfo(const std::string &creatorBundleName, + const ElementName &element, int32_t flags, int32_t sandBoxCloneIndex, + AbilityInfo &abilityInfo, int32_t userId); ErrCode GetCloneBundleInfo(const std::string &bundleName, int32_t flags, int32_t appCloneIndex, BundleInfo &bundleInfo, int32_t userId); ErrCode QueryCloneExtensionAbilityInfoWithAppIndex(const ElementName &element, int32_t flags, int32_t appCloneIndex, diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index f51b49a1fd..c208e00ed3 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -2185,6 +2185,15 @@ public: * @return Returns ERR_OK on success, others on failure. */ virtual int StartSelfUIAbilityByAppContext(const Want &want) override; + + /** + * StartSandboxCloneAbility - Start sandbox clone ability. + * @param want The want of the ability to start. + * @param params Parameters containing caller information. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) 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 23560fb78f..d682445fae 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -68,6 +68,7 @@ #include "pending_want_manager.h" #include "permission_verification.h" #include "resident_process_manager.h" +#include "sandbox_clone_params.h" #include "scene_board/ui_ability_lifecycle_manager.h" #include "start_ability_handler.h" #include "sub_managers_helper.h" @@ -2868,6 +2869,15 @@ protected: * @return Returns ERR_OK on success, others on failure. */ virtual int StartSelfUIAbilityByAppContext(const Want &want) override; + + /** + * StartSandboxCloneAbility - Start sandbox clone ability. + * @param want The want of the ability to start. + * @param params Parameters containing caller information. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) override; + private: int GetTopAbilityInner(sptr &token, uint64_t displayId = 0); @@ -2959,6 +2969,8 @@ private: const sptr &callerToken, uint32_t specifyTokenId = 0); int StartUIAbilityBySCBDefault(sptr sessionInfo, AbilityRuntime::StartParamsBySCB ¶ms, bool &isColdStart); + int HandleSandboxCloneLaunch(sptr sessionInfo, std::shared_ptr &sandboxCloneParams, + int32_t currentUserId, EventInfo &eventInfo); int StartUIAbilityByPreInstallInner(sptr sessionInfo, uint32_t specifyTokenId, AbilityRuntime::StartParamsBySCB ¶ms, bool &isColdStart); int32_t PreStartInner(const FreeInstallInfo& taskInfo); @@ -3060,6 +3072,13 @@ private: bool IsSystemUI(const std::string &bundleName) const; int32_t GetUidByCloneBundleInfo(std::string &bundleName, int32_t callerUid, int32_t userId, int32_t &appIndex) const; + + std::string GetCreatorBundleNameForSandboxClone(const Want &want, + const std::string &callerBundleName, uint32_t callerTokenId, int32_t &errCode); + + int32_t ProcessSandboxCloneLaunch(Want &want, const std::shared_ptr &sandboxCloneParams, + int32_t userId, AppExecFwk::AbilityInfo &abilityInfo); + sptr GetWantSenderByUserId(const WantSenderInfo &wantSenderInfo, const sptr &callerToken, int32_t uid, int32_t callerUid, int32_t callerUserId); diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index 0fbea59f91..78bc215dd0 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -452,6 +452,7 @@ private: int32_t ExecuteSkillDoneWithTokenInner(MessageParcel &data, MessageParcel &reply); int32_t QuerySkillTypeInner(MessageParcel &data, MessageParcel &reply); int32_t StartSelfUIAbilityByAppContextInner(MessageParcel &data, MessageParcel &reply); + int32_t StartSandboxCloneAbilityInner(MessageParcel &data, MessageParcel &reply); }; } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 21a8b9e23f..2b0a6dc4bc 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -41,6 +41,7 @@ #include "ipc_skeleton.h" #include "lifecycle_deal.h" #include "lifecycle_state_info.h" +#include "sandbox_clone_params.h" #include "session_info.h" #include "ui_extension_window_command.h" #include "uri.h" @@ -541,6 +542,10 @@ public: void SetStartSetting(const std::shared_ptr &setting); std::shared_ptr GetStartSetting() const; + void SetSandboxCloneParams(const std::shared_ptr ¶ms); + std::shared_ptr GetSandboxCloneParams() const; + void InitSandboxCloneParams(const AbilityRequest &abilityRequest); + void SetRestarting(const bool isRestart); void SetRestarting(const bool isRestart, int32_t canReStartCount); int32_t GetRestartCount() const; @@ -954,6 +959,7 @@ protected: bool isPluginAbility_ = false; bool isPrelaunch_ = false; std::atomic isGameSAPreLaunch_ = false; + std::shared_ptr sandboxCloneParams_ = nullptr; int32_t uiExtensionAbilityId_ = 0; // uiextension ability id int32_t uid_ = 0; diff --git a/services/abilitymgr/include/ability_record/ability_request.h b/services/abilitymgr/include/ability_record/ability_request.h index ebe3fe4620..b139691117 100644 --- a/services/abilitymgr/include/ability_record/ability_request.h +++ b/services/abilitymgr/include/ability_record/ability_request.h @@ -25,6 +25,7 @@ #include "irequest_start_ability_callback.h" #include "launch_param.h" #include "process_options.h" +#include "sandbox_clone_params.h" #include "session_info.h" #include "start_options.h" #include "start_specified_ability_params.h" @@ -76,6 +77,7 @@ struct AbilityRequest { std::shared_ptr processOptions = nullptr; std::shared_ptr startWindowOption = nullptr; std::shared_ptr startSpecifiedParams = nullptr; + std::shared_ptr sandboxCloneParams = nullptr; sptr uiExtensionAbilityConnectInfo = nullptr; int64_t restartTime = 0; @@ -105,6 +107,7 @@ struct AbilityRequest { bool isFromIcon = false; bool isShellCall = false; bool isTargetPlugin = false; + bool isWebSandBoxClone = false; // Indicates web sandbox clone launch // ERMS embedded atomic service bool isQueryERMS = false; bool isEmbeddedAllowed = false; diff --git a/services/abilitymgr/include/utils/dlp_utils.h b/services/abilitymgr/include/utils/dlp_utils.h index cee36c1769..dec0004b30 100644 --- a/services/abilitymgr/include/utils/dlp_utils.h +++ b/services/abilitymgr/include/utils/dlp_utils.h @@ -52,7 +52,9 @@ using Dlp = Security::DlpPermission::DlpPermissionKit; TAG_LOGE(AAFwkTag::ABILITYMGR, "caller null"); return true; } - if (abilityRecord->GetAppIndex() <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + int32_t appIndex = abilityRecord->GetAppIndex(); + if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { return true; } if (abilityRecord->GetApplicationInfo().bundleName == want.GetBundle()) { @@ -77,14 +79,16 @@ using Dlp = Security::DlpPermission::DlpPermissionKit; { #ifdef WITH_DLP int32_t dlpIndex = want.GetIntParam(AbilityRuntime::ServerConstant::DLP_INDEX, 0); - if (dlpIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX && dlpIndex != 0) { + if (dlpIndex != 0 && + (AbilityRuntime::GlobalConstant::IsAppCloneIndex(dlpIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(dlpIndex))) { return false; } if (callerToken != nullptr) { auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); if (abilityRecord != nullptr && - abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex())) { return true; } } diff --git a/services/abilitymgr/include/utils/start_ability_utils.h b/services/abilitymgr/include/utils/start_ability_utils.h index ea1eb54fc3..0fbdfe4d0b 100644 --- a/services/abilitymgr/include/utils/start_ability_utils.h +++ b/services/abilitymgr/include/utils/start_ability_utils.h @@ -22,6 +22,7 @@ #include "ability_info.h" #include "extension_ability_info.h" #include "irequest_start_ability_callback.h" +#include "sandbox_clone_params.h" #include "start_specified_ability_params.h" #include "want.h" @@ -80,6 +81,7 @@ struct StartAbilityUtils { static thread_local bool isWantWithAppCloneIndex; static thread_local bool ermsSupportBackToCallerFlag; static thread_local bool startSpecifiedBySCB; + static thread_local bool isSandBoxClone; }; struct StartAbilityInfoWrap { @@ -115,6 +117,7 @@ struct StartAbilityWrapParam { std::string specifiedFlag; bool isGamePrelaunch = false; sptr requestCallback = nullptr; + std::shared_ptr sandboxCloneParams = nullptr; }; } } diff --git a/services/abilitymgr/src/ability_auto_startup_service.cpp b/services/abilitymgr/src/ability_auto_startup_service.cpp index 0e44642f19..9577482079 100644 --- a/services/abilitymgr/src/ability_auto_startup_service.cpp +++ b/services/abilitymgr/src/ability_auto_startup_service.cpp @@ -466,7 +466,7 @@ bool AbilityAutoStartupService::GetBundleInfo(const std::string &bundleName, int TAG_LOGE(AAFwkTag::AUTO_STARTUP, "get bundleInfo fail"); return false; } - } else if (appIndex <= GlobalConstant::MAX_APP_CLONE_INDEX) { + } else if (GlobalConstant::IsAppCloneIndex(appIndex) || GlobalConstant::IsSandboxCloneIndex(appIndex)) { auto bundleFlag = static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) + static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ABILITY) + static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY) + diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index 496cb24c1f..84fe1197cd 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -1300,6 +1300,17 @@ ErrCode AbilityManagerClient::StartAbilityForPrelaunch(const Want &want, const i return abms->StartAbilityForPrelaunch(want, frameNum); } +ErrCode AbilityManagerClient::StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto abms = GetAbilityManager(); + CHECK_POINTER_RETURN_NOT_CONNECTED(abms); + TAG_LOGI(AAFwkTag::ABILITYMGR, "StartSandboxCloneAbility, ability: %{public}s/%{public}s, " + "callerBundleName: %{public}s, callerTokenId = %{public}u", want.GetBundle().c_str(), + want.GetElement().GetAbilityName().c_str(), params.callerBundleName.c_str(), params.callerTokenId); + return abms->StartSandboxCloneAbility(want, params); +} + void AbilityManagerClient::CallRequestDone(sptr token, sptr callStub) { AbilityRuntime::FreezeUtil::GetInstance().AddLifecycleEvent(token, "AbilityManagerClient::CallRequestDone"); diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index a1f6a7fa56..91550d98e3 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -8456,5 +8456,35 @@ int32_t AbilityManagerProxy::QuerySkillType(const std::string &bundleName, const } return result; } + +int32_t AbilityManagerProxy::StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!WriteInterfaceToken(data)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write interface token fail"); + return INNER_ERR; + } + + if (!data.WriteParcelable(&want)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write want fail"); + return ERR_WRITE_WANT; + } + + if (!data.WriteParcelable(¶ms)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "write params fail"); + return INNER_ERR; + } + + auto ret = SendRequest(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY, data, reply, option); + if (ret != NO_ERROR) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "request fail:%{public}d", ret); + return ret; + } + + return reply.ReadInt32(); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 54f5298aa5..4cbc961623 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -15,6 +15,7 @@ #include "ability_manager_service.h" +#include #include #include @@ -365,6 +366,7 @@ constexpr const char* BOOTEVENT_BOOT_ANIMATION_READY = "bootevent.bootanimation. constexpr const char* NEED_STARTINGWINDOW = "ohos.ability.NeedStartingWindow"; constexpr const char* PERMISSIONMGR_BUNDLE_NAME = "com.ohos.permissionmanager"; constexpr const char* PERMISSIONMGR_ABILITY_NAME = "com.ohos.permissionmanager.GrantAbility"; +constexpr const char* PERMISSION_CLI_MANAGE_WEB_SANDBOX = "ohos.permission.CLI_MANAGE_WEB_SANDBOX"; constexpr const char* SCENEBOARD_BUNDLE_NAME = "com.ohos.sceneboard"; constexpr const char* SPECIFY_TOKEN_ID = "specifyTokenId"; constexpr int CREATE_STATUS_BAR_TIMEOUT_MILLISECONDS = 5000; // 5s @@ -1462,8 +1464,28 @@ int AbilityManagerService::StartAbilityInner(StartAbilityWrapParam ¶m) int32_t validUserId = oriValidUserId; StartAbilityUtils::SetTargetCloneIndexInSameBundle(param.want, param.callerToken); + auto sandboxCloneParams = param.sandboxCloneParams; + if (param.callerToken != nullptr) { + auto callerRecord = Token::GetAbilityRecordByToken(param.callerToken); + if (callerRecord) { + sandboxCloneParams = callerRecord->GetSandboxCloneParams(); + TAG_LOGD(AAFwkTag::ABILITYMGR, "get sandboxCloneParams from callerRecord"); + } + } + // Process sandbox clone app launch if sandBoxCloneIndex parameter is present + AppExecFwk::AbilityInfo sandboxAbilityInfo; + auto cloneRet = ProcessSandboxCloneLaunch(param.want, sandboxCloneParams, validUserId, sandboxAbilityInfo); + if (cloneRet != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ProcessSandboxCloneLaunch failed: %{public}d", cloneRet); + AbilityEventUtil::SendStartAbilityErrorEvent(eventInfo, cloneRet, "ProcessSandboxCloneLaunch failed"); + return cloneRet; + } + int32_t appIndex = 0; - if (!StartAbilityUtils::GetAppIndex(param.want, param.callerToken, appIndex)) { + if (!sandboxAbilityInfo.bundleName.empty()) { + appIndex = sandboxAbilityInfo.applicationInfo.appIndex; + TAG_LOGD(AAFwkTag::ABILITYMGR, "Using sandbox clone appIndex: %{public}d from sandboxAbilityInfo", appIndex); + } else if (!StartAbilityUtils::GetAppIndex(param.want, param.callerToken, appIndex)) { AbilityEventUtil::SendStartAbilityErrorEvent(eventInfo, ERR_APP_CLONE_INDEX_INVALID, "GetAppIndex failed"); return ERR_APP_CLONE_INDEX_INVALID; } @@ -1476,6 +1498,19 @@ int AbilityManagerService::StartAbilityInner(StartAbilityWrapParam ¶m) return checkRet; } } + + // Cache the queried abilityInfo to avoid redundant BMS query + if (!sandboxAbilityInfo.bundleName.empty()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Caching sandbox clone abilityInfo for reuse"); + if (StartAbilityUtils::startAbilityInfo == nullptr) { + StartAbilityUtils::startAbilityInfo = std::make_shared(); + } + StartAbilityUtils::startAbilityInfo->abilityInfo = sandboxAbilityInfo; + StartAbilityUtils::isSandBoxClone = true; + TAG_LOGD(AAFwkTag::ABILITYMGR, "Cache set, bundle=%{public}s, appIndex=%{public}d", + sandboxAbilityInfo.bundleName.c_str(), sandboxAbilityInfo.applicationInfo.appIndex); + } + StartAbilityInfoWrap threadLocalInfo(param.want, validUserId, appIndex, param.callerToken); // Remove ATOMIC_SERVICE_SHARE_ROUTER if target is not atomic service or caller doesn't have permission if (StartAbilityUtils::startAbilityInfo != nullptr) { @@ -1523,6 +1558,7 @@ int AbilityManagerService::StartAbilityInner(StartAbilityWrapParam ¶m) abilityRequest.isStartByOEExt = param.isStartByOEExt; abilityRequest.specifiedFlag = param.specifiedFlag; abilityRequest.requestCallback = param.requestCallback; + abilityRequest.isWebSandBoxClone = !sandboxAbilityInfo.bundleName.empty(); #ifdef SUPPORT_SCREEN if (ImplicitStartProcessor::IsImplicitStartAction(param.want)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "is implicit start action"); @@ -1601,6 +1637,17 @@ int AbilityManagerService::StartAbilityInner(StartAbilityWrapParam ¶m) return result; } + // Store sandbox clone params in abilityRequest.want for later use in StartUIAbilityBySCB + if (!sandboxAbilityInfo.bundleName.empty() && param.sandboxCloneParams != nullptr) { + abilityRequest.want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME, + param.sandboxCloneParams->callerBundleName); + abilityRequest.want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID, + std::to_string(param.sandboxCloneParams->callerTokenId)); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Stored sandbox clone params in want: bundle = %{public}s, " + "tokenId = %{public}u", param.sandboxCloneParams->callerBundleName.c_str(), + param.sandboxCloneParams->callerTokenId); + } + if (abilityRequest.requestCode != DEFAULT_REQUEST_CODE && ForegroundAppConnectionManager::IsForegroundAppConnection(abilityRequest.abilityInfo, abilityRecord)) { DelayedSingleton::GetInstance()->OnCallerStarted(IPCSkeleton::GetCallingPid(), @@ -3255,12 +3302,20 @@ int AbilityManagerService::StartUIAbilityBySCBDefault(sptr sessionI auto requestCode = sessionInfo->requestCode; int32_t appIndex = 0; - if (!StartAbilityUtils::GetAppIndex(sessionInfo->want, sessionInfo->callerToken, appIndex)) { + auto sandboxCloneParams = std::make_shared(); + if (sessionInfo->want.HasParameter(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX)) { + appIndex = sessionInfo->want.GetIntParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 0); + auto cloneRet = HandleSandboxCloneLaunch(sessionInfo, sandboxCloneParams, currentUserId, eventInfo); + if (cloneRet != ERR_OK) { + return cloneRet; + } + } else if (!StartAbilityUtils::GetAppIndex(sessionInfo->want, sessionInfo->callerToken, appIndex)) { TAG_LOGE(AAFwkTag::ABILITYMGR, "get app index error"); return ERR_APP_CLONE_INDEX_INVALID; } StartAbilityInfoWrap threadLocalInfo(sessionInfo->want, currentUserId, appIndex, sessionInfo->callerToken); AbilityRequest abilityRequest; + abilityRequest.sandboxCloneParams = sandboxCloneParams; abilityRequest.processOptions = sessionInfo->processOptions; auto result = GenerateAbilityRequest(sessionInfo->want, requestCode, abilityRequest, sessionInfo->callerToken, currentUserId); @@ -3270,6 +3325,12 @@ int AbilityManagerService::StartUIAbilityBySCBDefault(sptr sessionI "generate ability request local error", true); return result; } + abilityRequest.isWebSandBoxClone = sessionInfo->want.GetBoolParam( + AbilityRuntime::GlobalConstant::IS_WEB_SANDBOX_CLONE, false); + sessionInfo->want.RemoveParam(AbilityRuntime::GlobalConstant::IS_WEB_SANDBOX_CLONE); + sessionInfo->want.RemoveParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX); + sessionInfo->want.RemoveParam(AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME); + sessionInfo->want.RemoveParam(AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID); if (sessionInfo->want.GetBoolParam(ServerConstant::IS_CALL_BY_SCB, true)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "interceptorExecuter_ called"); (sessionInfo->want).RemoveParam(IS_CALLING_FROM_DMS); @@ -3368,6 +3429,58 @@ int32_t AbilityManagerService::StartUIAbilityBySCBDefaultCommon(AbilityRequest & return uiAbilityManager->StartUIAbility(abilityRequest, sessionInfo, params, isColdStart); } +int AbilityManagerService::HandleSandboxCloneLaunch(sptr sessionInfo, + std::shared_ptr &sandboxCloneParams, int32_t currentUserId, EventInfo &eventInfo) +{ + AppExecFwk::AbilityInfo sandboxAbilityInfo; + if (sessionInfo->callerToken != nullptr) { + auto callerRecord = Token::GetAbilityRecordByToken(sessionInfo->callerToken); + if (callerRecord && callerRecord->GetAbilityInfo().bundleName == sessionInfo->want.GetBundle()) { + auto callerSandboxCloneParam = callerRecord->GetSandboxCloneParams(); + if (callerSandboxCloneParam && sandboxCloneParams) { + sandboxCloneParams->callerBundleName = callerSandboxCloneParam->callerBundleName; + sandboxCloneParams->callerTokenId = callerSandboxCloneParam->callerTokenId; + TAG_LOGD(AAFwkTag::ABILITYMGR, "get scb sandboxCloneParams from callerBundleName = %{public}s", + sandboxCloneParams->callerBundleName.c_str()); + } + } + } else { + sandboxCloneParams->callerBundleName = sessionInfo->want.GetStringParam( + AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME); + std::string callerTokenIdStr = sessionInfo->want.GetStringParam( + AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID); + if (!callerTokenIdStr.empty()) { + auto res = std::from_chars(callerTokenIdStr.data(), callerTokenIdStr.data() + callerTokenIdStr.size(), + sandboxCloneParams->callerTokenId); + if (res.ec != std::errc()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to parse callerTokenId: %{public}s", callerTokenIdStr.c_str()); + sandboxCloneParams->callerTokenId = 0; + } + } else { + TAG_LOGW(AAFwkTag::ABILITYMGR, "callerTokenId string is empty, using default value 0"); + sandboxCloneParams->callerTokenId = 0; + } + } + auto cloneRet = ProcessSandboxCloneLaunch(sessionInfo->want, sandboxCloneParams, currentUserId, + sandboxAbilityInfo); + if (cloneRet != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "ProcessSandboxCloneLaunch failed: %{public}d", cloneRet); + AbilityEventUtil::SendStartAbilityErrorEvent(eventInfo, cloneRet, "ProcessSandboxCloneLaunch failed"); + return cloneRet; + } + // Cache the queried abilityInfo to avoid redundant BMS query in GenerateAbilityRequest + if (!sandboxAbilityInfo.bundleName.empty()) { + if (StartAbilityUtils::startAbilityInfo == nullptr) { + StartAbilityUtils::startAbilityInfo = std::make_shared(); + } + StartAbilityUtils::startAbilityInfo->abilityInfo = sandboxAbilityInfo; + StartAbilityUtils::isSandBoxClone = true; + TAG_LOGD(AAFwkTag::ABILITYMGR, "SCB Cache set, bundle = %{public}s, appIndex = %{public}d", + sandboxAbilityInfo.bundleName.c_str(), sandboxAbilityInfo.applicationInfo.appIndex); + } + return ERR_OK; +} + int32_t AbilityManagerService::NotifySCBToRecoveryAfterInterception(const AbilityRequest &abilityRequest) { auto uiAbilityManager = GetUIAbilityManagerByUid(IPCSkeleton::GetCallingUid()); @@ -6703,6 +6816,78 @@ int32_t AbilityManagerService::GetUidByCloneBundleInfo( return bundleInfo.uid; } +std::string AbilityManagerService::GetCreatorBundleNameForSandboxClone(const Want &want, + const std::string &callerBundleName, uint32_t callerTokenId, int32_t &errCode) +{ + errCode = ERR_OK; + std::string inputCreatorBundleName = want.GetStringParam(AbilityRuntime::GlobalConstant::CREATOR_BUNDLE_NAME); + bool hasManageSandboxPermission = Security::AccessToken::AccessTokenKit::VerifyAccessToken( + callerTokenId, PERMISSION_CLI_MANAGE_WEB_SANDBOX, false) == + Security::AccessToken::PermissionState::PERMISSION_GRANTED; + + bool isCliCreatorBundleName = hasManageSandboxPermission && !inputCreatorBundleName.empty(); + std::string creatorBundleName; + creatorBundleName = isCliCreatorBundleName ? inputCreatorBundleName : callerBundleName; + + if (creatorBundleName.empty()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Failed to get creator bundle name"); + errCode = ERR_INVALID_VALUE; + return ""; + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "GetCreatorBundleName for sandboxClone: %{public}s", creatorBundleName.c_str()); + + return creatorBundleName; +} + +int32_t AbilityManagerService::ProcessSandboxCloneLaunch(Want &want, + const std::shared_ptr &sandboxCloneParams, int32_t userId, + AppExecFwk::AbilityInfo &abilityInfo) +{ + // Check if this is a sandbox clone launch (sandboxCloneParams is not null or has sandBoxCloneIndex parameter) + if (!sandboxCloneParams || !want.HasParameter(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX)) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Not a sandbox clone launch"); + return ERR_OK; + } + + int32_t sandBoxCloneIndex = want.GetIntParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 0); + if (!AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(sandBoxCloneIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Invalid sandBoxCloneIndex= %{public}d", sandBoxCloneIndex); + return ERR_SANDBOX_CLONE_INDEX_INVALID; + } + // Step 1: Get creator bundle name based on permission check, and get elementName. + int32_t errCode = ERR_OK; + std::string creatorBundleName = GetCreatorBundleNameForSandboxClone(want, sandboxCloneParams->callerBundleName, + sandboxCloneParams->callerTokenId, errCode); + if (errCode != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetCreatorBundleNameForSandboxClone failed: %{public}d", errCode); + return errCode; + } + std::string targetBundleName = want.GetBundle(); + std::string targetAbilityName = want.GetElement().GetAbilityName(); + std::string targetModuleName = want.GetModuleName(); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Creator bundle name: %{public}s, Target sandbox clone: bundle=%{public}s, " + "ability = %{public}s, module = %{public}s, sandBoxCloneIndex = %{public}d", creatorBundleName.c_str(), + targetBundleName.c_str(), targetAbilityName.c_str(), targetModuleName.c_str(), sandBoxCloneIndex); + + AppExecFwk::ElementName elementName; + elementName.SetBundleName(targetBundleName); + elementName.SetAbilityName(targetAbilityName); + elementName.SetModuleName(targetModuleName); + // Step 2: Query clone ability info from BMS + auto bundleMgrHelper = DelayedSingleton::GetInstance(); + CHECK_POINTER_AND_RETURN(bundleMgrHelper, GET_ABILITY_SERVICE_FAILED); + + errCode = IN_PROCESS_CALL(bundleMgrHelper->QuerySandboxCloneAbilityInfo(creatorBundleName, elementName, + static_cast(AppExecFwk::GetAbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION),sandBoxCloneIndex, + abilityInfo, userId)); + if (errCode != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "QuerySandboxCloneAbilityInfo failed, ret= %{public}d", errCode); + return errCode; + } + + return ERR_OK; +} + sptr AbilityManagerService::GetWantSenderByUserId(const WantSenderInfo &wantSenderInfo, const sptr &callerToken, int32_t uid, int32_t callerUid, int32_t callerUserId) { @@ -8550,7 +8735,7 @@ int AbilityManagerService::GenerateAbilityRequest(const Want &want, int requestC if (abilityRecord != nullptr) { request.callerTokenRecordId = abilityRecord->GetRecordId(); } - if (abilityRecord && abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX && + if (abilityRecord && AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()) && abilityRecord->GetApplicationInfo().bundleName == want.GetBundle()) { (const_cast(want)).SetParam(AbilityRuntime::ServerConstant::DLP_INDEX, abilityRecord->GetAppIndex()); (const_cast(want)).SetParam(DLP_PARAMS_SECURITY_FLAG, abilityRecord->GetSecurityFlag()); @@ -8691,7 +8876,7 @@ int AbilityManagerService::GenerateExtensionAbilityRequest(const Want &want, Abi } } } - if (abilityRecord && abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX && + if (abilityRecord && AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()) && abilityRecord->GetApplicationInfo().bundleName == want.GetBundle()) { (const_cast(want)).SetParam(AbilityRuntime::ServerConstant::DLP_INDEX, abilityRecord->GetAppIndex()); (const_cast(want)).SetParam(DLP_PARAMS_SECURITY_FLAG, abilityRecord->GetSecurityFlag()); @@ -18841,5 +19026,44 @@ int32_t AbilityManagerService::AtomicServicePreprocess(const Want &want) #endif return ATOMIC_URL; } + +int32_t AbilityManagerService::StartSandboxCloneAbility(const Want &want, const SandboxCloneParams ¶ms) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGI(AAFwkTag::ABILITYMGR, "StartSandboxCloneAbility called with callerBundleName = %{public}s, " + "callerUid = %{public}d, callerTokenId = %{public}u", params.callerBundleName.c_str(), params.callerUid, + params.callerTokenId); + + auto tokenId = IPCSkeleton::GetCallingTokenID(); + if (!Security::AccessToken::AccessTokenKit::IsCliToolToken(tokenId)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Caller is not CLI tool, tokenId=%{public}u", params.callerTokenId); + return ERR_PERMISSION_DENIED; + } + + if (!want.HasParameter(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "SANDBOX_CLONE_INDEX parameter not found in Want"); + return ERR_INVALID_VALUE; + } + + int32_t sandBoxCloneIndex = want.GetIntParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 0); + if (!AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(sandBoxCloneIndex)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Invalid sandBoxCloneIndex: %{public}d", sandBoxCloneIndex); + return ERR_SANDBOX_CLONE_INDEX_INVALID; + } + + Want modifiedWant = want; + modifiedWant.RemoveParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY); + modifiedWant.RemoveParam(AbilityRuntime::ServerConstant::DLP_INDEX); + + StartAbilityWrapParam startParam; + startParam.want = modifiedWant; + startParam.sandboxCloneParams = std::make_shared(params); + int32_t result = StartAbilityInner(startParam); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "StartSandboxCloneAbility failed: %{public}d", result); + return result; + } + return ERR_OK; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index e40dc153eb..678b7c92e6 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -333,6 +333,9 @@ int AbilityManagerStub::OnRemoteRequestInnerSeventh(uint32_t code, MessageParcel if (interfaceCode == AbilityManagerInterfaceCode::GET_PENDING_WANT_TYPE) { return GetPendingWantTypeInner(data, reply); } + if (interfaceCode == AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY) { + return StartSandboxCloneAbilityInner(data, reply); + } if (interfaceCode == AbilityManagerInterfaceCode::REGISTER_CANCEL_LISTENER) { return RegisterCancelListenerInner(data, reply); } @@ -5860,5 +5863,24 @@ int32_t AbilityManagerStub::StartSelfUIAbilityByAppContextInner(MessageParcel &d reply.WriteInt32(result); return NO_ERROR; } + +int32_t AbilityManagerStub::StartSandboxCloneAbilityInner(MessageParcel &data, MessageParcel &reply) +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "StartSandboxCloneAbility stub called"); + std::shared_ptr want(data.ReadParcelable()); + if (want == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "want null"); + return ERR_INVALID_VALUE; + } + std::shared_ptr params(data.ReadParcelable()); + if (params == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "params null"); + return ERR_INVALID_VALUE; + } + + int32_t result = StartSandboxCloneAbility(*want, *params); + reply.WriteInt32(result); + return NO_ERROR; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_record.cpp b/services/abilitymgr/src/ability_record.cpp index 96502772e0..9442652442 100644 --- a/services/abilitymgr/src/ability_record.cpp +++ b/services/abilitymgr/src/ability_record.cpp @@ -15,6 +15,7 @@ #include "ability_record.h" +#include #include #include "ability_manager_service.h" @@ -191,7 +192,13 @@ void AbilityRecord::Init(const AbilityRequest &abilityRequest) { SetUid(abilityRequest.uid); int32_t appIndex = 0; - (void)AbilityRuntime::StartupUtil::GetAppIndex(abilityRequest.want, appIndex); + if (abilityRequest.isWebSandBoxClone) { + appIndex = abilityRequest.abilityInfo.applicationInfo.appIndex; + InitSandboxCloneParams(abilityRequest); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Web sandbox clone, using appIndex from abilityInfo: %{public}d", appIndex); + } else { + (void)AbilityRuntime::StartupUtil::GetAppIndex(abilityRequest.want, appIndex); + } SetAppIndex(appIndex); SetSecurityFlag(abilityRequest.want.GetBoolParam(DLP_PARAMS_SECURITY_FLAG, false)); SetCallerAccessTokenId(abilityRequest.callerAccessTokenId); @@ -235,6 +242,20 @@ void AbilityRecord::Init(const AbilityRequest &abilityRequest) } } +void AbilityRecord::InitSandboxCloneParams(const AbilityRequest &abilityRequest) +{ + if (abilityRequest.sandboxCloneParams == nullptr) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "abilityRequest.sandboxCloneParams is nullptr"); + return; + } + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = abilityRequest.sandboxCloneParams->callerBundleName; + sandboxCloneParams->callerTokenId = abilityRequest.sandboxCloneParams->callerTokenId; + SetSandboxCloneParams(sandboxCloneParams); + TAG_LOGD(AAFwkTag::ABILITYMGR, "InitSandboxCloneParams, callerBundleName = %{public}s, callerTokenId = %{public}d", + sandboxCloneParams->callerBundleName.c_str(), sandboxCloneParams->callerTokenId); +} + AbilityRecordType AbilityRecord::GetAbilityRecordType() { return AbilityRecordType::BASE_ABILITY; @@ -1393,7 +1414,7 @@ void AbilityRecord::SendResultToCallers(bool schedulerdied) } std::shared_ptr callerAbilityRecord = caller->GetCaller(); if (callerAbilityRecord != nullptr && callerAbilityRecord->GetResult() != nullptr) { - bool isSandboxApp = appIndex_ > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX ? true : false; + bool isSandboxApp = AbilityRuntime::GlobalConstant::IsDlpIndex(appIndex_); callerAbilityRecord->SendResult(isSandboxApp, abilityInfo_.applicationInfo.accessTokenId, schedulerdied); } else { std::shared_ptr callerSystemAbilityRecord = caller->GetSaCaller(); @@ -2232,6 +2253,16 @@ std::shared_ptr AbilityRecord::GetStartSetting() const return lifeCycleStateInfo_.setting; } +void AbilityRecord::SetSandboxCloneParams(const std::shared_ptr ¶ms) +{ + sandboxCloneParams_ = params; +} + +std::shared_ptr AbilityRecord::GetSandboxCloneParams() const +{ + return sandboxCloneParams_; +} + void AbilityRecord::SetRestarting(const bool isRestart) { isRestarting_ = isRestart; @@ -2816,8 +2847,8 @@ void AbilityRecord::GrantUriPermission(Want &want, std::string targetBundleName, } // reject sandbox to grant uri permission by start ability auto caller = GetCallerRecord(); - if (caller && caller->appIndex_ > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "sandbox can not grant UriPermission"); + if (caller && AbilityRuntime::GlobalConstant::IsDlpIndex(caller->appIndex_)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "DLP sandbox can not grant UriPermission"); return; } auto callerTokenId = tokenId > 0 ? tokenId : @@ -2866,7 +2897,7 @@ void AbilityRecord::HandleDlpAttached() DelayedSingleton::GetInstance()->AddDlpManager(shared_from_this()); } - if (appIndex_ > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsDlpIndex(appIndex_)) { DelayedSingleton::GetInstance()->AddDlpAbility(shared_from_this()); } } @@ -2877,7 +2908,7 @@ void AbilityRecord::HandleDlpClosed() DelayedSingleton::GetInstance()->RemoveDlpManager(shared_from_this()); } - if (appIndex_ > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsDlpIndex(appIndex_)) { DelayedSingleton::GetInstance()->RemoveDlpAbility(shared_from_this()); } } diff --git a/services/abilitymgr/src/connection_state_manager.cpp b/services/abilitymgr/src/connection_state_manager.cpp index 7a3d31a26d..c0686a9b3e 100644 --- a/services/abilitymgr/src/connection_state_manager.cpp +++ b/services/abilitymgr/src/connection_state_manager.cpp @@ -506,7 +506,7 @@ bool ConnectionStateManager::HandleDlpAbilityInner(const std::shared_ptrGetAppIndex() <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (!AbilityRuntime::GlobalConstant::IsDlpIndex(dlpAbility->GetAppIndex())) { TAG_LOGD(AAFwkTag::CONNECTION, " not dlp ability, do not report connection stat"); return false; } diff --git a/services/abilitymgr/src/dlp_state_item.cpp b/services/abilitymgr/src/dlp_state_item.cpp index b3f13174cd..128c2514e2 100644 --- a/services/abilitymgr/src/dlp_state_item.cpp +++ b/services/abilitymgr/src/dlp_state_item.cpp @@ -53,7 +53,7 @@ int32_t DlpStateItem::GetOpenedAbilitySize() const bool DlpStateItem::HandleDlpConnectionState(const std::shared_ptr &record, bool isAdd, AbilityRuntime::DlpStateData &data) { - if (!record || record->GetAppIndex() <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (!record || !AbilityRuntime::GlobalConstant::IsDlpIndex(record->GetAppIndex())) { TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid dlp ability"); return false; } diff --git a/services/abilitymgr/src/mission/mission_list_manager.cpp b/services/abilitymgr/src/mission/mission_list_manager.cpp index a6313f89d3..d962b47b34 100644 --- a/services/abilitymgr/src/mission/mission_list_manager.cpp +++ b/services/abilitymgr/src/mission/mission_list_manager.cpp @@ -709,7 +709,7 @@ void MissionListManager::BuildInnerMissionInfo(InnerMissionInfo &info, const std info.missionInfo.unclearable = abilityRequest.abilityInfo.unclearableMission; info.isTemporary = abilityRequest.abilityInfo.removeMissionAfterTerminate; auto dlpIndex = abilityRequest.want.GetIntParam(AbilityRuntime::ServerConstant::DLP_INDEX, 0); - if (dlpIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsDlpIndex(dlpIndex)) { info.isTemporary = true; } info.specifiedFlag = abilityRequest.specifiedFlag; @@ -1922,8 +1922,8 @@ void MissionListManager::CompleteTerminateAndUpdateMission(const std::shared_ptr terminateAbilityList_.remove(it); // update inner mission info time bool excludeFromMissions = abilityRecord->GetAbilityInfo().excludeFromMissions; - if ((abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) || - abilityRecord->GetAbilityInfo().removeMissionAfterTerminate || excludeFromMissions) { + bool isDlp = AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()); + if (isDlp || abilityRecord->GetAbilityInfo().removeMissionAfterTerminate || excludeFromMissions) { RemoveMissionLocked(abilityRecord->GetMissionId(), excludeFromMissions); return; } @@ -2144,7 +2144,7 @@ void MissionListManager::UpdateSnapShot(const sptr &token, return; } int32_t missionId = abilityRecord->GetMissionId(); - auto isPrivate = abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX; + auto isPrivate = AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()); DelayedSingleton::GetInstance()->UpdateMissionSnapshot(missionId, pixelMap, isPrivate); if (listenerController_) { listenerController_->NotifyMissionSnapshotChanged(missionId); @@ -2332,7 +2332,7 @@ void MissionListManager::UpdateMissionSnapshot(const std::shared_ptrGetMissionId(); MissionSnapshot snapshot; - snapshot.isPrivate = (abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX); + snapshot.isPrivate = AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()); DelayedSingleton::GetInstance()->UpdateMissionSnapshot(missionId, abilityRecord->GetToken(), snapshot); if (listenerController_) { @@ -2870,8 +2870,9 @@ void MissionListManager::HandleAbilityDiedByDefault(std::shared_ptrGetMissionId(); if (!ability->IsUninstallAbility()) { - if ((ability->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) || - ability->GetAbilityInfo().removeMissionAfterTerminate || ability->GetAbilityInfo().excludeFromMissions) { + bool isDlp = AbilityRuntime::GlobalConstant::IsDlpIndex(ability->GetAppIndex()); + if (isDlp || ability->GetAbilityInfo().removeMissionAfterTerminate || + ability->GetAbilityInfo().excludeFromMissions) { RemoveMissionLocked(missionId, ability->GetAbilityInfo().excludeFromMissions); } else { InnerMissionInfo info; @@ -3819,8 +3820,7 @@ bool MissionListManager::GetMissionSnapshot(int32_t missionId, MissionSnapshot& auto abilityRecord = GetAbilityRecordByTokenInner(abilityToken); if (abilityRecord && abilityRecord->IsAbilityState(FOREGROUND)) { forceSnapshot = true; - missionSnapshot.isPrivate = - (abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX); + missionSnapshot.isPrivate = AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex()); } } return DelayedSingleton::GetInstance()->GetMissionSnapshot( diff --git a/services/abilitymgr/src/sandbox_clone_params.cpp b/services/abilitymgr/src/sandbox_clone_params.cpp new file mode 100644 index 0000000000..db3f88d60d --- /dev/null +++ b/services/abilitymgr/src/sandbox_clone_params.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2026 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 "sandbox_clone_params.h" + +namespace OHOS { +namespace AAFwk { +bool SandboxCloneParams::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(callerBundleName)) { + return false; + } + if (!parcel.ReadInt32(callerUid)) { + return false; + } + if (!parcel.ReadUint32(callerTokenId)) { + return false; + } + return true; +} + +SandboxCloneParams *SandboxCloneParams::Unmarshalling(Parcel &parcel) +{ + SandboxCloneParams *params = new (std::nothrow) SandboxCloneParams(); + if (params == nullptr) { + return nullptr; + } + + if (!params->ReadFromParcel(parcel)) { + delete params; + params = nullptr; + } + return params; +} + +bool SandboxCloneParams::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(callerBundleName)) { + return false; + } + if (!parcel.WriteInt32(callerUid)) { + return false; + } + if (!parcel.WriteUint32(callerTokenId)) { + return false; + } + return true; +} +} // namespace AAFwk +} // namespace OHOS diff --git a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp index 58a09e77a8..2eb302da97 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -795,6 +795,21 @@ int UIAbilityLifecycleManager::NotifySCBToStartUIAbility(AbilityRequest &ability sessionInfo->persistentId = persistentId; sessionInfo->reuse = reuse; } + // Store isWebSandBoxClone and appIndex in want for SCB callback. + if (abilityRequest.isWebSandBoxClone) { + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::IS_WEB_SANDBOX_CLONE, + abilityRequest.isWebSandBoxClone); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, + abilityRequest.abilityInfo.applicationInfo.appIndex); + std::string callerBundleName = abilityRequest.want.GetStringParam( + AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME); + std::string callerTokenId = abilityRequest.want.GetStringParam( + AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME, callerBundleName); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID, callerTokenId); + TAG_LOGD(AAFwkTag::ABILITYMGR, "WebSandBoxClone params: bundle = %{public}s, tokenId = %{public}s", + callerBundleName.c_str(), callerTokenId.c_str()); + } sessionInfo->userId = userId_; sessionInfo->isAtomicService = (abilityInfo.applicationInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE); TAG_LOGI(AAFwkTag::ABILITYMGR, diff --git a/services/abilitymgr/src/start_ability_handler.cpp b/services/abilitymgr/src/start_ability_handler.cpp index 20b9f8d65e..4489c1e6ea 100644 --- a/services/abilitymgr/src/start_ability_handler.cpp +++ b/services/abilitymgr/src/start_ability_handler.cpp @@ -25,7 +25,7 @@ namespace OHOS { namespace AAFwk { bool StartAbilityParams::IsCallerSandboxApp() { - return GetCallerAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX; + return AbilityRuntime::GlobalConstant::IsDlpIndex(GetCallerAppIndex()); } #ifdef WITH_DLP diff --git a/services/abilitymgr/src/utils/start_ability_utils.cpp b/services/abilitymgr/src/utils/start_ability_utils.cpp index e2bfb250b4..7bf8b23262 100644 --- a/services/abilitymgr/src/utils/start_ability_utils.cpp +++ b/services/abilitymgr/src/utils/start_ability_utils.cpp @@ -43,12 +43,13 @@ thread_local int32_t StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE thread_local bool StartAbilityUtils::isWantWithAppCloneIndex = false; thread_local bool StartAbilityUtils::ermsSupportBackToCallerFlag = false; thread_local bool StartAbilityUtils::startSpecifiedBySCB = false; +thread_local bool StartAbilityUtils::isSandBoxClone = false; bool StartAbilityUtils::GetAppIndex(const Want &want, sptr callerToken, int32_t &appIndex) { auto abilityRecord = Token::GetAbilityRecordByToken(callerToken); if (abilityRecord && abilityRecord->GetApplicationInfo().bundleName == want.GetBundle() && - abilityRecord->GetAppIndex() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + AbilityRuntime::GlobalConstant::IsDlpIndex(abilityRecord->GetAppIndex())) { appIndex = abilityRecord->GetAppIndex(); return true; } @@ -137,6 +138,10 @@ StartAbilityInfoWrap::StartAbilityInfoWrap(const Want &want, int32_t validUserId if (StartAbilityUtils::startAbilityInfo != nullptr) { TAG_LOGW(AAFwkTag::ABILITYMGR, "startAbilityInfo created"); } + if (StartAbilityUtils::isSandBoxClone) { + return; + } + Want localWant = want; if (!StartAbilityUtils::IsCallFromAncoShellOrBroker(callerToken)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "not call from anco or broker."); @@ -184,6 +189,7 @@ StartAbilityInfoWrap::StartAbilityInfoWrap() StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE; StartAbilityUtils::isWantWithAppCloneIndex = false; StartAbilityUtils::ermsSupportBackToCallerFlag = false; + StartAbilityUtils::isSandBoxClone = false; } StartAbilityInfoWrap::~StartAbilityInfoWrap() @@ -196,6 +202,7 @@ StartAbilityInfoWrap::~StartAbilityInfoWrap() StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE; StartAbilityUtils::isWantWithAppCloneIndex = false; StartAbilityUtils::ermsSupportBackToCallerFlag = false; + StartAbilityUtils::isSandBoxClone = false; } void StartAbilityInfoWrap::SetStartAbilityInfo(const AppExecFwk::AbilityInfo& abilityInfo) @@ -205,6 +212,8 @@ void StartAbilityInfoWrap::SetStartAbilityInfo(const AppExecFwk::AbilityInfo& ab } StartAbilityUtils::startAbilityInfo = std::make_shared(); StartAbilityUtils::startAbilityInfo->abilityInfo = abilityInfo; + TAG_LOGD(AAFwkTag::ABILITYMGR, "SetStartAbilityInfo: cache set, bundle = %{public}s, appIndex = %{public}d", + abilityInfo.bundleName.c_str(), abilityInfo.applicationInfo.appIndex); } namespace { @@ -432,6 +441,8 @@ void StartAbilityUtils::SetTargetCloneIndexInSameBundle(const Want &want, sptrGetApplicationInfo().appIndex; if (appIndex >= 0 && appIndex < AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { (const_cast(want)).SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, appIndex); + } else if (AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { + (const_cast(want)).SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, appIndex); } } diff --git a/services/abilitymgr/src/utils/uri_utils.cpp b/services/abilitymgr/src/utils/uri_utils.cpp index 293f327dab..2337da69c1 100644 --- a/services/abilitymgr/src/utils/uri_utils.cpp +++ b/services/abilitymgr/src/utils/uri_utils.cpp @@ -381,7 +381,7 @@ bool UriUtils::IsSandboxApp(uint32_t tokenId) TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret); return false; } - return hapInfo.instIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX; + return AbilityRuntime::GlobalConstant::IsDlpIndex(hapInfo.instIndex); } return false; } diff --git a/services/appmgr/include/utils/appspawn_util.h b/services/appmgr/include/utils/appspawn_util.h index 4aeedf4a1d..1a7acbcf77 100644 --- a/services/appmgr/include/utils/appspawn_util.h +++ b/services/appmgr/include/utils/appspawn_util.h @@ -72,8 +72,9 @@ static uint64_t BuildStartFlags(const AAFwk::Want &want, const ApplicationInfo & if (want.GetBoolParam("ohos.ability.params.extensionControl", false)) { startFlags = startFlags | (START_FLAG_BASE << StartFlags::EXTENSION_CONTROLLED); } - if (applicationInfo.multiAppMode.multiAppModeType == MultiAppModeType::APP_CLONE && applicationInfo.appIndex > 0 && - applicationInfo.appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if ((applicationInfo.multiAppMode.multiAppModeType == MultiAppModeType::APP_CLONE && applicationInfo.appIndex > 0 && + applicationInfo.appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(applicationInfo.appIndex)) { startFlags = startFlags | (START_FLAG_BASE << APP_FLAGS_CLONE_ENABLE); } if (applicationInfo.hwasanEnabled) { diff --git a/services/appmgr/src/app_mgr_service.cpp b/services/appmgr/src/app_mgr_service.cpp index 8fe0c7c885..aef738d84c 100644 --- a/services/appmgr/src/app_mgr_service.cpp +++ b/services/appmgr/src/app_mgr_service.cpp @@ -490,7 +490,7 @@ int32_t AppMgrService::ClearUpApplicationData(const std::string &bundleName, int isCheckDebugApp = true; } } - if (appCloneIndex < 0 || appCloneIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (appCloneIndex < 0 || AbilityRuntime::GlobalConstant::IsDlpIndex(appCloneIndex)) { TAG_LOGE(AAFwkTag::APPMGR, "appCloneIndex invalid"); return AAFwk::ERR_APP_CLONE_INDEX_INVALID; } diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 1d38e51209..e98af72329 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -2711,7 +2711,8 @@ bool AppMgrServiceInner::GetBundleAndHapInfo(const AbilityInfo &abilityInfo, static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY) | static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) | static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION), bundleInfo, userId)); - } else if (appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + } else if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { bundleMgrResult = IN_PROCESS_CALL(bundleMgrHelper->GetCloneBundleInfo(appInfo->bundleName, static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) | static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION), @@ -2726,7 +2727,8 @@ bool AppMgrServiceInner::GetBundleAndHapInfo(const AbilityInfo &abilityInfo, return false; } bool hapQueryResult = false; - if (appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { hapQueryResult = bundleMgrHelper->GetHapModuleInfo(abilityInfo, userId, hapModuleInfo); } else { hapQueryResult = (bundleMgrHelper->GetSandboxHapModuleInfo(abilityInfo, appIndex, userId, hapModuleInfo) == 0); @@ -9651,7 +9653,7 @@ int32_t AppMgrServiceInner::IsAppRunning(const std::string &bundleName, int32_t TAG_LOGE(AAFwkTag::APPMGR, "permission verification fail"); return ERR_PERMISSION_DENIED; } - if (appCloneIndex < 0 || appCloneIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (appCloneIndex < 0 || AbilityRuntime::GlobalConstant::IsDlpIndex(appCloneIndex)) { TAG_LOGE(AAFwkTag::APPMGR, "appCloneIndex invalid"); return AAFwk::ERR_APP_CLONE_INDEX_INVALID; } @@ -9698,7 +9700,7 @@ int32_t AppMgrServiceInner::IsAppRunning(const std::string &bundleName, int32_t TAG_LOGE(AAFwkTag::APPMGR, "permission verification fail"); return ERR_PERMISSION_DENIED; } - if (appCloneIndex < 0 || appCloneIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (appCloneIndex < 0 || AbilityRuntime::GlobalConstant::IsDlpIndex(appCloneIndex)) { TAG_LOGI(AAFwkTag::APPMGR, "appCloneIndex invalid"); appCloneIndex = -1; } diff --git a/services/appmgr/src/module_running_record.cpp b/services/appmgr/src/module_running_record.cpp index 48a32c752d..1df0add498 100644 --- a/services/appmgr/src/module_running_record.cpp +++ b/services/appmgr/src/module_running_record.cpp @@ -386,7 +386,8 @@ void ModuleRunningRecord::GetHapModuleInfo(HapModuleInfo &info) int32_t bundleMgrResult; auto flag = static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) | static_cast(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE); - if (appIndex_ <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex_) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex_)) { bundleMgrResult = IN_PROCESS_CALL(bundleMgrHelper->GetCloneBundleInfo(appInfo_->bundleName, flag, appIndex_, bundleInfo, userId)); } else { diff --git a/services/uripermmgr/src/file_uri_distribution_utils.cpp b/services/uripermmgr/src/file_uri_distribution_utils.cpp index 2130555da8..7f1c30dd26 100644 --- a/services/uripermmgr/src/file_uri_distribution_utils.cpp +++ b/services/uripermmgr/src/file_uri_distribution_utils.cpp @@ -281,7 +281,8 @@ int32_t FUDUtils::GetTokenIdByBundleName(const std::string &bundleName, int32_t tokenId = bundleInfo.applicationInfo.accessTokenId; return ERR_OK; } - if (appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + if (AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex) || + AbilityRuntime::GlobalConstant::IsSandboxCloneIndex(appIndex)) { auto bundleFlag = static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION); if (IN_PROCESS_CALL(bms->GetCloneBundleInfo(bundleName, bundleFlag, appIndex, bundleInfo, userId)) != ERR_OK) { TAG_LOGW(AAFwkTag::URIPERMMGR, "Failed GetCloneBundleInfo"); @@ -325,7 +326,7 @@ bool FUDUtils::IsSandboxApp(uint32_t tokenId) TAG_LOGE(AAFwkTag::URIPERMMGR, "GetHapTokenInfo failed, ret:%{public}d", ret); return false; } - return hapInfo.instIndex > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX; + return AbilityRuntime::GlobalConstant::IsDlpIndex(hapInfo.instIndex); } return false; } diff --git a/test/mock/common/include/mock_bundle_manager_proxy.h b/test/mock/common/include/mock_bundle_manager_proxy.h index eb49052305..cb2e30bc10 100644 --- a/test/mock/common/include/mock_bundle_manager_proxy.h +++ b/test/mock/common/include/mock_bundle_manager_proxy.h @@ -51,6 +51,9 @@ public: AppExecFwk::ExtensionAbilityInfo &extensionAbilityInfo)); MOCK_METHOD5(QueryCloneAbilityInfo, ErrCode(const AppExecFwk::ElementName &element, int32_t flags, int32_t appIndex, AppExecFwk::AbilityInfo &abilityInfo, int32_t userId)); + MOCK_METHOD6(QuerySandboxCloneAbilityInfo, ErrCode(const std::string &creatorBundleName, + const AppExecFwk::ElementName &element, int32_t flags, int32_t sandBoxCloneIndex, + AppExecFwk::AbilityInfo &abilityInfo, int32_t userId)); MOCK_METHOD4(QueryExtensionAbilityInfos, bool(const Want&, const int32_t&, const int32_t&, std::vector &extensionInfos)); MOCK_METHOD3(QueryAbilityInfoByUri, bool(const std::string&, int32_t, AppExecFwk::AbilityInfo&)); diff --git a/test/unittest/ability_manager_client_branch_test/ability_manager_client_branch_test.cpp b/test/unittest/ability_manager_client_branch_test/ability_manager_client_branch_test.cpp index 3515b09fab..0bfad6ae75 100644 --- a/test/unittest/ability_manager_client_branch_test/ability_manager_client_branch_test.cpp +++ b/test/unittest/ability_manager_client_branch_test/ability_manager_client_branch_test.cpp @@ -33,6 +33,7 @@ #include "mission_snapshot.h" #include "snapshot.h" #include "start_params_by_SCB.h" +#include "sandbox_clone_params.h" using namespace testing::ext; using namespace testing; @@ -2903,6 +2904,149 @@ HWTEST_F(AbilityManagerClientBranchTest, RegisterSAInterceptor_0100, TestSize.Le EXPECT_EQ(client_->RegisterSAInterceptor(nullptr), ERR_OK); } +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with valid parameters + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_001, TestSize.Level1) +{ + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 1314; + params.callerTokenId = 123456; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_OK)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with error return + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_002, TestSize.Level1) +{ + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 123456; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_PERMISSION_DENIED)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_PERMISSION_DENIED, result); +} + +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with empty bundle name + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_003, TestSize.Level1) +{ + Want want; + SandboxCloneParams params; + params.callerBundleName = ""; + params.callerUid = 10001; + params.callerTokenId = 123456; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_INVALID_VALUE)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_INVALID_VALUE, result); +} + +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with negative UID + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_004, TestSize.Level1) +{ + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = -1; + params.callerTokenId = 123456; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_OK)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with zero token ID + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_005, TestSize.Level1) +{ + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 0; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_OK)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_OK, result); +} + +/* + * Feature: AbilityManagerClient + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerClient StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the StartSandboxCloneAbility call with maximum values + */ +HWTEST_F(AbilityManagerClientBranchTest, StartSandboxCloneAbility_006, TestSize.Level1) +{ + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = INT32_MAX; + params.callerTokenId = UINT32_MAX; + + EXPECT_CALL(*mock_, StartSandboxCloneAbility(_, _)) + .Times(1) + .WillOnce(Return(ERR_OK)); + auto result = client_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(ERR_OK, result); +} + /** * @tc.name: StartSelfUIAbilityInCurrentProcess_0100 * @tc.desc: StartSelfUIAbilityInCurrentProcess diff --git a/test/unittest/ability_manager_client_branch_test/ability_manager_stub_mock_test.h b/test/unittest/ability_manager_client_branch_test/ability_manager_stub_mock_test.h index 8c5e08e9ba..315fabeb72 100644 --- a/test/unittest/ability_manager_client_branch_test/ability_manager_stub_mock_test.h +++ b/test/unittest/ability_manager_client_branch_test/ability_manager_stub_mock_test.h @@ -19,6 +19,7 @@ #include #include #include "ability_manager_interface.h" +#include "sandbox_clone_params.h" namespace OHOS { namespace AAFwk { @@ -464,6 +465,7 @@ public: uint32_t specifyTokenId, int32_t userId, int requestCode)); MOCK_METHOD1(StartSelf, int(sptr token)); MOCK_METHOD3(StartSelfUIAbilityInChildProcess, ErrCode(const Want &, const std::string &, sptr)); + MOCK_METHOD2(StartSandboxCloneAbility, int32_t(const Want&, const SandboxCloneParams&)); }; } // namespace AAFwk } // namespace OHOS diff --git a/test/unittest/ability_manager_proxy_test/ability_manager_proxy_test.cpp b/test/unittest/ability_manager_proxy_test/ability_manager_proxy_test.cpp index b67e4ad249..ed7cfb8984 100644 --- a/test/unittest/ability_manager_proxy_test/ability_manager_proxy_test.cpp +++ b/test/unittest/ability_manager_proxy_test/ability_manager_proxy_test.cpp @@ -34,6 +34,7 @@ #include "mission_listener_interface.h" #include "mission_snapshot.h" #include "snapshot.h" +#include "sandbox_clone_params.h" using namespace testing::ext; using namespace testing; @@ -4081,5 +4082,180 @@ HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSelf_003, TestSize.Le EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SELF), mock_->code_); EXPECT_NE(res, NO_ERROR); } + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify the normal process of StartSandboxCloneAbility + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_001, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_001 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 123456; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + EXPECT_EQ(res, NO_ERROR); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_001 end"); +} + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbility with SendRequest failure + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_002, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_002 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeErrorSendRequest)); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 123456; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + EXPECT_NE(res, NO_ERROR); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_002 end"); +} + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbility with empty Want + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_003, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_003 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + + Want want; + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 123456; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_003 end"); +} + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbility with empty params + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_004, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_004 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = ""; + params.callerUid = -1; + params.callerTokenId = 0; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_004 end"); +} + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbility with maximum values + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_005, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_005 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = INT32_MAX; + params.callerTokenId = UINT32_MAX; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_005 end"); +} + +/* + * Feature: AbilityManagerService + * Function: StartSandboxCloneAbility + * SubFunction: NA + * FunctionPoints: AbilityManagerProxy StartSandboxCloneAbility + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbility with long bundle name + */ +HWTEST_F(AbilityManagerProxyTest, AbilityManagerProxy_StartSandboxCloneAbility_006, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_006 start"); + + EXPECT_CALL(*mock_, SendRequest(_, _, _, _)) + .Times(1) + .WillOnce(Invoke(mock_.GetRefPtr(), &AbilityManagerStubMock::InvokeSendRequest)); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + SandboxCloneParams params; + params.callerBundleName = "com.very.long.caller.bundle.name.that.exceeds.normal.length"; + params.callerUid = 10001; + params.callerTokenId = 123456; + + auto res = proxy_->StartSandboxCloneAbility(want, params); + EXPECT_EQ(static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), mock_->code_); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerProxy_StartSandboxCloneAbility_006 end"); +} } // namespace AAFwk } // namespace OHOS diff --git a/test/unittest/ability_manager_service_first_test/ability_manager_service_first_test.cpp b/test/unittest/ability_manager_service_first_test/ability_manager_service_first_test.cpp index 611514cc7c..f628ea8ed7 100644 --- a/test/unittest/ability_manager_service_first_test/ability_manager_service_first_test.cpp +++ b/test/unittest/ability_manager_service_first_test/ability_manager_service_first_test.cpp @@ -33,6 +33,7 @@ #undef protected #include "ability_manager_errors.h" #include "connection_observer_errors.h" +#include "appexecfwk_errors.h" #include "hilog_tag_wrapper.h" #include "insight_intent_execute_manager.h" #include "insight_intent_execute_param.h" @@ -48,6 +49,8 @@ #include "start_ability_utils.h" #include "string_wrapper.h" #include "utils/window_options_utils.h" +#include "sandbox_clone_params.h" +#include "global_constant.h" using namespace testing; using namespace testing::ext; @@ -1130,7 +1133,7 @@ HWTEST_F(AbilityManagerServiceFirstTest, StopExtensionAbility_002, TestSize.Leve abilityRecord->appIndex_ = -1; abilityRecord->abilityInfo_.applicationInfo.bundleName = "com.ix.hiservcie"; EXPECT_EQ(abilityMs_->StopExtensionAbility(want, abilityRecord->GetToken(), -1, ExtensionAbilityType::SERVICE), - CHECK_PERMISSION_FAILED); + ERR_INVALID_CALLER); TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFirstTest StopExtensionAbility_002 end"); } @@ -3032,5 +3035,368 @@ HWTEST_F(AbilityManagerServiceFirstTest, StartSelfUIAbilityInChildProcess_0400, auto res = abilityMs_->StartSelfUIAbilityInChildProcess(want, specifiedFlag, callerToken); EXPECT_EQ(res, ERROR_UIABILITY_NOT_BELONG_TO_CALLER); } + +/** + * @tc.name: GetCreatorBundleNameForSandboxClone_0100 + * @tc.desc: Test GetCreatorBundleNameForSandboxClone with permission and input creator bundle name + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, GetCreatorBundleNameForSandboxClone_0100, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::CREATOR_BUNDLE_NAME, std::string("com.creator.bundle")); + std::string callerBundleName = "com.caller.bundle"; + uint32_t callerTokenId = 1; + int32_t errCode = ERR_OK; + + // Mock permission check - assuming no permission by default + std::string result = abilityMs_->GetCreatorBundleNameForSandboxClone( + want, callerBundleName, callerTokenId, errCode); + + // Without permission, should use caller bundle name + EXPECT_EQ(result, callerBundleName); + EXPECT_EQ(errCode, ERR_OK); +} + +/** + * @tc.name: GetCreatorBundleNameForSandboxClone_0200 + * @tc.desc: Test GetCreatorBundleNameForSandboxClone with empty input creator bundle name + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, GetCreatorBundleNameForSandboxClone_0200, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + std::string callerBundleName = "com.caller.bundle"; + uint32_t callerTokenId = 1; + int32_t errCode = ERR_OK; + + std::string result = abilityMs_->GetCreatorBundleNameForSandboxClone( + want, callerBundleName, callerTokenId, errCode); + + EXPECT_EQ(result, callerBundleName); + EXPECT_EQ(errCode, ERR_OK); +} + +/** + * @tc.name: GetCreatorBundleNameForSandboxClone_0300 + * @tc.desc: Test GetCreatorBundleNameForSandboxClone with empty caller bundle name (error case) + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, GetCreatorBundleNameForSandboxClone_0300, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + std::string callerBundleName = ""; + uint32_t callerTokenId = 1; + int32_t errCode = ERR_OK; + + std::string result = abilityMs_->GetCreatorBundleNameForSandboxClone( + want, callerBundleName, callerTokenId, errCode); + + EXPECT_TRUE(result.empty()); + EXPECT_EQ(errCode, ERR_INVALID_VALUE); +} + +/** + * @tc.name: GetCreatorBundleNameForSandboxClone_0400 + * @tc.desc: Test GetCreatorBundleNameForSandboxClone with input creator bundle name and no permission + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, GetCreatorBundleNameForSandboxClone_0400, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::CREATOR_BUNDLE_NAME, std::string("com.creator.bundle")); + std::string callerBundleName = "com.caller.bundle"; + uint32_t callerTokenId = 1; + int32_t errCode = ERR_OK; + + std::string result = abilityMs_->GetCreatorBundleNameForSandboxClone( + want, callerBundleName, callerTokenId, errCode); + + // Without permission, should use caller bundle name, not the input creator bundle name + EXPECT_EQ(result, callerBundleName); + EXPECT_EQ(errCode, ERR_OK); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0100 + * @tc.desc: Test ProcessSandboxCloneLaunch with null sandboxCloneParams + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0100, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + std::shared_ptr sandboxCloneParams = nullptr; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_OK); + EXPECT_TRUE(abilityInfo.bundleName.empty()); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0200 + * @tc.desc: Test ProcessSandboxCloneLaunch with sandboxCloneParams but no SANDBOX_CLONE_INDEX parameter + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0200, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = "com.caller.bundle"; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_OK); + EXPECT_TRUE(abilityInfo.bundleName.empty()); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0300 + * @tc.desc: Test ProcessSandboxCloneLaunch with invalid sandboxCloneIndex (below minimum) + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0300, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 1999); + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = "com.caller.bundle"; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_SANDBOX_CLONE_INDEX_INVALID); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0400 + * @tc.desc: Test ProcessSandboxCloneLaunch with invalid sandboxCloneIndex (above maximum) + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0400, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 3001); + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = "com.caller.bundle"; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_SANDBOX_CLONE_INDEX_INVALID); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0500 + * @tc.desc: Test ProcessSandboxCloneLaunch with empty caller bundle name + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0500, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetElementName("com.target.bundle", "TestAbility", "entry"); + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 2000); + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = ""; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + // Should fail due to empty caller bundle name + EXPECT_EQ(result, ERR_INVALID_VALUE); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_0600 + * @tc.desc: Test ProcessSandboxCloneLaunch with negative sandboxCloneIndex + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_0600, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, -1); + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = "com.caller.bundle"; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_SANDBOX_CLONE_INDEX_INVALID); +} + +/** + * @tc.name: ProcessSandboxCloneLaunch_1000 + * @tc.desc: Test ProcessSandboxCloneLaunch with sandboxCloneIndex = 0 + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, ProcessSandboxCloneLaunch_1000, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 0); + auto sandboxCloneParams = std::make_shared(); + sandboxCloneParams->callerBundleName = "com.caller.bundle"; + sandboxCloneParams->callerUid = 1000; + sandboxCloneParams->callerTokenId = 1; + int32_t userId = 100; + AppExecFwk::AbilityInfo abilityInfo; + + int32_t result = abilityMs_->ProcessSandboxCloneLaunch( + want, sandboxCloneParams, userId, abilityInfo); + + EXPECT_EQ(result, ERR_SANDBOX_CLONE_INDEX_INVALID); +} + +/** + * @tc.name: StartSandboxCloneAbility_0100 + * @tc.desc: Test StartSandboxCloneAbility with valid parameters but no CLI tool token + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, StartSandboxCloneAbility_0100, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 2000); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 1000; + params.callerTokenId = 1; + + int32_t result = abilityMs_->StartSandboxCloneAbility(want, params); + + // Should fail due to no CLI tool token + EXPECT_EQ(result, ERR_PERMISSION_DENIED); +} + +/** + * @tc.name: StartSandboxCloneAbility_0200 + * @tc.desc: Test StartSandboxCloneAbility without SANDBOX_CLONE_INDEX parameter + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, StartSandboxCloneAbility_0200, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 1000; + params.callerTokenId = 1; + + int32_t result = abilityMs_->StartSandboxCloneAbility(want, params); + + // Should fail due to missing SANDBOX_CLONE_INDEX parameter + EXPECT_EQ(result, ERR_PERMISSION_DENIED); +} + +/** + * @tc.name: StartSandboxCloneAbility_0300 + * @tc.desc: Test StartSandboxCloneAbility with invalid sandboxCloneIndex + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, StartSandboxCloneAbility_0300, TestSize.Level1) +{ + auto abilityMs_ = std::make_shared(); + ASSERT_NE(abilityMs_, nullptr); + + Want want; + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 1999); + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 1000; + params.callerTokenId = 1; + + int32_t result = abilityMs_->StartSandboxCloneAbility(want, params); + + // Should fail due to no CLI tool token (even before index validation) + EXPECT_EQ(result, ERR_PERMISSION_DENIED); +} + +/** + * @tc.name: IsWebSandBoxClone_0100 + * @tc.desc: Test isWebSandBoxClone functionality through AbilityRequest + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, IsWebSandBoxClone_0100, TestSize.Level1) +{ + // Test the isWebSandBoxClone flag in AbilityRequest + AbilityRequest abilityRequest; + abilityRequest.isWebSandBoxClone = true; + + EXPECT_TRUE(abilityRequest.isWebSandBoxClone); +} + +/** + * @tc.name: IsWebSandBoxClone_0200 + * @tc.desc: Test isWebSandBoxClone set to false + * @tc.type: FUNC + */ +HWTEST_F(AbilityManagerServiceFirstTest, IsWebSandBoxClone_0200, TestSize.Level1) +{ + AbilityRequest abilityRequest; + abilityRequest.isWebSandBoxClone = false; + + EXPECT_FALSE(abilityRequest.isWebSandBoxClone); +} + } // namespace AAFwk } // namespace OHOS diff --git a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp index 9d3ec48de4..a8a56da6a0 100644 --- a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp +++ b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp @@ -1178,6 +1178,15 @@ std::shared_ptr AbilityRecord::GetStartSetting() const return lifeCycleStateInfo_.setting; } +void AbilityRecord::SetSandboxCloneParams(const std::shared_ptr ¶ms) {} + +std::shared_ptr AbilityRecord::GetSandboxCloneParams() const +{ + return nullptr; +} + +void AbilityRecord::InitSandboxCloneParams(const AbilityRequest &abilityRequest) {} + void AbilityRecord::SetRestarting(const bool isRestart) { } diff --git a/test/unittest/ability_manager_service_fourth_test/ability_manager_service_fourth_test.cpp b/test/unittest/ability_manager_service_fourth_test/ability_manager_service_fourth_test.cpp index 6cc37b9656..e17e790a01 100644 --- a/test/unittest/ability_manager_service_fourth_test/ability_manager_service_fourth_test.cpp +++ b/test/unittest/ability_manager_service_fourth_test/ability_manager_service_fourth_test.cpp @@ -39,6 +39,7 @@ #include "start_params_by_SCB.h" #include "system_ability_definition.h" #include "ability_util.h" +#include "global_constant.h" using namespace testing; using namespace testing::ext; @@ -1312,6 +1313,102 @@ HWTEST_F(AbilityManagerServiceFourthTest, StartUIAbilityBySCB_001, TestSize.Leve TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest StartUIAbilityBySCB_001 end"); } +/* + * Feature: AbilityManagerService + * Function: HandleSandboxCloneLaunch + * FunctionPoints: AbilityManagerService HandleSandboxCloneLaunch parses caller info and returns ERR_OK + */ +HWTEST_F(AbilityManagerServiceFourthTest, HandleSandboxCloneLaunch_001, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_001 start"); + auto abilityMs = std::make_shared(); + sptr sessionInfo = new (std::nothrow) SessionInfo(); + ASSERT_NE(sessionInfo, nullptr); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME, + std::string("com.test.caller")); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID, std::string("123456")); + + auto sandboxCloneParams = std::make_shared(); + ASSERT_NE(sandboxCloneParams, nullptr); + EventInfo eventInfo; + // Without SANDBOX_CLONE_INDEX, ProcessSandboxCloneLaunch short-circuits to ERR_OK. + auto ret = abilityMs->HandleSandboxCloneLaunch(sessionInfo, sandboxCloneParams, TEST_VALID_USER_ID, eventInfo); + EXPECT_EQ(ret, ERR_OK); + EXPECT_EQ(sandboxCloneParams->callerBundleName, "com.test.caller"); + EXPECT_EQ(sandboxCloneParams->callerTokenId, 123456u); + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_001 end"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleSandboxCloneLaunch + * FunctionPoints: AbilityManagerService HandleSandboxCloneLaunch uses default 0 when callerTokenId is empty + */ +HWTEST_F(AbilityManagerServiceFourthTest, HandleSandboxCloneLaunch_002, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_002 start"); + auto abilityMs = std::make_shared(); + sptr sessionInfo = new (std::nothrow) SessionInfo(); + ASSERT_NE(sessionInfo, nullptr); + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_BUNDLE_NAME, + std::string("com.test.caller")); + // CLI_CALLER_TOKEN_ID is not set, GetStringParam returns empty -> callerTokenId defaults to 0. + + auto sandboxCloneParams = std::make_shared(); + ASSERT_NE(sandboxCloneParams, nullptr); + EventInfo eventInfo; + auto ret = abilityMs->HandleSandboxCloneLaunch(sessionInfo, sandboxCloneParams, TEST_VALID_USER_ID, eventInfo); + EXPECT_EQ(ret, ERR_OK); + EXPECT_EQ(sandboxCloneParams->callerBundleName, "com.test.caller"); + EXPECT_EQ(sandboxCloneParams->callerTokenId, 0u); + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_002 end"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleSandboxCloneLaunch + * FunctionPoints: AbilityManagerService HandleSandboxCloneLaunch falls back to 0 on invalid callerTokenId + */ +HWTEST_F(AbilityManagerServiceFourthTest, HandleSandboxCloneLaunch_003, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_003 start"); + auto abilityMs = std::make_shared(); + sptr sessionInfo = new (std::nothrow) SessionInfo(); + ASSERT_NE(sessionInfo, nullptr); + // A non-numeric token id makes std::from_chars fail, so callerTokenId falls back to 0. + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::CLI_CALLER_TOKEN_ID, std::string("invalid_token")); + + auto sandboxCloneParams = std::make_shared(); + ASSERT_NE(sandboxCloneParams, nullptr); + EventInfo eventInfo; + auto ret = abilityMs->HandleSandboxCloneLaunch(sessionInfo, sandboxCloneParams, TEST_VALID_USER_ID, eventInfo); + EXPECT_EQ(ret, ERR_OK); + EXPECT_EQ(sandboxCloneParams->callerTokenId, 0u); + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_003 end"); +} + +/* + * Feature: AbilityManagerService + * Function: HandleSandboxCloneLaunch + * FunctionPoints: AbilityManagerService HandleSandboxCloneLaunch propagates error on invalid sandbox clone index + */ +HWTEST_F(AbilityManagerServiceFourthTest, HandleSandboxCloneLaunch_004, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_004 start"); + auto abilityMs = std::make_shared(); + sptr sessionInfo = new (std::nothrow) SessionInfo(); + ASSERT_NE(sessionInfo, nullptr); + // Valid sandbox clone index range is [2000, 3000]; an out-of-range value is rejected. + sessionInfo->want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, 100); + + auto sandboxCloneParams = std::make_shared(); + ASSERT_NE(sandboxCloneParams, nullptr); + EventInfo eventInfo; + auto ret = abilityMs->HandleSandboxCloneLaunch(sessionInfo, sandboxCloneParams, TEST_VALID_USER_ID, eventInfo); + EXPECT_EQ(ret, ERR_SANDBOX_CLONE_INDEX_INVALID); + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerServiceFourthTest HandleSandboxCloneLaunch_004 end"); +} + /* * Feature: AbilityManagerService * Function: IsDmsAlive diff --git a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp index c3901367d7..d8476e2ba9 100644 --- a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp +++ b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp @@ -1191,6 +1191,15 @@ std::shared_ptr AbilityRecord::GetStartSetting() const return lifeCycleStateInfo_.setting; } +void AbilityRecord::SetSandboxCloneParams(const std::shared_ptr ¶ms) {} + +std::shared_ptr AbilityRecord::GetSandboxCloneParams() const +{ + return nullptr; +} + +void AbilityRecord::InitSandboxCloneParams(const AbilityRequest &abilityRequest) {} + void AbilityRecord::SetRestarting(const bool isRestart) { } diff --git a/test/unittest/ability_manager_stub_test/ability_manager_stub_impl_mock.h b/test/unittest/ability_manager_stub_test/ability_manager_stub_impl_mock.h index 4857d11c75..3e4aee6efc 100644 --- a/test/unittest/ability_manager_stub_test/ability_manager_stub_impl_mock.h +++ b/test/unittest/ability_manager_stub_test/ability_manager_stub_impl_mock.h @@ -19,6 +19,7 @@ #include #include #include "ability_manager_interface.h" +#include "sandbox_clone_params.h" #define private public #include "ability_manager_stub.h" #undef private @@ -485,6 +486,7 @@ public: MOCK_METHOD4(StartAbilityByOEExt, int32_t(const Want&, sptr, int32_t, const std::string&)); MOCK_METHOD1(StartSelf, int(sptr token)); MOCK_METHOD3(StartSelfUIAbilityInChildProcess, ErrCode(const Want&, const std::string&, sptr)); + MOCK_METHOD2(StartSandboxCloneAbility, int32_t(const Want&, const SandboxCloneParams&)); int32_t GetUserLockedBundleList(int32_t userId, std::unordered_set &userLockedBundleList) override { diff --git a/test/unittest/ability_manager_stub_test/ability_manager_stub_test.cpp b/test/unittest/ability_manager_stub_test/ability_manager_stub_test.cpp index 6816678fe8..d96606e02d 100644 --- a/test/unittest/ability_manager_stub_test/ability_manager_stub_test.cpp +++ b/test/unittest/ability_manager_stub_test/ability_manager_stub_test.cpp @@ -22,6 +22,7 @@ #include "mock_ability_connect_callback.h" #include "mock_ability_token.h" #include "mock_sa_interceptor_stub.h" +#include "sandbox_clone_params.h" using namespace testing::ext; using namespace testing; @@ -5225,6 +5226,98 @@ HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_SetGamePreLaunchCompleteTime EXPECT_EQ(result, NO_ERROR); } +/* + * Feature: AbilityManagerStub + * Function: OnRemoteRequest + * SubFunction: NA + * FunctionPoints: AbilityManagerStub StartSandboxCloneAbilityInner via OnRemoteRequest + * EnvConditions: code is START_SANDBOX_CLONE_ABILITY + * CaseDescription: Verify dispatching START_SANDBOX_CLONE_ABILITY through OnRemoteRequest + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_StartSandboxCloneAbility_OnRemote_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbility_OnRemote_0100 start"); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + + WriteInterfaceToken(data); + + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + ASSERT_TRUE(data.WriteParcelable(&want)); + + SandboxCloneParams params; + params.callerBundleName = "com.caller.bundle"; + params.callerUid = 10001; + params.callerTokenId = 123456; + ASSERT_TRUE(data.WriteParcelable(¶ms)); + + EXPECT_CALL(*stub_, StartSandboxCloneAbility(_, _)).WillOnce(Return(ERR_OK)); + int res = stub_->OnRemoteRequest( + static_cast(AbilityManagerInterfaceCode::START_SANDBOX_CLONE_ABILITY), data, reply, option); + EXPECT_EQ(res, NO_ERROR); + EXPECT_EQ(reply.ReadInt32(), ERR_OK); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbility_OnRemote_0100 end"); +} + +/* + * Feature: AbilityManagerStub + * Function: StartSandboxCloneAbilityInner + * SubFunction: NA + * FunctionPoints: AbilityManagerStub StartSandboxCloneAbilityInner + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbilityInner with null want + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_StartSandboxCloneAbilityInner_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbilityInner_0100 start"); + + MessageParcel data; + MessageParcel reply; + WriteInterfaceToken(data); + + // Write empty want (nullptr) + ASSERT_TRUE(data.WriteParcelable(static_cast(nullptr))); + + auto result = stub_->StartSandboxCloneAbilityInner(data, reply); + EXPECT_EQ(result, ERR_INVALID_VALUE); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbilityInner_0100 end"); +} + +/* + * Feature: AbilityManagerStub + * Function: StartSandboxCloneAbilityInner + * SubFunction: NA + * FunctionPoints: AbilityManagerStub StartSandboxCloneAbilityInner + * EnvConditions: NA + * CaseDescription: Verify StartSandboxCloneAbilityInner with null params + */ +HWTEST_F(AbilityManagerStubTest, AbilityManagerStub_StartSandboxCloneAbilityInner_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbilityInner_0200 start"); + + MessageParcel data; + MessageParcel reply; + WriteInterfaceToken(data); + + // Write valid want + Want want; + want.SetElementName("com.test.bundle", "TestAbility"); + ASSERT_TRUE(data.WriteParcelable(&want)); + + // Write empty params (nullptr) + ASSERT_TRUE(data.WriteParcelable(static_cast(nullptr))); + + auto result = stub_->StartSandboxCloneAbilityInner(data, reply); + EXPECT_EQ(result, ERR_INVALID_VALUE); + + TAG_LOGI(AAFwkTag::TEST, "AbilityManagerStub_StartSandboxCloneAbilityInner_0200 end"); +} + /* * Feature: AbilityManagerService * Function: OnRemoteRequest diff --git a/test/unittest/ability_permission_util_second_test/mock/src/mock_bundle_mgr_helper.cpp b/test/unittest/ability_permission_util_second_test/mock/src/mock_bundle_mgr_helper.cpp index a8d8671e2b..b47fde30c1 100755 --- a/test/unittest/ability_permission_util_second_test/mock/src/mock_bundle_mgr_helper.cpp +++ b/test/unittest/ability_permission_util_second_test/mock/src/mock_bundle_mgr_helper.cpp @@ -336,6 +336,13 @@ ErrCode BundleMgrHelper::QueryCloneAbilityInfo( return ERR_OK; } +ErrCode BundleMgrHelper::QuerySandboxCloneAbilityInfo(const std::string &creatorBundleName, + const ElementName &element, int32_t flags, int32_t sandBoxCloneIndex, + AbilityInfo &abilityInfo, int32_t userId) +{ + return ERR_OK; +} + ErrCode BundleMgrHelper::GetCloneBundleInfo( const std::string& bundleName, int32_t flags, int32_t appCloneIndex, BundleInfo& bundleInfo, int32_t userId) { diff --git a/test/unittest/sandbox_clone_params_test/BUILD.gn b/test/unittest/sandbox_clone_params_test/BUILD.gn new file mode 100644 index 0000000000..1a93befc4a --- /dev/null +++ b/test/unittest/sandbox_clone_params_test/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2026 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. + +import("//build/test.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +module_output_path = "ability_runtime/ability_runtime/abilitymgr" + +ohos_unittest("sandbox_clone_params_test") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "../../cfi_blocklist.txt" + } + branch_protector_ret = "pac_ret" + + include_dirs = [ + "${ability_runtime_path}/interfaces/inner_api/ability_manager/include", + "${ability_runtime_services_path}/abilitymgr/include", + ] + + sources = [ + "${ability_runtime_services_path}/abilitymgr/src/sandbox_clone_params.cpp", + "sandbox_clone_params_test.cpp", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + ] + + defines = [] + + cflags_cc = [] +} + +group("unittest") { + testonly = true + deps = [ ":sandbox_clone_params_test" ] +} diff --git a/test/unittest/sandbox_clone_params_test/sandbox_clone_params_test.cpp b/test/unittest/sandbox_clone_params_test/sandbox_clone_params_test.cpp new file mode 100644 index 0000000000..1b1ff11cfa --- /dev/null +++ b/test/unittest/sandbox_clone_params_test/sandbox_clone_params_test.cpp @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2026 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 + +#include "sandbox_clone_params.h" +#include "parcel.h" + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::AAFwk; + +namespace { +const std::string TEST_CALLER_BUNDLE_NAME = "com.test.caller.bundle"; +const std::string EMPTY_STRING = ""; +const int32_t TEST_CALLER_UID = 10001; +const uint32_t TEST_CALLER_TOKEN_ID = 12345678; +const int32_t TEST_INVALID_UID = -1; +} // namespace + +class SandboxCloneParamsTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void SandboxCloneParamsTest::SetUpTestCase() +{} + +void SandboxCloneParamsTest::TearDownTestCase() +{} + +void SandboxCloneParamsTest::SetUp() +{} + +void SandboxCloneParamsTest::TearDown() +{} + +/** + * @tc.name: SandboxCloneParams_001 + * @tc.desc: Test SandboxCloneParams default construction + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_001, TestSize.Level1) +{ + SandboxCloneParams params; + EXPECT_TRUE(params.callerBundleName.empty()); + EXPECT_EQ(params.callerUid, -1); + EXPECT_EQ(params.callerTokenId, 0); +} + +/** + * @tc.name: SandboxCloneParams_002 + * @tc.desc: Test SandboxCloneParams with values + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_002, TestSize.Level1) +{ + SandboxCloneParams params; + params.callerBundleName = TEST_CALLER_BUNDLE_NAME; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + EXPECT_EQ(params.callerBundleName, TEST_CALLER_BUNDLE_NAME); + EXPECT_EQ(params.callerUid, TEST_CALLER_UID); + EXPECT_EQ(params.callerTokenId, TEST_CALLER_TOKEN_ID); +} + +/** + * @tc.name: SandboxCloneParams_Marshalling_001 + * @tc.desc: Test SandboxCloneParams Marshalling with valid data + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Marshalling_001, TestSize.Level1) +{ + SandboxCloneParams params; + params.callerBundleName = TEST_CALLER_BUNDLE_NAME; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SandboxCloneParams_Marshalling_002 + * @tc.desc: Test SandboxCloneParams Marshalling with empty bundle name + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Marshalling_002, TestSize.Level1) +{ + SandboxCloneParams params; + params.callerBundleName = EMPTY_STRING; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SandboxCloneParams_Marshalling_003 + * @tc.desc: Test SandboxCloneParams Marshalling with negative UID + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Marshalling_003, TestSize.Level1) +{ + SandboxCloneParams params; + params.callerBundleName = TEST_CALLER_BUNDLE_NAME; + params.callerUid = TEST_INVALID_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SandboxCloneParams_Marshalling_004 + * @tc.desc: Test SandboxCloneParams Marshalling with zero token ID + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Marshalling_004, TestSize.Level1) +{ + SandboxCloneParams params; + params.callerBundleName = TEST_CALLER_BUNDLE_NAME; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = 0; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SandboxCloneParams_ReadFromParcel_001 + * @tc.desc: Test SandboxCloneParams ReadFromParcel with valid data + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_ReadFromParcel_001, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = TEST_CALLER_BUNDLE_NAME; + originalParams.callerUid = TEST_CALLER_UID; + originalParams.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams readParams; + bool result = readParams.ReadFromParcel(parcel); + EXPECT_TRUE(result); + EXPECT_EQ(readParams.callerBundleName, TEST_CALLER_BUNDLE_NAME); + EXPECT_EQ(readParams.callerUid, TEST_CALLER_UID); + EXPECT_EQ(readParams.callerTokenId, TEST_CALLER_TOKEN_ID); +} + +/** + * @tc.name: SandboxCloneParams_ReadFromParcel_002 + * @tc.desc: Test SandboxCloneParams ReadFromParcel with empty bundle name + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_ReadFromParcel_002, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = EMPTY_STRING; + originalParams.callerUid = TEST_CALLER_UID; + originalParams.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams readParams; + bool result = readParams.ReadFromParcel(parcel); + EXPECT_TRUE(result); + EXPECT_TRUE(readParams.callerBundleName.empty()); + EXPECT_EQ(readParams.callerUid, TEST_CALLER_UID); + EXPECT_EQ(readParams.callerTokenId, TEST_CALLER_TOKEN_ID); +} + +/** + * @tc.name: SandboxCloneParams_ReadFromParcel_003 + * @tc.desc: Test SandboxCloneParams ReadFromParcel with negative UID + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_ReadFromParcel_003, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = TEST_CALLER_BUNDLE_NAME; + originalParams.callerUid = TEST_INVALID_UID; + originalParams.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams readParams; + bool result = readParams.ReadFromParcel(parcel); + EXPECT_TRUE(result); + EXPECT_EQ(readParams.callerBundleName, TEST_CALLER_BUNDLE_NAME); + EXPECT_EQ(readParams.callerUid, TEST_INVALID_UID); + EXPECT_EQ(readParams.callerTokenId, TEST_CALLER_TOKEN_ID); +} + +/** + * @tc.name: SandboxCloneParams_ReadFromParcel_004 + * @tc.desc: Test SandboxCloneParams ReadFromParcel with maximum values + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_ReadFromParcel_004, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = TEST_CALLER_BUNDLE_NAME; + originalParams.callerUid = INT32_MAX; + originalParams.callerTokenId = UINT32_MAX; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams readParams; + bool result = readParams.ReadFromParcel(parcel); + EXPECT_TRUE(result); + EXPECT_EQ(readParams.callerBundleName, TEST_CALLER_BUNDLE_NAME); + EXPECT_EQ(readParams.callerUid, INT32_MAX); + EXPECT_EQ(readParams.callerTokenId, UINT32_MAX); +} + +/** + * @tc.name: SandboxCloneParams_Unmarshalling_001 + * @tc.desc: Test SandboxCloneParams Unmarshalling with valid data + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Unmarshalling_001, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = TEST_CALLER_BUNDLE_NAME; + originalParams.callerUid = TEST_CALLER_UID; + originalParams.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams* unmarshalledParams = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(unmarshalledParams, nullptr); + EXPECT_EQ(unmarshalledParams->callerBundleName, TEST_CALLER_BUNDLE_NAME); + EXPECT_EQ(unmarshalledParams->callerUid, TEST_CALLER_UID); + EXPECT_EQ(unmarshalledParams->callerTokenId, TEST_CALLER_TOKEN_ID); + delete unmarshalledParams; +} + +/** + * @tc.name: SandboxCloneParams_Unmarshalling_002 + * @tc.desc: Test SandboxCloneParams Unmarshalling with empty parcel + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Unmarshalling_002, TestSize.Level1) +{ + Parcel parcel; + // Empty parcel + + SandboxCloneParams* unmarshalledParams = SandboxCloneParams::Unmarshalling(parcel); + // Unmarshalling should succeed but with empty/default values + ASSERT_NE(unmarshalledParams, nullptr); + delete unmarshalledParams; +} + +/** + * @tc.name: SandboxCloneParams_Unmarshalling_003 + * @tc.desc: Test SandboxCloneParams Unmarshalling round trip + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_Unmarshalling_003, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = "com.example.bundle"; + originalParams.callerUid = 99999; + originalParams.callerTokenId = 88888888; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams* unmarshalledParams = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(unmarshalledParams, nullptr); + EXPECT_EQ(unmarshalledParams->callerBundleName, "com.example.bundle"); + EXPECT_EQ(unmarshalledParams->callerUid, 99999); + EXPECT_EQ(unmarshalledParams->callerTokenId, 88888888); + delete unmarshalledParams; +} + +/** + * @tc.name: SandboxCloneParams_RoundTrip_001 + * @tc.desc: Test SandboxCloneParams complete round trip (Marshalling -> Unmarshalling) + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_RoundTrip_001, TestSize.Level1) +{ + SandboxCloneParams originalParams; + originalParams.callerBundleName = TEST_CALLER_BUNDLE_NAME; + originalParams.callerUid = TEST_CALLER_UID; + originalParams.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + ASSERT_TRUE(originalParams.Marshalling(parcel)); + + SandboxCloneParams* restoredParams = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(restoredParams, nullptr); + EXPECT_EQ(restoredParams->callerBundleName, originalParams.callerBundleName); + EXPECT_EQ(restoredParams->callerUid, originalParams.callerUid); + EXPECT_EQ(restoredParams->callerTokenId, originalParams.callerTokenId); + delete restoredParams; +} + +/** + * @tc.name: SandboxCloneParams_LongString_001 + * @tc.desc: Test SandboxCloneParams with very long bundle name + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_LongString_001, TestSize.Level1) +{ + SandboxCloneParams params; + std::string longBundleName(1000, 'a'); // 1000 character string + params.callerBundleName = longBundleName; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); + + SandboxCloneParams* readParams = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(readParams, nullptr); + EXPECT_EQ(readParams->callerBundleName, longBundleName); + delete readParams; +} + +/** + * @tc.name: SandboxCloneParams_SpecialCharacters_001 + * @tc.desc: Test SandboxCloneParams with special characters in bundle name + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_SpecialCharacters_001, TestSize.Level1) +{ + SandboxCloneParams params; + std::string specialBundleName = "com.test.bund!e@nam#e$v%i&l*"; + params.callerBundleName = specialBundleName; + params.callerUid = TEST_CALLER_UID; + params.callerTokenId = TEST_CALLER_TOKEN_ID; + + Parcel parcel; + bool result = params.Marshalling(parcel); + EXPECT_TRUE(result); + + SandboxCloneParams* readParams = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(readParams, nullptr); + EXPECT_EQ(readParams->callerBundleName, specialBundleName); + delete readParams; +} + +/** + * @tc.name: SandboxCloneParams_MultipleOperations_001 + * @tc.desc: Test multiple Marshalling and Unmarshalling operations + * @tc.type: FUNC + */ +HWTEST_F(SandboxCloneParamsTest, SandboxCloneParams_MultipleOperations_001, TestSize.Level1) +{ + Parcel parcel; + + for (int i = 0; i < 10; i++) { + SandboxCloneParams params; + params.callerBundleName = "com.bundle" + std::to_string(i); + params.callerUid = 10000 + i; + params.callerTokenId = 100000 + i; + + ASSERT_TRUE(params.Marshalling(parcel)); + } + + // Read back all params + for (int i = 0; i < 10; i++) { + SandboxCloneParams* params = SandboxCloneParams::Unmarshalling(parcel); + ASSERT_NE(params, nullptr); + EXPECT_EQ(params->callerBundleName, "com.bundle" + std::to_string(i)); + EXPECT_EQ(params->callerUid, 10000 + i); + EXPECT_EQ(params->callerTokenId, 100000 + i); + delete params; + } +} diff --git a/tools/ohos-aa/include/ohos_aa_command.h b/tools/ohos-aa/include/ohos_aa_command.h index 9d5cf628b6..779e4eb998 100644 --- a/tools/ohos-aa/include/ohos_aa_command.h +++ b/tools/ohos-aa/include/ohos_aa_command.h @@ -60,6 +60,8 @@ const std::string HELP_MSG_START = "ohos-aa start - Start an ability on the syst " --abilityname Ability name to be started\n" " --bundlename bundle name to be started\n" " --modulename module name to be started\n" + " --sandboxCloneIndex sandbox clone index for launching sandbox clone application (range: 2000-3000)\n" + " --creatorBundle creator bundle name for sandbox clone application\n" " --uri URI for implicit startup\n" " --action action for implicit startup\n" " --entity entity for implicit startup\n" @@ -116,7 +118,9 @@ enum OptionType { OPTION_ENTITY, OPTION_HELP, OPTION_TYPE, - OPTION_TIME + OPTION_TIME, + OPTION_SANDBOX_CLONE_INDEX, // Sandbox clone index for clone application + OPTION_CREATOR_BUNDLE // Creator bundle name (untrusted, from command line) }; const std::string SHORT_OPTIONS = ""; @@ -135,6 +139,8 @@ struct option LONG_OPTIONS[] = { {"ps", required_argument, 0, OPTION_PARAMETER_STRING}, {"pb", required_argument, 0, OPTION_PARAMETER_BOOL}, {"psn", required_argument, 0, OPTION_PARAMETER_NULL_STRING}, + {"sandboxCloneIndex", required_argument, 0, OPTION_SANDBOX_CLONE_INDEX}, + {"creatorBundle", required_argument, 0, OPTION_CREATOR_BUNDLE}, {0, 0, 0, 0} }; } @@ -178,6 +184,7 @@ private: void FormatOutputForWithWait(const Want &want, const AbilityStartWithWaitObserverData& data); bool startAbilityWithWaitFlag_ = false; + bool StartSandboxCloneAbilityFlag_ = false; std::map errorInfoMap_; }; } // namespace AAFwk diff --git a/tools/ohos-aa/ohos-aa.json b/tools/ohos-aa/ohos-aa.json index 878aa166d2..aafee52cee 100644 --- a/tools/ohos-aa/ohos-aa.json +++ b/tools/ohos-aa/ohos-aa.json @@ -76,6 +76,14 @@ "type": "string", "description": "moduleName" }, + "sandboxCloneIndex": { + "type": "integer", + "description": "Sandbox clone index for launching sandbox clone application (range: 2000-3000)" + }, + "creatorBundle": { + "type": "string", + "description": "Creator bundle name for sandbox clone application" + }, "uri": { "type": "string", "description": "URI" diff --git a/tools/ohos-aa/src/ohos_aa_command.cpp b/tools/ohos-aa/src/ohos_aa_command.cpp index d37c539cdd..171369575b 100644 --- a/tools/ohos-aa/src/ohos_aa_command.cpp +++ b/tools/ohos-aa/src/ohos_aa_command.cpp @@ -23,6 +23,7 @@ #include "ability_manager_client.h" #include "ability_start_with_wait_observer.h" #include "ability_start_with_wait_observer_utils.h" +#include "global_constant.h" #include "hilog_tag_wrapper.h" #include "iservice_registry.h" #include "system_ability_definition.h" @@ -99,6 +100,9 @@ const std::string ERR_NOT_IN_APP_PROVISION_MODE_SOLUTION_ONE = const std::string ERR_APP_CLONE_INDEX_INVALID_SOLUTION_ONE = "Confirm whether the appCloneIndex is valid"; +const std::string ERR_SANDBOX_CLONE_INDEX_INVALID_SOLUTION_ONE = + "Confirm whether the sandboxCloneIndex is valid (range: 2000-3000)"; + const std::string ERR_STATIC_CFG_PERMISSION_SOLUTION_ONE = "Confirm whether the permissions of the specified process are correct"; @@ -213,6 +217,11 @@ ErrCode ClawAaShellCommand::CreateErrorInfoMap() "If the appCloneIndex carried in the parameters of the command is an invalid value, return that error code.", {ERR_APP_CLONE_INDEX_INVALID_SOLUTION_ONE}}; + errorInfoMap_[ERR_SANDBOX_CLONE_INDEX_INVALID] = {"ERR_SANDBOX_CLONE_INDEX_INVALID", + "The passed sandboxCloneIndex is invalid.", + "If the sandboxCloneIndex carried in the parameters of the command is an invalid value, return that error code.", + {ERR_SANDBOX_CLONE_INDEX_INVALID_SOLUTION_ONE}}; + errorInfoMap_[START_ABILITY_WAITING] = {"ERR_ABILITY_START_ABILITY_WAITING", "Another ability is being started. Wait until it finishes starting.", "High system concurrency.", @@ -306,6 +315,29 @@ ErrCode ClawAaShellCommand::RunAsStartAbility() if (result == OHOS::ERR_OK) { if (startAbilityWithWaitFlag_) { result = StartAbilityWithWait(want); + } else if (StartSandboxCloneAbilityFlag_) { + SandboxCloneParams params; + // Get caller info from environment variables (set by SA-CLI via config["env"]) + if (const char* envCallerUid = std::getenv("ohos_cli_callerUid")) { + auto res = std::from_chars(envCallerUid, envCallerUid + std::strlen(envCallerUid), params.callerUid); + if (res.ec != std::errc()) { + TAG_LOGE(AAFwkTag::AA_TOOL, "Invalid callerUid from env: %{public}s", envCallerUid); + params.callerUid = -1; + } + } + if (const char* envCallerTokenId = std::getenv("ohos_cli_callerTokenId")) { + auto res = std::from_chars(envCallerTokenId, envCallerTokenId + std::strlen(envCallerTokenId), + params.callerTokenId); + if (res.ec != std::errc()) { + TAG_LOGE(AAFwkTag::AA_TOOL, "Invalid callerTokenId from env: %{public}s", envCallerTokenId); + params.callerTokenId = 0; + } + } + if (const char* envCallerBundleName = std::getenv("ohos_cli_callerBundleName")) + params.callerBundleName = envCallerBundleName; + TAG_LOGI(AAFwkTag::AA_TOOL, "StartSandboxCloneAbility with callerUid=%{public}d, callerTokenId=%{public}u, " + "callerBundleName=%{public}s", params.callerUid, params.callerTokenId, params.callerBundleName.c_str()); + result = AbilityManagerClient::GetInstance()->StartSandboxCloneAbility(want, params); } else { result = AbilityManagerClient::GetInstance()->StartAbility(want); } @@ -627,6 +659,9 @@ ErrCode ClawAaShellCommand::MakeWantFromCmd(Want& want, int32_t& userId) bool hasWindowHeight = false; int windowWidth = 0; bool hasWindowWidth = false; + int32_t sandBoxCloneIndex = 0; + bool hasSandBoxCloneIndex = false; + std::string creatorBundleName; // Creator bundle name (untrusted, from command line) while (true) { counter++; @@ -906,6 +941,31 @@ ErrCode ClawAaShellCommand::MakeWantFromCmd(Want& want, int32_t& userId) break; } + case OPTION_SANDBOX_CLONE_INDEX: { + // 'ohos-aa start --sandboxCloneIndex xxx' + if (optarg != nullptr) { + std::string sandBoxCloneIndexStr = optarg; + if (!std::regex_match(sandBoxCloneIndexStr, std::regex(STRING_TEST_REGEX_INTEGER_NUMBERS))) { + TAG_LOGE(AAFwkTag::AA_TOOL, "invalid sandboxCloneIndex: %{public}s", + sandBoxCloneIndexStr.c_str()); + result = ERR_SANDBOX_CLONE_INDEX_INVALID; + break; + } + sandBoxCloneIndex = std::stoi(sandBoxCloneIndexStr); + hasSandBoxCloneIndex = true; + StartSandboxCloneAbilityFlag_ = true; + TAG_LOGI(AAFwkTag::AA_TOOL, "sandBoxCloneIndex = %{public}d, Flag_ set to true", sandBoxCloneIndex); + } + break; + } + case OPTION_CREATOR_BUNDLE: { + // 'ohos-aa start --creatorBundle xxx' + if (optarg != nullptr) { + creatorBundleName = optarg; + TAG_LOGI(AAFwkTag::AA_TOOL, "creatorBundleName = %{public}s", creatorBundleName.c_str()); + } + break; + } case OPTION_URI: { // 'aa start -U xxx' @@ -1005,6 +1065,15 @@ ErrCode ClawAaShellCommand::MakeWantFromCmd(Want& want, int32_t& userId) if (hasWindowWidth) { want.SetParam(Want::PARAM_RESV_WINDOW_WIDTH, windowWidth); } + // Sandbox clone application support parameters + if (hasSandBoxCloneIndex) { + want.SetParam(AbilityRuntime::GlobalConstant::SANDBOX_CLONE_INDEX, sandBoxCloneIndex); + } + // Set creator bundle name (untrusted, from command line parameter) + if (!creatorBundleName.empty()) { + want.SetParam(AbilityRuntime::GlobalConstant::CREATOR_BUNDLE_NAME, creatorBundleName); + TAG_LOGI(AAFwkTag::AA_TOOL, "creatorBundleName: %{public}s", creatorBundleName.c_str()); + } } } diff --git a/tools/ohos-aa/tests/ohos_aa_command_start_test.cpp b/tools/ohos-aa/tests/ohos_aa_command_start_test.cpp index c0c83a7d39..6940f58406 100644 --- a/tools/ohos-aa/tests/ohos_aa_command_start_test.cpp +++ b/tools/ohos-aa/tests/ohos_aa_command_start_test.cpp @@ -557,3 +557,175 @@ HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2400, Function | MediumTe std::string result = cmd.ExecCommand(); EXPECT_NE(result.find("start ability successfully"), std::string::npos); } + +/** + * @tc.number: Ohos_Aa_Command_Start_2500 + * @tc.name: ExecCommand + * @tc.desc: Verify start with valid sandboxCloneIndex parameter. + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2500, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_2500"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"2000", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("start ability successfully"), std::string::npos); +} + +/** + * @tc.number: Ohos_Aa_Command_Start_2600 + * @tc.name: ExecCommand + * @tc.desc: Verify start with sandboxCloneIndex at max boundary (3000). + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2600, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_2600"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"3000", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("start ability successfully"), std::string::npos); +} + +/** + * @tc.number: Ohos_Aa_Command_Start_2700 + * @tc.name: ExecCommand + * @tc.desc: Verify start with sandboxCloneIndex at mid-range (2500). + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2700, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_2700"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"2500", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("start ability successfully"), std::string::npos); +} + +/** + * @tc.number: Ohos_Aa_Command_Start_2800 + * @tc.name: ExecCommand + * @tc.desc: Verify start with invalid non-numeric sandboxCloneIndex + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2800, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_2800"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"abc", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("Invalid"), std::string::npos); +} + +/** + * @tc.number: Ohos_Aa_Command_Start_2900 + * @tc.name: ExecCommand + * @tc.desc: Verify start with sandboxCloneIndex and creatorBundle together. + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_2900, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_2900"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"2001", + (char*)"--creatorBundle", + (char*)"com.creator.bundle", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("start ability successfully"), std::string::npos); +} + +/** + * @tc.number: Ohos_Aa_Command_Start_3000 + * @tc.name: ExecCommand + * @tc.desc: Verify start with sandboxCloneIndex and moduleName together. + */ +HWTEST_F(OhosAaCommandStartTest, Ohos_Aa_Command_Start_3000, Function | MediumTest | Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "Ohos_Aa_Command_Start_3000"); + + char* argv[] = { + (char*)TOOL_NAME.c_str(), + (char*)cmd_.c_str(), + (char*)"--abilityname", + (char*)STRING_ABILITY_NAME.c_str(), + (char*)"--bundlename", + (char*)STRING_BUNDLE_NAME.c_str(), + (char*)"--modulename", + (char*)STRING_MODULE_NAME.c_str(), + (char*)"--sandboxCloneIndex", + (char*)"2002", + (char*)"", + }; + int argc = sizeof(argv) / sizeof(argv[0]) - 1; + + ClawAaShellCommand cmd(argc, argv); + cmd.CreateErrorInfoMap(); + std::string result = cmd.ExecCommand(); + EXPECT_NE(result.find("start ability successfully"), std::string::npos); +} diff --git a/utils/global/constant/global_constant.h b/utils/global/constant/global_constant.h index c00a276dee..36a87512f6 100644 --- a/utils/global/constant/global_constant.h +++ b/utils/global/constant/global_constant.h @@ -19,6 +19,26 @@ namespace OHOS::AbilityRuntime { namespace GlobalConstant { constexpr int32_t MAX_APP_CLONE_INDEX = 1000; +constexpr int32_t MIN_SANDBOX_CLONE_INDEX = 2000; +constexpr int32_t MAX_SANDBOX_CLONE_INDEX = 3000; + +// Helper functions to determine index type +constexpr bool IsAppCloneIndex(int32_t index) +{ + return index >= 0 && index <= MAX_APP_CLONE_INDEX; +} + +constexpr bool IsSandboxCloneIndex(int32_t index) +{ + return index >= MIN_SANDBOX_CLONE_INDEX && index <= MAX_SANDBOX_CLONE_INDEX; +} + +constexpr bool IsDlpIndex(int32_t index) +{ + // DLP indices are those that are neither AppClone nor SandboxClone + // AppClone: [0~1000], SandboxClone: [2000~3000], DLP: other ranges + return !IsAppCloneIndex(index) && !IsSandboxCloneIndex(index); +} constexpr int32_t TIMEOUT_UNIT_TIME = 1000; constexpr int32_t TIMEOUT_UNIT_TIME_MICRO = 1000 * 1000; @@ -67,6 +87,13 @@ constexpr int32_t TYPE_OTHERS = 2; constexpr int32_t MIGRATE_CLIENT_TIMEOUT_MULTIPLE = 3; +// Sandbox clone related parameter +constexpr const char* SANDBOX_CLONE_INDEX = "ohos.ability.cli.sandBoxCloneIndex"; +constexpr const char* CLI_CALLER_BUNDLE_NAME = "ohos.ability.cli.callerBundleName"; +constexpr const char* CLI_CALLER_TOKEN_ID = "ohos.ability.cli.callerTokenId"; +constexpr const char* IS_WEB_SANDBOX_CLONE = "ohos.ability.params.isWebSandBoxClone"; +constexpr const char* CREATOR_BUNDLE_NAME = "ohos.ability.cli.creatorBundleName"; + constexpr int32_t GetLoadTimeOutBase() { return TIMEOUT_UNIT_TIME * LOAD_TIMEOUT_MULTIPLE; diff --git a/utils/server/startup/src/startup_util.cpp b/utils/server/startup/src/startup_util.cpp index 8930b8fc99..15ffe80be4 100644 --- a/utils/server/startup/src/startup_util.cpp +++ b/utils/server/startup/src/startup_util.cpp @@ -32,11 +32,11 @@ bool StartupUtil::GetAppIndex(const AAFwk::Want &want, int32_t &appIndex) { if (want.HasParameter(ServerConstant::DLP_INDEX)) { appIndex = want.GetIntParam(ServerConstant::DLP_INDEX, 0); - return appIndex > GlobalConstant::MAX_APP_CLONE_INDEX; + return AbilityRuntime::GlobalConstant::IsDlpIndex(appIndex); } if (want.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY)) { appIndex = want.GetIntParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, 0); - return (appIndex >= 0 && appIndex <= GlobalConstant::MAX_APP_CLONE_INDEX); + return AbilityRuntime::GlobalConstant::IsAppCloneIndex(appIndex); } appIndex = 0; return true;