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
51 namespace OHOS {
52 namespace HiviewDFX {
53 namespace {
54 #undef LOG_DOMAIN
55 #define LOG_DOMAIN 0xD002D0A
56 #undef LOG_TAG
57 #define LOG_TAG "HiDebug_NAPI"
58 constexpr int ONE_VALUE_LIMIT = 1;
59 constexpr int ARRAY_INDEX_FIRST = 0;
60 constexpr int ARRAY_INDEX_SECOND = 1;
61 constexpr int REMOVE_NAPI_WRAP_PARAM_COUNT = 2;
62 constexpr int NAME_LEN = 128;
63 constexpr int BYTE_2_KB_SHIFT_BITS = 10;
64 constexpr int FIRST_POS = 0;
65 constexpr int SECOND_POS = 1;
66 constexpr int THIRD_POS = 2;
67 constexpr int PSS_MIN = 1024;
68 constexpr int PSS_MAX = 4 * 1024 * 1024;
69 constexpr int JS_MIN = 85;
70 constexpr int JS_MAX = 95;
71 constexpr int FD_MIN = 10;
72 constexpr int FD_MAX = 10000;
73 constexpr int THREAD_MIN = 1;
74 constexpr int THREAD_MAX = 1000;
75 const std::string SLASH_STR = "/";
76 const std::string DEFAULT_FILENAME = "undefined";
77 const std::string JSON_FILE = ".json";
78 const std::string HEAPSNAPSHOT_FILE = ".heapsnapshot";
79 const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype";
80 const std::string KEY_HIVIEW_DEVELOP_TYPE = "persist.hiview.leak_detector";
81 enum 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
92 const std::unordered_set<std::string> RESOURCE_TYPE_LIST{
93 "pss_memory",
94 "js_heap",
95 "fd",
96 "thread"
97 };
98 static 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
MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)104 static 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
CreateFile(const std::string &path)111 static 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
IsLegalPath(const std::string& path)130 static 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
IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize)139 static 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
GetDumpParam(napi_env env, napi_callback_info info, int& serviceId, int& fd, std::vector<std::u16string>& args)152 static 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
GetFileNameParam(napi_env env, napi_callback_info info)204 static 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
GetTheOnlyStringParam(napi_env env, napi_callback_info info, std::string &fileName)236 static 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
GetTraceParam(napi_env env, napi_callback_info info, uint32_t& traceFlag, uint32_t& limitSize, std::vector<uint64_t>& tags)268 static 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
StartProfiling(napi_env env, napi_callback_info info)315 napi_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
StartJsCpuProfiling(napi_env env, napi_callback_info info)343 napi_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
StopProfiling(napi_env env, napi_callback_info info)378 napi_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
StopJsCpuProfiling(napi_env env, napi_callback_info info)386 napi_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
DumpHeapData(napi_env env, napi_callback_info info)394 napi_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
DumpJsHeapData(napi_env env, napi_callback_info info)418 napi_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
GetPss(napi_env env, napi_callback_info info)448 napi_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
GetSharedDirty(napi_env env, napi_callback_info info)463 napi_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
GetPrivateDirty(napi_env env, napi_callback_info info)479 napi_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
GetCpuUsage(napi_env env, napi_callback_info info)495 napi_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
GetNativeHeapSize(napi_env env, napi_callback_info info)506 napi_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
GetNativeHeapAllocatedSize(napi_env env, napi_callback_info info)514 napi_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
GetNativeHeapFreeSize(napi_env env, napi_callback_info info)523 napi_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
GetServiceDump(napi_env env, napi_callback_info info)532 static 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
GetVss(napi_env env, napi_callback_info info)560 napi_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
GetSystemCpuUsage(napi_env env, napi_callback_info info)576 static 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
RemoveNapiWrap(napi_env env, napi_callback_info info)590 static 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
GetAppVMMemoryInfo(napi_env env, napi_callback_info info)635 napi_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
ConvertThreadCpuUsageToJs(napi_env env, napi_value &result, uint32_t threadIdValue, double cpuUsageValue)668 static 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
ConvertThreadCpuUsageMapToJs(napi_env env, napi_value &result, const std::map<uint32_t, double> &threadMap)681 static 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
GetAppThreadCpuUsage(napi_env env, napi_callback_info info)693 napi_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
GetAppMemoryLimit(napi_env env, napi_callback_info info)706 napi_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
GetAppNativeMemInfo(napi_env env, napi_callback_info info)747 napi_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
GetSystemMemInfo(napi_env env, napi_callback_info info)794 napi_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
StartAppTraceCapture(napi_env env, napi_callback_info info)826 napi_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
StopAppTraceCapture(napi_env env, napi_callback_info info)873 napi_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
GetVMRuntimeStats(napi_env env, napi_callback_info info)894 napi_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
GetVMRuntimeStat(napi_env env, napi_callback_info info)905 napi_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
JudgeValueRange(const std::string &type, int32_t value)924 static 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
GetAppResourceLimitParam(napi_env env, napi_callback_info info, std::string& type, int32_t& value, bool& enabledDebugLog)935 static 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
CreateSanBoxDir()990 static 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
CheckVersionType(const std::string& type, const std::string& key)1005 static 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
SetAppResourceLimit(napi_env env, napi_callback_info info)1011 napi_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
IsDebugState(napi_env env, napi_callback_info info)1053 napi_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
1071 class GraphicAsyncTask : public AsyncTask {
1072 public:
GraphicAsyncTask()1073 GraphicAsyncTask() : AsyncTask("graphicAsyncTask"), apiInvokeRecorder_("getGraphicsMemory") {}
1074
1075 protected:
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
1095 private:
1096 std::optional<int> result_{};
1097 ApiInvokeRecorder apiInvokeRecorder_;
1098 };
1099
GetGraphicsMemory(napi_env env, napi_callback_info info)1100 napi_value GetGraphicsMemory(napi_env env, napi_callback_info info)
1101 {
1102 return AsyncTask::GetPromise<GraphicAsyncTask>(env);
1103 }
1104
GetGraphicsMemorySync(napi_env env, napi_callback_info info)1105 napi_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
DeclareHiDebugInterface(napi_env env, napi_value exports)1120 napi_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
1160 static 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
HiDebugRegisterModule(void)1170 extern "C" __attribute__((constructor)) void HiDebugRegisterModule(void)
1171 {
1172 napi_module_register(&hidebugModule);
1173 }
1174 } // HiviewDFX
1175 } // OHOS
1176