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