1ba5c3796Sopenharmony_ci/* 2ba5c3796Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3ba5c3796Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4ba5c3796Sopenharmony_ci * you may not use this file except in compliance with the License. 5ba5c3796Sopenharmony_ci * You may obtain a copy of the License at 6ba5c3796Sopenharmony_ci * 7ba5c3796Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8ba5c3796Sopenharmony_ci * 9ba5c3796Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10ba5c3796Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11ba5c3796Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ba5c3796Sopenharmony_ci * See the License for the specific language governing permissions and 13ba5c3796Sopenharmony_ci * limitations under the License. 14ba5c3796Sopenharmony_ci */ 15ba5c3796Sopenharmony_ci#ifndef OHOS_MEMORY_DUMP_COMMAND_DISPATCHER_H 16ba5c3796Sopenharmony_ci#define OHOS_MEMORY_DUMP_COMMAND_DISPATCHER_H 17ba5c3796Sopenharmony_ci 18ba5c3796Sopenharmony_ci#include "memory_level_constants.h" 19ba5c3796Sopenharmony_ci#include "memory_level_manager.h" 20ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 21ba5c3796Sopenharmony_ci#include "purgeable_mem_manager.h" 22ba5c3796Sopenharmony_ci#endif 23ba5c3796Sopenharmony_ci 24ba5c3796Sopenharmony_cinamespace OHOS { 25ba5c3796Sopenharmony_cinamespace Memory { 26ba5c3796Sopenharmony_ciconstexpr unsigned int ONTRIM_LEVEL_PARAM_SIZE = 1; 27ba5c3796Sopenharmony_ciconstexpr unsigned int RECLAIM_TYPE_PARAM_SIZE = 1; 28ba5c3796Sopenharmony_ciconstexpr unsigned int RECLAIM_HEAP_ID_PARAM_SIZE = 2; 29ba5c3796Sopenharmony_ciconstexpr unsigned int RECLAIM_ASHM_ID_PARAM_SIZE = 2; 30ba5c3796Sopenharmony_ciconstexpr unsigned int RECLAIM_SUBSCRIBER_ID_PARAM_SIZE = 1; 31ba5c3796Sopenharmony_ciconstexpr unsigned int FIRST_INDEX = 0; 32ba5c3796Sopenharmony_ciconstexpr unsigned int SECOND_INDEX = 1; 33ba5c3796Sopenharmony_ciconstexpr unsigned int THIRD_INDEX = 2; 34ba5c3796Sopenharmony_ciconstexpr unsigned int APP_STATE_PARAM_SIZE = 3; 35ba5c3796Sopenharmony_ci 36ba5c3796Sopenharmony_ci#define CHECK_SIZE(container, len, fd, actionIfFailed) \ 37ba5c3796Sopenharmony_ci do { \ 38ba5c3796Sopenharmony_ci if ((container).size() != (len)) { \ 39ba5c3796Sopenharmony_ci dprintf(fd, "size error\n"); \ 40ba5c3796Sopenharmony_ci actionIfFailed; \ 41ba5c3796Sopenharmony_ci } \ 42ba5c3796Sopenharmony_ci } while (0) 43ba5c3796Sopenharmony_ci 44ba5c3796Sopenharmony_ciinline bool HasCommand(const std::map<std::string, std::vector<std::string>> &keyValuesMapping, 45ba5c3796Sopenharmony_ci const std::string &command) 46ba5c3796Sopenharmony_ci{ 47ba5c3796Sopenharmony_ci return keyValuesMapping.find(command) != keyValuesMapping.end(); 48ba5c3796Sopenharmony_ci} 49ba5c3796Sopenharmony_ci 50ba5c3796Sopenharmony_civoid ShowHelpInfo(const int fd) 51ba5c3796Sopenharmony_ci{ 52ba5c3796Sopenharmony_ci dprintf(fd, "Usage:\n"); 53ba5c3796Sopenharmony_ci dprintf(fd, "-h |help for memmgrservice dumper\n"); 54ba5c3796Sopenharmony_ci dprintf(fd, "-a |dump all info\n"); 55ba5c3796Sopenharmony_ci dprintf(fd, "-e |dump event observer\n"); 56ba5c3796Sopenharmony_ci dprintf(fd, "-r |dump reclaim info and adj\n"); 57ba5c3796Sopenharmony_ci dprintf(fd, "-c |dump config\n"); 58ba5c3796Sopenharmony_ci dprintf(fd, "-m |show malloc state\n"); 59ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 60ba5c3796Sopenharmony_ci dprintf(fd, "-s |show subscriber all the pid which can be reclaimed\n"); 61ba5c3796Sopenharmony_ci dprintf(fd, "-d {pid} {uid} {state} |trigger appstate changed\n\n"); 62ba5c3796Sopenharmony_ci dprintf(fd, "-t trigger memory onTrim:\n" 63ba5c3796Sopenharmony_ci "-t 1 ---------------------- level_purgeable\n" 64ba5c3796Sopenharmony_ci "-t 2 ---------------------- level_moderate\n" 65ba5c3796Sopenharmony_ci "-t 3 ---------------------- level_low\n" 66ba5c3796Sopenharmony_ci "-t 4 ---------------------- level_critical\n\n"); 67ba5c3796Sopenharmony_ci dprintf(fd, "-f trigger purgeable memory Reclaim:\n" 68ba5c3796Sopenharmony_ci "-f 1 ---------------------- purg_heap all\n" 69ba5c3796Sopenharmony_ci "-f 2 ---------------------- purg_ashmem all\n" 70ba5c3796Sopenharmony_ci "-f 3 ---------------------- purg_subscriber all\n" 71ba5c3796Sopenharmony_ci "-f 4 ---------------------- purg all purgeable memory\n" 72ba5c3796Sopenharmony_ci "-f 1 -id {userId} {size} -- purg_heap by memCG and size(KB). if userId=0, reclaim system_lru\n" 73ba5c3796Sopenharmony_ci "-f 2 -id {ashmId} {time} -- purg_ashm by ashmId, which can get from /proc/purgeable_ashmem_trigger\n" 74ba5c3796Sopenharmony_ci "-f 3 -id {pid} ------------ purg_subscriber by pid. if pid=0, reclaim subscriber all\n\n"); 75ba5c3796Sopenharmony_ci#endif 76ba5c3796Sopenharmony_ci} 77ba5c3796Sopenharmony_ci 78ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 79ba5c3796Sopenharmony_civoid PrintOntrimError(const int fd) 80ba5c3796Sopenharmony_ci{ 81ba5c3796Sopenharmony_ci dprintf(fd, "\n error: unrecognized memory level, please input correct format as follows:\n" 82ba5c3796Sopenharmony_ci "-t 1 ---------------------- level_purgeable\n" 83ba5c3796Sopenharmony_ci "-t 2 ---------------------- level_moderate\n" 84ba5c3796Sopenharmony_ci "-t 3 ---------------------- level_low\n" 85ba5c3796Sopenharmony_ci "-t 4 ---------------------- level_critical\n"); 86ba5c3796Sopenharmony_ci} 87ba5c3796Sopenharmony_ci 88ba5c3796Sopenharmony_civoid PrintReclaimError(const int fd) 89ba5c3796Sopenharmony_ci{ 90ba5c3796Sopenharmony_ci dprintf(fd, "\n error: trigger force reclaim failed, please input correct info as follows:\n" 91ba5c3796Sopenharmony_ci "-f 1 ---------------------- purg_heap all\n" 92ba5c3796Sopenharmony_ci "-f 2 ---------------------- purg_ashmem all\n" 93ba5c3796Sopenharmony_ci "-f 3 ---------------------- purg_subscriber all\n" 94ba5c3796Sopenharmony_ci "-f 4 ---------------------- purg all purgeable memory\n" 95ba5c3796Sopenharmony_ci "-f 1 -id {userId} {size} -- purg_heap by memCG and size(KB). if userId=0, reclaim system_lru\n" 96ba5c3796Sopenharmony_ci "-f 2 -id {ashmId} {time} -- purg_ashm by ashmId, which can get from /proc/purgeable_ashmem_trigger\n" 97ba5c3796Sopenharmony_ci "-f 3 -id {pid} ------------ purg_subscriber by pid. if pid=0, reclaim subscriber all\n"); 98ba5c3796Sopenharmony_ci} 99ba5c3796Sopenharmony_ci 100ba5c3796Sopenharmony_civoid DispatchTriggerMemLevel(const int fd, std::map<std::string, std::vector<std::string>> &keyValuesMapping) 101ba5c3796Sopenharmony_ci{ 102ba5c3796Sopenharmony_ci std::vector<std::string> values = keyValuesMapping["-t"]; 103ba5c3796Sopenharmony_ci CHECK_SIZE(values, ONTRIM_LEVEL_PARAM_SIZE, fd, return); 104ba5c3796Sopenharmony_ci 105ba5c3796Sopenharmony_ci int level; 106ba5c3796Sopenharmony_ci try { 107ba5c3796Sopenharmony_ci level = std::stoi(values[FIRST_INDEX]); 108ba5c3796Sopenharmony_ci } catch (...) { 109ba5c3796Sopenharmony_ci PrintOntrimError(fd); 110ba5c3796Sopenharmony_ci return; 111ba5c3796Sopenharmony_ci } 112ba5c3796Sopenharmony_ci 113ba5c3796Sopenharmony_ci SystemMemoryInfo info = {MemorySource::MANUAL_DUMP, SystemMemoryLevel::UNKNOWN}; 114ba5c3796Sopenharmony_ci switch (level) { 115ba5c3796Sopenharmony_ci case MEMORY_LEVEL_PURGEABLE: 116ba5c3796Sopenharmony_ci info.level = SystemMemoryLevel::MEMORY_LEVEL_PURGEABLE; 117ba5c3796Sopenharmony_ci break; 118ba5c3796Sopenharmony_ci case MEMORY_LEVEL_MODERATE: 119ba5c3796Sopenharmony_ci info.level = SystemMemoryLevel::MEMORY_LEVEL_MODERATE; 120ba5c3796Sopenharmony_ci break; 121ba5c3796Sopenharmony_ci case MEMORY_LEVEL_LOW: 122ba5c3796Sopenharmony_ci info.level = SystemMemoryLevel::MEMORY_LEVEL_LOW; 123ba5c3796Sopenharmony_ci break; 124ba5c3796Sopenharmony_ci case MEMORY_LEVEL_CRITICAL: 125ba5c3796Sopenharmony_ci info.level = SystemMemoryLevel::MEMORY_LEVEL_CRITICAL; 126ba5c3796Sopenharmony_ci break; 127ba5c3796Sopenharmony_ci default: 128ba5c3796Sopenharmony_ci PrintOntrimError(fd); 129ba5c3796Sopenharmony_ci return; 130ba5c3796Sopenharmony_ci } 131ba5c3796Sopenharmony_ci MemoryLevelManager::GetInstance().TriggerMemoryLevelByDump(info); 132ba5c3796Sopenharmony_ci} 133ba5c3796Sopenharmony_ci 134ba5c3796Sopenharmony_civoid ParseForceReclaimType(const int fd, std::map<std::string, std::vector<std::string>> &keyValuesMapping, 135ba5c3796Sopenharmony_ci DumpReclaimInfo &dumpInfo) 136ba5c3796Sopenharmony_ci{ 137ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::UNKNOWN; 138ba5c3796Sopenharmony_ci dumpInfo.ifReclaimTypeAll = true; 139ba5c3796Sopenharmony_ci 140ba5c3796Sopenharmony_ci std::vector<std::string> values = keyValuesMapping["-f"]; 141ba5c3796Sopenharmony_ci CHECK_SIZE(values, RECLAIM_TYPE_PARAM_SIZE, fd, return); 142ba5c3796Sopenharmony_ci 143ba5c3796Sopenharmony_ci int type; 144ba5c3796Sopenharmony_ci try { 145ba5c3796Sopenharmony_ci type = std::stoi(values[FIRST_INDEX]); 146ba5c3796Sopenharmony_ci } catch (...) { 147ba5c3796Sopenharmony_ci return; 148ba5c3796Sopenharmony_ci } 149ba5c3796Sopenharmony_ci switch (type) { 150ba5c3796Sopenharmony_ci case PURGEABLE_TYPE_HEAP: 151ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::PURGEABLE_HEAP; 152ba5c3796Sopenharmony_ci break; 153ba5c3796Sopenharmony_ci case PURGEABLE_TYPE_ASHMEM: 154ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::PURGEABLE_ASHMEM; 155ba5c3796Sopenharmony_ci break; 156ba5c3796Sopenharmony_ci case PURGEABLE_TYPE_SUBSCRIBER: 157ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::PURGEABLE_SUBSCRIBER; 158ba5c3796Sopenharmony_ci break; 159ba5c3796Sopenharmony_ci case PURGEABLE_TYPE_ALL: 160ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::PURGEABLE_ALL; 161ba5c3796Sopenharmony_ci break; 162ba5c3796Sopenharmony_ci default: 163ba5c3796Sopenharmony_ci return; 164ba5c3796Sopenharmony_ci } 165ba5c3796Sopenharmony_ci} 166ba5c3796Sopenharmony_ci 167ba5c3796Sopenharmony_cibool ParseForceReclaimId(const int fd, std::map<std::string, std::vector<std::string>> &keyValuesMapping, 168ba5c3796Sopenharmony_ci DumpReclaimInfo &dumpInfo) 169ba5c3796Sopenharmony_ci{ 170ba5c3796Sopenharmony_ci dumpInfo.ifReclaimTypeAll = false; 171ba5c3796Sopenharmony_ci std::vector<std::string> values = keyValuesMapping["-id"]; 172ba5c3796Sopenharmony_ci switch (dumpInfo.reclaimType) { 173ba5c3796Sopenharmony_ci case PurgeableMemoryType::PURGEABLE_HEAP: 174ba5c3796Sopenharmony_ci CHECK_SIZE(values, RECLAIM_HEAP_ID_PARAM_SIZE, fd, return false); // {userId} {size} 175ba5c3796Sopenharmony_ci try { 176ba5c3796Sopenharmony_ci dumpInfo.memcgUserId = std::stoi(values[FIRST_INDEX]); 177ba5c3796Sopenharmony_ci dumpInfo.reclaimHeapSizeKB = std::stoi(values[SECOND_INDEX]); 178ba5c3796Sopenharmony_ci } catch (...) { 179ba5c3796Sopenharmony_ci return false; 180ba5c3796Sopenharmony_ci } 181ba5c3796Sopenharmony_ci break; 182ba5c3796Sopenharmony_ci case PurgeableMemoryType::PURGEABLE_ASHMEM: 183ba5c3796Sopenharmony_ci CHECK_SIZE(values, RECLAIM_ASHM_ID_PARAM_SIZE, fd, return false); // {ashmId} {time} 184ba5c3796Sopenharmony_ci try { 185ba5c3796Sopenharmony_ci dumpInfo.ashmId = std::stoul(values[FIRST_INDEX]); 186ba5c3796Sopenharmony_ci dumpInfo.ashmTime = std::stoul(values[SECOND_INDEX]); 187ba5c3796Sopenharmony_ci } catch (...) { 188ba5c3796Sopenharmony_ci return false; 189ba5c3796Sopenharmony_ci } 190ba5c3796Sopenharmony_ci break; 191ba5c3796Sopenharmony_ci case PurgeableMemoryType::PURGEABLE_SUBSCRIBER: 192ba5c3796Sopenharmony_ci CHECK_SIZE(values, RECLAIM_SUBSCRIBER_ID_PARAM_SIZE, fd, return false); // {pid} 193ba5c3796Sopenharmony_ci if (values[0] == std::string("0")) { // reclaim subscriber all when pid = 0 194ba5c3796Sopenharmony_ci dumpInfo.ifReclaimTypeAll = true; 195ba5c3796Sopenharmony_ci return true; 196ba5c3796Sopenharmony_ci } 197ba5c3796Sopenharmony_ci try { 198ba5c3796Sopenharmony_ci dumpInfo.subscriberPid = std::stoi(values[FIRST_INDEX]); 199ba5c3796Sopenharmony_ci } catch (...) { 200ba5c3796Sopenharmony_ci return false; 201ba5c3796Sopenharmony_ci } 202ba5c3796Sopenharmony_ci break; 203ba5c3796Sopenharmony_ci default: 204ba5c3796Sopenharmony_ci return false; 205ba5c3796Sopenharmony_ci } 206ba5c3796Sopenharmony_ci return true; 207ba5c3796Sopenharmony_ci} 208ba5c3796Sopenharmony_ci 209ba5c3796Sopenharmony_cibool PurgeableMemoryDump(int fd, std::map<std::string, std::vector<std::string>> &keyValuesMapping) 210ba5c3796Sopenharmony_ci{ 211ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-s")) { 212ba5c3796Sopenharmony_ci PurgeableMemManager::GetInstance().DumpSubscribers(fd); 213ba5c3796Sopenharmony_ci return true; 214ba5c3796Sopenharmony_ci } 215ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-t")) { 216ba5c3796Sopenharmony_ci DispatchTriggerMemLevel(fd, keyValuesMapping); 217ba5c3796Sopenharmony_ci return true; 218ba5c3796Sopenharmony_ci } 219ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-f")) { 220ba5c3796Sopenharmony_ci DumpReclaimInfo dumpInfo; 221ba5c3796Sopenharmony_ci ParseForceReclaimType(fd, keyValuesMapping, dumpInfo); 222ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-id") && !ParseForceReclaimId(fd, keyValuesMapping, dumpInfo)) { 223ba5c3796Sopenharmony_ci dumpInfo.reclaimType = PurgeableMemoryType::UNKNOWN; 224ba5c3796Sopenharmony_ci } 225ba5c3796Sopenharmony_ci if (PurgeableMemManager::GetInstance().ForceReclaimByDump(dumpInfo)) { 226ba5c3796Sopenharmony_ci dprintf(fd, "trigger force reclaim success!\n"); 227ba5c3796Sopenharmony_ci } else { 228ba5c3796Sopenharmony_ci PrintReclaimError(fd); 229ba5c3796Sopenharmony_ci } 230ba5c3796Sopenharmony_ci return true; 231ba5c3796Sopenharmony_ci } 232ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-d")) { 233ba5c3796Sopenharmony_ci std::vector<std::string> appState = keyValuesMapping["-d"]; 234ba5c3796Sopenharmony_ci if (appState.size() < APP_STATE_PARAM_SIZE) { 235ba5c3796Sopenharmony_ci dprintf(fd, "params number is less than %{publid}d!\n", APP_STATE_PARAM_SIZE); 236ba5c3796Sopenharmony_ci return true; 237ba5c3796Sopenharmony_ci } 238ba5c3796Sopenharmony_ci int32_t pid = std::stoi(appState[FIRST_INDEX]); 239ba5c3796Sopenharmony_ci int32_t uid = std::stoi(appState[SECOND_INDEX]); 240ba5c3796Sopenharmony_ci int32_t state = std::stoi(appState[THIRD_INDEX]); 241ba5c3796Sopenharmony_ci PurgeableMemManager::GetInstance().ChangeAppState(pid, uid, state); 242ba5c3796Sopenharmony_ci return true; 243ba5c3796Sopenharmony_ci } 244ba5c3796Sopenharmony_ci return false; 245ba5c3796Sopenharmony_ci} 246ba5c3796Sopenharmony_ci#endif // USE_PURGEABLE_MEMORY 247ba5c3796Sopenharmony_ci 248ba5c3796Sopenharmony_civoid DispatchDumpCommand(const int fd, std::map<std::string, std::vector<std::string>> &keyValuesMapping) 249ba5c3796Sopenharmony_ci{ 250ba5c3796Sopenharmony_ci if (keyValuesMapping.empty() || HasCommand(keyValuesMapping, "-h")) { 251ba5c3796Sopenharmony_ci ShowHelpInfo(fd); 252ba5c3796Sopenharmony_ci return; 253ba5c3796Sopenharmony_ci } 254ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-a")) { 255ba5c3796Sopenharmony_ci MemMgrEventCenter::GetInstance().Dump(fd); 256ba5c3796Sopenharmony_ci ReclaimPriorityManager::GetInstance().Dump(fd); 257ba5c3796Sopenharmony_ci return; 258ba5c3796Sopenharmony_ci } 259ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-e")) { 260ba5c3796Sopenharmony_ci MemMgrEventCenter::GetInstance().Dump(fd); 261ba5c3796Sopenharmony_ci return; 262ba5c3796Sopenharmony_ci } 263ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-r")) { 264ba5c3796Sopenharmony_ci ReclaimPriorityManager::GetInstance().Dump(fd); 265ba5c3796Sopenharmony_ci return; 266ba5c3796Sopenharmony_ci } 267ba5c3796Sopenharmony_ci if (HasCommand(keyValuesMapping, "-c")) { 268ba5c3796Sopenharmony_ci MemmgrConfigManager::GetInstance().Dump(fd); 269ba5c3796Sopenharmony_ci return; 270ba5c3796Sopenharmony_ci } 271ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 272ba5c3796Sopenharmony_ci if (PurgeableMemoryDump(fd, keyValuesMapping)) { 273ba5c3796Sopenharmony_ci return; 274ba5c3796Sopenharmony_ci } 275ba5c3796Sopenharmony_ci#endif 276ba5c3796Sopenharmony_ci} 277ba5c3796Sopenharmony_ci 278ba5c3796Sopenharmony_ci} // namespace Memory 279ba5c3796Sopenharmony_ci} // namespace OHOS 280ba5c3796Sopenharmony_ci#endif // OHOS_MEMORY_DUMP_COMMAND_DISPATCHER_H