diff --git a/README_zh.md b/README_zh.md index f8e38370c0dedabf0764cf6559077c5a3e8dc826..f11e87f6c86f8fa99f6a9bd7a7bb58017dc6d91a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -69,6 +69,7 @@ | 优先级 | 描述 | |------------------------------------------------------------------------------------------|-------------| | -1000 | 系统进程,属于该优先级的进程不会被查杀策略查杀,支持白名单配置。 | +| -800 | 常驻进程,属于该优先级的进程可以被查杀,但优先级较低,且被杀后可以再被拉起,支持白名单配置。 | | 0 | 前台应用。 | | 100 | 正在进行后台短时任务的应用。 | | 200 | 后台可感知应用,如正在执行导航、播放音乐等长时任务的应用。 | diff --git a/common/include/kernel_interface.h b/common/include/kernel_interface.h index b5cab9607164c5c39a0de39c016d33827ee69c1f..8e56f5ea92e7cc6604ecb1adb0a7a9be3e55c27b 100644 --- a/common/include/kernel_interface.h +++ b/common/include/kernel_interface.h @@ -67,6 +67,7 @@ public: std::string JoinPath(const std::string& prefixPath, const std::string& midPath, const std::string& subPath); bool GetPidProcInfo(struct ProcInfo &procInfo); + bool GetProcNameByPid(int pid, std::string &name); void ReadZswapdPressureShow(std::map& result); int GetCurrentBuffer(); int KillOneProcessByPid(int pid); diff --git a/common/include/memmgr_config_manager.h b/common/include/memmgr_config_manager.h index 0f925698eb309a7588396ebdb573fdb860123081..d7362a8a2f2078493c0b1f6f5e857d1ca6c1f815 100644 --- a/common/include/memmgr_config_manager.h +++ b/common/include/memmgr_config_manager.h @@ -49,6 +49,11 @@ public: SystemMemoryLevelConfig(int moderate, int low, int critical); }; +class ReclaimPriorityConfig { +public: + std::set killalbeSystemApps_; +}; + class ReclaimRatiosConfig { public: int minScore; @@ -82,6 +87,7 @@ public: std::shared_ptr GetAvailBufferSize(); std::shared_ptr GetSystemMemoryLevelConfig(); const ReclaimRatiosConfigSet GetReclaimRatiosConfigSet(); + const ReclaimPriorityConfig& GetReclaimPriorityConfig(); private: void InitDefaultConfig(); @@ -89,6 +95,8 @@ private: bool ParseKillConfig(const xmlNodePtr &rootNodePtr); bool ParseReclaimConfig(const xmlNodePtr &rootNodePtr); bool ParseSystemMemoryLevelConfig(const xmlNodePtr &rootNodePtr); + bool ParseReclaimPriorityConfig(const xmlNodePtr &rootNodePtr); + bool ParseReclaimPriorityKillableSystemAppsConfig(const xmlNodePtr &rootNodePtr); bool GetModuleParam(const xmlNodePtr &currNodePtr, std::map ¶m); void SetIntParam(std::map ¶m, std::string key, int &dst); void SetUnsignedIntParam(std::map ¶m, std::string key, unsigned int &dst); @@ -103,6 +111,7 @@ private: std::shared_ptr availBufferSize_; std::shared_ptr systemMemoryLevelConfig_; ReclaimRatiosConfigSet reclaimRatiosConfigSet_; + ReclaimPriorityConfig reclaimPriorityConfig_; void AddReclaimRatiosConfigToSet(std::shared_ptr reclaimRatiosConfig); void ClearReclaimRatiosConfigSet(); MemmgrConfigManager(); diff --git a/common/src/kernel_interface.cpp b/common/src/kernel_interface.cpp index b509da5fdd3b09f67987bd9fcf24d66a70cd5c3e..cedb742f4af7018caf4244ea1095d3298cabe7a9 100644 --- a/common/src/kernel_interface.cpp +++ b/common/src/kernel_interface.cpp @@ -211,12 +211,14 @@ bool KernelInterface::GetPidProcInfo(struct ProcInfo &procInfo) // 1 (init) S 0 0 0 0 -1 4210944 1 ... std::string stat, statm, statPid, vss, rss; if (!ReadFromFile(statPath, stat)) { + HILOGD("stat file error!"); return false; } std::istringstream isStat(stat); isStat >> statPid >> procInfo.name >> procInfo.status; if (statPid != std::to_string(procInfo.pid)) { + HILOGD("pid error!"); return false; } @@ -224,6 +226,7 @@ bool KernelInterface::GetPidProcInfo(struct ProcInfo &procInfo) // format like: // 640 472 369 38 0 115 0 if (!ReadFromFile(statmPath, statm)) { + HILOGD("statm file error!"); return false; } std::istringstream isStatm(statm); @@ -235,6 +238,19 @@ bool KernelInterface::GetPidProcInfo(struct ProcInfo &procInfo) return true; } +bool KernelInterface::GetProcNameByPid(int pid, std::string &name) +{ + std::string statusPath = JoinPath("/proc/", std::to_string(pid), "/status"); + std::string statusContent, nameTag; + if (!ReadFromFile(statusPath, statusContent)) { + HILOGE("status file [%{public}s] error!", statusPath.c_str()); + return false; + } + std::istringstream statusStream(statusContent); + statusStream >> nameTag >> name; + return true; +} + void KernelInterface::ReadZswapdPressureShow(std::map& result) { std::string contentStr; diff --git a/common/src/memmgr_config_manager.cpp b/common/src/memmgr_config_manager.cpp index 07016ecd455bf3b76a36c487b4b14d94882bf4b6..e10252274183c2ceaa73415c74e9d38155541138 100644 --- a/common/src/memmgr_config_manager.cpp +++ b/common/src/memmgr_config_manager.cpp @@ -129,6 +129,65 @@ bool MemmgrConfigManager::ParseXmlRootNode(const xmlNodePtr &rootNodePtr) ParseSystemMemoryLevelConfig(currNode); continue; } + if (name.compare("reclaimPriorityConfig") == 0) { + ParseReclaimPriorityConfig(currNode); + continue; + } + HILOGW("unknown node :<%{public}s>", name.c_str()); + return false; + } + return true; +} + +const ReclaimPriorityConfig& MemmgrConfigManager::GetReclaimPriorityConfig() +{ + return reclaimPriorityConfig_; +} + +bool MemmgrConfigManager::ParseReclaimPriorityConfig(const xmlNodePtr &rootNodePtr) +{ + if (!CheckNode(rootNodePtr) || !HasChild(rootNodePtr)) { + return true; + } + for (xmlNodePtr currNode = rootNodePtr->xmlChildrenNode; currNode != nullptr; currNode = currNode->next) { + if (!CheckNode(currNode)) { + return false; + } + std::string name = std::string(reinterpret_cast(currNode->name)); + if (name.compare("killalbeSystemApps") == 0) { + ParseReclaimPriorityKillableSystemAppsConfig(currNode); + continue; + } + HILOGW("unknown node :<%{public}s>", name.c_str()); + return false; + } + return true; +} + +bool MemmgrConfigManager::ParseReclaimPriorityKillableSystemAppsConfig(const xmlNodePtr &rootNodePtr) +{ + if (!CheckNode(rootNodePtr) || !HasChild(rootNodePtr)) { + return true; + } + for (xmlNodePtr currNode = rootNodePtr->xmlChildrenNode; currNode != nullptr; currNode = currNode->next) { + if (!CheckNode(currNode)) { + return false; + } + std::string name = std::string(reinterpret_cast(currNode->name)); + if (name.compare("killableSysApp") == 0) { + auto contentPtr = xmlNodeGetContent(currNode); + if (contentPtr == nullptr) { + continue; + } + std::string value = std::string(reinterpret_cast(contentPtr)); + HILOGW("read a killable app: %{public}s", value.c_str()); + if (value.size() == 0) { + HILOGE("read a empty killable app: %{public}s, ignore it!", value.c_str()); + continue; + } + reclaimPriorityConfig_.killalbeSystemApps_.insert(value); + xmlFree(contentPtr); + } HILOGW("unknown node :<%{public}s>", name.c_str()); return false; } diff --git a/profile/memmgr_config.xml b/profile/memmgr_config.xml index a7f3ff15b46151d99bd3c7232e164434e86169c0..7c6f85c5142c7973c4c5114e33dda8787495b6cb 100644 --- a/profile/memmgr_config.xml +++ b/profile/memmgr_config.xml @@ -1,25 +1,30 @@ - - - - - 800 - 750 - 850 - 200 - - - 0 - 1000 - 60 - 10 - 50 - - - - - - 819200 - 716800 - 614400 - - + + + + + 800 + 750 + 850 + 200 + + + 0 + 1000 + 60 + 10 + 50 + + + + + + + + + + + 819200 + 716800 + 614400 + + diff --git a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h index b9cf7cb70e1fdafae1d957ce8e55e33307b40ac7..780d390659a18b7a7615540dc6428cd7e1bae652 100644 --- a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h +++ b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_constants.h @@ -25,6 +25,8 @@ namespace OHOS { namespace Memory { // system app constexpr int RECLAIM_PRIORITY_SYSTEM = -1000; +// killable system app +constexpr int RECLAIM_PRIORITY_KILLABLE_SYSTEM = -800; // foreground process priority constexpr int RECLAIM_PRIORITY_FOREGROUND = 0; // visible process priority @@ -49,9 +51,6 @@ constexpr int RECLAIM_PRIORITY_UNKNOWN = 1000; constexpr int RECLAIM_PRIORITY_MIN = -1000; constexpr int RECLAIM_PRIORITY_MAX = 1000; -constexpr std::string_view SYSTEM_UI_BUNDLE_NAME = "com.ohos.systemui"; -constexpr std::string_view LAUNCHER_BUNDLE_NAME = "com.ohos.launcher"; - const int USER_ID_SHIFT = 200000; #define GET_OS_ACCOUNT_ID_BY_UID(bundleUid) ((bundleUid) / USER_ID_SHIFT) diff --git a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h index c51d095cd51aac195eb417c05087196e6c218a08..0196d98fdec05ab601aff978d9a85e9b6d1f1bcd 100644 --- a/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h +++ b/services/memmgrservice/include/reclaim_priority_manager/reclaim_priority_manager.h @@ -24,6 +24,7 @@ #include "account_bundle_info.h" #include "os_account_manager.h" #include "reclaim_param.h" +#include "memmgr_config_manager.h" #include #include @@ -116,8 +117,14 @@ private: std::shared_ptr handler_; std::map updateReasonStrMapping_; std::string unkown_reason = "UNKOWN_REASON"; + ReclaimPriorityConfig config_; + std::set allKillableSystemApps_; + ReclaimPriorityManager(); bool GetEventHandler(); + void GetAllKillableSystemApps(); + void GetKillableSystemAppsFromAms(std::set &killableApps); + void HandlePreStartedProcs(); bool UpdateReclaimPriorityInner(pid_t pid, int bundleUid, const std::string &bundleName, AppStateUpdateReason priorityReason); bool OsAccountChangedInner(int accountId, AccountSA::OS_ACCOUNT_SWITCH_MOD switchMod); @@ -135,7 +142,8 @@ private: std::shared_ptr FindOsAccountById(int accountId); void RemoveOsAccountById(int accountId); void AddOsAccountInfo(std::shared_ptr account); - bool IsSystemApp(std::shared_ptr bundle); + bool IsKillableSystemApp(std::shared_ptr bundle); + void NotifyKillableSystemAppsAdded(std::set &newKillableApps); static inline int GetOsAccountLocalIdFromUid(int bundleUid) { diff --git a/services/memmgrservice/src/mem_mgr_service.cpp b/services/memmgrservice/src/mem_mgr_service.cpp index 2f04511a363e176c1104cf600666a1189140dc33..e85866237f2932b7cc2f93d2a4082eda892f99d0 100644 --- a/services/memmgrservice/src/mem_mgr_service.cpp +++ b/services/memmgrservice/src/mem_mgr_service.cpp @@ -16,6 +16,7 @@ #include "mem_mgr_service.h" #include "memmgr_log.h" #include "system_ability_definition.h" +#include "memmgr_config_manager.h" #include "mem_mgr_event_center.h" #include "reclaim_priority_manager.h" #include "reclaim_strategy_manager.h" @@ -38,6 +39,8 @@ MemMgrService::MemMgrService() : SystemAbility(MEMORY_MANAGER_SA_ID, true) bool MemMgrService::Init() { + MemmgrConfigManager::GetInstance().Init(); + // init reclaim priority manager if (!ReclaimPriorityManager::GetInstance().Init()) { HILOGE("ReclaimPriorityManager init failed"); diff --git a/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp b/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp index f84f5607fd8e006f7c0a8d6d10049561ca45fb2e..30d670a50f04e6d82d2800f6dab7324248c8cef9 100644 --- a/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp +++ b/services/memmgrservice/src/reclaim_priority_manager/reclaim_priority_manager.cpp @@ -49,6 +49,18 @@ bool WriteOomScoreAdjToKernel(std::shared_ptr bundle) return true; } +bool WriteOomScoreAdjToKernel(pid_t pid, int priority) +{ + HILOGD("called"); + std::stringstream ss; + ss << "/proc/" << pid << "/oom_score_adj"; + std::string path = ss.str(); + std::string content = std::to_string(priority); + HILOGD("prepare to echo %{public}s > %{public}s", content.c_str(), path.c_str()); + KernelInterface::GetInstance().EchoToPath(path.c_str(), content.c_str()); + return true; +} + ReclaimPriorityManager::ReclaimPriorityManager() { updateReasonStrMapping_[static_cast(AppStateUpdateReason::CREATE_PROCESS)] = "CREATE_PROCESS"; @@ -86,7 +98,10 @@ std::string& ReclaimPriorityManager::AppStateUpdateResonToString(AppStateUpdateR bool ReclaimPriorityManager::Init() { + config_ = MemmgrConfigManager::GetInstance().GetReclaimPriorityConfig(); initialized_ = GetEventHandler(); + GetAllKillableSystemApps(); + HandlePreStartedProcs(); if (initialized_) { HILOGI("init successed"); } else { @@ -104,6 +119,56 @@ bool ReclaimPriorityManager::GetEventHandler() return true; } +void ReclaimPriorityManager::GetAllKillableSystemApps() +{ + HILOGI("called"); + // get killable system apps from xml + allKillableSystemApps_.merge(config_.killalbeSystemApps_); + // get killable system apps from fwk (finally from bms) + std::set killableSystemAppsFromAms_; + GetKillableSystemAppsFromAms(killableSystemAppsFromAms_); + allKillableSystemApps_.merge(killableSystemAppsFromAms_); +} + +void ReclaimPriorityManager::GetKillableSystemAppsFromAms(std::set &killableApps) +{ + // get killable system apps from fwk (finally from bms) +} + +// if user install new killable system apps, fwk should tell me by calling this interface. +// if user uninstall some killable system apps, we can do nothing since killable info will be updated on next rebooting. +void ReclaimPriorityManager::NotifyKillableSystemAppsAdded(std::set &newKillableApps) +{ + allKillableSystemApps_.merge(newKillableApps); +} + +// handle process started before our service +void ReclaimPriorityManager::HandlePreStartedProcs() +{ + std::vector preStartedPids; + KernelInterface::GetInstance().GetAllProcPids(preStartedPids); + for (unsigned int pid : preStartedPids) { + unsigned int uid = 0; + if (!KernelInterface::GetInstance().GetUidByPid(pid, uid)) { + HILOGE("process[pid=%{public}d] started before me, but GetUidByPid failed.", pid); + continue; + } + struct ProcInfo procInfo; + std::string name; + if (!KernelInterface::GetInstance().GetProcNameByPid(pid, name)) { + HILOGE("process[pid=%{public}d, uid=%{public}d] started before me, but GetProcNameByPid failed.", pid, uid); + continue; + } + bool killable = false;; + if (allKillableSystemApps_.find(name) != allKillableSystemApps_.end()) { + killable = true; + WriteOomScoreAdjToKernel(pid, RECLAIM_PRIORITY_KILLABLE_SYSTEM); + } + HILOGI("process[pid=%{public}d, uid=%{public}d, name=%{public}s] started before me, killable = %{public}d", + pid, uid, name.c_str(), killable); + } +} + void ReclaimPriorityManager::GetBundlePrioSet(BunldeCopySet &bundleSet) { // add lock @@ -272,11 +337,9 @@ bool ReclaimPriorityManager::UpdateReclaimPriority(pid_t pid, int bundleUid, con return handler_->PostImmediateTask(updateReclaimPriorityInnerFunc); } -bool ReclaimPriorityManager::IsSystemApp(std::shared_ptr bundle) +bool ReclaimPriorityManager::IsKillableSystemApp(std::shared_ptr bundle) { - // special case: launcher and system ui bundle - if (bundle != nullptr && (bundle->name_.compare(LAUNCHER_BUNDLE_NAME) == 0 || - bundle->name_.compare(SYSTEM_UI_BUNDLE_NAME) == 0)) { + if (allKillableSystemApps_.find(bundle->name_) != allKillableSystemApps_.end()) { return true; } return false; @@ -293,6 +356,7 @@ void ReclaimPriorityManager::UpdateBundlePriority(std::shared_ptr account = FindOsAccountById(accountId); if (account == nullptr) { DECLARE_SHARED_POINTER(AccountBundleInfo, tmpAccount); @@ -314,8 +378,9 @@ bool ReclaimPriorityManager::HandleCreateProcess(pid_t pid, int bundleUid, const action = AppAction::CREATE_PROCESS_AND_APP; } ProcessPriorityInfo proc(pid, bundleUid, RECLAIM_PRIORITY_FOREGROUND); - if (IsSystemApp(bundle)) { - proc.priority_ = RECLAIM_PRIORITY_SYSTEM; + if (IsKillableSystemApp(bundle)) { + HILOGI("[bundleName=%{public}s, pid=%{public}d] is a killable system app", bundleName.c_str(), pid); + proc.priority_ = RECLAIM_PRIORITY_KILLABLE_SYSTEM; } bundle->AddProc(proc); UpdateBundlePriority(bundle); diff --git a/services/memmgrservice/src/reclaim_strategy_manager/reclaim_strategy_manager.cpp b/services/memmgrservice/src/reclaim_strategy_manager/reclaim_strategy_manager.cpp index 5f9fcc2f0262ade62ab7469803c9602a3f576c19..6e867587c641ccbf8e3688959a63835fbf62686b 100644 --- a/services/memmgrservice/src/reclaim_strategy_manager/reclaim_strategy_manager.cpp +++ b/services/memmgrservice/src/reclaim_strategy_manager/reclaim_strategy_manager.cpp @@ -41,7 +41,6 @@ bool ReclaimStrategyManager::Init() if (!GetEventHandler_()) { break; } - MemmgrConfigManager::GetInstance().Init(); AvailBufferManager::GetInstance().Init(); if (!MemcgMgr::GetInstance().SetRootMemcgPara()) { break; diff --git a/test/BUILD.gn b/test/BUILD.gn index 1f65dc69da4ba057a2e2ef4df10d44385c934f77..aa77df3c5275e298f431af1089f440292d424d50 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -24,6 +24,7 @@ memmgr_service_configs = [ "${memmgr_service}:memory_memmgr_config" ] memmgr_deps = [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", "//foundation/resourceschedule/memmgr/services/memmgrservice:memmgrservice", + "//third_party/libxml2:xml2", "//utils/native/base:utils", ] diff --git a/test/unittest/phone/reclaim_priority_manager_test.cpp b/test/unittest/phone/reclaim_priority_manager_test.cpp index e03be9ea731780377c42f47692f10ddb2851b2c0..aad7bc4ae46f71acab465a4709e8cb1fa26d76e3 100644 --- a/test/unittest/phone/reclaim_priority_manager_test.cpp +++ b/test/unittest/phone/reclaim_priority_manager_test.cpp @@ -113,21 +113,6 @@ HWTEST_F(ReclaimPriorityManagerTest, IsProcExist, TestSize.Level1) "com.ohos.reclaim_test", AppStateUpdateReason::PROCESS_TERMINATED); } -HWTEST_F(ReclaimPriorityManagerTest, IsSystemApp, TestSize.Level1) -{ - std::shared_ptr bundle_1 = std::make_shared("test", 101, 100); - bool isSystem = ReclaimPriorityManager::GetInstance().IsSystemApp(bundle_1); - EXPECT_EQ(isSystem, false); - - std::shared_ptr bundle_2 = std::make_shared("com.ohos.systemui", 102, 100); - isSystem = ReclaimPriorityManager::GetInstance().IsSystemApp(bundle_2); - EXPECT_EQ(isSystem, true); - - std::shared_ptr bundle_3 = std::make_shared("com.ohos.launcher", 103, 100); - isSystem = ReclaimPriorityManager::GetInstance().IsSystemApp(bundle_3); - EXPECT_EQ(isSystem, true); -} - HWTEST_F(ReclaimPriorityManagerTest, UpdateReclaimPriorityProcessCreate, TestSize.Level1) { int pid = 10002; @@ -173,28 +158,6 @@ HWTEST_F(ReclaimPriorityManagerTest, UpdateReclaimPriorityProcessTerminate, Test "com.ohos.reclaim_test", AppStateUpdateReason::PROCESS_TERMINATED); } -HWTEST_F(ReclaimPriorityManagerTest, UpdateReclaimPrioritySystemProcess, TestSize.Level1) -{ - int pid = 10005; - int uid = 20010005; - ReclaimPriorityManager::GetInstance().UpdateReclaimPriorityInner(pid, uid, - "com.ohos.systemui", AppStateUpdateReason::CREATE_PROCESS); - ReclaimPriorityManager::GetInstance().UpdateReclaimPriorityInner(pid, uid, - "com.ohos.systemui", AppStateUpdateReason::BACKGROUND); - - int account_id = ReclaimPriorityManager::GetInstance().GetOsAccountLocalIdFromUid(uid); - std::shared_ptr account = ReclaimPriorityManager::GetInstance().FindOsAccountById(account_id); - std::shared_ptr bundle = account->FindBundleById(uid); - bool isSystem = ReclaimPriorityManager::GetInstance().IsSystemApp(bundle); - EXPECT_EQ(isSystem, true); - - int priority = bundle->priority_; - EXPECT_EQ(priority, RECLAIM_PRIORITY_SYSTEM); - - ReclaimPriorityManager::GetInstance().UpdateReclaimPriorityInner(pid, uid, - "com.ohos.reclaim_test", AppStateUpdateReason::PROCESS_TERMINATED); -} - HWTEST_F(ReclaimPriorityManagerTest, UpdateReclaimPriorityBackground, TestSize.Level1) { int pid = 10006;