diff --git a/services/appmgr/include/app_mgr_service_inner.h b/services/appmgr/include/app_mgr_service_inner.h index d94ff51f98..476969b8e4 100644 --- a/services/appmgr/include/app_mgr_service_inner.h +++ b/services/appmgr/include/app_mgr_service_inner.h @@ -1898,6 +1898,9 @@ private: void RemoveRenderRecordNoAttach(const std::shared_ptr &hostRecord, int32_t renderPid); + void ReportUIExtensionProcColdStartToRss(const std::shared_ptr& abilityInfo, + const std::shared_ptr& want); + private: /** * ClearUpApplicationData, clear the application data. diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 2d2b856a9a..f7f36cccff 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -1064,6 +1064,7 @@ void AppMgrServiceInner::LoadAbility(std::shared_ptr abilityInfo, s appRecord->SetPreloadMode(PreloadMode::PRELOAD_BY_PHASE); } } + ReportUIExtensionProcColdStartToRss(abilityInfo, want); LoadAbilityNoAppRecord(appRecord, loadParam->isShellCall, appInfo, abilityInfo, processName, specifiedProcessFlag, bundleInfo, hapModuleInfo, want, appExistFlag, false, AppExecFwk::PreloadMode::PRESS_DOWN, loadParam->token, customProcessFlag, loadParam->isStartupHide); @@ -1128,6 +1129,29 @@ void AppMgrServiceInner::LoadAbility(std::shared_ptr abilityInfo, s AfterLoadAbility(appRecord, abilityInfo, loadParam); } +void AppMgrServiceInner::ReportUIExtensionProcColdStartToRss(const std::shared_ptr& abilityInfo, + const std::shared_ptr& want) +{ + if (abilityInfo == nullptr || want == nullptr) { + return; + } + + if (AAFwk::UIExtensionUtils::IsUIExtension(abilityInfo->extensionAbilityType)) { + int32_t extensionAbilityType = static_cast(abilityInfo->extensionAbilityType); + int hostPid = want->GetIntParam(UIEXTENSION_ROOT_HOST_PID, -1); + auto hostAppRecord = appRunningManager_->GetAppRunningRecordByPid(hostPid); + std::string hostBundleName; + if (hostAppRecord) { + hostBundleName = hostAppRecord->GetBundleName(); + } + std::string bundleName = want->GetElement().GetBundleName(); + std::string abilityName = want->GetElement().GetAbilityName(); + std::string moduleName = want->GetElement().GetModuleName(); + AAFwk::ResSchedUtil::GetInstance().ReportUIExtensionProcColdStartToRss(extensionAbilityType, + hostPid, hostBundleName, bundleName, abilityName, moduleName); + } +} + void AppMgrServiceInner::AfterLoadAbility(std::shared_ptr appRecord, std::shared_ptr abilityInfo, std::shared_ptr loadParam) { diff --git a/services/common/include/res_sched_util.h b/services/common/include/res_sched_util.h index bd578fdb67..eca9c35eb7 100644 --- a/services/common/include/res_sched_util.h +++ b/services/common/include/res_sched_util.h @@ -57,6 +57,9 @@ public: const AbilityInfo &abilityInfo, int64_t resSchedType, int32_t callerUid, int32_t callerPid); void ReportEventToRSS(const int32_t uid, const std::string &bundleName, const std::string &reason, const int32_t pid = -1, const int32_t callerPid = -1); + void ReportUIExtensionProcColdStartToRss( + int32_t extensionAbilityType, int hostPid, const std::string& hostBundleName, + const std::string& bundleName, const std::string& abilityName, const std::string& moduleName); void PromotePriorityToRSS(int32_t callerUid, int32_t callerPid, const std::string &targetBundleName, int32_t targetUid, int32_t targetPid); std::string GetThawReasonByAbilityType(const AbilityInfo &abilityInfo); diff --git a/services/common/src/res_sched_util.cpp b/services/common/src/res_sched_util.cpp index 0cceb29d53..8dbd4c2f29 100644 --- a/services/common/src/res_sched_util.cpp +++ b/services/common/src/res_sched_util.cpp @@ -114,6 +114,25 @@ void ResSchedUtil::ReportPreloadApplicationToRSS(const std::shared_ptr payload { + {"extensionAbilityType", std::to_string(extensionAbilityType)}, + {"hostPid", std::to_string(hostPid)}, + {"hostBundleName", hostBundleName}, + {"bundleName", bundleName}, + {"abilityName", abilityName}, + {"moduleName", moduleName}, + }; + TAG_LOGD(AAFwkTag::DEFAULT, "resType:%{public}u, call", resType); + ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, 0, payload); +#endif +} + std::string ResSchedUtil::GetThawReasonByAbilityType(const AbilityInfo &abilityInfo) { std::string reason; diff --git a/test/unittest/app_mgr_service_inner_test/BUILD.gn b/test/unittest/app_mgr_service_inner_test/BUILD.gn index e55e89a4c4..7415146af9 100644 --- a/test/unittest/app_mgr_service_inner_test/BUILD.gn +++ b/test/unittest/app_mgr_service_inner_test/BUILD.gn @@ -47,6 +47,7 @@ ohos_unittest("AppMgrServiceInnerTest") { "mock/src/mock_my_app_utils_flag.cpp", "mock/src/mock_my_flag.cpp", "mock/src/mock_permission_verification.cpp", + "mock/src/mock_res_sched_util.cpp", ] configs = [ "${ability_runtime_services_path}/appmgr:appmgr_config" ] diff --git a/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp b/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp index 18c81d179b..7ee824b9f2 100644 --- a/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp +++ b/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp @@ -40,6 +40,7 @@ #include "mock_native_token.h" #include "mock_permission_verification.h" #include "mock_render_scheduler.h" +#include "mock_res_sched_util.h" #include "mock_sa_call.h" #include "mock_task_handler_wrap.h" #include "param.h" @@ -447,6 +448,77 @@ HWTEST_F(AppMgrServiceInnerTest, LoadAbility_001, TestSize.Level0) TAG_LOGI(AAFwkTag::TEST, "LoadAbility_001 end"); } +/** + * @tc.name: CheckLoadAbilityConditions_001 + * @tc.desc: check load ability conditions. + * @tc.type: FUNC + * @tc.require: issueI5W4S7 + */ +HWTEST_F(AppMgrServiceInnerTest, ReportUIExtensionProcColdStartToRss_001, TestSize.Level1) +{ + auto appMgrServiceInner = std::make_shared(); + EXPECT_NE(appMgrServiceInner, nullptr); + // do test1 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(nullptr, nullptr); + + int32_t hostPid = 102; + // fill want + std::shared_ptr want = std::make_shared(); + want->SetParam("ability.want.params.uiExtensionRootHostPid", hostPid); + want->SetElementName("bundleName", "abilityName"); + want->SetModuleName("moduleName"); + + // do test2 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(nullptr, want); + // do test3 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(abilityInfo_, nullptr); + + // fill extensionAbilityType + abilityInfo_->extensionAbilityType = AppExecFwk::ExtensionAbilityType::SYSPICKER_PHOTOEDITOR; // 504 + // EXPECT_CALL + EXPECT_CALL(ResSchedUtil::GetInstance(), ReportUIExtensionProcColdStartToRss( + Eq(static_cast(AppExecFwk::ExtensionAbilityType::SYSPICKER_PHOTOEDITOR)), + Eq(hostPid), + StrEq(""), + StrEq("bundleName"), + StrEq("abilityName"), + StrEq("moduleName") + )).Times(1); + // do test4 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(abilityInfo_, want); + + // fill appRunningManager_ + std::string hostBundleName = "wantHostBundleName"; + std::shared_ptr infoHost = std::make_shared(); + infoHost->bundleName = hostBundleName; + int32_t recordIdHost = RECORD_ID + 1; + std::string processNameHost = "appRunningRecordProcessNameHost"; + auto appRunningRecordHost = std::make_shared(infoHost, recordIdHost, processNameHost); + ASSERT_NE(appRunningRecordHost, nullptr); + appRunningRecordHost->priorityObject_->pid_ = hostPid; + appMgrServiceInner->appRunningManager_->appRunningRecordMap_.emplace(recordIdHost, appRunningRecordHost); + + // fill abilityInfo_ + abilityInfo_->extensionAbilityType = AppExecFwk::ExtensionAbilityType::SYSPICKER_PHOTOPICKER; // 404 + + // EXPECT_CALL + EXPECT_CALL(ResSchedUtil::GetInstance(), ReportUIExtensionProcColdStartToRss( + Eq(static_cast(AppExecFwk::ExtensionAbilityType::SYSPICKER_PHOTOEDITOR)), + Eq(hostPid), + StrEq(hostBundleName), + StrEq("bundleName"), + StrEq("abilityName"), + StrEq("moduleName") + )).Times(1); + // do test5 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(abilityInfo_, want); + + // fill abilityInfo_ with not UIExtension + abilityInfo_->extensionAbilityType = AppExecFwk::ExtensionAbilityType::BACKUP; + // do test6 + appMgrServiceInner->ReportUIExtensionProcColdStartToRss(abilityInfo_, want); +} + /** * @tc.name: CheckLoadAbilityConditions_001 * @tc.desc: check load ability conditions. diff --git a/test/unittest/app_mgr_service_inner_test/mock/include/mock_res_sched_util.h b/test/unittest/app_mgr_service_inner_test/mock/include/mock_res_sched_util.h new file mode 100644 index 0000000000..411f554d8f --- /dev/null +++ b/test/unittest/app_mgr_service_inner_test/mock/include/mock_res_sched_util.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 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_RES_SCHED_UTIL_H +#define OHOS_ABILITY_RUNTIME_RES_SCHED_UTIL_H + +#include + +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { + +class ResSchedUtilBase { +public: + ResSchedUtilBase() = default; + virtual ~ResSchedUtilBase() = default; + DISALLOW_COPY_AND_MOVE(ResSchedUtilBase); + + virtual void ReportUIExtensionProcColdStartToRss( + int32_t extensionAbilityType, int hostPid, const std::string& hostBundleName, + const std::string& bundleName, const std::string& abilityName, const std::string& moduleName) = 0; +}; + +class ResSchedUtil : public ResSchedUtilBase { +public: + ResSchedUtil() = default; + virtual ~ResSchedUtil() = default; + DISALLOW_COPY_AND_MOVE(ResSchedUtil); + + static ResSchedUtil &GetInstance(); + + MOCK_METHOD(void, ReportUIExtensionProcColdStartToRss, + (int32_t extensionAbilityType, int hostPid, const std::string& hostBundleName, + const std::string& bundleName, const std::string& abilityName, const std::string& moduleName), ()); +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_RES_SCHED_UTIL_H diff --git a/test/unittest/app_mgr_service_inner_test/mock/src/mock_res_sched_util.cpp b/test/unittest/app_mgr_service_inner_test/mock/src/mock_res_sched_util.cpp new file mode 100644 index 0000000000..3cbbcba430 --- /dev/null +++ b/test/unittest/app_mgr_service_inner_test/mock/src/mock_res_sched_util.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 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 "mock_res_sched_util.h" + +namespace OHOS { +namespace AAFwk { + +ResSchedUtil &ResSchedUtil::GetInstance() +{ + static ResSchedUtil instance; + return instance; +} + +} // namespace AAFwk +} // namespace OHOS diff --git a/test/unittest/cache_process_manager_second_test/mock/src/moc_res_sched_util.cpp b/test/unittest/cache_process_manager_second_test/mock/src/moc_res_sched_util.cpp index 37481a16d8..bfa18dc538 100644 --- a/test/unittest/cache_process_manager_second_test/mock/src/moc_res_sched_util.cpp +++ b/test/unittest/cache_process_manager_second_test/mock/src/moc_res_sched_util.cpp @@ -49,6 +49,12 @@ void ResSchedUtil::ReportPreloadApplicationToRSS(const std::shared_ptr(AppExecFwk::ExtensionAbilityType::SYSPICKER_PHOTOPICKER); + int32_t hostPid = 102; + std::string hostBundleName = "hostBundleName"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + std::string moduleName = "moduleName"; + AAFwk::ResSchedUtil::GetInstance().ReportUIExtensionProcColdStartToRss(pickerType, + hostPid, hostBundleName, bundleName, abilityName, moduleName); + SUCCEED(); + int64_t resSchedType = AAFwk::RES_TYPE_SCB_START_ABILITY; + int64_t ret = AAFwk::ResSchedUtil::GetInstance().convertType(resSchedType); + EXPECT_EQ(resSchedType, ret); +} + /** * @tc.number: GetThawReasonByAbilityType * @tc.desc: Test GetThawReasonByAbilityType