From 91013ad9a628d4061d8ca28997678fe16bb2ce9f Mon Sep 17 00:00:00 2001 From: xlw Date: Tue, 9 Jul 2024 10:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E8=BA=AB=E9=80=82=E9=85=8D=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlw Change-Id: Ib90233b376301a5a9df0f9cbdb15db2017c75d22 --- .../js_dialog_session_utils.cpp | 19 ++ .../js_dialog_session_utils.h | 1 + .../bundle_mgr_helper.cpp | 14 ++ .../include/ability_manager_client.h | 2 +- .../include/ability_manager_interface.h | 2 +- .../include/dialog_session_info.h | 3 + .../bundle_mgr_helper.h | 1 + .../include/ability_manager_proxy.h | 2 +- .../include/ability_manager_service.h | 4 +- .../dialog_session/dialog_session_manager.h | 40 +++- ...bility_ecological_rule_mgr_service_param.h | 2 +- .../include/implicit_start_processor.h | 10 +- .../abilitymgr/include/start_ability_utils.h | 3 + .../include/system_dialog_scheduler.h | 3 + .../abilitymgr/src/ability_manager_client.cpp | 2 +- .../abilitymgr/src/ability_manager_proxy.cpp | 2 +- .../src/ability_manager_service.cpp | 42 +++- .../dialog_session/dialog_session_info.cpp | 9 +- .../dialog_session/dialog_session_manager.cpp | 220 ++++++++++++++---- .../ability_ecological_rule_mgr_service.cpp | 4 +- ...lity_ecological_rule_mgr_service_param.cpp | 6 +- .../src/implicit_start_processor.cpp | 105 ++++++++- .../ecological_rule_interceptor.cpp | 6 +- .../abilitymgr/src/start_ability_utils.cpp | 21 ++ .../src/system_dialog_scheduler.cpp | 6 + .../ams_system_dialog/AppScope/app.json | 4 +- .../SelectorServiceExtAbility.ts | 22 +- .../src/main/ets/pages/selectorPcDialog.ets | 7 +- .../main/ets/pages/selectorPhoneDialog.ets | 37 ++- .../base/media/app_icon_clone_index_1.svg | 10 + .../base/media/app_icon_clone_index_2.svg | 10 + .../base/media/app_icon_clone_index_3.svg | 10 + .../base/media/app_icon_clone_index_4.svg | 10 + .../base/media/app_icon_clone_index_5.svg | 10 + 34 files changed, 539 insertions(+), 110 deletions(-) create mode 100644 services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_1.svg create mode 100644 services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_2.svg create mode 100644 services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_3.svg create mode 100644 services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_4.svg create mode 100644 services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_5.svg diff --git a/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.cpp b/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.cpp index a67fcee65f..72ef201ab7 100644 --- a/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.cpp +++ b/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.cpp @@ -68,6 +68,10 @@ napi_value WrapDialogAbilityInfo(napi_env env, const AAFwk::DialogAbilityInfo &d SetPropertyValueByPropertyName(env, jsObject, "abilityLabelId", jsValue); jsValue = WrapBoolToJS(env, dialogAbilityInfo.visible); SetPropertyValueByPropertyName(env, jsObject, "visible", jsValue); + jsValue = WrapInt32ToJS(env, dialogAbilityInfo.appIndex); + SetPropertyValueByPropertyName(env, jsObject, "appIndex", jsValue); + jsValue = WrapMultiAppModeData(env, dialogAbilityInfo.multiAppMode); + SetPropertyValueByPropertyName(env, jsObject, "multiAppMode", jsValue); return jsObject; } @@ -90,5 +94,20 @@ napi_value WrapDialogSessionInfo(napi_env env, const AAFwk::DialogSessionInfo &d return jsObject; } + +napi_value WrapMultiAppModeData(napi_env env, const AppExecFwk::MultiAppModeData &multiAppMode) +{ + napi_value jsObject = nullptr; + napi_value jsValue = nullptr; + NAPI_CALL(env, napi_create_object(env, &jsObject)); + + jsValue = WrapInt32ToJS(env, static_cast(multiAppMode.multiAppModeType)); + SetPropertyValueByPropertyName(env, jsObject, "multiAppModeType", jsValue); + + jsValue = WrapInt32ToJS(env, static_cast(multiAppMode.maxCount)); + SetPropertyValueByPropertyName(env, jsObject, "maxCount", jsValue); + + return jsObject; +} } // namespace AbilityRuntime } // nampspace OHOS diff --git a/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.h b/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.h index 81984a9569..a7932e032b 100644 --- a/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.h +++ b/frameworks/js/napi/js_dialog_session/js_dialog_session_utils.h @@ -30,6 +30,7 @@ namespace AppExecFwk { napi_value WrapArrayDialogAbilityInfoToJS(napi_env env, const std::vector &value); napi_value WrapDialogSessionInfo(napi_env env, const AAFwk::DialogSessionInfo &dialogSessionInfo); napi_value WrapDialogAbilityInfo(napi_env env, const AAFwk::DialogAbilityInfo &dialogAbilityInfo); +napi_value WrapMultiAppModeData(napi_env env, const AppExecFwk::MultiAppModeData &multiAppMode); } // namespace AppExecFwk } // namespace OHOS #endif // OHOS_ABILITY_RUNTIME_JS_DIALOG_SESSION_UTILS_H 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 3bcfc8f1db..02fb8b8e04 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 @@ -867,5 +867,19 @@ ErrCode BundleMgrHelper::QueryCloneExtensionAbilityInfoWithAppIndex(const Elemen return bundleMgr->QueryCloneExtensionAbilityInfoWithAppIndex(element, flags, appCloneIndex, extensionInfo, userId); } +ErrCode BundleMgrHelper::GetCloneAppIndexes(const std::string &bundleName, std::vector &appIndexes, + int32_t userId) +{ + TAG_LOGD(AAFwkTag::BUNDLEMGRHELPER, "Called."); + auto bundleMgr = Connect(); + if (bundleMgr == nullptr) { + TAG_LOGE(AAFwkTag::BUNDLEMGRHELPER, "Failed to connect."); + return ERR_APPEXECFWK_SERVICE_INTERNAL_ERROR; + } + + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + return bundleMgr->GetCloneAppIndexes(bundleName, appIndexes, userId); +} + } // namespace AppExecFwk } // namespace OHOS \ No newline at end of file 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 5aa52ce070..d4f9c8cc05 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -1034,7 +1034,7 @@ public: void UpdateMissionSnapShot(sptr token, std::shared_ptr pixelMap); - ErrCode GetDialogSessionInfo(const std::string dialogSessionId, sptr &info); + ErrCode GetDialogSessionInfo(const std::string &dialogSessionId, sptr &info); ErrCode SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllow); #endif 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 bdcc4ff633..3edd398ee9 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -936,7 +936,7 @@ public: return 0; } - virtual int GetDialogSessionInfo(const std::string dialogSessionId, sptr &dialogSessionInfo) + virtual int GetDialogSessionInfo(const std::string &dialogSessionId, sptr &dialogSessionInfo) { return 0; } diff --git a/interfaces/inner_api/ability_manager/include/dialog_session_info.h b/interfaces/inner_api/ability_manager/include/dialog_session_info.h index fc6f550944..af2b7303cf 100644 --- a/interfaces/inner_api/ability_manager/include/dialog_session_info.h +++ b/interfaces/inner_api/ability_manager/include/dialog_session_info.h @@ -19,6 +19,7 @@ #include #include +#include "application_info.h" #include "json_serializer.h" #include "parcel.h" #include "refbase.h" @@ -35,6 +36,8 @@ struct DialogAbilityInfo { int32_t abilityIconId = 0; int32_t abilityLabelId = 0; bool visible = true; + int32_t appIndex = 0; + AppExecFwk::MultiAppModeData multiAppMode; std::string GetURI() const; bool ParseURI(const std::string &uri); 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 a7b8f81e58..c5082b7feb 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 @@ -99,6 +99,7 @@ public: BundleInfo &bundleInfo, int32_t userId); ErrCode QueryCloneExtensionAbilityInfoWithAppIndex(const ElementName &element, int32_t flags, int32_t appCloneIndex, ExtensionAbilityInfo &extensionInfo, int32_t userId); + ErrCode GetCloneAppIndexes(const std::string &bundleName, std::vector &appIndexes, int32_t userId); private: sptr Connect(); diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index 6b28c2314f..8bde587a38 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -729,7 +729,7 @@ public: virtual int PrepareTerminateAbility( const sptr &token, sptr &callback) override; - virtual int GetDialogSessionInfo(const std::string dialogSessionId, sptr &info) override; + virtual int GetDialogSessionInfo(const std::string &dialogSessionId, sptr &info) override; virtual int SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllow) override; diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 16af167a3b..636316b51e 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -1121,11 +1121,13 @@ public: void HandleUnfocused(const sptr &focusChangeInfo); - virtual int GetDialogSessionInfo(const std::string dialogSessionId, + virtual int GetDialogSessionInfo(const std::string &dialogSessionId, sptr &dialogSessionInfo) override; virtual int SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllowed) override; + int CreateCloneSelectorDialog(AbilityRequest &request, int32_t userId, const std::string &replaceWantString = ""); + virtual int RegisterAbilityFirstFrameStateObserver(const sptr &observer, const std::string &bundleName) override; diff --git a/services/abilitymgr/include/dialog_session/dialog_session_manager.h b/services/abilitymgr/include/dialog_session/dialog_session_manager.h index 5e26da4165..ba8f1c4d4f 100644 --- a/services/abilitymgr/include/dialog_session/dialog_session_manager.h +++ b/services/abilitymgr/include/dialog_session/dialog_session_manager.h @@ -38,37 +38,61 @@ struct DialogCallerInfo { bool isSelector = false; }; +enum class SelectorType { + IMPLICIT_START_SELECTOR = 0, + APP_CLONR_SELECTOR = 1 +}; + class DialogSessionManager { public: static DialogSessionManager &GetInstance(); ~DialogSessionManager() = default; - sptr GetDialogSessionInfo(const std::string dialogSessionId) const; + sptr GetDialogSessionInfo(const std::string &dialogSessionId) const; - std::shared_ptr GetDialogCallerInfo(const std::string dialogSessionId) const; + std::shared_ptr GetDialogCallerInfo(const std::string &dialogSessionId) const; int SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllowed); int CreateJumpModalDialog(AbilityRequest &abilityRequest, int32_t userId, const Want &replaceWant); - int CreateSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, + int CreateImplicitSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, std::vector &dialogAppInfos); + int CreateCloneSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, + std::vector &dialogAppInfos, const std::string &replaceWant); + + int HandleErmsResult(AbilityRequest &abilityRequest, int32_t userId, const Want &replaceWant); + + bool IsCreateCloneSelectorDialog(const std::string &bundleName, int32_t userId); + private: DialogSessionManager() = default; std::string GenerateDialogSessionId(); - void SetDialogSessionInfo(const std::string dialogSessionId, sptr &dilogSessionInfo, + void SetDialogSessionInfo(const std::string &dialogSessionId, sptr &dilogSessionInfo, std::shared_ptr &dialogCallerInfo); - void ClearDialogContext(const std::string dialogSessionId); + void ClearDialogContext(const std::string &dialogSessionId); void ClearAllDialogContexts(); - bool GenerateDialogSessionRecord(AbilityRequest &abilityRequest, int32_t userId, - std::string &dialogSessionId, std::vector &dialogAppInfos, bool isSelector); + std::string GenerateDialogSessionRecordCommon(AbilityRequest &abilityRequest, int32_t userId, + const AAFwk::WantParams ¶meters, std::vector &dialogAppInfos, bool isSelector); - int CreateModalDialogCommon(const Want &replaceWant, sptr callerToken, std::string dialogSessionId); + void GenerateCallerAbilityInfo(AbilityRequest &abilityRequest, DialogAbilityInfo &callerAbilityInfo); + + void GenerateSelectorTargetAbilityInfos(std::vector &dialogAppInfos, + std::vector &targetAbilityInfos); + + void GenerateJumpTargetAbilityInfos(AbilityRequest &abilityRequest, + std::vector &targetAbilityInfos); + + void GenerateDialogCallerInfo(AbilityRequest &abilityRequest, int32_t userId, + std::shared_ptr dialogCallerInfo, bool isSelector); + + int CreateModalDialogCommon(const Want &replaceWant, sptr callerToken, + const std::string &dialogSessionId); mutable ffrt::mutex dialogSessionRecordLock_; std::unordered_map> dialogSessionInfoMap_; diff --git a/services/abilitymgr/include/ecological_rule/ability_ecological_rule_mgr_service_param.h b/services/abilitymgr/include/ecological_rule/ability_ecological_rule_mgr_service_param.h index a49f530125..6214fe5836 100644 --- a/services/abilitymgr/include/ecological_rule/ability_ecological_rule_mgr_service_param.h +++ b/services/abilitymgr/include/ecological_rule/ability_ecological_rule_mgr_service_param.h @@ -28,7 +28,7 @@ namespace EcologicalRuleMgrService { using Want = OHOS::AAFwk::Want; struct AbilityExperienceRule : public Parcelable { - bool isAllow = true; + int32_t resultCode = 10; std::string sceneCode = ""; sptr replaceWant = nullptr; diff --git a/services/abilitymgr/include/implicit_start_processor.h b/services/abilitymgr/include/implicit_start_processor.h index 8c9f02cbcc..5248fac810 100644 --- a/services/abilitymgr/include/implicit_start_processor.h +++ b/services/abilitymgr/include/implicit_start_processor.h @@ -58,7 +58,8 @@ public: static bool IsImplicitStartAction(const Want &want); - int ImplicitStartAbility(AbilityRequest &request, int32_t userId, int32_t windowMode = 0); + int ImplicitStartAbility(AbilityRequest &request, int32_t userId, int32_t windowMode = 0, + const std::string &replaceWantString = "", bool isAppCloneSelector = false); void ResetCallingIdentityAsCaller(int32_t tokenId); @@ -69,6 +70,13 @@ public: private: int GenerateAbilityRequestByAction(int32_t userId, AbilityRequest &request, std::vector &dialogAppInfos, bool isMoreHapList, bool &findDefaultApp); + + int GenerateAbilityRequestByAppIndexes(int32_t userId, AbilityRequest &request, + std::vector &dialogAppInfos); + + int FindExtensionInfo(const Want &want, int32_t flags, int32_t userId, int32_t appIndex, + AppExecFwk::AbilityInfo &abilityInfo); + std::string MatchTypeAndUri(const AAFwk::Want &want); std::shared_ptr GetBundleManagerHelper(); std::vector SplitStr(const std::string& str, char delimiter); diff --git a/services/abilitymgr/include/start_ability_utils.h b/services/abilitymgr/include/start_ability_utils.h index b29e341d30..eb99a03065 100644 --- a/services/abilitymgr/include/start_ability_utils.h +++ b/services/abilitymgr/include/start_ability_utils.h @@ -53,12 +53,15 @@ struct StartAbilityUtils { static bool GetCallerAbilityInfo(const sptr &callerToken, AppExecFwk::AbilityInfo &abilityInfo); static int32_t CheckAppProvisionMode(const Want& want, int32_t userId); + static std::vector GetCloneAppIndexes(const std::string &bundleName, int32_t userId); static thread_local std::shared_ptr startAbilityInfo; static thread_local std::shared_ptr callerAbilityInfo; static thread_local bool skipCrowTest; static thread_local bool skipStartOther; static thread_local bool skipErms; + static thread_local int32_t ermsResultCode; + static thread_local bool isWantWithAppCloneIndex; }; struct StartAbilityInfoWrap { diff --git a/services/abilitymgr/include/system_dialog_scheduler.h b/services/abilitymgr/include/system_dialog_scheduler.h index 39254c47ca..06d3662509 100644 --- a/services/abilitymgr/include/system_dialog_scheduler.h +++ b/services/abilitymgr/include/system_dialog_scheduler.h @@ -17,6 +17,7 @@ #include +#include "application_info.h" #include "bundle_mgr_interface.h" #include "singleton.h" @@ -59,6 +60,8 @@ struct DialogAppInfo { std::string abilityName = {}; std::string moduleName = {}; bool visible = true; + int32_t appIndex = 0; + AppExecFwk::MultiAppModeData multiAppMode; }; /** * @class SystemDialogScheduler diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index db9052744b..38fa5025f1 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -1331,7 +1331,7 @@ ErrCode AbilityManagerClient::PrepareTerminateAbility(sptr token, return abms->PrepareTerminateAbility(token, callback); } -ErrCode AbilityManagerClient::GetDialogSessionInfo(const std::string dialogSessionId, sptr &info) +ErrCode AbilityManagerClient::GetDialogSessionInfo(const std::string &dialogSessionId, sptr &info) { auto abms = GetAbilityManager(); CHECK_POINTER_RETURN_NOT_CONNECTED(abms); diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index a2b649dc0b..7206eab8a9 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -3056,7 +3056,7 @@ int AbilityManagerProxy::PrepareTerminateAbility(const sptr &toke return reply.ReadInt32(); } -int AbilityManagerProxy::GetDialogSessionInfo(const std::string dialogSessionId, sptr &info) +int AbilityManagerProxy::GetDialogSessionInfo(const std::string &dialogSessionId, sptr &info) { MessageParcel data; MessageParcel reply; diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index ab1814df2b..58225c957c 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -1179,7 +1179,12 @@ int AbilityManagerService::StartAbilityInner(const Want &want, const sptr(abilityRequest.abilityInfo)); result = afterCheckExecuter_ == nullptr ? ERR_INVALID_VALUE : afterCheckExecuter_->DoProcess(afterCheckParam); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "afterCheckExecuter_ is nullptr or DoProcess return error."); + return result; + } if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { ReportEventToRSS(abilityRequest.abilityInfo, callerToken); abilityRequest.want.SetParam(IS_CALL_BY_SCB, false); @@ -6893,11 +6907,6 @@ int AbilityManagerService::StartAbilityByCall(const Want &want, const sptrResolveLocked(abilityRequest); } @@ -10188,7 +10197,7 @@ int32_t AbilityManagerService::OpenFile(const Uri& uri, uint32_t flag) return collaborator->OpenFile(uri, flag); } #ifdef SUPPORT_SCREEN -int AbilityManagerService::GetDialogSessionInfo(const std::string dialogSessionId, +int AbilityManagerService::GetDialogSessionInfo(const std::string &dialogSessionId, sptr &dialogSessionInfo) { CHECK_CALLER_IS_SYSTEM_APP; @@ -10206,6 +10215,13 @@ int AbilityManagerService::SendDialogResult(const Want &want, const std::string CHECK_CALLER_IS_SYSTEM_APP; return DialogSessionManager::GetInstance().SendDialogResult(want, dialogSessionId, isAllowed); } + +int AbilityManagerService::CreateCloneSelectorDialog(AbilityRequest &request, int32_t userId, + const std::string &replaceWantString) +{ + CHECK_POINTER_AND_RETURN(implicitStartProcessor_, ERR_IMPLICIT_START_ABILITY_FAIL); + return implicitStartProcessor_->ImplicitStartAbility(request, userId, 0, replaceWantString, true); +} #endif // SUPPORT_SCREEN void AbilityManagerService::RemoveLauncherDeathRecipient(int32_t userId) { @@ -11143,9 +11159,13 @@ int AbilityManagerService::StartUIAbilityByPreInstallInner(sptr ses return result; } #ifdef SUPPORT_SCREEN - if (result != ERR_OK && isReplaceWantExist && - callerBundleName != BUNDLE_NAME_DIALOG) { - return DialogSessionManager::GetInstance().CreateJumpModalDialog(abilityRequest, GetUserId(), newWant); + if (result != ERR_OK && isReplaceWantExist && callerBundleName != BUNDLE_NAME_DIALOG) { + return DialogSessionManager::GetInstance().HandleErmsResult(abilityRequest, GetUserId(), newWant); + } + if (result == ERR_OK && + DialogSessionManager::GetInstance().IsCreateCloneSelectorDialog(abilityInfo.bundleName, GetUserId())) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "create clone selector dialog"); + return CreateCloneSelectorDialog(abilityRequest, GetUserId()); } #endif // SUPPORT_SCREEN diff --git a/services/abilitymgr/src/dialog_session/dialog_session_info.cpp b/services/abilitymgr/src/dialog_session/dialog_session_info.cpp index fa46604fb7..acee947fa0 100644 --- a/services/abilitymgr/src/dialog_session/dialog_session_info.cpp +++ b/services/abilitymgr/src/dialog_session/dialog_session_info.cpp @@ -25,14 +25,16 @@ namespace OHOS { namespace AAFwk { constexpr int32_t CYCLE_LIMIT = 1000; -constexpr size_t MEMBER_NUM = 8; +constexpr size_t MEMBER_NUM = 11; std::string DialogAbilityInfo::GetURI() const { return bundleName + "/" + moduleName + "/" + abilityName + "/" + std::to_string(bundleIconId) + "/" + std::to_string(bundleLabelId) + "/" + std::to_string(abilityIconId) + "/" + std::to_string(abilityLabelId) + "/" + - std::to_string(visible); + std::to_string(visible) + "/" + std::to_string(appIndex) + "/" + + std::to_string(static_cast(multiAppMode.multiAppModeType)) + "/" + + std::to_string(multiAppMode.maxCount); } bool DialogAbilityInfo::ParseURI(const std::string &uri) @@ -55,6 +57,9 @@ bool DialogAbilityInfo::ParseURI(const std::string &uri) abilityIconId = static_cast(std::stoi(uriVec[index++])); abilityLabelId = static_cast(std::stoi(uriVec[index++])); visible = std::stoi(uriVec[index++]); + appIndex = static_cast(std::stoi(uriVec[index++])); + multiAppMode.multiAppModeType = static_cast(std::stoi(uriVec[index++])); + multiAppMode.maxCount = static_cast(std::stoi(uriVec[index++])); return true; } diff --git a/services/abilitymgr/src/dialog_session/dialog_session_manager.cpp b/services/abilitymgr/src/dialog_session/dialog_session_manager.cpp index aec0bc2e36..2f514d2da3 100644 --- a/services/abilitymgr/src/dialog_session/dialog_session_manager.cpp +++ b/services/abilitymgr/src/dialog_session/dialog_session_manager.cpp @@ -27,7 +27,9 @@ #include "int_wrapper.h" #include "modal_system_ui_extension.h" #include "parameters.h" +#include "start_ability_utils.h" #include "string_wrapper.h" +#include "want.h" #include "want_params_wrapper.h" namespace OHOS { @@ -35,6 +37,7 @@ namespace AAFwk { using OHOS::AppExecFwk::BundleInfo; namespace { constexpr const char* UIEXTENSION_MODAL_TYPE = "ability.want.params.modalType"; +constexpr int32_t ERMS_ISALLOW_RESULTCODE = 10; } DialogSessionManager &DialogSessionManager::GetInstance() @@ -63,7 +66,7 @@ std::string DialogSessionManager::GenerateDialogSessionId() return dialogSessionId; } -void DialogSessionManager::SetDialogSessionInfo(const std::string dialogSessionId, +void DialogSessionManager::SetDialogSessionInfo(const std::string &dialogSessionId, sptr &dilogSessionInfo, std::shared_ptr &dialogCallerInfo) { std::lock_guard guard(dialogSessionRecordLock_); @@ -71,7 +74,7 @@ void DialogSessionManager::SetDialogSessionInfo(const std::string dialogSessionI dialogCallerInfoMap_[dialogSessionId] = dialogCallerInfo; } -sptr DialogSessionManager::GetDialogSessionInfo(const std::string dialogSessionId) const +sptr DialogSessionManager::GetDialogSessionInfo(const std::string &dialogSessionId) const { std::lock_guard guard(dialogSessionRecordLock_); auto it = dialogSessionInfoMap_.find(dialogSessionId); @@ -82,7 +85,7 @@ sptr DialogSessionManager::GetDialogSessionInfo(const std::st return nullptr; } -std::shared_ptr DialogSessionManager::GetDialogCallerInfo(const std::string dialogSessionId) const +std::shared_ptr DialogSessionManager::GetDialogCallerInfo(const std::string &dialogSessionId) const { std::lock_guard guard(dialogSessionRecordLock_); auto it = dialogCallerInfoMap_.find(dialogSessionId); @@ -93,7 +96,7 @@ std::shared_ptr DialogSessionManager::GetDialogCallerInfo(cons return nullptr; } -void DialogSessionManager::ClearDialogContext(const std::string dialogSessionId) +void DialogSessionManager::ClearDialogContext(const std::string &dialogSessionId) { std::lock_guard guard(dialogSessionRecordLock_); auto it = dialogSessionInfoMap_.find(dialogSessionId); @@ -114,26 +117,29 @@ void DialogSessionManager::ClearAllDialogContexts() dialogCallerInfoMap_.clear(); } -bool DialogSessionManager::GenerateDialogSessionRecord(AbilityRequest &abilityRequest, int32_t userId, - std::string &dialogSessionId, std::vector &dialogAppInfos, bool isSelector) +void DialogSessionManager::GenerateCallerAbilityInfo(AbilityRequest &abilityRequest, + DialogAbilityInfo &callerAbilityInfo) { - HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - auto dialogSessionInfo = sptr::MakeSptr(); - CHECK_POINTER_AND_RETURN(dialogSessionInfo, ERR_INVALID_VALUE); sptr callerToken = abilityRequest.callerToken; if (callerToken != nullptr) { auto callerRecord = Token::GetAbilityRecordByToken(callerToken); - CHECK_POINTER_AND_RETURN(callerRecord, ERR_INVALID_VALUE); - dialogSessionInfo->callerAbilityInfo.bundleName = callerRecord->GetAbilityInfo().bundleName; - dialogSessionInfo->callerAbilityInfo.moduleName = callerRecord->GetAbilityInfo().moduleName; - dialogSessionInfo->callerAbilityInfo.abilityName = callerRecord->GetAbilityInfo().name; - dialogSessionInfo->callerAbilityInfo.abilityIconId = callerRecord->GetAbilityInfo().iconId; - dialogSessionInfo->callerAbilityInfo.abilityLabelId = callerRecord->GetAbilityInfo().labelId; - dialogSessionInfo->callerAbilityInfo.bundleIconId = callerRecord->GetApplicationInfo().iconId; - dialogSessionInfo->callerAbilityInfo.bundleLabelId = callerRecord->GetApplicationInfo().labelId; + CHECK_POINTER(callerRecord); + callerAbilityInfo.bundleName = callerRecord->GetAbilityInfo().bundleName; + callerAbilityInfo.moduleName = callerRecord->GetAbilityInfo().moduleName; + callerAbilityInfo.abilityName = callerRecord->GetAbilityInfo().name; + callerAbilityInfo.abilityIconId = callerRecord->GetAbilityInfo().iconId; + callerAbilityInfo.abilityLabelId = callerRecord->GetAbilityInfo().labelId; + callerAbilityInfo.bundleIconId = callerRecord->GetApplicationInfo().iconId; + callerAbilityInfo.bundleLabelId = callerRecord->GetApplicationInfo().labelId; + callerAbilityInfo.visible = callerRecord->GetAbilityInfo().visible; + callerAbilityInfo.appIndex = callerRecord->GetApplicationInfo().appIndex; + callerAbilityInfo.multiAppMode = callerRecord->GetApplicationInfo().multiAppMode; } - dialogSessionInfo->parameters.SetParam("deviceType", AAFwk::String::Box(OHOS::system::GetDeviceType())); - dialogSessionInfo->parameters.SetParam("userId", AAFwk::Integer::Box(userId)); +} + +void DialogSessionManager::GenerateSelectorTargetAbilityInfos(std::vector &dialogAppInfos, + std::vector &targetAbilityInfos) +{ for (auto &dialogAppInfo : dialogAppInfos) { DialogAbilityInfo targetDialogAbilityInfo; targetDialogAbilityInfo.bundleName = dialogAppInfo.bundleName; @@ -144,22 +150,39 @@ bool DialogSessionManager::GenerateDialogSessionRecord(AbilityRequest &abilityRe targetDialogAbilityInfo.bundleIconId = dialogAppInfo.bundleIconId; targetDialogAbilityInfo.bundleLabelId = dialogAppInfo.bundleLabelId; targetDialogAbilityInfo.visible = dialogAppInfo.visible; - dialogSessionInfo->targetAbilityInfos.emplace_back(targetDialogAbilityInfo); + targetDialogAbilityInfo.appIndex = dialogAppInfo.appIndex; + targetDialogAbilityInfo.multiAppMode = dialogAppInfo.multiAppMode; + targetAbilityInfos.emplace_back(targetDialogAbilityInfo); } - std::shared_ptr dialogCallerInfo = std::make_shared(); - if (isSelector) { - dialogSessionInfo->parameters.SetParam("action", AAFwk::String::Box(abilityRequest.want.GetAction())); - dialogSessionInfo->parameters.SetParam("wantType", AAFwk::String::Box(abilityRequest.want.GetType())); - dialogSessionInfo->parameters.SetParam("uri", AAFwk::String::Box(abilityRequest.want.GetUriString())); - dialogCallerInfo->isSelector = true; - } - dialogCallerInfo->callerToken = callerToken; +} + +void DialogSessionManager::GenerateJumpTargetAbilityInfos(AbilityRequest &abilityRequest, + std::vector &targetAbilityInfos) +{ + DialogAbilityInfo targetDialogAbilityInfo; + targetDialogAbilityInfo.bundleName = abilityRequest.abilityInfo.bundleName; + targetDialogAbilityInfo.moduleName = abilityRequest.abilityInfo.moduleName; + targetDialogAbilityInfo.abilityName = abilityRequest.abilityInfo.name; + targetDialogAbilityInfo.abilityIconId = abilityRequest.abilityInfo.iconId; + targetDialogAbilityInfo.abilityLabelId = abilityRequest.abilityInfo.labelId; + targetDialogAbilityInfo.bundleIconId = abilityRequest.abilityInfo.applicationInfo.iconId; + targetDialogAbilityInfo.bundleLabelId = abilityRequest.abilityInfo.applicationInfo.labelId; + targetDialogAbilityInfo.visible = abilityRequest.abilityInfo.visible; + targetDialogAbilityInfo.appIndex = abilityRequest.abilityInfo.applicationInfo.appIndex; + targetDialogAbilityInfo.multiAppMode = abilityRequest.abilityInfo.applicationInfo.multiAppMode; + targetAbilityInfos.emplace_back(targetDialogAbilityInfo); +} + +void DialogSessionManager::GenerateDialogCallerInfo(AbilityRequest &abilityRequest, int32_t userId, + std::shared_ptr dialogCallerInfo, bool isSelector) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + CHECK_POINTER(dialogCallerInfo); + dialogCallerInfo->isSelector = isSelector; + dialogCallerInfo->callerToken = abilityRequest.callerToken; dialogCallerInfo->requestCode = abilityRequest.requestCode; dialogCallerInfo->targetWant = abilityRequest.want; dialogCallerInfo->userId = userId; - dialogSessionId = GenerateDialogSessionId(); - SetDialogSessionInfo(dialogSessionId, dialogSessionInfo, dialogCallerInfo); - return true; } int DialogSessionManager::SendDialogResult(const Want &want, const std::string &dialogSessionId, bool isAllowed) @@ -179,6 +202,10 @@ int DialogSessionManager::SendDialogResult(const Want &want, const std::string & targetWant.SetElement(want.GetElement()); targetWant.SetParam("isSelector", dialogCallerInfo->isSelector); targetWant.SetParam("dialogSessionId", dialogSessionId); + if (want.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY)) { + int32_t appIndex = want.GetIntParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, 0); + targetWant.SetParam(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY, appIndex); + } sptr callerToken = dialogCallerInfo->callerToken; auto abilityMgr = DelayedSingleton::GetInstance(); if (!abilityMgr) { @@ -193,39 +220,105 @@ int DialogSessionManager::SendDialogResult(const Want &want, const std::string & return ret; } +std::string DialogSessionManager::GenerateDialogSessionRecordCommon(AbilityRequest &abilityRequest, int32_t userId, + const AAFwk::WantParams ¶meters, std::vector &dialogAppInfos, bool isSelector) +{ + auto dialogSessionInfo = sptr::MakeSptr(); + CHECK_POINTER_AND_RETURN(dialogSessionInfo, ""); + + GenerateCallerAbilityInfo(abilityRequest, dialogSessionInfo->callerAbilityInfo); + + if (isSelector) { + GenerateSelectorTargetAbilityInfos(dialogAppInfos, dialogSessionInfo->targetAbilityInfos); + } else { + GenerateJumpTargetAbilityInfos(abilityRequest, dialogSessionInfo->targetAbilityInfos); + } + + dialogSessionInfo->parameters = parameters; + + std::shared_ptr dialogCallerInfo = std::make_shared(); + GenerateDialogCallerInfo(abilityRequest, userId, dialogCallerInfo, isSelector); + + std::string dialogSessionId = GenerateDialogSessionId(); + SetDialogSessionInfo(dialogSessionId, dialogSessionInfo, dialogCallerInfo); + + return dialogSessionId; +} + int DialogSessionManager::CreateJumpModalDialog(AbilityRequest &abilityRequest, int32_t userId, const Want &replaceWant) { - std::string dialogSessionId; - std::vector dialogAppInfos(1); - dialogAppInfos.front().bundleName = abilityRequest.abilityInfo.bundleName; - dialogAppInfos.front().moduleName = abilityRequest.abilityInfo.moduleName; - dialogAppInfos.front().abilityName = abilityRequest.abilityInfo.name; - dialogAppInfos.front().abilityIconId = abilityRequest.abilityInfo.iconId; - dialogAppInfos.front().abilityLabelId = abilityRequest.abilityInfo.labelId; - dialogAppInfos.front().bundleIconId = abilityRequest.abilityInfo.applicationInfo.iconId; - dialogAppInfos.front().bundleLabelId = abilityRequest.abilityInfo.applicationInfo.labelId; - if (!GenerateDialogSessionRecord(abilityRequest, userId, dialogSessionId, dialogAppInfos, false)) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + + AAFwk::WantParams parameters; + + parameters.SetParam("deviceType", AAFwk::String::Box(OHOS::system::GetDeviceType())); + parameters.SetParam("userId", AAFwk::Integer::Box(userId)); + + std::vector dialogAppInfos; + std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, parameters, + dialogAppInfos, false); + if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); - return INNER_ERR; + return ERR_INVALID_VALUE; } + return CreateModalDialogCommon(replaceWant, abilityRequest.callerToken, dialogSessionId); } -int DialogSessionManager::CreateSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, int32_t userId, - std::vector &dialogAppInfos) +int DialogSessionManager::CreateImplicitSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, + int32_t userId, std::vector &dialogAppInfos) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); - std::string dialogSessionId; - if (!GenerateDialogSessionRecord(abilityRequest, userId, dialogSessionId, dialogAppInfos, true)) { + + AAFwk::Want sessionWant; + + sessionWant.SetParam("deviceType", OHOS::system::GetDeviceType()); + sessionWant.SetParam("userId", userId); + sessionWant.SetParam("action", abilityRequest.want.GetAction()); + sessionWant.SetParam("wantType", abilityRequest.want.GetType()); + sessionWant.SetParam("uri", abilityRequest.want.GetUriString()); + sessionWant.SetParam("entities", abilityRequest.want.GetEntities()); + sessionWant.SetParam("appselector.selectorType", static_cast(SelectorType::IMPLICIT_START_SELECTOR)); + bool showCaller = abilityRequest.want.GetBoolParam("showcaller", false); + sessionWant.SetParam("showCaller", showCaller); + + std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, sessionWant.GetParams(), + dialogAppInfos, true); + if (dialogSessionId == "") { TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); - return INNER_ERR; + return ERR_INVALID_VALUE; } + + return CreateModalDialogCommon(want, abilityRequest.callerToken, dialogSessionId); +} + +int DialogSessionManager::CreateCloneSelectorModalDialog(AbilityRequest &abilityRequest, const Want &want, + int32_t userId, std::vector &dialogAppInfos, const std::string &replaceWant) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + AAFwk::WantParams parameters; + + parameters.SetParam("deviceType", AAFwk::String::Box(OHOS::system::GetDeviceType())); + parameters.SetParam("userId", AAFwk::Integer::Box(userId)); + parameters.SetParam("appselector.selectorType", + AAFwk::Integer::Box(static_cast(SelectorType::APP_CLONR_SELECTOR))); + if (replaceWant != "") { + parameters.SetParam("replaceWant", AAFwk::String::Box(replaceWant)); + } + + std::string dialogSessionId = GenerateDialogSessionRecordCommon(abilityRequest, userId, parameters, + dialogAppInfos, true); + if (dialogSessionId == "") { + TAG_LOGE(AAFwkTag::ABILITYMGR, "generate dialog session record failed"); + return ERR_INVALID_VALUE; + } + return CreateModalDialogCommon(want, abilityRequest.callerToken, dialogSessionId); } int DialogSessionManager::CreateModalDialogCommon(const Want &replaceWant, sptr callerToken, - std::string dialogSessionId) + const std::string &dialogSessionId) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); (const_cast(replaceWant)).SetParam("dialogSessionId", dialogSessionId); @@ -262,5 +355,36 @@ int DialogSessionManager::CreateModalDialogCommon(const Want &replaceWant, sptr< (const_cast(replaceWant)).SetParam(UIEXTENSION_MODAL_TYPE, 1); return connection->CreateModalUIExtension(replaceWant) ? ERR_OK : INNER_ERR; } + +int DialogSessionManager::HandleErmsResult(AbilityRequest &abilityRequest, int32_t userId, + const Want &replaceWant) +{ + std::string bundleName = abilityRequest.abilityInfo.bundleName; + if (StartAbilityUtils::ermsResultCode < ERMS_ISALLOW_RESULTCODE || + !IsCreateCloneSelectorDialog(bundleName, userId)) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "create jump modal dialog"); + return CreateJumpModalDialog(abilityRequest, userId, replaceWant); + } + auto abilityMgr = DelayedSingleton::GetInstance(); + if (!abilityMgr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityMgr is nullptr."); + return INNER_ERR; + } + return abilityMgr->CreateCloneSelectorDialog(abilityRequest, userId, replaceWant.ToString()); +} + +bool DialogSessionManager::IsCreateCloneSelectorDialog(const std::string &bundleName, int32_t userId) +{ + if (StartAbilityUtils::isWantWithAppCloneIndex) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "want with app clone index."); + return false; + } + auto appIndexes = StartAbilityUtils::GetCloneAppIndexes(bundleName, userId); + if (appIndexes.empty()) { + TAG_LOGI(AAFwkTag::ABILITYMGR, "The application do not create clone index."); + return false; + } + return true; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service.cpp b/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service.cpp index 9a7fd455b0..c84b1265b4 100644 --- a/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service.cpp +++ b/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service.cpp @@ -145,8 +145,8 @@ int32_t AbilityEcologicalRuleMgrServiceClient::QueryStartExperience(const OHOS:: if (rule.replaceWant != nullptr) { rule.replaceWant->SetParam(ERMS_ORIGINAL_TARGET, want.ToString()); TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, - "queryStart finish: isAllow = %{public}d, sceneCode = %{public}s, replaceWant = %{public}s", rule.isAllow, - rule.sceneCode.c_str(), (*(rule.replaceWant)).ToString().c_str()); + "queryStart finish: resultCode = %{public}d, sceneCode = %{public}s, replaceWant = %{public}s", + rule.resultCode, rule.sceneCode.c_str(), (*(rule.replaceWant)).ToString().c_str()); } int64_t cost = GetCurrentTimeMicro() - start; TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, diff --git a/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service_param.cpp b/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service_param.cpp index 4e740358c3..75656afa1a 100644 --- a/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service_param.cpp +++ b/services/abilitymgr/src/ecological_rule/ability_ecological_rule_mgr_service_param.cpp @@ -35,7 +35,7 @@ AbilityExperienceRule *AbilityExperienceRule::Unmarshalling(Parcel &in) return nullptr; } - if (!in.ReadBool(rule->isAllow)) { + if (!in.ReadInt32(rule->resultCode)) { delete rule; return nullptr; } @@ -52,8 +52,8 @@ AbilityExperienceRule *AbilityExperienceRule::Unmarshalling(Parcel &in) bool AbilityExperienceRule::Marshalling(Parcel &parcel) const { - if (!parcel.WriteBool(isAllow)) { - TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write isAllow failed"); + if (!parcel.WriteInt32(resultCode)) { + TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write resultCode failed"); return false; } diff --git a/services/abilitymgr/src/implicit_start_processor.cpp b/services/abilitymgr/src/implicit_start_processor.cpp index 3eb42ed82a..aab83b9fa1 100644 --- a/services/abilitymgr/src/implicit_start_processor.cpp +++ b/services/abilitymgr/src/implicit_start_processor.cpp @@ -25,6 +25,7 @@ #include "errors.h" #include "ecological_rule/ability_ecological_rule_mgr_service.h" #include "event_report.h" +#include "global_constant.h" #include "hilog_tag_wrapper.h" #include "hilog_wrapper.h" #include "hitrace_meter.h" @@ -32,6 +33,7 @@ #include "parameters.h" #include "scene_board_judgement.h" #include "start_ability_utils.h" +#include "startup_util.h" #include "want.h" namespace OHOS { @@ -89,7 +91,8 @@ bool ImplicitStartProcessor::IsImplicitStartAction(const Want &want) return false; } -int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_t userId, int32_t windowMode) +int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_t userId, int32_t windowMode, + const std::string &replaceWantString, bool isAppCloneSelector) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGI(AAFwkTag::ABILITYMGR, "implicit start ability by type: %{public}d", request.callType); @@ -99,9 +102,14 @@ int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_ std::vector dialogAppInfos; request.want.RemoveParam(APP_CLONE_INDEX); bool findDefaultApp = false; - auto ret = GenerateAbilityRequestByAction(userId, request, dialogAppInfos, false, findDefaultApp); + int32_t ret = ERR_OK; + if (isAppCloneSelector) { + ret = GenerateAbilityRequestByAppIndexes(userId, request, dialogAppInfos); + } else { + ret = GenerateAbilityRequestByAction(userId, request, dialogAppInfos, false, findDefaultApp); + } if (ret != ERR_OK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "generate ability request by action failed."); + TAG_LOGE(AAFwkTag::ABILITYMGR, "generate ability request failed."); return ret; } AbilityUtil::WantSetParameterWindowMode(request.want, windowMode); @@ -139,7 +147,8 @@ int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_ } if (want.GetBoolParam("isCreateAppGallerySelector", false)) { want.RemoveParam("isCreateAppGallerySelector"); - DialogSessionManager::GetInstance().CreateSelectorModalDialog(request, want, userId, dialogAppInfos); + DialogSessionManager::GetInstance().CreateImplicitSelectorModalDialog(request, want, userId, + dialogAppInfos); return ERR_IMPLICIT_START_ABILITY_FAIL; } TAG_LOGE(AAFwkTag::ABILITYMGR, "implicit query ability infos failed, show tips dialog."); @@ -156,7 +165,8 @@ int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_ } if (want.GetBoolParam("isCreateAppGallerySelector", false)) { want.RemoveParam("isCreateAppGallerySelector"); - DialogSessionManager::GetInstance().CreateSelectorModalDialog(request, want, userId, dialogAppInfos); + DialogSessionManager::GetInstance().CreateImplicitSelectorModalDialog(request, want, userId, + dialogAppInfos); return ERR_IMPLICIT_START_ABILITY_FAIL; } std::vector dialogAllAppInfos; @@ -209,7 +219,12 @@ int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_ } if (want.GetBoolParam("isCreateAppGallerySelector", false)) { want.RemoveParam("isCreateAppGallerySelector"); - return DialogSessionManager::GetInstance().CreateSelectorModalDialog(request, want, userId, dialogAppInfos); + if (isAppCloneSelector) { + return DialogSessionManager::GetInstance().CreateCloneSelectorModalDialog(request, want, + userId, dialogAppInfos, replaceWantString); + } + return DialogSessionManager::GetInstance().CreateImplicitSelectorModalDialog(request, + want, userId, dialogAppInfos); } ret = abilityMgr->ImplicitStartAbilityAsCaller(request.want, request.callerToken, nullptr); // reset calling indentity @@ -228,7 +243,12 @@ int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_ } if (want.GetBoolParam("isCreateAppGallerySelector", false)) { want.RemoveParam("isCreateAppGallerySelector"); - return DialogSessionManager::GetInstance().CreateSelectorModalDialog(request, want, userId, dialogAppInfos); + if (isAppCloneSelector) { + return DialogSessionManager::GetInstance().CreateCloneSelectorModalDialog(request, want, userId, + dialogAppInfos, replaceWantString); + } + return DialogSessionManager::GetInstance().CreateImplicitSelectorModalDialog(request, want, userId, + dialogAppInfos); } ret = abilityMgr->ImplicitStartAbilityAsCaller(request.want, request.callerToken, nullptr); // reset calling indentity @@ -449,12 +469,78 @@ int ImplicitStartProcessor::GenerateAbilityRequestByAction(int32_t userId, dialogAppInfo.bundleIconId = info.applicationInfo.iconId; dialogAppInfo.bundleLabelId = info.applicationInfo.labelId; dialogAppInfo.visible = info.visible; + dialogAppInfo.appIndex = info.applicationInfo.appIndex; + dialogAppInfo.multiAppMode = info.applicationInfo.multiAppMode; dialogAppInfos.emplace_back(dialogAppInfo); } return ERR_OK; } +int ImplicitStartProcessor::GenerateAbilityRequestByAppIndexes(int32_t userId, AbilityRequest &request, + std::vector &dialogAppInfos) +{ + auto appIndexes = StartAbilityUtils::GetCloneAppIndexes(request.want.GetBundle(), userId); + if (appIndexes.size() > AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "The size of appIndexes is too large."); + return ERR_INVALID_VALUE; + } + auto bms = GetBundleManagerHelper(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + auto abilityInfoFlag = static_cast(AbilityRuntime::StartupUtil::BuildAbilityInfoFlag()) | + static_cast(AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL); + std::vector abilityInfos; + abilityInfos.emplace_back(request.abilityInfo); + for (auto &appIndex: appIndexes) { + AppExecFwk::AbilityInfo abilityInfo; + IN_PROCESS_CALL_WITHOUT_RET(bms->QueryCloneAbilityInfo(request.want.GetElement(), abilityInfoFlag, appIndex, + abilityInfo, userId)); + if (abilityInfo.name.empty() || abilityInfo.bundleName.empty()) { + int32_t ret = FindExtensionInfo(request.want, abilityInfoFlag, userId, appIndex, abilityInfo); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "query clone extension info failed."); + return ret; + } + } + abilityInfos.emplace_back(abilityInfo); + } + for (const auto &info : abilityInfos) { + DialogAppInfo dialogAppInfo; + dialogAppInfo.abilityName = info.name; + dialogAppInfo.bundleName = info.bundleName; + dialogAppInfo.moduleName = info.moduleName; + dialogAppInfo.abilityIconId = info.iconId; + dialogAppInfo.abilityLabelId = info.labelId; + dialogAppInfo.bundleIconId = info.applicationInfo.iconId; + dialogAppInfo.bundleLabelId = info.applicationInfo.labelId; + dialogAppInfo.visible = info.visible; + dialogAppInfo.appIndex = info.applicationInfo.appIndex; + dialogAppInfo.multiAppMode = info.applicationInfo.multiAppMode; + dialogAppInfos.emplace_back(dialogAppInfo); + } + return ERR_OK; +} + +int ImplicitStartProcessor::FindExtensionInfo(const Want &want, int32_t flags, int32_t userId, + int32_t appIndex, AppExecFwk::AbilityInfo &abilityInfo) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + auto bms = GetBundleManagerHelper(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + AppExecFwk::ExtensionAbilityInfo extensionInfo; + IN_PROCESS_CALL_WITHOUT_RET(bms->QueryCloneExtensionAbilityInfoWithAppIndex(want.GetElement(), + flags, appIndex, extensionInfo, userId)); + if (extensionInfo.bundleName.empty() || extensionInfo.name.empty()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "extensionInfo empty."); + return RESOLVE_ABILITY_ERR; + } + if (AbilityRuntime::StartupUtil::IsSupportAppClone(extensionInfo.type)) { + AbilityRuntime::StartupUtil::InitAbilityInfoFromExtension(extensionInfo, abilityInfo); + return ERR_OK; + } + return ERR_APP_CLONE_INDEX_INVALID; +} + int ImplicitStartProcessor::QueryBmsAppInfos(AbilityRequest &request, int32_t userId, std::vector &dialogAppInfos) { @@ -492,6 +578,9 @@ int ImplicitStartProcessor::QueryBmsAppInfos(AbilityRequest &request, int32_t us dialogAppInfo.abilityLabelId = abilityInfo.labelId; dialogAppInfo.bundleIconId = abilityInfo.applicationInfo.iconId; dialogAppInfo.bundleLabelId = abilityInfo.applicationInfo.labelId; + dialogAppInfo.visible = abilityInfo.visible; + dialogAppInfo.appIndex = abilityInfo.applicationInfo.appIndex; + dialogAppInfo.multiAppMode = abilityInfo.applicationInfo.multiAppMode; dialogAppInfos.emplace_back(dialogAppInfo); } } @@ -723,6 +812,8 @@ void ImplicitStartProcessor::AddAbilityInfoToDialogInfos(const AddInfoParam &par dialogAppInfo.bundleIconId = param.info.applicationInfo.iconId; dialogAppInfo.bundleLabelId = param.info.applicationInfo.labelId; dialogAppInfo.visible = param.info.visible; + dialogAppInfo.appIndex = param.info.applicationInfo.appIndex; + dialogAppInfo.multiAppMode = param.info.applicationInfo.multiAppMode; dialogAppInfos.emplace_back(dialogAppInfo); } diff --git a/services/abilitymgr/src/interceptor/ecological_rule_interceptor.cpp b/services/abilitymgr/src/interceptor/ecological_rule_interceptor.cpp index 266a7a3fab..d623e60436 100644 --- a/services/abilitymgr/src/interceptor/ecological_rule_interceptor.cpp +++ b/services/abilitymgr/src/interceptor/ecological_rule_interceptor.cpp @@ -32,6 +32,7 @@ namespace { constexpr const char* ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE = "persist.sys.abilityms.support.ecologicalrulemgrservice"; constexpr const char* BUNDLE_NAME_SCENEBOARD = "com.ohos.sceneboard"; +constexpr int32_t ERMS_ISALLOW_RESULTCODE = 10; } ErrCode EcologicalRuleInterceptor::DoProcess(AbilityInterceptorParam param) { @@ -64,7 +65,8 @@ ErrCode EcologicalRuleInterceptor::DoProcess(AbilityInterceptorParam param) return ERR_OK; } TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule success"); - if (rule.isAllow) { + StartAbilityUtils::ermsResultCode = rule.resultCode; + if (rule.resultCode == ERMS_ISALLOW_RESULTCODE) { TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "ecological rule is allow, keep going."); return ERR_OK; } @@ -126,7 +128,7 @@ bool EcologicalRuleInterceptor::DoProcess(Want &want, int32_t userId) TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule failed, keep going."); return true; } - return rule.isAllow; + return rule.resultCode == ERMS_ISALLOW_RESULTCODE; } void EcologicalRuleInterceptor::GetEcologicalTargetInfo(const Want &want, ErmsCallerInfo &callerInfo) diff --git a/services/abilitymgr/src/start_ability_utils.cpp b/services/abilitymgr/src/start_ability_utils.cpp index 3100b5b4ae..cc7e723e2a 100644 --- a/services/abilitymgr/src/start_ability_utils.cpp +++ b/services/abilitymgr/src/start_ability_utils.cpp @@ -31,12 +31,15 @@ namespace AAFwk { namespace { constexpr const char* SCREENSHOT_BUNDLE_NAME = "com.huawei.ohos.screenshot"; constexpr const char* SCREENSHOT_ABILITY_NAME = "com.huawei.ohos.screenshot.ServiceExtAbility"; +constexpr int32_t ERMS_ISALLOW_RESULTCODE = 10; } thread_local std::shared_ptr StartAbilityUtils::startAbilityInfo; thread_local std::shared_ptr StartAbilityUtils::callerAbilityInfo; thread_local bool StartAbilityUtils::skipCrowTest = false; thread_local bool StartAbilityUtils::skipStartOther = false; thread_local bool StartAbilityUtils::skipErms = false; +thread_local int32_t StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE; +thread_local bool StartAbilityUtils::isWantWithAppCloneIndex = false; bool StartAbilityUtils::GetAppIndex(const Want &want, sptr callerToken, int32_t &appIndex) { @@ -112,6 +115,15 @@ int32_t StartAbilityUtils::CheckAppProvisionMode(const Want& want, int32_t userI return ERR_OK; } +std::vector StartAbilityUtils::GetCloneAppIndexes(const std::string &bundleName, int32_t userId) +{ + std::vector appIndexes; + auto bms = AbilityUtil::GetBundleManagerHelper(); + CHECK_POINTER_AND_RETURN(bms, appIndexes); + IN_PROCESS_CALL_WITHOUT_RET(bms->GetCloneAppIndexes(bundleName, appIndexes, userId)); + return appIndexes; +} + StartAbilityInfoWrap::StartAbilityInfoWrap(const Want &want, int32_t validUserId, int32_t appIndex, const sptr &callerToken, bool isExtension) { @@ -142,6 +154,13 @@ StartAbilityInfoWrap::StartAbilityInfoWrap(const Want &want, int32_t validUserId TAG_LOGW(AAFwkTag::ABILITYMGR, "callerAbilityInfo has been created"); } StartAbilityUtils::callerAbilityInfo = StartAbilityInfo::CreateCallerAbilityInfo(callerToken); + + StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE; + StartAbilityUtils::isWantWithAppCloneIndex = false; + if (want.HasParameter(AAFwk::Want::PARAM_APP_CLONE_INDEX_KEY) && appIndex >= 0 && + appIndex < AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) { + StartAbilityUtils::isWantWithAppCloneIndex = true; + } } StartAbilityInfoWrap::~StartAbilityInfoWrap() @@ -151,6 +170,8 @@ StartAbilityInfoWrap::~StartAbilityInfoWrap() StartAbilityUtils::skipCrowTest = false; StartAbilityUtils::skipStartOther = false; StartAbilityUtils::skipErms = false; + StartAbilityUtils::ermsResultCode = ERMS_ISALLOW_RESULTCODE; + StartAbilityUtils::isWantWithAppCloneIndex = false; } std::shared_ptr StartAbilityInfo::CreateStartAbilityInfo(const Want &want, int32_t userId, diff --git a/services/abilitymgr/src/system_dialog_scheduler.cpp b/services/abilitymgr/src/system_dialog_scheduler.cpp index b2c21b78d4..3b1eec6dd4 100644 --- a/services/abilitymgr/src/system_dialog_scheduler.cpp +++ b/services/abilitymgr/src/system_dialog_scheduler.cpp @@ -352,6 +352,9 @@ const std::string SystemDialogScheduler::GetSelectorParams(const std::vector = new Map(); for (let i = 1; i <= globalThis.params.hapList.length; i++) { - console.info(TAG, 'hapList[' + (i - 1).toString() + ']: ' + JSON.stringify(globalThis.params.hapList[i])); + console.info(TAG, 'hapList[' + (i - 1).toString() + ']: ' + JSON.stringify(globalThis.params.hapList[i - 1])); await this.getHapResource(globalThis.params.hapList[i - 1], showHapList, jsonIconMap); if (i % lineNums === 0) { phoneShowHapList.push(showHapList); @@ -65,7 +65,7 @@ export default class SelectorServiceExtensionAbility extends extension { let signalRowShowHapList = []; let signalRowPhoneShowHapList = []; for (let i = 1; i <= globalThis.params.hapList.length; i++) { - console.info(TAG, 'hapList[' + (i - 1).toString() + ']: ' + JSON.stringify(globalThis.params.hapList[i])); + console.info(TAG, 'hapList[' + (i - 1).toString() + ']: ' + JSON.stringify(globalThis.params.hapList[i - 1])); await this.getHapResource(globalThis.params.hapList[i - 1], signalRowShowHapList, jsonIconMap); if (i % signalRowlineNums === 0) { signalRowPhoneShowHapList.push(signalRowShowHapList); @@ -99,19 +99,30 @@ export default class SelectorServiceExtensionAbility extends extension { let appIcon = ''; let type = ''; let userId = Number('0'); + let appIndex = Number(hap.appIndex); if (!globalThis.params.isDefaultSelector) { type = hap.type; userId = Number(hap.userId); } let lableId = Number(hap.label); + if (lableId === 0) { + lableId = Number(hap.bundleLabel); + } let moduleContext = globalThis.selectExtensionContext.createModuleContext(bundleName, moduleName); await moduleContext.resourceManager.getString(lableId).then(value => { - appName = value; + if (appIndex === 0) { + appName = value; + } else { + appName = value + hap.appIndex; + } }).catch(error => { console.error(TAG, 'getString error:' + JSON.stringify(error)); }); let iconId = Number(hap.icon); + if (iconId === 0) { + iconId = Number(hap.bundleIcon); + } await moduleContext.resourceManager.getMediaBase64(iconId).then(value => { appIcon = value; if (appIcon.indexOf('image/json') > -1) { @@ -123,7 +134,8 @@ export default class SelectorServiceExtensionAbility extends extension { imageDescriptor; let foregroundDescriptor: drawableDescriptor.DrawableDescriptor = layeredDrawableDescriptor.getForeground(); if (foregroundDescriptor !== null && foregroundDescriptor !== undefined) { - jsonIconMap.set(bundleName + ':' + moduleName + ':' + abilityName, foregroundDescriptor.getPixelMap()); + jsonIconMap.set(bundleName + ':' + moduleName + ':' + abilityName + ':' + hap.appIndex, + foregroundDescriptor.getPixelMap()); } else { console.error(TAG, 'get foregroundDescriptor is null'); } @@ -136,7 +148,7 @@ export default class SelectorServiceExtensionAbility extends extension { console.error(TAG, 'getMediaBase64 error:' + JSON.stringify(error)); }); showHapList.push(bundleName + '#' + abilityName + '#' + appName + - '#' + appIcon + '#' + moduleName + '#' + type + '#' + userId); + '#' + appIcon + '#' + moduleName + '#' + type + '#' + userId + '#' + appIndex); } async onRequest(want, startId) { diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPcDialog.ets b/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPcDialog.ets index 1b99992ab0..f6cebc23be 100644 --- a/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPcDialog.ets +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPcDialog.ets @@ -79,6 +79,7 @@ struct SelectorPcDialog { globalThis.abilityWant.bundleName = item.split('#')[0]; globalThis.abilityWant.abilityName = item.split('#')[1]; globalThis.abilityWant.moduleName = item.split('#')[4]; + globalThis.abilityWant.parameters['ohos.extra.param.key.appCloneIndex'] = Number(item.split('#')[7]); globalThis.selectExtensionContext.startAbilityAsCaller(globalThis.abilityWant, (data, error) => { if (error) { console.error(this.TAG + ' startAbility finish, error: ' + JSON.stringify(error)); @@ -148,7 +149,7 @@ struct SelectorPcDialog { let foregroundDescriptor: drawableDescriptor.DrawableDescriptor = layeredDrawableDescriptor.getForeground(); if (foregroundDescriptor !== null && foregroundDescriptor !== undefined) { - globalThis.jsonIconMap.set(bundleName + ':' + moduleName + ':' + abilityName, + globalThis.jsonIconMap.set(bundleName + ':' + moduleName + ':' + abilityName + ':' + hap.appIndex, foregroundDescriptor.getPixelMap()); } else { console.error(this.TAG, 'get foregroundDescriptor is null'); @@ -276,7 +277,7 @@ struct SelectorPcDialog { if (item.split('#')[3] != '') { if (item.split('#')[3].indexOf('image/json') > -1) { Image(globalThis.jsonIconMap.get(item.split('#')[0] + ':' + item.split('#')[4] + - ':' + item.split('#')[1])) + ':' + item.split('#')[1] + ':' + item.split('#')[7])) .height(48) .width(48) .alignSelf(ItemAlign.Center) @@ -372,7 +373,7 @@ struct SelectorPcDialog { if (item.split('#')[3] != '') { if (item.split('#')[3].indexOf('image/json') > -1) { Image(globalThis.jsonIconMap.get(item.split('#')[0] + ':' + item.split('#')[4] + - ':' + item.split('#')[1])) + ':' + item.split('#')[1] + ':' + item.split('#')[7])) .height(48) .width(48) .alignSelf(ItemAlign.Center) diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPhoneDialog.ets b/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPhoneDialog.ets index 4c46f0e0df..577e3de206 100644 --- a/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPhoneDialog.ets +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/ets/pages/selectorPhoneDialog.ets @@ -83,6 +83,29 @@ struct SelectorPhoneDialog { @State private hapList: HapInfo[] = []; private TAG = 'SelectorDialog_Phone_Page'; + @Builder + elementIconCombine(iconSrc: string, appIndex: string) { + RelativeContainer() { + Image(iconSrc) + .id('iconLab') + .height(60) + .width(60) + .alignSelf(ItemAlign.Center); + if (appIndex !== '0') { + Image($r('app.media.app_icon_clone_index_' + appIndex)) + .height(18) + .width(18) + .alignRules({ + end: { anchor: 'iconLab', align: HorizontalAlign.End }, + bottom: { anchor: 'iconLab', align: VerticalAlign.Bottom } + }) + } + } + .height(60) + .width(60) + .alignSelf(ItemAlign.Center); + } + aboutToAppear(): void { console.log(this.TAG, 'dialog page appears'); this.hapList = globalThis.params.hapList; @@ -99,6 +122,7 @@ struct SelectorPhoneDialog { globalThis.abilityWant.bundleName = item.split('#')[0]; globalThis.abilityWant.abilityName = item.split('#')[1]; globalThis.abilityWant.moduleName = item.split('#')[4]; + globalThis.abilityWant.parameters['ohos.extra.param.key.appCloneIndex'] = Number(item.split('#')[7]); globalThis.selectExtensionContext.startAbilityAsCaller(globalThis.abilityWant, (data, error) => { if (error) { console.error(this.TAG + ' startAbility finish, error: ' + JSON.stringify(error)); @@ -158,16 +182,11 @@ struct SelectorPhoneDialog { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) { if (item.split('#')[3] != '') { if (item.split('#')[3].indexOf('image/json') > -1) { - Image(globalThis.jsonIconMap.get(item.split('#')[0] + ':' + item.split('#')[4] + - ':' + item.split('#')[1])) - .height(60) - .width(60) - .alignSelf(ItemAlign.Center); + this.elementIconCombine(globalThis.jsonIconMap.get(item.split('#')[0] + ':' + + item.split('#')[4] + ':' + item.split('#')[1] + ':' + item.split('#')[7]), + item.split('#')[7]); } else { - Image(item.split('#')[3]) - .height(60) - .width(60) - .alignSelf(ItemAlign.Center); + this.elementIconCombine(item.split('#')[3], item.split('#')[7]); } } else { Image($r('app.media.app_icon')) diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_1.svg b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_1.svg new file mode 100644 index 0000000000..9ffedee3d2 --- /dev/null +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_1.svg @@ -0,0 +1,10 @@ + + + 画板 + + + + + + + \ No newline at end of file diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_2.svg b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_2.svg new file mode 100644 index 0000000000..ed4b17f123 --- /dev/null +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_2.svg @@ -0,0 +1,10 @@ + + + 画板备份 6 + + + + + + + \ No newline at end of file diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_3.svg b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_3.svg new file mode 100644 index 0000000000..39852e4570 --- /dev/null +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_3.svg @@ -0,0 +1,10 @@ + + + 画板备份 7 + + + + + + + \ No newline at end of file diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_4.svg b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_4.svg new file mode 100644 index 0000000000..fbce202557 --- /dev/null +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_4.svg @@ -0,0 +1,10 @@ + + + 画板备份 8 + + + + + + + \ No newline at end of file diff --git a/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_5.svg b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_5.svg new file mode 100644 index 0000000000..91c4473567 --- /dev/null +++ b/services/dialog_ui/ams_system_dialog/entry/src/main/resources/base/media/app_icon_clone_index_5.svg @@ -0,0 +1,10 @@ + + + 画板备份 9 + + + + + + + \ No newline at end of file