1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "hidebug_ffi.h" 17 18 #include <numeric> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <memory> 23 #include <unistd.h> 24 #include <malloc.h> 25 #include <codecvt> 26 #include <string> 27 #include <vector> 28 #include <parameters.h> 29 30 #include "file_ex.h" 31 #include "directory_ex.h" 32 #include "hidebug_native_interface.h" 33 #include "hilog/log.h" 34 #include "hidebug_util.h" 35 #include "system_ability_definition.h" 36 #include "iservice_registry.h" 37 38 namespace OHOS::HiviewDFX { 39 40 #undef LOG_DOMAIN 41 #define LOG_DOMAIN 0xD002D0A 42 #undef LOG_TAG 43 #define LOG_TAG "CJ_HiDebug" 44 45 constexpr auto KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype"; 46 constexpr auto KEY_HIVIEW_DEVELOP_TYPE = "persist.hiview.leak_detector"; 47 48 enum ErrorCode { 49 MEM_ERROR = 1, 50 PERMISSION_ERROR = 201, 51 PARAMETER_ERROR = 401, 52 VERSION_ERROR = 801, 53 SYSTEM_ABILITY_NOT_FOUND = 11400101, 54 HAVA_ALREADY_TRACE = 11400102, 55 WITHOUT_WRITE_PERMISSON = 11400103, 56 SYSTEM_STATUS_ABNORMAL = 11400104, 57 NO_CAPTURE_TRACE_RUNNING = 11400105, 58 }; 59 60 extern "C" { FfiHidebugGetPss()61 uint64_t FfiHidebugGetPss() 62 { 63 auto natveMemInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false); 64 return natveMemInfoOption ? static_cast<uint64_t>(natveMemInfoOption->pss) : 0; 65 } 66 FfiHidebugGetVss()67 uint64_t FfiHidebugGetVss() 68 { 69 auto vssOption = HidebugNativeInterface::GetInstance().GetVss(); 70 return vssOption ? vssOption.value() : 0; 71 } 72 FfiHidebugGetNativeHeapSize()73 uint64_t FfiHidebugGetNativeHeapSize() 74 { 75 struct mallinfo mi = mallinfo(); 76 return static_cast<uint64_t>(mi.uordblks + mi.fordblks); 77 } 78 FfiHidebugGetNativeHeapAllocatedSize()79 uint64_t FfiHidebugGetNativeHeapAllocatedSize() 80 { 81 struct mallinfo mi = mallinfo(); 82 return static_cast<uint64_t>(mi.uordblks); 83 } 84 FfiHidebugGetNativeHeapFreeSize()85 uint64_t FfiHidebugGetNativeHeapFreeSize() 86 { 87 struct mallinfo mi = mallinfo(); 88 return static_cast<uint64_t>(mi.fordblks); 89 } 90 FfiHidebugGetSharedDirty()91 uint64_t FfiHidebugGetSharedDirty() 92 { 93 auto nativeMemInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false); 94 return nativeMemInfoOption ? static_cast<uint64_t>(nativeMemInfoOption->sharedDirty) : 0; 95 } 96 FfiHidebugGetPrivateDirty()97 uint64_t FfiHidebugGetPrivateDirty() 98 { 99 auto nativeMemInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false); 100 return nativeMemInfoOption ? static_cast<uint64_t>(nativeMemInfoOption->privateDirty) : 0; 101 } 102 FfiHidebugGetCpuUsage()103 double FfiHidebugGetCpuUsage() 104 { 105 return HidebugNativeInterface::GetInstance().GetCpuUsage(); 106 } 107 FfiHidebugGetSystemCpuUsage(int32_t & code)108 double FfiHidebugGetSystemCpuUsage(int32_t &code) 109 { 110 auto cpuUsageOptional = HidebugNativeInterface::GetInstance().GetSystemCpuUsage(); 111 if (cpuUsageOptional.has_value()) { 112 return cpuUsageOptional.value(); 113 } 114 code = ErrorCode::SYSTEM_STATUS_ABNORMAL; 115 return 0; 116 } 117 FfiHidebugGetAppThreadCpuUsage(int32_t & code)118 ThreadCpuUsageArr FfiHidebugGetAppThreadCpuUsage(int32_t &code) 119 { 120 ThreadCpuUsageArr arr{ .head = nullptr, .size = 0}; 121 std::map<uint32_t, double> threadMap = HidebugNativeInterface::GetInstance().GetAppThreadCpuUsage(); 122 auto size = threadMap.size(); 123 if (size <= 0) { 124 return arr; 125 } 126 arr.head = static_cast<CThreadCpuUsage *>(malloc(sizeof(CThreadCpuUsage) * size)); 127 if (arr.head == nullptr) { 128 code = ErrorCode::MEM_ERROR; 129 return arr; 130 } 131 size_t idx = 0; 132 for (const auto[id, usage] : threadMap) { 133 arr.head[idx] = CThreadCpuUsage{ .threadId = id, .cpuUsage = usage }; 134 idx++; 135 } 136 arr.size = static_cast<int64_t>(idx); 137 return arr; 138 } 139 FfiHidebugGetSystemMemInfo(int32_t & code)140 CSystemMemInfo FfiHidebugGetSystemMemInfo(int32_t &code) 141 { 142 CSystemMemInfo info{.totalMem = 0, .freeMem = 0, .availableMem = 0}; 143 auto systemMemInfo = HidebugNativeInterface::GetInstance().GetSystemMemInfo(); 144 if (!systemMemInfo) { 145 code = ErrorCode::MEM_ERROR; 146 return info; 147 } 148 info.totalMem = static_cast<uint64_t>(systemMemInfo->totalMem); 149 info.freeMem = static_cast<uint64_t>(systemMemInfo->freeMem); 150 info.availableMem = static_cast<uint64_t>(systemMemInfo->availableMem); 151 return info; 152 } 153 FfiHidebugGetAppNativeMemInfo(int32_t & code)154 CNativeMemInfo FfiHidebugGetAppNativeMemInfo(int32_t &code) 155 { 156 CNativeMemInfo info{}; 157 auto nativeMemInfo = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(); 158 if (!nativeMemInfo) { 159 code = ErrorCode::MEM_ERROR; 160 return info; 161 } 162 info.pss = nativeMemInfo->pss; 163 info.vss = nativeMemInfo->vss; 164 info.rss = nativeMemInfo->rss; 165 info.sharedDirty = nativeMemInfo->sharedDirty; 166 info.privateDirty = nativeMemInfo->privateDirty; 167 info.sharedClean = nativeMemInfo->sharedClean; 168 info.privateClean = nativeMemInfo->privateClean; 169 return info; 170 } 171 FfiHidebugGetAppMemoryLimit(int32_t & code)172 CMemoryLimit FfiHidebugGetAppMemoryLimit(int32_t &code) 173 { 174 CMemoryLimit limit{.rssLimit = 0, .vssLimit = 0}; 175 auto memoryLimit = HidebugNativeInterface::GetInstance().GetAppMemoryLimit(); 176 if (!memoryLimit) { 177 code = ErrorCode::MEM_ERROR; 178 return limit; 179 } 180 limit.rssLimit = memoryLimit->rssLimit; 181 limit.vssLimit = memoryLimit->vssLimit; 182 return limit; 183 } 184 FfiHidebugGetServiceDump(int32_t serviceId,int32_t fd,CArrString args)185 int32_t FfiHidebugGetServiceDump(int32_t serviceId, int32_t fd, CArrString args) 186 { 187 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 188 if (!sam) { 189 return ErrorCode::MEM_ERROR; 190 } 191 sptr<IRemoteObject> sa = sam->CheckSystemAbility(serviceId); 192 if (sa == nullptr) { 193 return ErrorCode::SYSTEM_ABILITY_NOT_FOUND; 194 } 195 std::vector<std::u16string> cargs; 196 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> strCnv; 197 for (int64_t i = 0; i < args.size; i++) { 198 cargs.push_back(strCnv.from_bytes(args.head[i])); 199 } 200 int dumpResult = sa->Dump(fd, cargs); 201 HILOG_INFO(LOG_CORE, "Dump result: %{public}d", dumpResult); 202 return 0; 203 } 204 FfiHidebugStartAppTraceCapture(CArrUnit tags,int32_t flag,uint32_t limitSize,int32_t & code)205 char *FfiHidebugStartAppTraceCapture(CArrUnit tags, int32_t flag, uint32_t limitSize, int32_t &code) 206 { 207 std::vector<uint64_t> taglist; 208 uint64_t *tagPtr = static_cast<uint64_t *>(tags.head); 209 for (int64_t i = 0; i < tags.size; i++) { 210 taglist.push_back(tagPtr[i]); 211 } 212 uint64_t tag = std::accumulate(taglist.begin(), taglist.end(), 0ull, 213 [](uint64_t a, uint64_t b) { return a | b; }); 214 std::string file; 215 code = HidebugNativeInterface::GetInstance().StartAppTraceCapture(tag, flag, limitSize, file); 216 if (code != TRACE_SUCCESS || file.empty()) { 217 return nullptr; 218 } 219 auto len = file.length() + 1; 220 char *res = static_cast<char *>(malloc(sizeof(char) * len)); 221 if (res == nullptr) { 222 return nullptr; 223 } 224 return std::char_traits<char>::copy(res, file.c_str(), len); 225 } 226 FfiHidebugStopAppTraceCapture()227 int32_t FfiHidebugStopAppTraceCapture() 228 { 229 return HidebugNativeInterface::GetInstance().StopAppTraceCapture(); 230 } 231 FfiHidebugSetAppResourceLimit(const char * type,int32_t value,bool enableDebugLog)232 int32_t FfiHidebugSetAppResourceLimit(const char *type, int32_t value, bool enableDebugLog) 233 { 234 if (!CheckVersionType("beta", KEY_HIVIEW_USER_TYPE) && 235 !CheckVersionType("enable", KEY_HIVIEW_DEVELOP_TYPE)) { 236 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. Not developer options or beta versions"); 237 return ErrorCode::VERSION_ERROR; 238 } 239 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 240 if (!abilityManager) { 241 return ErrorCode::MEM_ERROR; 242 } 243 sptr<IRemoteObject> remoteObject = abilityManager->CheckSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID); 244 if (remoteObject == nullptr) { 245 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. No this system ability."); 246 return ErrorCode::SYSTEM_STATUS_ABNORMAL; 247 } 248 if (HidebugNativeInterface::GetInstance().GetMemoryLeakResource(std::string(type), value, enableDebugLog) 249 == NATIVE_SUCCESS) { 250 CreateResourceLimitDir(); 251 } 252 return 0; 253 } 254 FfiHidebugIsDebugState()255 bool FfiHidebugIsDebugState() 256 { 257 return HidebugNativeInterface::GetInstance().IsDebuggerConnected(); 258 } 259 } 260 } 261