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