1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. 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 <algorithm> 17#include <cerrno> 18#include <codecvt> 19#include <fstream> 20#include <string> 21#include <memory> 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <fcntl.h> 25#include <ctime> 26#include <malloc.h> 27#include <parameters.h> 28#include <unistd.h> 29 30#include "application_context.h" 31#include "context.h" 32#include "cpu_collector.h" 33#include "directory_ex.h" 34#include "dump_usage.h" 35#include "file_ex.h" 36#include "hiappevent_util.h" 37#include "hidebug_native_interface.h" 38#include "hilog/log.h" 39#include "iservice_registry.h" 40#include "memory_collector.h" 41#include "napi_hidebug_init.h" 42#include "napi/native_api.h" 43#include "napi/native_node_api.h" 44#include "native_engine/native_engine.h" 45#include "refbase.h" 46#include "storage_acl.h" 47#include "system_ability_definition.h" 48#include "napi_hidebug_gc.h" 49#include "napi_util.h" 50 51namespace OHOS { 52namespace HiviewDFX { 53namespace { 54#undef LOG_DOMAIN 55#define LOG_DOMAIN 0xD002D0A 56#undef LOG_TAG 57#define LOG_TAG "HiDebug_NAPI" 58constexpr int ONE_VALUE_LIMIT = 1; 59constexpr int ARRAY_INDEX_FIRST = 0; 60constexpr int ARRAY_INDEX_SECOND = 1; 61constexpr int REMOVE_NAPI_WRAP_PARAM_COUNT = 2; 62constexpr int NAME_LEN = 128; 63constexpr int BYTE_2_KB_SHIFT_BITS = 10; 64constexpr int FIRST_POS = 0; 65constexpr int SECOND_POS = 1; 66constexpr int THIRD_POS = 2; 67constexpr int PSS_MIN = 1024; 68constexpr int PSS_MAX = 4 * 1024 * 1024; 69constexpr int JS_MIN = 85; 70constexpr int JS_MAX = 95; 71constexpr int FD_MIN = 10; 72constexpr int FD_MAX = 10000; 73constexpr int THREAD_MIN = 1; 74constexpr int THREAD_MAX = 1000; 75const std::string SLASH_STR = "/"; 76const std::string DEFAULT_FILENAME = "undefined"; 77const std::string JSON_FILE = ".json"; 78const std::string HEAPSNAPSHOT_FILE = ".heapsnapshot"; 79const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype"; 80const std::string KEY_HIVIEW_DEVELOP_TYPE = "persist.hiview.leak_detector"; 81enum ErrorCode { 82 PERMISSION_ERROR = 201, 83 PARAMETER_ERROR = 401, 84 VERSION_ERROR = 801, 85 SYSTEM_ABILITY_NOT_FOUND = 11400101, 86 HAVA_ALREADY_TRACE = 11400102, 87 WITHOUT_WRITE_PERMISSON = 11400103, 88 SYSTEM_STATUS_ABNORMAL = 11400104, 89 NO_CAPTURE_TRACE_RUNNING = 11400105, 90}; 91 92const std::unordered_set<std::string> RESOURCE_TYPE_LIST{ 93 "pss_memory", 94 "js_heap", 95 "fd", 96 "thread" 97}; 98static std::map<std::string, std::pair<int, int>> limitResource = { 99 {{"pss_memory", {PSS_MIN, PSS_MAX}}, {"js_heap", {JS_MIN, JS_MAX}}, 100 {"fd", {FD_MIN, FD_MAX}}, {"thread", {THREAD_MIN, THREAD_MAX}}} 101}; 102} 103 104static bool MatchValueType(napi_env env, napi_value value, napi_valuetype targetType) 105{ 106 napi_valuetype valueType = napi_undefined; 107 napi_typeof(env, value, &valueType); 108 return valueType == targetType; 109} 110 111static bool CreateFile(const std::string &path) 112{ 113 if (access(path.c_str(), F_OK) == 0) { 114 if (access(path.c_str(), W_OK) == 0) { 115 return true; 116 } 117 return false; 118 } 119 const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r----- 120 int fd = creat(path.c_str(), defaultMode); 121 if (fd == -1) { 122 HILOG_ERROR(LOG_CORE, "file create failed, errno = %{public}d", errno); 123 return false; 124 } else { 125 close(fd); 126 return true; 127 } 128} 129 130static bool IsLegalPath(const std::string& path) 131{ 132 if (path.find("./") != std::string::npos || 133 path.find("../") != std::string::npos) { 134 return false; 135 } 136 return true; 137} 138 139static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize) 140{ 141 bool isArray = false; 142 arraySize = 0; 143 if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) { 144 return false; 145 } 146 if (napi_get_array_length(env, param, &arraySize) != napi_ok) { 147 return false; 148 } 149 return true; 150} 151 152static bool GetDumpParam(napi_env env, napi_callback_info info, 153 int& serviceId, int& fd, std::vector<std::u16string>& args) 154{ 155 const int valueNum = 3; 156 size_t argc = valueNum; 157 napi_value argv[valueNum] = {nullptr}; 158 napi_value thisVar = nullptr; 159 void *data = nullptr; 160 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 161 if (argc != valueNum) { 162 HILOG_ERROR(LOG_CORE, "invalid number = %{public}d of params.", ONE_VALUE_LIMIT); 163 return false; 164 } 165 int thirdPos = 2; 166 if (!MatchValueType(env, argv[0], napi_number) && 167 !MatchValueType(env, argv[1], napi_number) && 168 !MatchValueType(env, argv[thirdPos], napi_object)) { 169 HILOG_ERROR(LOG_CORE, "params type error."); 170 return false; 171 } 172 if (napi_get_value_int32(env, argv[0], &serviceId) != napi_ok) { 173 HILOG_ERROR(LOG_CORE, "Get input serviceId failed."); 174 return false; 175 } 176 if (napi_get_value_int32(env, argv[1], &fd) != napi_ok) { 177 HILOG_ERROR(LOG_CORE, "Get input fd failed."); 178 return false; 179 } 180 uint32_t arraySize = 0; 181 if (!IsArrayForNapiValue(env, argv[thirdPos], arraySize)) { 182 HILOG_ERROR(LOG_CORE, "Get input args failed."); 183 return false; 184 } 185 for (uint32_t i = 0; i < arraySize; i++) { 186 napi_value jsValue = nullptr; 187 if (napi_get_element(env, argv[thirdPos], i, &jsValue) != napi_ok) { 188 HILOG_ERROR(LOG_CORE, "get_element -> Get input args failed."); 189 return false; 190 } 191 const size_t bufSize = 256; 192 size_t bufLen = 0; 193 char buf[bufSize] = {0}; 194 if (napi_get_value_string_utf8(env, jsValue, buf, bufSize - 1, &bufLen) != napi_ok) { 195 HILOG_ERROR(LOG_CORE, "get_value -> Get input args failed."); 196 return false; 197 } 198 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> strCnv; 199 args.push_back(strCnv.from_bytes(buf)); 200 } 201 return true; 202} 203 204static std::string GetFileNameParam(napi_env env, napi_callback_info info) 205{ 206 size_t argc = ONE_VALUE_LIMIT; 207 napi_value argv[ONE_VALUE_LIMIT] = { nullptr }; 208 napi_value thisVar = nullptr; 209 void *data = nullptr; 210 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 211 if (argc != ONE_VALUE_LIMIT) { 212 HILOG_ERROR(LOG_CORE, "invalid number = %{public}d of params.", ONE_VALUE_LIMIT); 213 return DEFAULT_FILENAME; 214 } 215 if (!MatchValueType(env, argv[ARRAY_INDEX_FIRST], napi_string)) { 216 HILOG_ERROR(LOG_CORE, "Type error, should be string type!"); 217 return DEFAULT_FILENAME; 218 } 219 size_t bufLen = 0; 220 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufLen); 221 if (status != napi_ok) { 222 HILOG_ERROR(LOG_CORE, "Get input filename param length failed."); 223 return DEFAULT_FILENAME; 224 } 225 const int bufMax = 128; 226 if (bufLen > bufMax || bufLen == 0) { 227 HILOG_ERROR(LOG_CORE, "input filename param length is illegal."); 228 return DEFAULT_FILENAME; 229 } 230 char buf[bufLen + 1]; 231 napi_get_value_string_utf8(env, argv[0], buf, bufLen + 1, &bufLen); 232 std::string fileName = buf; 233 return fileName; 234} 235 236static bool GetTheOnlyStringParam(napi_env env, napi_callback_info info, std::string &fileName) 237{ 238 size_t argc = ONE_VALUE_LIMIT; 239 napi_value argv[ONE_VALUE_LIMIT] = { nullptr }; 240 napi_value thisVar = nullptr; 241 void *data = nullptr; 242 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 243 if (argc != ONE_VALUE_LIMIT) { 244 HILOG_ERROR(LOG_CORE, "invalid number = %{public}d of params.", ONE_VALUE_LIMIT); 245 return false; 246 } 247 if (!MatchValueType(env, argv[ARRAY_INDEX_FIRST], napi_string)) { 248 HILOG_ERROR(LOG_CORE, "Type error, should be string type!"); 249 return false; 250 } 251 size_t bufLen = 0; 252 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufLen); 253 if (status != napi_ok) { 254 HILOG_ERROR(LOG_CORE, "Get input filename param length failed."); 255 return false; 256 } 257 const int bufMax = 128; 258 if (bufLen > bufMax || bufLen == 0) { 259 HILOG_ERROR(LOG_CORE, "input filename param length is illegal."); 260 return false; 261 } 262 char buf[bufLen + 1]; 263 napi_get_value_string_utf8(env, argv[0], buf, bufLen + 1, &bufLen); 264 fileName = buf; 265 return true; 266} 267 268static bool GetTraceParam(napi_env env, napi_callback_info info, 269 uint32_t& traceFlag, uint32_t& limitSize, std::vector<uint64_t>& tags) 270{ 271 const int valueNum = 3; 272 size_t argc = valueNum; 273 napi_value argv[valueNum] = {nullptr}; 274 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 275 if (argc != valueNum) { 276 HILOG_ERROR(LOG_CORE, "invalid numbers of params!"); 277 return false; 278 } 279 if (!MatchValueType(env, argv[FIRST_POS], napi_object) && 280 !MatchValueType(env, argv[SECOND_POS], napi_number) && 281 !MatchValueType(env, argv[THIRD_POS], napi_number)) { 282 HILOG_ERROR(LOG_CORE, "params type error."); 283 return false; 284 } 285 uint32_t arraySize = 0; 286 if (!IsArrayForNapiValue(env, argv[FIRST_POS], arraySize)) { 287 HILOG_ERROR(LOG_CORE, "Get input tags failed."); 288 return false; 289 } 290 uint64_t tag = 0; 291 bool lossless = true; 292 for (uint32_t i = 0; i < arraySize; ++i) { 293 napi_value jsValue = nullptr; 294 if (napi_get_element(env, argv[FIRST_POS], i, &jsValue) != napi_ok) { 295 HILOG_ERROR(LOG_CORE, "get_element -> Get input tags failed."); 296 return false; 297 } 298 if (napi_get_value_bigint_uint64(env, jsValue, &tag, &lossless) != napi_ok) { 299 HILOG_ERROR(LOG_CORE, "Get input tags failed."); 300 return false; 301 } 302 tags.push_back(tag); 303 } 304 if (napi_get_value_uint32(env, argv[SECOND_POS], &traceFlag) != napi_ok) { 305 HILOG_ERROR(LOG_CORE, "Get input traceFlag failed."); 306 return false; 307 } 308 if (napi_get_value_uint32(env, argv[THIRD_POS], &limitSize) != napi_ok) { 309 HILOG_ERROR(LOG_CORE, "Get input limitSize failed."); 310 return false; 311 } 312 return true; 313} 314 315napi_value StartProfiling(napi_env env, napi_callback_info info) 316{ 317 ApiInvokeRecorder apiInvokeRecorder("startProfiling"); 318 std::string fileName = GetFileNameParam(env, info); 319 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); 320 if (context == nullptr) { 321 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 322 return CreateErrorMessage(env, "Get ApplicationContext failed."); 323 } 324 std::string filesDir = context->GetFilesDir(); 325 if (filesDir.empty()) { 326 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 327 return CreateErrorMessage(env, "Get App files dir failed."); 328 } 329 std::string filePath = filesDir + SLASH_STR + fileName + JSON_FILE; 330 if (!IsLegalPath(filePath)) { 331 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 332 return CreateErrorMessage(env, "input fileName is illegal."); 333 } 334 if (!CreateFile(filePath)) { 335 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 336 return CreateErrorMessage(env, "file created failed."); 337 } 338 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 339 engine->StartCpuProfiler(filePath); 340 return CreateUndefined(env); 341} 342 343napi_value StartJsCpuProfiling(napi_env env, napi_callback_info info) 344{ 345 ApiInvokeRecorder apiInvokeRecorder("startJsCpuProfiling"); 346 std::string fileName; 347 if (!GetTheOnlyStringParam(env, info, fileName)) { 348 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 349 std::string paramErrorMessage = "Invalid parameter, require a string parameter."; 350 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 351 return CreateUndefined(env); 352 } 353 HILOG_INFO(LOG_CORE, "filename: %{public}s.", fileName.c_str()); 354 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); 355 if (context == nullptr) { 356 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 357 return CreateErrorMessage(env, "Get ApplicationContext failed."); 358 } 359 std::string filesDir = context->GetFilesDir(); 360 if (filesDir.empty()) { 361 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 362 return CreateErrorMessage(env, "Get App files dir failed."); 363 } 364 std::string filePath = filesDir + SLASH_STR + fileName + JSON_FILE; 365 if (!IsLegalPath(filePath)) { 366 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 367 return CreateErrorMessage(env, "input fileName is illegal."); 368 } 369 if (!CreateFile(filePath)) { 370 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 371 return CreateErrorMessage(env, "file created failed."); 372 } 373 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 374 engine->StartCpuProfiler(filePath); 375 return CreateUndefined(env); 376} 377 378napi_value StopProfiling(napi_env env, napi_callback_info info) 379{ 380 ApiInvokeRecorder apiInvokeRecorder("stopProfiling"); 381 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 382 engine->StopCpuProfiler(); 383 return CreateUndefined(env); 384} 385 386napi_value StopJsCpuProfiling(napi_env env, napi_callback_info info) 387{ 388 ApiInvokeRecorder apiInvokeRecorder("stopJsCpuProfiling"); 389 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 390 engine->StopCpuProfiler(); 391 return CreateUndefined(env); 392} 393 394napi_value DumpHeapData(napi_env env, napi_callback_info info) 395{ 396 ApiInvokeRecorder apiInvokeRecorder("dumpHeapData"); 397 std::string fileName = GetFileNameParam(env, info); 398 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); 399 if (context == nullptr) { 400 return CreateErrorMessage(env, "Get ApplicationContext failed."); 401 } 402 std::string filesDir = context->GetFilesDir(); 403 if (filesDir.empty()) { 404 return CreateErrorMessage(env, "Get App files dir failed."); 405 } 406 std::string filePath = filesDir + SLASH_STR + fileName + HEAPSNAPSHOT_FILE; 407 if (!IsLegalPath(filePath)) { 408 return CreateErrorMessage(env, "input fileName is illegal."); 409 } 410 if (!CreateFile(filePath)) { 411 return CreateErrorMessage(env, "file created failed."); 412 } 413 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 414 engine->DumpHeapSnapshot(filePath, true, DumpFormat::JSON, false, true); 415 return CreateUndefined(env); 416} 417 418napi_value DumpJsHeapData(napi_env env, napi_callback_info info) 419{ 420 ApiInvokeRecorder apiInvokeRecorder("dumpJsHeapData"); 421 std::string fileName; 422 if (!GetTheOnlyStringParam(env, info, fileName)) { 423 std::string paramErrorMessage = "Invalid parameter, require a string parameter."; 424 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 425 return CreateUndefined(env); 426 } 427 HILOG_ERROR(LOG_CORE, "filename: %{public}s.", fileName.c_str()); 428 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); 429 if (context == nullptr) { 430 return CreateErrorMessage(env, "Get ApplicationContext failed."); 431 } 432 std::string filesDir = context->GetFilesDir(); 433 if (filesDir.empty()) { 434 return CreateErrorMessage(env, "Get App files dir failed."); 435 } 436 std::string filePath = filesDir + SLASH_STR + fileName + HEAPSNAPSHOT_FILE; 437 if (!IsLegalPath(filePath)) { 438 return CreateErrorMessage(env, "input fileName is illegal."); 439 } 440 if (!CreateFile(filePath)) { 441 return CreateErrorMessage(env, "file created failed."); 442 } 443 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 444 engine->DumpHeapSnapshot(filePath, true, DumpFormat::JSON, false, true); 445 return CreateUndefined(env); 446} 447 448napi_value GetPss(napi_env env, napi_callback_info info) 449{ 450 napi_value pss; 451 std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create(); 452 if (collector != nullptr) { 453 int pid = getprocpid(); 454 auto collectResult = collector->CollectProcessMemory(pid); 455 int32_t pssInfo = collectResult.data.pss + collectResult.data.swapPss; 456 napi_create_bigint_uint64(env, pssInfo, &pss); 457 } else { 458 napi_create_bigint_uint64(env, 0, &pss); 459 } 460 return pss; 461} 462 463napi_value GetSharedDirty(napi_env env, napi_callback_info info) 464{ 465 ApiInvokeRecorder apiInvokeRecorder("getSharedDirty"); 466 napi_value sharedDirty; 467 std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create(); 468 if (collector != nullptr) { 469 int pid = getprocpid(); 470 auto collectResult = collector->CollectProcessMemory(pid); 471 int32_t sharedDirtyInfo = collectResult.data.sharedDirty; 472 napi_create_bigint_uint64(env, sharedDirtyInfo, &sharedDirty); 473 } else { 474 napi_create_bigint_uint64(env, 0, &sharedDirty); 475 } 476 return sharedDirty; 477} 478 479napi_value GetPrivateDirty(napi_env env, napi_callback_info info) 480{ 481 ApiInvokeRecorder apiInvokeRecorder("getPrivateDirty"); 482 napi_value privateDirtyValue; 483 std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create(); 484 if (collector != nullptr) { 485 pid_t pid = getprocpid(); 486 auto collectResult = collector->CollectProcessMemory(pid); 487 int32_t privateDirty = collectResult.data.privateDirty; 488 napi_create_bigint_uint64(env, privateDirty, &privateDirtyValue); 489 } else { 490 napi_create_bigint_uint64(env, 0, &privateDirtyValue); 491 } 492 return privateDirtyValue; 493} 494 495napi_value GetCpuUsage(napi_env env, napi_callback_info info) 496{ 497 ApiInvokeRecorder apiInvokeRecorder("getCpuUsage"); 498 napi_value cpuUsageValue; 499 std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>(); 500 pid_t pid = getprocpid(); 501 double cpuUsage = dumpUsage->GetCpuUsage(pid); 502 napi_create_double(env, cpuUsage, &cpuUsageValue); 503 return cpuUsageValue; 504} 505 506napi_value GetNativeHeapSize(napi_env env, napi_callback_info info) 507{ 508 struct mallinfo mi = mallinfo(); 509 napi_value nativeHeapSize; 510 napi_create_bigint_uint64(env, uint64_t(mi.uordblks + mi.fordblks), &nativeHeapSize); 511 return nativeHeapSize; 512} 513 514napi_value GetNativeHeapAllocatedSize(napi_env env, napi_callback_info info) 515{ 516 ApiInvokeRecorder apiInvokeRecorder("getNativeHeapAllocatedSize"); 517 struct mallinfo mi = mallinfo(); 518 napi_value nativeHeapAllocatedSize; 519 napi_create_bigint_uint64(env, uint64_t(mi.uordblks), &nativeHeapAllocatedSize); 520 return nativeHeapAllocatedSize; 521} 522 523napi_value GetNativeHeapFreeSize(napi_env env, napi_callback_info info) 524{ 525 ApiInvokeRecorder apiInvokeRecorder("getNativeHeapFreeSize"); 526 struct mallinfo mi = mallinfo(); 527 napi_value nativeHeapFreeSize; 528 napi_create_bigint_uint64(env, uint64_t(mi.fordblks), &nativeHeapFreeSize); 529 return nativeHeapFreeSize; 530} 531 532static napi_value GetServiceDump(napi_env env, napi_callback_info info) 533{ 534 ApiInvokeRecorder apiInvokeRecorder("getServiceDump"); 535 int serviceAbilityId = 0; 536 int fd = 0; 537 std::vector<std::u16string> args; 538 if (!GetDumpParam(env, info, serviceAbilityId, fd, args)) { 539 std::string paramErrorMessage = "The parameter check failed."; 540 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 541 return CreateUndefined(env); 542 } 543 544 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 545 if (!sam) { 546 return CreateUndefined(env); 547 } 548 sptr<IRemoteObject> sa = sam->CheckSystemAbility(serviceAbilityId); 549 if (sa == nullptr) { 550 HILOG_ERROR(LOG_CORE, "no this system ability."); 551 std::string idErrorMessage = "ServiceId invalid. The system ability does not exist."; 552 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_ABILITY_NOT_FOUND).c_str(), idErrorMessage.c_str()); 553 return CreateUndefined(env); 554 } 555 int dumpResult = sa->Dump(fd, args); 556 HILOG_INFO(LOG_CORE, "Dump result: %{public}d", dumpResult); 557 return CreateUndefined(env); 558} 559 560napi_value GetVss(napi_env env, napi_callback_info info) 561{ 562 ApiInvokeRecorder apiInvokeRecorder("getVss"); 563 napi_value vss; 564 std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create(); 565 if (collector != nullptr) { 566 pid_t pid = getprocpid(); 567 auto collectResult = collector->CollectProcessVss(pid); 568 uint64_t vssInfo = collectResult.data; 569 napi_create_bigint_uint64(env, vssInfo, &vss); 570 } else { 571 napi_create_bigint_uint64(env, 0, &vss); 572 } 573 return vss; 574} 575 576static napi_value GetSystemCpuUsage(napi_env env, napi_callback_info info) 577{ 578 ApiInvokeRecorder apiInvokeRecorder("getSystemCpuUsage"); 579 auto cpuUsageOptional = HidebugNativeInterface::CreateInstance()->GetSystemCpuUsage(); 580 if (!cpuUsageOptional.has_value()) { 581 std::string paramErrorMessage = "The status of the system CPU usage is abnormal."; 582 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), paramErrorMessage.c_str()); 583 return CreateUndefined(env); 584 } 585 napi_value retMsg = nullptr; 586 napi_create_double(env, cpuUsageOptional.value(), &retMsg); 587 return retMsg; 588} 589 590static napi_value RemoveNapiWrap(napi_env env, napi_callback_info info) 591{ 592 ApiInvokeRecorder apiInvokeRecorder("removeNapiWrap"); 593 size_t argc = REMOVE_NAPI_WRAP_PARAM_COUNT; 594 napi_value argv[REMOVE_NAPI_WRAP_PARAM_COUNT] = {nullptr}; 595 napi_value thisVar = nullptr; 596 void *data = nullptr; 597 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 598 if (argc != REMOVE_NAPI_WRAP_PARAM_COUNT || 599 (!MatchValueType(env, argv[ARRAY_INDEX_FIRST], napi_object) || 600 !MatchValueType(env, argv[ARRAY_INDEX_SECOND], napi_boolean))) { 601 HILOG_DEBUG(LOG_CORE, "RemoveNapiWrap Failed to parse parameters, argc %{public}d", (int)argc); 602 std::string paramErrorMessage = "The parameter check failed."; 603 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 604 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 605 return CreateUndefined(env); 606 } 607 608 // remove jsObj's wrap 609 auto jsObj = argv[ARRAY_INDEX_FIRST]; 610 void *nativePtr = nullptr; 611 napi_remove_wrap(env, jsObj, (void **)&nativePtr); 612 613 // remove jsObj's properties wrap 614 bool needRemoveProperty = false; 615 napi_get_value_bool(env, argv[ARRAY_INDEX_SECOND], &needRemoveProperty); 616 if (needRemoveProperty) { 617 napi_value allPropertyNames = nullptr; 618 napi_object_get_keys(env, jsObj, &allPropertyNames); 619 uint32_t nameCount = 0; 620 napi_get_array_length(env, allPropertyNames, &nameCount); 621 for (size_t i = 0; i < nameCount; ++i) { 622 napi_value propertyName = nullptr; 623 napi_get_element(env, allPropertyNames, i, &propertyName); 624 char name[NAME_LEN] = {0}; 625 size_t len = 0; 626 napi_get_value_string_utf8(env, propertyName, name, NAME_LEN, &len); 627 napi_value propertyObj = nullptr; 628 napi_get_named_property(env, jsObj, name, &propertyObj); 629 napi_remove_wrap(env, propertyObj, (void **)&nativePtr); 630 } 631 } 632 return CreateUndefined(env); 633} 634 635napi_value GetAppVMMemoryInfo(napi_env env, napi_callback_info info) 636{ 637 ApiInvokeRecorder apiInvokeRecorder("getAppVMMemoryInfo"); 638 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 639 if (engine == nullptr) { 640 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 641 return CreateUndefined(env); 642 } 643 644 napi_value vMMemoryInfo; 645 napi_create_object(env, &vMMemoryInfo); 646 647 napi_value totalHeap; 648 uint64_t totalHeapValue = engine->GetHeapTotalSize(); 649 totalHeapValue = totalHeapValue >> BYTE_2_KB_SHIFT_BITS; 650 napi_create_bigint_uint64(env, totalHeapValue, &totalHeap); 651 napi_set_named_property(env, vMMemoryInfo, "totalHeap", totalHeap); 652 653 napi_value heapUsed; 654 uint64_t heapUsedValue = engine->GetHeapUsedSize(); 655 heapUsedValue = heapUsedValue >> BYTE_2_KB_SHIFT_BITS; 656 napi_create_bigint_uint64(env, heapUsedValue, &heapUsed); 657 napi_set_named_property(env, vMMemoryInfo, "heapUsed", heapUsed); 658 659 napi_value allArraySize; 660 uint64_t allArraySizeValue = engine->GetArrayBufferSize(); 661 allArraySizeValue = allArraySizeValue >> BYTE_2_KB_SHIFT_BITS; 662 napi_create_bigint_uint64(env, allArraySizeValue, &allArraySize); 663 napi_set_named_property(env, vMMemoryInfo, "allArraySize", allArraySize); 664 665 return vMMemoryInfo; 666} 667 668static void ConvertThreadCpuUsageToJs(napi_env env, napi_value &result, uint32_t threadIdValue, double cpuUsageValue) 669{ 670 napi_create_object(env, &result); 671 672 napi_value threadId; 673 napi_create_uint32(env, threadIdValue, &threadId); 674 napi_set_named_property(env, result, "threadId", threadId); 675 676 napi_value cpuUsage; 677 napi_create_double(env, cpuUsageValue, &cpuUsage); 678 napi_set_named_property(env, result, "cpuUsage", cpuUsage); 679} 680 681static void ConvertThreadCpuUsageMapToJs(napi_env env, napi_value &result, const std::map<uint32_t, double> &threadMap) 682{ 683 napi_create_array(env, &result); 684 size_t idx = 0; 685 for (const auto[threadId, cpuUsage] : threadMap) { 686 napi_value obj = nullptr; 687 ConvertThreadCpuUsageToJs(env, obj, threadId, cpuUsage); 688 napi_set_element(env, result, idx, obj); 689 idx++; 690 } 691} 692 693napi_value GetAppThreadCpuUsage(napi_env env, napi_callback_info info) 694{ 695 ApiInvokeRecorder apiInvokeRecorder("getAppThreadCpuUsage"); 696 napi_value result; 697 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 698 if (!nativeInterface) { 699 return CreateUndefined(env); 700 } 701 std::map<uint32_t, double> threadMap = nativeInterface->GetAppThreadCpuUsage(); 702 ConvertThreadCpuUsageMapToJs(env, result, threadMap); 703 return result; 704} 705 706napi_value GetAppMemoryLimit(napi_env env, napi_callback_info info) 707{ 708 ApiInvokeRecorder apiInvokeRecorder("getAppMemoryLimit"); 709 napi_value appMemoryLimit; 710 napi_create_object(env, &appMemoryLimit); 711 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 712 if (!nativeInterface) { 713 return CreateUndefined(env); 714 } 715 716 auto memoryLimit = nativeInterface->GetAppMemoryLimit(); 717 if (!memoryLimit) { 718 return CreateUndefined(env); 719 } 720 napi_value rssLimit; 721 napi_create_bigint_uint64(env, memoryLimit->rssLimit, &rssLimit); 722 napi_set_named_property(env, appMemoryLimit, "rssLimit", rssLimit); 723 724 napi_value vssLimit; 725 napi_create_bigint_uint64(env, memoryLimit->vssLimit, &vssLimit); 726 napi_set_named_property(env, appMemoryLimit, "vssLimit", vssLimit); 727 728 NativeEngine *engine = reinterpret_cast<NativeEngine *>(env); 729 if (engine == nullptr) { 730 return CreateUndefined(env); 731 } 732 napi_value vmHeapLimit; 733 uint64_t vmHeapLimitValue = engine->GetHeapLimitSize(); 734 vmHeapLimitValue = vmHeapLimitValue >> BYTE_2_KB_SHIFT_BITS; 735 napi_create_bigint_uint64(env, vmHeapLimitValue, &vmHeapLimit); 736 napi_set_named_property(env, appMemoryLimit, "vmHeapLimit", vmHeapLimit); 737 738 napi_value vmTotalHeapSize; 739 uint64_t vmTotalHeapSizeValue = engine->GetProcessHeapLimitSize(); 740 vmTotalHeapSizeValue = vmTotalHeapSizeValue >> BYTE_2_KB_SHIFT_BITS; 741 napi_create_bigint_uint64(env, vmTotalHeapSizeValue, &vmTotalHeapSize); 742 napi_set_named_property(env, appMemoryLimit, "vmTotalHeapSize", vmTotalHeapSize); 743 744 return appMemoryLimit; 745} 746 747napi_value GetAppNativeMemInfo(napi_env env, napi_callback_info info) 748{ 749 ApiInvokeRecorder apiInvokeRecorder("getAppNativeMemInfo"); 750 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 751 if (!nativeInterface) { 752 return CreateUndefined(env); 753 } 754 755 auto nativeMemInfo = nativeInterface->GetAppNativeMemInfo(); 756 if (!nativeMemInfo) { 757 return CreateUndefined(env); 758 } 759 760 napi_value memInfo; 761 napi_create_object(env, &memInfo); 762 763 napi_value pss; 764 napi_create_bigint_uint64(env, nativeMemInfo->pss, &pss); 765 napi_set_named_property(env, memInfo, "pss", pss); 766 767 napi_value rss; 768 napi_create_bigint_uint64(env, nativeMemInfo->rss, &rss); 769 napi_set_named_property(env, memInfo, "rss", rss); 770 771 napi_value sharedDirty; 772 napi_create_bigint_uint64(env, nativeMemInfo->sharedDirty, &sharedDirty); 773 napi_set_named_property(env, memInfo, "sharedDirty", sharedDirty); 774 775 napi_value privateDirty; 776 napi_create_bigint_uint64(env, nativeMemInfo->privateDirty, &privateDirty); 777 napi_set_named_property(env, memInfo, "privateDirty", privateDirty); 778 779 napi_value sharedClean; 780 napi_create_bigint_uint64(env, nativeMemInfo->sharedClean, &sharedClean); 781 napi_set_named_property(env, memInfo, "sharedClean", sharedClean); 782 783 napi_value privateClean; 784 napi_create_bigint_uint64(env, nativeMemInfo->privateClean, &privateClean); 785 napi_set_named_property(env, memInfo, "privateClean", privateClean); 786 787 napi_value vss; 788 napi_create_bigint_uint64(env, nativeMemInfo->vss, &vss); 789 napi_set_named_property(env, memInfo, "vss", vss); 790 791 return memInfo; 792} 793 794napi_value GetSystemMemInfo(napi_env env, napi_callback_info info) 795{ 796 ApiInvokeRecorder apiInvokeRecorder("getSystemMemInfo"); 797 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 798 if (!nativeInterface) { 799 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 800 return CreateUndefined(env); 801 } 802 803 auto systemMemInfo = nativeInterface->GetSystemMemInfo(); 804 if (!systemMemInfo) { 805 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 806 return CreateUndefined(env); 807 } 808 809 napi_value sysMemInfo; 810 napi_create_object(env, &sysMemInfo); 811 812 napi_value totalMem; 813 napi_create_bigint_uint64(env, systemMemInfo->memTotal, &totalMem); 814 napi_set_named_property(env, sysMemInfo, "totalMem", totalMem); 815 816 napi_value freeMem; 817 napi_create_bigint_uint64(env, systemMemInfo->memFree, &freeMem); 818 napi_set_named_property(env, sysMemInfo, "freeMem", freeMem); 819 820 napi_value availableMem; 821 napi_create_bigint_uint64(env, systemMemInfo->memAvailable, &availableMem); 822 napi_set_named_property(env, sysMemInfo, "availableMem", availableMem); 823 return sysMemInfo; 824} 825 826napi_value StartAppTraceCapture(napi_env env, napi_callback_info info) 827{ 828 ApiInvokeRecorder apiInvokeRecorder("startAppTraceCapture"); 829 napi_value result; 830 uint32_t traceFlag = 0; 831 uint32_t limitSize = 0; 832 std::vector<uint64_t> tags; 833 if (!GetTraceParam(env, info, traceFlag, limitSize, tags)) { 834 std::string paramErrorMessage = "Invalid argument"; 835 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 836 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 837 } 838 uint64_t tag = std::accumulate(tags.begin(), tags.end(), 0ull, [](uint64_t a, uint64_t b) { return a | b; }); 839 std::string file; 840 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 841 if (!nativeInterface) { 842 std::string errorMessage = "The status of the trace is abnormal"; 843 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 844 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errorMessage.c_str()); 845 return CreateUndefined(env); 846 } 847 auto ret = nativeInterface->StartAppTraceCapture(tag, traceFlag, limitSize, file); 848 if (ret == HIDEBUG_SUCCESS) { 849 napi_create_string_utf8(env, file.c_str(), NAPI_AUTO_LENGTH, &result); 850 return result; 851 } 852 if (ret == HIDEBUG_INVALID_ARGUMENT) { 853 std::string errorMessage = "Invalid argument"; 854 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 855 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), errorMessage.c_str()); 856 } 857 if (ret == HIDEBUG_TRACE_CAPTURED_ALREADY) { 858 std::string errorMessage = "Capture trace already enabled."; 859 apiInvokeRecorder.SetErrorCode(ErrorCode::HAVA_ALREADY_TRACE); 860 napi_throw_error(env, std::to_string(ErrorCode::HAVA_ALREADY_TRACE).c_str(), errorMessage.c_str()); 861 } 862 if (ret == HIDEBUG_NO_PERMISSION) { 863 std::string errorMessage = "No write permission on the file."; 864 apiInvokeRecorder.SetErrorCode(ErrorCode::WITHOUT_WRITE_PERMISSON); 865 napi_throw_error(env, std::to_string(ErrorCode::WITHOUT_WRITE_PERMISSON).c_str(), errorMessage.c_str()); 866 } 867 std::string errorMessage = "Abnormal trace status."; 868 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 869 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errorMessage.c_str()); 870 return CreateUndefined(env); 871} 872 873napi_value StopAppTraceCapture(napi_env env, napi_callback_info info) 874{ 875 ApiInvokeRecorder apiInvokeRecorder("stopAppTraceCapture"); 876 auto nativeInterface = HidebugNativeInterface::CreateInstance(); 877 if (!nativeInterface) { 878 return CreateUndefined(env); 879 } 880 auto ret = nativeInterface->StopAppTraceCapture(); 881 if (ret == HIDEBUG_TRACE_ABNORMAL) { 882 std::string errorMessage = "The status of the trace is abnormal"; 883 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 884 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errorMessage.c_str()); 885 } 886 if (ret == HIDEBUG_NO_TRACE_RUNNING) { 887 std::string errorMessage = "No capture trace running"; 888 apiInvokeRecorder.SetErrorCode(ErrorCode::NO_CAPTURE_TRACE_RUNNING); 889 napi_throw_error(env, std::to_string(ErrorCode::NO_CAPTURE_TRACE_RUNNING).c_str(), errorMessage.c_str()); 890 } 891 return CreateUndefined(env); 892} 893 894napi_value GetVMRuntimeStats(napi_env env, napi_callback_info info) 895{ 896 ApiInvokeRecorder apiInvokeRecorder("getVMRuntimeStats"); 897 napi_value vmRunTimeStats; 898 napi_create_object(env, &vmRunTimeStats); 899 for (const auto &[k, v] : GC::vmGcMap_) { 900 napi_set_named_property(env, vmRunTimeStats, k.c_str(), v(env)); 901 } 902 return vmRunTimeStats; 903} 904 905napi_value GetVMRuntimeStat(napi_env env, napi_callback_info info) 906{ 907 ApiInvokeRecorder apiInvokeRecorder("getVMRuntimeStat"); 908 std::string param; 909 if (!GetTheOnlyStringParam(env, info, param)) { 910 std::string paramErrorMessage = "Invalid parameter, a string parameter required."; 911 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 912 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 913 return CreateUndefined(env); 914 } 915 if (GC::vmGcMap_.find(param) == GC::vmGcMap_.end()) { 916 std::string paramErrorMessage = "Invalid parameter, unknown property."; 917 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str()); 918 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 919 return CreateUndefined(env); 920 } 921 return GC::vmGcMap_.at(param)(env); 922} 923 924static bool JudgeValueRange(const std::string &type, int32_t value) 925{ 926 if (limitResource.find(type) != limitResource.end()) { 927 auto limitValue = limitResource[type]; 928 if (value >= limitValue.first && value <= limitValue.second) { 929 return true; 930 } 931 } 932 return false; 933} 934 935static bool GetAppResourceLimitParam(napi_env env, napi_callback_info info, std::string& type, 936 int32_t& value, bool& enabledDebugLog) 937{ 938 const int valueNum = 3; 939 size_t argc = valueNum; 940 napi_value argv[valueNum] = { nullptr }; 941 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); 942 if (argc != valueNum) { 943 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Invalid numbers of params!"); 944 return false; 945 } 946 if (!MatchValueType(env, argv[FIRST_POS], napi_string) && 947 !MatchValueType(env, argv[SECOND_POS], napi_number) && 948 !MatchValueType(env, argv[THIRD_POS], napi_boolean)) { 949 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam params type error."); 950 return false; 951 } 952 size_t bufLen = 0; 953 napi_status status = napi_get_value_string_utf8(env, argv[FIRST_POS], nullptr, 0, &bufLen); 954 if (status != napi_ok) { 955 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Get input filename param length failed."); 956 return false; 957 } 958 const int bufMax = 128; 959 if (bufLen > bufMax || bufLen == 0) { 960 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. input filename param length is illegal."); 961 return false; 962 } 963 std::vector<char> buf(bufLen + 1, 0); 964 napi_get_value_string_utf8(env, argv[FIRST_POS], buf.data(), bufLen + 1, &bufLen); 965 type = std::string(buf.data()); 966 if (type.empty()) { 967 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Resource type is invalid."); 968 return false; 969 } 970 auto findType = std::find(RESOURCE_TYPE_LIST.begin(), RESOURCE_TYPE_LIST.end(), type); 971 if (findType == RESOURCE_TYPE_LIST.end()) { 972 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Resource type is invalid."); 973 return false; 974 } 975 if (napi_get_value_int32(env, argv[SECOND_POS], &value) != napi_ok || value < 0) { 976 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Input value error."); 977 return false; 978 } 979 if (!JudgeValueRange(type, value)) { 980 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. The value range is invalid."); 981 return false; 982 } 983 if (napi_get_value_bool(env, argv[THIRD_POS], &enabledDebugLog) != napi_ok) { 984 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Get input enabledDebugLog failed."); 985 return false; 986 } 987 return true; 988} 989 990static bool CreateSanBoxDir() 991{ 992 constexpr mode_t defaultLogDirMode = 0x0770; 993 const std::string reourceLimitDir = "/data/storage/el2/log/resourcelimit/"; 994 if (!OHOS::FileExists(reourceLimitDir)) { 995 OHOS::ForceCreateDirectory(reourceLimitDir); 996 OHOS::ChangeModeDirectory(reourceLimitDir, defaultLogDirMode); 997 } 998 if (OHOS::StorageDaemon::AclSetAccess(reourceLimitDir, "g:1201:rwx") != 0) { 999 HILOG_ERROR(LOG_CORE, "CreateSanBoxDir Failed to AclSetAccess"); 1000 return false; 1001 } 1002 return true; 1003} 1004 1005static bool CheckVersionType(const std::string& type, const std::string& key) 1006{ 1007 auto versionType = OHOS::system::GetParameter(key, "unknown"); 1008 return (versionType.find(type) != std::string::npos); 1009} 1010 1011napi_value SetAppResourceLimit(napi_env env, napi_callback_info info) 1012{ 1013 ApiInvokeRecorder apiInvokeRecorder("setAppResourceLimit"); 1014 if (!CheckVersionType("beta", KEY_HIVIEW_USER_TYPE) && 1015 !CheckVersionType("enable", KEY_HIVIEW_DEVELOP_TYPE)) { 1016 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. Not developer options or beta versions"); 1017 apiInvokeRecorder.SetErrorCode(ErrorCode::VERSION_ERROR); 1018 return CreateUndefined(env); 1019 } 1020 std::string type = ""; 1021 int32_t value = 0; 1022 bool enabledDebugLog = false; 1023 if (!GetAppResourceLimitParam(env, info, type, value, enabledDebugLog)) { 1024 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR); 1025 return CreateUndefined(env); 1026 } 1027 if (type == "js_heap") { // js_heap set value 1028 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 1029 engine->SetJsDumpThresholds(value); 1030 } 1031 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 1032 if (!abilityManager) { 1033 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_ABILITY_NOT_FOUND); 1034 return CreateUndefined(env); 1035 } 1036 sptr<IRemoteObject> remoteObject = abilityManager->CheckSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID); 1037 if (remoteObject == nullptr) { 1038 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. No this system ability."); 1039 std::string idErrorMessage = "system ability is not exist."; 1040 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), idErrorMessage.c_str()); 1041 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 1042 return CreateUndefined(env); 1043 } 1044 auto result = HidebugNativeInterface::CreateInstance()->GetMemoryLeakResource(type, value, enabledDebugLog); 1045 if (result == MemoryState::MEMORY_FAILED) { 1046 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 1047 return CreateUndefined(env); 1048 } 1049 CreateSanBoxDir(); 1050 return CreateUndefined(env); 1051} 1052 1053napi_value IsDebugState(napi_env env, napi_callback_info info) 1054{ 1055 ApiInvokeRecorder apiInvokeRecorder("isDebugState"); 1056 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env); 1057 if (engine == nullptr) { 1058 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 1059 return CreateUndefined(env); 1060 } 1061 1062 bool debugState = engine->GetIsDebugModeEnabled() || 1063 HidebugNativeInterface::CreateInstance()->IsDebuggerConnected(); 1064 1065 napi_value result = nullptr; 1066 napi_get_boolean(env, debugState, &result); 1067 return result; 1068} 1069 1070 1071class GraphicAsyncTask : public AsyncTask { 1072public: 1073 GraphicAsyncTask() : AsyncTask("graphicAsyncTask"), apiInvokeRecorder_("getGraphicsMemory") {} 1074 1075protected: 1076 void Work(napi_env env) override 1077 { 1078 result_ = HidebugNativeInterface::CreateInstance()->GetGraphicsMemory(); 1079 } 1080 1081 void Done(napi_env env, napi_status status) override 1082 { 1083 if (result_.has_value()) { 1084 napi_value ret; 1085 napi_create_int32(env, result_.value(), &ret); 1086 napi_resolve_deferred(env, deferred_, ret); 1087 } else { 1088 constexpr const char* errMsg = "Failed to get the application memory due to a remote exception"; 1089 apiInvokeRecorder_.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 1090 napi_reject_deferred(env, deferred_, 1091 CreateErrorMessage(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL), errMsg)); 1092 } 1093 } 1094 1095private: 1096 std::optional<int> result_{}; 1097 ApiInvokeRecorder apiInvokeRecorder_; 1098}; 1099 1100napi_value GetGraphicsMemory(napi_env env, napi_callback_info info) 1101{ 1102 return AsyncTask::GetPromise<GraphicAsyncTask>(env); 1103} 1104 1105napi_value GetGraphicsMemorySync(napi_env env, napi_callback_info info) 1106{ 1107 ApiInvokeRecorder apiInvokeRecorder("getGraphicsMemorySync"); 1108 std::optional<int32_t> result = HidebugNativeInterface::CreateInstance()->GetGraphicsMemory(); 1109 if (result.has_value()) { 1110 napi_value ret; 1111 napi_create_int32(env, result.value(), &ret); 1112 return ret; 1113 } 1114 constexpr const char* errMsg = "Failed to get the application memory due to a remote exception"; 1115 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errMsg); 1116 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL); 1117 return CreateUndefined(env); 1118} 1119 1120napi_value DeclareHiDebugInterface(napi_env env, napi_value exports) 1121{ 1122 ApiInvokeRecorder::InitProcessor(); 1123 napi_property_descriptor desc[] = { 1124 DECLARE_NAPI_FUNCTION("startProfiling", StartProfiling), 1125 DECLARE_NAPI_FUNCTION("stopProfiling", StopProfiling), 1126 DECLARE_NAPI_FUNCTION("dumpHeapData", DumpHeapData), 1127 DECLARE_NAPI_FUNCTION("startJsCpuProfiling", StartJsCpuProfiling), 1128 DECLARE_NAPI_FUNCTION("stopJsCpuProfiling", StopJsCpuProfiling), 1129 DECLARE_NAPI_FUNCTION("dumpJsHeapData", DumpJsHeapData), 1130 DECLARE_NAPI_FUNCTION("getPss", GetPss), 1131 DECLARE_NAPI_FUNCTION("getSharedDirty", GetSharedDirty), 1132 DECLARE_NAPI_FUNCTION("getPrivateDirty", GetPrivateDirty), 1133 DECLARE_NAPI_FUNCTION("getCpuUsage", GetCpuUsage), 1134 DECLARE_NAPI_FUNCTION("getServiceDump", GetServiceDump), 1135 DECLARE_NAPI_FUNCTION("getNativeHeapSize", GetNativeHeapSize), 1136 DECLARE_NAPI_FUNCTION("getNativeHeapAllocatedSize", GetNativeHeapAllocatedSize), 1137 DECLARE_NAPI_FUNCTION("getNativeHeapFreeSize", GetNativeHeapFreeSize), 1138 DECLARE_NAPI_FUNCTION("getVss", GetVss), 1139 DECLARE_NAPI_FUNCTION("removeNapiWrap", RemoveNapiWrap), 1140 DECLARE_NAPI_FUNCTION("getAppVMMemoryInfo", GetAppVMMemoryInfo), 1141 DECLARE_NAPI_FUNCTION("getAppThreadCpuUsage", GetAppThreadCpuUsage), 1142 DECLARE_NAPI_FUNCTION("getSystemCpuUsage", GetSystemCpuUsage), 1143 DECLARE_NAPI_FUNCTION("getAppMemoryLimit", GetAppMemoryLimit), 1144 DECLARE_NAPI_FUNCTION("getAppNativeMemInfo", GetAppNativeMemInfo), 1145 DECLARE_NAPI_FUNCTION("getSystemMemInfo", GetSystemMemInfo), 1146 DECLARE_NAPI_FUNCTION("startAppTraceCapture", StartAppTraceCapture), 1147 DECLARE_NAPI_FUNCTION("stopAppTraceCapture", StopAppTraceCapture), 1148 DECLARE_NAPI_FUNCTION("getVMRuntimeStats", GetVMRuntimeStats), 1149 DECLARE_NAPI_FUNCTION("getVMRuntimeStat", GetVMRuntimeStat), 1150 DECLARE_NAPI_FUNCTION("setAppResourceLimit", SetAppResourceLimit), 1151 DECLARE_NAPI_FUNCTION("isDebugState", IsDebugState), 1152 DECLARE_NAPI_FUNCTION("getGraphicsMemory", GetGraphicsMemory), 1153 DECLARE_NAPI_FUNCTION("getGraphicsMemorySync", GetGraphicsMemorySync), 1154 }; 1155 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 1156 InitNapiClass(env, exports); 1157 return exports; 1158} 1159 1160static napi_module hidebugModule = { 1161 .nm_version = 1, 1162 .nm_flags = 0, 1163 .nm_filename = nullptr, 1164 .nm_register_func = HiviewDFX::DeclareHiDebugInterface, 1165 .nm_modname = "hidebug", 1166 .nm_priv = ((void *)0), 1167 .reserved = {0} 1168}; 1169 1170extern "C" __attribute__((constructor)) void HiDebugRegisterModule(void) 1171{ 1172 napi_module_register(&hidebugModule); 1173} 1174} // HiviewDFX 1175} // OHOS 1176