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 <codecvt>
17 #include <string>
18 #include <malloc.h>
19 #include <parameters.h>
20
21 #include "application_context.h"
22 #include "context.h"
23 #include "directory_ex.h"
24 #include "faultlogger_client.h"
25 #include "file_ex.h"
26 #include "hiappevent_util.h"
27 #include "hidebug_native_interface.h"
28 #include "hidebug_util.h"
29 #include "hilog/log.h"
30 #include "iservice_registry.h"
31 #include "napi_hidebug_dump.h"
32 #include "napi_hidebug_init.h"
33 #include "napi/native_api.h"
34 #include "napi/native_node_api.h"
35 #include "native_engine/native_engine.h"
36 #include "refbase.h"
37 #include "system_ability_definition.h"
38 #include "napi_hidebug_vm.h"
39 #include "napi_util.h"
40 #include "error_code.h"
41
42 namespace OHOS {
43 namespace HiviewDFX {
44 namespace {
45 #undef LOG_DOMAIN
46 #define LOG_DOMAIN 0xD002D0A
47 #undef LOG_TAG
48 #define LOG_TAG "HiDebug_NAPI"
49 constexpr int REMOVE_NAPI_WRAP_PARAM_COUNT = 2;
50 constexpr int NAME_LEN = 128;
51 constexpr int BYTE_2_KB_SHIFT_BITS = 10;
52 constexpr int FIRST_POS = 0;
53 constexpr int SECOND_POS = 1;
54 constexpr int THIRD_POS = 2;
55 constexpr int TRIM_LEVEL_MAX = 1;
56 constexpr int ENABLE_ARGS_NO_PARAMS = 0;
57 constexpr int ENABLE_ARGS_ONE_PARAMS = 1;
58 constexpr int ENABLE_ARGS_TWO_PARAMS = 2;
59 constexpr double DEFAULT_SAMPLE_RATE = 2500;
60 constexpr double DEFAULT_MAX_SIMUTANEOUS_ALLOCATIONS = 1000;
61 constexpr int DEFAULT_DURATION = 7;
62 constexpr auto SLASH_STR = "/";
63 constexpr auto JSON_FILE = ".json";
64 constexpr auto KEY_HIVIEW_DEVELOP_TYPE = "persist.hiview.leak_detector";
65
66 struct GwpAsanParams {
67 bool alwaysEnabled = false;
68 double sampleRate = DEFAULT_SAMPLE_RATE;
69 double maxSimutaneousAllocations = DEFAULT_MAX_SIMUTANEOUS_ALLOCATIONS;
70 int32_t duration = DEFAULT_DURATION;
71 };
72 }
73
GetDumpParam(napi_env env,napi_callback_info info,int & serviceId,int & fd,std::vector<std::u16string> & args)74 static bool GetDumpParam(napi_env env, napi_callback_info info,
75 int& serviceId, int& fd, std::vector<std::u16string>& args)
76 {
77 constexpr int valueNum = 3;
78 size_t argc = valueNum;
79 napi_value argv[valueNum] = {nullptr};
80 napi_value thisVar = nullptr;
81 void *data = nullptr;
82 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
83 if (argc != valueNum) {
84 HILOG_ERROR(LOG_CORE, "invalid number = %{public}zu of params.", argc);
85 return false;
86 }
87 if (!GetNapiInt32Value(env, argv[FIRST_POS], serviceId)) {
88 HILOG_ERROR(LOG_CORE, "Get input serviceId failed.");
89 return false;
90 }
91 if (!GetNapiInt32Value(env, argv[SECOND_POS], fd)) {
92 HILOG_ERROR(LOG_CORE, "Get input fd failed.");
93 return false;
94 }
95 uint32_t arraySize = 0;
96 if (!GetNapiArrayLength(env, argv[THIRD_POS], arraySize)) {
97 HILOG_ERROR(LOG_CORE, "Get input args failed.");
98 return false;
99 }
100 for (uint32_t i = 0; i < arraySize; i++) {
101 napi_value jsValue = nullptr;
102 if (napi_get_element(env, argv[THIRD_POS], i, &jsValue) != napi_ok) {
103 HILOG_ERROR(LOG_CORE, "get_element -> Get input args failed.");
104 return false;
105 }
106 const size_t bufSize = 256;
107 size_t bufLen = 0;
108 char buf[bufSize] = {0};
109 if (napi_get_value_string_utf8(env, jsValue, buf, bufSize - 1, &bufLen) != napi_ok) {
110 HILOG_ERROR(LOG_CORE, "get_value -> Get input args failed.");
111 return false;
112 }
113 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> strCnv;
114 args.push_back(strCnv.from_bytes(buf));
115 }
116 return true;
117 }
118
GetTraceParam(napi_env env,napi_callback_info info,uint32_t & traceFlag,uint32_t & limitSize,std::vector<uint64_t> & tags)119 static bool GetTraceParam(napi_env env, napi_callback_info info,
120 uint32_t& traceFlag, uint32_t& limitSize, std::vector<uint64_t>& tags)
121 {
122 constexpr int valueNum = 3;
123 size_t argc = valueNum;
124 napi_value argv[valueNum] = {nullptr};
125 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
126 if (argc != valueNum) {
127 HILOG_ERROR(LOG_CORE, "invalid numbers of params!");
128 return false;
129 }
130 uint32_t arraySize = 0;
131 if (!GetNapiArrayLength(env, argv[FIRST_POS], arraySize)) {
132 HILOG_ERROR(LOG_CORE, "Get input tags failed.");
133 return false;
134 }
135 uint64_t tag = 0;
136 bool lossless = true;
137 for (uint32_t i = 0; i < arraySize; ++i) {
138 napi_value jsValue = nullptr;
139 if (napi_get_element(env, argv[FIRST_POS], i, &jsValue) != napi_ok) {
140 HILOG_ERROR(LOG_CORE, "get_element -> Get input tags failed.");
141 return false;
142 }
143 if (napi_get_value_bigint_uint64(env, jsValue, &tag, &lossless) != napi_ok) {
144 HILOG_ERROR(LOG_CORE, "Get input tags failed.");
145 return false;
146 }
147 tags.push_back(tag);
148 }
149 if (!GetNapiUint32Value(env, argv[SECOND_POS], traceFlag)) {
150 HILOG_ERROR(LOG_CORE, "Get input traceFlag failed.");
151 return false;
152 }
153 if (!GetNapiUint32Value(env, argv[THIRD_POS], limitSize)) {
154 HILOG_ERROR(LOG_CORE, "Get input limitSize failed.");
155 return false;
156 }
157 return true;
158 }
159
StartProfiling(napi_env env,napi_callback_info info)160 napi_value StartProfiling(napi_env env, napi_callback_info info)
161 {
162 ApiInvokeRecorder apiInvokeRecorder("startProfiling");
163 std::string fileName = GetFileNameParam(env, info);
164 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext();
165 if (context == nullptr) {
166 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
167 return CreateErrorMessage(env, "Get ApplicationContext failed.");
168 }
169 std::string filesDir = context->GetFilesDir();
170 if (filesDir.empty()) {
171 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
172 return CreateErrorMessage(env, "Get App files dir failed.");
173 }
174 std::string filePath = filesDir + SLASH_STR + fileName + JSON_FILE;
175 if (!IsLegalPath(filePath)) {
176 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
177 return CreateErrorMessage(env, "input fileName is illegal.");
178 }
179 if (!CreateFile(filePath)) {
180 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
181 return CreateErrorMessage(env, "file created failed.");
182 }
183 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
184 engine->StartCpuProfiler(filePath);
185 return CreateUndefined(env);
186 }
187
StartJsCpuProfiling(napi_env env,napi_callback_info info)188 napi_value StartJsCpuProfiling(napi_env env, napi_callback_info info)
189 {
190 ApiInvokeRecorder apiInvokeRecorder("startJsCpuProfiling");
191 std::string fileName;
192 if (!GetTheOnlyStringParam(env, info, fileName)) {
193 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
194 std::string paramErrorMessage = "Invalid parameter, require a string parameter.";
195 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str());
196 return CreateUndefined(env);
197 }
198 HILOG_INFO(LOG_CORE, "filename: %{public}s.", fileName.c_str());
199 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext();
200 if (context == nullptr) {
201 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
202 return CreateErrorMessage(env, "Get ApplicationContext failed.");
203 }
204 std::string filesDir = context->GetFilesDir();
205 if (filesDir.empty()) {
206 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
207 return CreateErrorMessage(env, "Get App files dir failed.");
208 }
209 std::string filePath = filesDir + SLASH_STR + fileName + JSON_FILE;
210 if (!IsLegalPath(filePath)) {
211 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
212 return CreateErrorMessage(env, "input fileName is illegal.");
213 }
214 if (!CreateFile(filePath)) {
215 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
216 return CreateErrorMessage(env, "file created failed.");
217 }
218 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
219 engine->StartCpuProfiler(filePath);
220 return CreateUndefined(env);
221 }
222
StopProfiling(napi_env env,napi_callback_info info)223 napi_value StopProfiling(napi_env env, napi_callback_info info)
224 {
225 ApiInvokeRecorder apiInvokeRecorder("stopProfiling");
226 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
227 engine->StopCpuProfiler();
228 return CreateUndefined(env);
229 }
230
StopJsCpuProfiling(napi_env env,napi_callback_info info)231 napi_value StopJsCpuProfiling(napi_env env, napi_callback_info info)
232 {
233 ApiInvokeRecorder apiInvokeRecorder("stopJsCpuProfiling");
234 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
235 engine->StopCpuProfiler();
236 return CreateUndefined(env);
237 }
238
GetPss(napi_env env,napi_callback_info info)239 napi_value GetPss(napi_env env, napi_callback_info info)
240 {
241 napi_value retValue = nullptr;
242 auto memInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false);
243 napi_create_bigint_uint64(env, memInfoOption ? static_cast<uint64_t>(memInfoOption->pss) : 0, &retValue);
244 return retValue;
245 }
246
GetSharedDirty(napi_env env,napi_callback_info info)247 napi_value GetSharedDirty(napi_env env, napi_callback_info info)
248 {
249 ApiInvokeRecorder apiInvokeRecorder("getSharedDirty");
250 napi_value retValue = nullptr;
251 auto memInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false);
252 napi_create_bigint_uint64(env, memInfoOption ? static_cast<uint64_t>(memInfoOption->sharedDirty) : 0, &retValue);
253 return retValue;
254 }
255
GetPrivateDirty(napi_env env,napi_callback_info info)256 napi_value GetPrivateDirty(napi_env env, napi_callback_info info)
257 {
258 ApiInvokeRecorder apiInvokeRecorder("getPrivateDirty");
259 napi_value retValue = nullptr;
260 auto memInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false);
261 napi_create_bigint_uint64(env, memInfoOption ? static_cast<uint64_t>(memInfoOption->privateDirty) : 0, &retValue);
262 return retValue;
263 }
264
GetCpuUsage(napi_env env,napi_callback_info info)265 napi_value GetCpuUsage(napi_env env, napi_callback_info info)
266 {
267 constexpr uint32_t reportTimeOutSec = 5 * 60;
268 constexpr uint32_t limitSize = 100;
269 static MultipleRecordReporter multipleRecordReporter(reportTimeOutSec, limitSize);
270 ApiInvokeRecorder apiInvokeRecorder("getCpuUsage", multipleRecordReporter);
271 double cpuUsage = HidebugNativeInterface::GetInstance().GetCpuUsage();
272 napi_value retValue = nullptr;
273 napi_create_double(env, cpuUsage, &retValue);
274 return retValue;
275 }
276
GetNativeHeapSize(napi_env env,napi_callback_info info)277 napi_value GetNativeHeapSize(napi_env env, napi_callback_info info)
278 {
279 struct mallinfo mi = mallinfo();
280 napi_value retValue = nullptr;
281 napi_create_bigint_uint64(env, uint64_t(mi.uordblks + mi.fordblks), &retValue);
282 return retValue;
283 }
284
GetNativeHeapAllocatedSize(napi_env env,napi_callback_info info)285 napi_value GetNativeHeapAllocatedSize(napi_env env, napi_callback_info info)
286 {
287 ApiInvokeRecorder apiInvokeRecorder("getNativeHeapAllocatedSize");
288 struct mallinfo mi = mallinfo();
289 napi_value retValue = nullptr;
290 napi_create_bigint_uint64(env, uint64_t(mi.uordblks), &retValue);
291 return retValue;
292 }
293
GetNativeHeapFreeSize(napi_env env,napi_callback_info info)294 napi_value GetNativeHeapFreeSize(napi_env env, napi_callback_info info)
295 {
296 ApiInvokeRecorder apiInvokeRecorder("getNativeHeapFreeSize");
297 struct mallinfo mi = mallinfo();
298 napi_value retValue = nullptr;
299 napi_create_bigint_uint64(env, uint64_t(mi.fordblks), &retValue);
300 return retValue;
301 }
302
GetServiceDump(napi_env env,napi_callback_info info)303 static napi_value GetServiceDump(napi_env env, napi_callback_info info)
304 {
305 ApiInvokeRecorder apiInvokeRecorder("getServiceDump");
306 int serviceAbilityId = 0;
307 int fd = 0;
308 std::vector<std::u16string> args;
309 if (!GetDumpParam(env, info, serviceAbilityId, fd, args)) {
310 std::string paramErrorMessage = "The parameter check failed.";
311 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str());
312 return CreateUndefined(env);
313 }
314
315 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
316 if (!sam) {
317 return CreateUndefined(env);
318 }
319 sptr<IRemoteObject> sa = sam->CheckSystemAbility(serviceAbilityId);
320 if (sa == nullptr) {
321 HILOG_ERROR(LOG_CORE, "no this system ability.");
322 std::string idErrorMessage = "ServiceId invalid. The system ability does not exist.";
323 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_ABILITY_NOT_FOUND).c_str(), idErrorMessage.c_str());
324 return CreateUndefined(env);
325 }
326 int dumpResult = sa->Dump(fd, args);
327 HILOG_INFO(LOG_CORE, "Dump result: %{public}d", dumpResult);
328 return CreateUndefined(env);
329 }
330
GetVss(napi_env env,napi_callback_info info)331 napi_value GetVss(napi_env env, napi_callback_info info)
332 {
333 ApiInvokeRecorder apiInvokeRecorder("getVss");
334 napi_value retValue = nullptr;
335 auto vssInfoOption = HidebugNativeInterface::GetInstance().GetVss();
336 napi_create_bigint_uint64(env, vssInfoOption ? vssInfoOption.value() : 0, &retValue);
337 return retValue;
338 }
339
GetSystemCpuUsage(napi_env env,napi_callback_info info)340 static napi_value GetSystemCpuUsage(napi_env env, napi_callback_info info)
341 {
342 constexpr uint32_t reportTimeOutSec = 5 * 60;
343 constexpr uint32_t limitSize = 100;
344 static MultipleRecordReporter multipleRecordReporter(reportTimeOutSec, limitSize);
345 ApiInvokeRecorder apiInvokeRecorder("getSystemCpuUsage", multipleRecordReporter);
346 auto cpuUsageOptional = HidebugNativeInterface::GetInstance().GetSystemCpuUsage();
347 if (!cpuUsageOptional) {
348 std::string paramErrorMessage = "The status of the system CPU usage is abnormal.";
349 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), paramErrorMessage.c_str());
350 return CreateUndefined(env);
351 }
352 napi_value retMsg = nullptr;
353 napi_create_double(env, cpuUsageOptional.value(), &retMsg);
354 return retMsg;
355 }
356
RemoveNapiWrap(napi_env env,napi_callback_info info)357 static napi_value RemoveNapiWrap(napi_env env, napi_callback_info info)
358 {
359 size_t argc = REMOVE_NAPI_WRAP_PARAM_COUNT;
360 napi_value argv[REMOVE_NAPI_WRAP_PARAM_COUNT] = {nullptr};
361 napi_value thisVar = nullptr;
362 void *data = nullptr;
363 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
364 if (argc != REMOVE_NAPI_WRAP_PARAM_COUNT ||
365 (!MatchValueType(env, argv[FIRST_POS], napi_object) ||
366 !MatchValueType(env, argv[SECOND_POS], napi_boolean))) {
367 HILOG_DEBUG(LOG_CORE, "RemoveNapiWrap Failed to parse parameters, argc %{public}d", (int)argc);
368 std::string paramErrorMessage = "The parameter check failed.";
369 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage.c_str());
370 return CreateUndefined(env);
371 }
372
373 // remove jsObj's wrap
374 auto jsObj = argv[FIRST_POS];
375 void *nativePtr = nullptr;
376 napi_remove_wrap(env, jsObj, (void **)&nativePtr);
377
378 // remove jsObj's properties wrap
379 bool needRemoveProperty = false;
380 napi_get_value_bool(env, argv[SECOND_POS], &needRemoveProperty);
381 if (needRemoveProperty) {
382 napi_value allPropertyNames = nullptr;
383 napi_object_get_keys(env, jsObj, &allPropertyNames);
384 uint32_t nameCount = 0;
385 napi_get_array_length(env, allPropertyNames, &nameCount);
386 for (size_t i = 0; i < nameCount; ++i) {
387 napi_value propertyName = nullptr;
388 napi_get_element(env, allPropertyNames, i, &propertyName);
389 char name[NAME_LEN] = {0};
390 size_t len = 0;
391 napi_get_value_string_utf8(env, propertyName, name, NAME_LEN, &len);
392 napi_value propertyObj = nullptr;
393 napi_get_named_property(env, jsObj, name, &propertyObj);
394 napi_remove_wrap(env, propertyObj, (void **)&nativePtr);
395 }
396 }
397 return CreateUndefined(env);
398 }
399
GetAppVMMemoryInfo(napi_env env,napi_callback_info info)400 napi_value GetAppVMMemoryInfo(napi_env env, napi_callback_info info)
401 {
402 ApiInvokeRecorder apiInvokeRecorder("getAppVMMemoryInfo");
403 uint64_t allArraySizeValue{0};
404 uint64_t heapUsedValue{0};
405 uint64_t totalHeapValue{0};
406 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
407 if (engine) {
408 allArraySizeValue = engine->GetArrayBufferSize();
409 heapUsedValue = engine->GetHeapUsedSize();
410 totalHeapValue = engine->GetHeapTotalSize();
411 }
412
413 napi_value vMMemoryInfo;
414 napi_create_object(env, &vMMemoryInfo);
415
416 napi_value totalHeap;
417 totalHeapValue = totalHeapValue >> BYTE_2_KB_SHIFT_BITS;
418 napi_create_bigint_uint64(env, totalHeapValue, &totalHeap);
419 napi_set_named_property(env, vMMemoryInfo, "totalHeap", totalHeap);
420
421 napi_value heapUsed;
422 heapUsedValue = heapUsedValue >> BYTE_2_KB_SHIFT_BITS;
423 napi_create_bigint_uint64(env, heapUsedValue, &heapUsed);
424 napi_set_named_property(env, vMMemoryInfo, "heapUsed", heapUsed);
425
426 napi_value allArraySize;
427 allArraySizeValue = allArraySizeValue >> BYTE_2_KB_SHIFT_BITS;
428 napi_create_bigint_uint64(env, allArraySizeValue, &allArraySize);
429 napi_set_named_property(env, vMMemoryInfo, "allArraySize", allArraySize);
430
431 return vMMemoryInfo;
432 }
433
ConvertThreadCpuUsageToJs(napi_env env,napi_value & result,uint32_t threadIdValue,double cpuUsageValue)434 static void ConvertThreadCpuUsageToJs(napi_env env, napi_value &result, uint32_t threadIdValue, double cpuUsageValue)
435 {
436 napi_create_object(env, &result);
437
438 napi_value threadId = nullptr;
439 napi_create_uint32(env, threadIdValue, &threadId);
440 napi_set_named_property(env, result, "threadId", threadId);
441
442 napi_value cpuUsage = nullptr;
443 napi_create_double(env, cpuUsageValue, &cpuUsage);
444 napi_set_named_property(env, result, "cpuUsage", cpuUsage);
445 }
446
ConvertThreadCpuUsageMapToJs(napi_env env,napi_value & result,const std::map<uint32_t,double> & threadMap)447 static void ConvertThreadCpuUsageMapToJs(napi_env env, napi_value &result, const std::map<uint32_t, double> &threadMap)
448 {
449 napi_create_array(env, &result);
450 size_t idx = 0;
451 for (const auto& [threadId, cpuUsage] : threadMap) {
452 napi_value obj = nullptr;
453 ConvertThreadCpuUsageToJs(env, obj, threadId, cpuUsage);
454 napi_set_element(env, result, idx, obj);
455 idx++;
456 }
457 }
458
GetAppThreadCpuUsage(napi_env env,napi_callback_info info)459 napi_value GetAppThreadCpuUsage(napi_env env, napi_callback_info info)
460 {
461 ApiInvokeRecorder apiInvokeRecorder("getAppThreadCpuUsage");
462 napi_value result = nullptr;
463 std::map<uint32_t, double> threadMap = HidebugNativeInterface::GetInstance().GetAppThreadCpuUsage();
464 ConvertThreadCpuUsageMapToJs(env, result, threadMap);
465 return result;
466 }
467
GetAppMemoryLimit(napi_env env,napi_callback_info info)468 napi_value GetAppMemoryLimit(napi_env env, napi_callback_info info)
469 {
470 ApiInvokeRecorder apiInvokeRecorder("getAppMemoryLimit");
471 napi_value appMemoryLimit = nullptr;
472 napi_create_object(env, &appMemoryLimit);
473 auto memoryLimitOption = HidebugNativeInterface::GetInstance().GetAppMemoryLimit();
474 if (!memoryLimitOption) {
475 memoryLimitOption.emplace();
476 }
477 napi_value rssLimit = nullptr;
478 napi_create_bigint_uint64(env, memoryLimitOption->rssLimit, &rssLimit);
479 napi_set_named_property(env, appMemoryLimit, "rssLimit", rssLimit);
480
481 napi_value vssLimit = nullptr;
482 napi_create_bigint_uint64(env, memoryLimitOption->vssLimit, &vssLimit);
483 napi_set_named_property(env, appMemoryLimit, "vssLimit", vssLimit);
484 uint64_t vmHeapLimitValue{0};
485 uint64_t vmTotalHeapSizeValue{0};
486 NativeEngine *engine = reinterpret_cast<NativeEngine *>(env);
487 if (engine) {
488 vmHeapLimitValue = engine->GetHeapLimitSize();
489 vmTotalHeapSizeValue = engine->GetProcessHeapLimitSize();
490 }
491 napi_value vmHeapLimit = nullptr;
492 vmHeapLimitValue = vmHeapLimitValue >> BYTE_2_KB_SHIFT_BITS;
493 napi_create_bigint_uint64(env, vmHeapLimitValue, &vmHeapLimit);
494 napi_set_named_property(env, appMemoryLimit, "vmHeapLimit", vmHeapLimit);
495 napi_value vmTotalHeapSize = nullptr;
496 vmTotalHeapSizeValue = vmTotalHeapSizeValue >> BYTE_2_KB_SHIFT_BITS;
497 napi_create_bigint_uint64(env, vmTotalHeapSizeValue, &vmTotalHeapSize);
498 napi_set_named_property(env, appMemoryLimit, "vmTotalHeapSize", vmTotalHeapSize);
499 return appMemoryLimit;
500 }
501
ConvertToJsNativeMemInfo(napi_env env,const NativeMemInfo & nativeMemInfo)502 napi_value ConvertToJsNativeMemInfo(napi_env env, const NativeMemInfo& nativeMemInfo)
503 {
504 napi_value memInfo = nullptr;
505 napi_create_object(env, &memInfo);
506 napi_value pss = nullptr;
507 napi_create_bigint_uint64(env, nativeMemInfo.pss, &pss);
508 napi_set_named_property(env, memInfo, "pss", pss);
509
510 napi_value rss = nullptr;
511 napi_create_bigint_uint64(env, nativeMemInfo.rss, &rss);
512 napi_set_named_property(env, memInfo, "rss", rss);
513
514 napi_value sharedDirty = nullptr;
515 napi_create_bigint_uint64(env, nativeMemInfo.sharedDirty, &sharedDirty);
516 napi_set_named_property(env, memInfo, "sharedDirty", sharedDirty);
517
518 napi_value privateDirty = nullptr;
519 napi_create_bigint_uint64(env, nativeMemInfo.privateDirty, &privateDirty);
520 napi_set_named_property(env, memInfo, "privateDirty", privateDirty);
521
522 napi_value sharedClean = nullptr;
523 napi_create_bigint_uint64(env, nativeMemInfo.sharedClean, &sharedClean);
524 napi_set_named_property(env, memInfo, "sharedClean", sharedClean);
525
526 napi_value privateClean = nullptr;
527 napi_create_bigint_uint64(env, nativeMemInfo.privateClean, &privateClean);
528 napi_set_named_property(env, memInfo, "privateClean", privateClean);
529
530 napi_value vss = nullptr;
531 napi_create_bigint_uint64(env, nativeMemInfo.vss, &vss);
532 napi_set_named_property(env, memInfo, "vss", vss);
533 return memInfo;
534 }
535
GetAppNativeMemInfo(napi_env env,napi_callback_info info)536 napi_value GetAppNativeMemInfo(napi_env env, napi_callback_info info)
537 {
538 ApiInvokeRecorder apiInvokeRecorder("getAppNativeMemInfo");
539 auto memInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false);
540 return memInfoOption ? ConvertToJsNativeMemInfo(env, *memInfoOption) : ConvertToJsNativeMemInfo(env, {});
541 }
542
GetAppNativeMemInfoWithCache(napi_env env,napi_callback_info info)543 napi_value GetAppNativeMemInfoWithCache(napi_env env, napi_callback_info info)
544 {
545 ApiInvokeRecorder apiInvokeRecorder("getAppNativeMemInfoWithCache");
546 constexpr auto paramNum = 1;
547 size_t argc = paramNum;
548 napi_value argv = nullptr ;
549 napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
550 bool forceRefresh = false;
551 if (argc > paramNum || (argc == paramNum && !OHOS::HiviewDFX::GetNapiBoolValue(env, argv, forceRefresh))) {
552 constexpr auto paramErrorMessage = "Invalid argument";
553 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
554 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage);
555 return CreateUndefined(env);
556 }
557 auto memInfoOption = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(!forceRefresh);
558 return memInfoOption ? ConvertToJsNativeMemInfo(env, *memInfoOption) : ConvertToJsNativeMemInfo(env, {});
559 }
560
561 class GetAppNativeMemInfoAsyncTask : public AsyncTask {
562 public:
GetAppNativeMemInfoAsyncTask()563 GetAppNativeMemInfoAsyncTask() : AsyncTask("getAppNativeMemInfoAsync"),
564 apiInvokeRecorder_("getAppNativeMemInfoAsync") {}
565
566 protected:
Work(napi_env env)567 void Work(napi_env env) override
568 {
569 result_ = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo(false);
570 }
571
Done(napi_env env,napi_status status)572 void Done(napi_env env, napi_status status) override
573 {
574 napi_value ret = result_ ? ConvertToJsNativeMemInfo(env, result_.value()) : ConvertToJsNativeMemInfo(env, {});
575 napi_resolve_deferred(env, deferred_, ret);
576 }
577
578 private:
579 std::optional<NativeMemInfo> result_{};
580 ApiInvokeRecorder apiInvokeRecorder_;
581 };
582
GetAppNativeMemInfoAsync(napi_env env,napi_callback_info info)583 napi_value GetAppNativeMemInfoAsync(napi_env env, napi_callback_info info)
584 {
585 return AsyncTask::GetPromise<GetAppNativeMemInfoAsyncTask>(env);
586 }
587
GetSystemMemInfo(napi_env env,napi_callback_info info)588 napi_value GetSystemMemInfo(napi_env env, napi_callback_info info)
589 {
590 ApiInvokeRecorder apiInvokeRecorder("getSystemMemInfo");
591 auto systemMemInfoOption = HidebugNativeInterface::GetInstance().GetSystemMemInfo();
592 if (!systemMemInfoOption) {
593 systemMemInfoOption.emplace();
594 }
595 napi_value sysMemInfo = nullptr;
596 napi_create_object(env, &sysMemInfo);
597
598 napi_value totalMem = nullptr;
599 napi_create_bigint_uint64(env, static_cast<uint64_t>(systemMemInfoOption->totalMem), &totalMem);
600 napi_set_named_property(env, sysMemInfo, "totalMem", totalMem);
601
602 napi_value freeMem = nullptr;
603 napi_create_bigint_uint64(env, static_cast<uint64_t>(systemMemInfoOption->freeMem), &freeMem);
604 napi_set_named_property(env, sysMemInfo, "freeMem", freeMem);
605
606 napi_value availableMem = nullptr;
607 napi_create_bigint_uint64(env, static_cast<uint64_t>(systemMemInfoOption->availableMem), &availableMem);
608 napi_set_named_property(env, sysMemInfo, "availableMem", availableMem);
609 return sysMemInfo;
610 }
611
StartAppTraceCapture(napi_env env,napi_callback_info info)612 napi_value StartAppTraceCapture(napi_env env, napi_callback_info info)
613 {
614 ApiInvokeRecorder apiInvokeRecorder("startAppTraceCapture");
615 napi_value result = nullptr;
616 uint32_t traceFlag = 0;
617 uint32_t limitSize = 0;
618 std::vector<uint64_t> tags;
619 if (!GetTraceParam(env, info, traceFlag, limitSize, tags)) {
620 constexpr auto paramErrorMessage = "Invalid argument";
621 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
622 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), paramErrorMessage);
623 }
624 uint64_t tag = std::accumulate(tags.begin(), tags.end(), 0ull, [](uint64_t a, uint64_t b) { return a | b; });
625 std::string file;
626 auto ret = HidebugNativeInterface::GetInstance().StartAppTraceCapture(tag, traceFlag, limitSize, file);
627 if (ret == TRACE_SUCCESS) {
628 napi_create_string_utf8(env, file.c_str(), NAPI_AUTO_LENGTH, &result);
629 return result;
630 }
631 if (ret == TRACE_INVALID_ARGUMENT) {
632 constexpr auto errorMessage = "Invalid argument";
633 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
634 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(), errorMessage);
635 return CreateUndefined(env);
636 }
637 if (ret == TRACE_CAPTURED_ALREADY) {
638 constexpr auto errorMessage = "Capture trace already enabled.";
639 apiInvokeRecorder.SetErrorCode(ErrorCode::HAVA_ALREADY_TRACE);
640 napi_throw_error(env, std::to_string(ErrorCode::HAVA_ALREADY_TRACE).c_str(), errorMessage);
641 return CreateUndefined(env);
642 }
643 if (ret == TRACE_NO_PERMISSION) {
644 constexpr auto errorMessage = "No write permission on the file.";
645 apiInvokeRecorder.SetErrorCode(ErrorCode::WITHOUT_WRITE_PERMISSON);
646 napi_throw_error(env, std::to_string(ErrorCode::WITHOUT_WRITE_PERMISSON).c_str(), errorMessage);
647 return CreateUndefined(env);
648 }
649 constexpr auto errorMessage = "Abnormal trace status.";
650 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
651 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errorMessage);
652 return CreateUndefined(env);
653 }
654
StopAppTraceCapture(napi_env env,napi_callback_info info)655 napi_value StopAppTraceCapture(napi_env env, napi_callback_info info)
656 {
657 ApiInvokeRecorder apiInvokeRecorder("stopAppTraceCapture");
658 const auto ret = HidebugNativeInterface::GetInstance().StopAppTraceCapture();
659 if (ret == TRACE_ABNORMAL) {
660 std::string errorMessage = "The status of the trace is abnormal";
661 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
662 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errorMessage.c_str());
663 }
664 if (ret == NO_TRACE_RUNNING) {
665 std::string errorMessage = "No capture trace running";
666 apiInvokeRecorder.SetErrorCode(ErrorCode::NO_CAPTURE_TRACE_RUNNING);
667 napi_throw_error(env, std::to_string(ErrorCode::NO_CAPTURE_TRACE_RUNNING).c_str(), errorMessage.c_str());
668 }
669 return CreateUndefined(env);
670 }
671
JudgeValueRange(const std::string & type,int32_t value)672 static bool JudgeValueRange(const std::string &type, int32_t value)
673 {
674 if (type == "pss_memory") {
675 constexpr int pssMin = 1024;
676 constexpr int pssMax = 4 * 1024 * 1024;
677 return value >= pssMin && value <= pssMax;
678 }
679 if (type == "js_memory") {
680 constexpr int jsMin = 85;
681 constexpr int jsMax = 95;
682 return value >= jsMin && value <= jsMax;
683 }
684 if (type == "fd_memory") {
685 constexpr int fdMin = 10;
686 constexpr int fdMax = 10000;
687 return value >= fdMin && value <= fdMax;
688 }
689 if (type == "thread_memory") {
690 constexpr int threadMin = 1;
691 constexpr int threadMax = 1000;
692 return value >= threadMin && value <= threadMax;
693 }
694 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Resource type is invalid.");
695 return false;
696 }
697
GetAppResourceLimitParam(napi_env env,napi_callback_info info,std::string & type,int32_t & value,bool & enabledDebugLog)698 static bool GetAppResourceLimitParam(napi_env env, napi_callback_info info, std::string& type,
699 int32_t& value, bool& enabledDebugLog)
700 {
701 constexpr int valueNum = 3;
702 size_t argc = valueNum;
703 napi_value argv[valueNum] = { nullptr };
704 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
705 if (argc != valueNum) {
706 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Invalid numbers of params!");
707 return false;
708 }
709 constexpr int paramMaxLen = 128;
710 if (!GetNapiStringValue(env, argv[FIRST_POS], type, paramMaxLen)) {
711 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Resource type is invalid.");
712 return false;
713 }
714 if (!GetNapiInt32Value(env, argv[SECOND_POS], value)) {
715 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Input value error.");
716 return false;
717 }
718 if (!JudgeValueRange(type, value)) {
719 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. The value range is invalid.");
720 return false;
721 }
722 if (!GetNapiBoolValue(env, argv[THIRD_POS], enabledDebugLog)) {
723 HILOG_ERROR(LOG_CORE, "GetAppResourceLimitParam failed. Get input enabledDebugLog failed.");
724 return false;
725 }
726 return true;
727 }
728
SetAppResourceLimit(napi_env env,napi_callback_info info)729 napi_value SetAppResourceLimit(napi_env env, napi_callback_info info)
730 {
731 ApiInvokeRecorder apiInvokeRecorder("setAppResourceLimit");
732 CreateResourceLimitDir();
733 if (!IsBetaVersion() && !CheckVersionType("enable", KEY_HIVIEW_DEVELOP_TYPE)) {
734 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. Not developer options or beta versions");
735 apiInvokeRecorder.SetErrorCode(ErrorCode::VERSION_ERROR);
736 return CreateUndefined(env);
737 }
738 std::string type;
739 int32_t value = 0;
740 bool enabledDebugLog = false;
741 if (!GetAppResourceLimitParam(env, info, type, value, enabledDebugLog)) {
742 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
743 return CreateUndefined(env);
744 }
745 if (type == "js_heap") { // js_heap set value
746 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
747 engine->SetJsDumpThresholds(value);
748 }
749 auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
750 if (!abilityManager) {
751 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_ABILITY_NOT_FOUND);
752 return CreateUndefined(env);
753 }
754 sptr<IRemoteObject> remoteObject = abilityManager->CheckSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID);
755 if (remoteObject == nullptr) {
756 HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. No this system ability.");
757 std::string idErrorMessage = "system ability is not exist.";
758 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), idErrorMessage.c_str());
759 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
760 return CreateUndefined(env);
761 }
762 if (HidebugNativeInterface::GetInstance().GetMemoryLeakResource(type, value, enabledDebugLog) != NATIVE_SUCCESS) {
763 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
764 }
765 return CreateUndefined(env);
766 }
767
IsDebugState(napi_env env,napi_callback_info info)768 napi_value IsDebugState(napi_env env, napi_callback_info info)
769 {
770 ApiInvokeRecorder apiInvokeRecorder("isDebugState");
771 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
772 bool debugState = (engine && engine->GetIsDebugModeEnabled()) ||
773 HidebugNativeInterface::GetInstance().IsDebuggerConnected();
774 napi_value result = nullptr;
775 napi_get_boolean(env, debugState, &result);
776 return result;
777 }
778
779 class GraphicAsyncTask : public AsyncTask {
780 public:
GraphicAsyncTask()781 GraphicAsyncTask() : AsyncTask("graphicAsyncTask"), apiInvokeRecorder_("getGraphicsMemory") {}
782
783 protected:
Work(napi_env env)784 void Work(napi_env env) override
785 {
786 result_ = HidebugNativeInterface::GetInstance().GetGraphicsMemory();
787 }
788
Done(napi_env env,napi_status status)789 void Done(napi_env env, napi_status status) override
790 {
791 if (result_) {
792 napi_value ret;
793 napi_create_int32(env, result_.value(), &ret);
794 napi_resolve_deferred(env, deferred_, ret);
795 } else {
796 constexpr const char* errMsg = "Failed to get the application memory due to a remote exception";
797 apiInvokeRecorder_.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
798 napi_reject_deferred(env, deferred_,
799 CreateErrorMessage(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL), errMsg));
800 }
801 }
802
803 private:
804 std::optional<int> result_{};
805 ApiInvokeRecorder apiInvokeRecorder_;
806 };
807
GetGraphicsMemory(napi_env env,napi_callback_info info)808 napi_value GetGraphicsMemory(napi_env env, napi_callback_info info)
809 {
810 return AsyncTask::GetPromise<GraphicAsyncTask>(env);
811 }
812
GetGraphicsMemorySync(napi_env env,napi_callback_info info)813 napi_value GetGraphicsMemorySync(napi_env env, napi_callback_info info)
814 {
815 ApiInvokeRecorder apiInvokeRecorder("getGraphicsMemorySync");
816 std::optional<int32_t> result = HidebugNativeInterface::GetInstance().GetGraphicsMemory();
817 if (result) {
818 napi_value ret;
819 napi_create_int32(env, result.value(), &ret);
820 return ret;
821 }
822 constexpr const char* errMsg = "Failed to get the application memory due to a remote exception";
823 napi_throw_error(env, std::to_string(ErrorCode::SYSTEM_STATUS_ABNORMAL).c_str(), errMsg);
824 apiInvokeRecorder.SetErrorCode(ErrorCode::SYSTEM_STATUS_ABNORMAL);
825 return CreateUndefined(env);
826 }
827
ParseGwpAsanOptions(napi_env env,napi_value value,GwpAsanParams & gwpAsanParams)828 bool ParseGwpAsanOptions(napi_env env, napi_value value, GwpAsanParams& gwpAsanParams)
829 {
830 if (!MatchValueType(env, value, napi_object)) {
831 HILOG_ERROR(LOG_CORE, "The type of options must be GwpAsanOptions.");
832 return false;
833 }
834
835 //alwaysEnabled?: bool
836 napi_value nAlwaysEnabled = nullptr;
837 if (GetNapiObjectProperty(env, value, "alwaysEnabled", nAlwaysEnabled)) {
838 if (!GetNapiBoolValue(env, nAlwaysEnabled, gwpAsanParams.alwaysEnabled)) {
839 HILOG_ERROR(LOG_CORE, "AlwaysEnabled type must be boolean");
840 return false;
841 }
842 }
843
844 //sampleRate?: number
845 napi_value nSampleRate = nullptr;
846 if (GetNapiObjectProperty(env, value, "sampleRate", nSampleRate)) {
847 if (!GetNapiDoubleValue(env, nSampleRate, gwpAsanParams.sampleRate)) {
848 HILOG_ERROR(LOG_CORE, "SampleRate type must be a num");
849 return false;
850 }
851 }
852
853 //maxSimutaneousAllocations?: number
854 napi_value nMaxSimutaneousAllocations = nullptr;
855 if (GetNapiObjectProperty(env, value, "maxSimutaneousAllocations", nMaxSimutaneousAllocations)) {
856 if (!GetNapiDoubleValue(env, nMaxSimutaneousAllocations, gwpAsanParams.maxSimutaneousAllocations)) {
857 HILOG_ERROR(LOG_CORE, "MaxSimutaneousAllocations type must be a num");
858 return false;
859 }
860 }
861 if (gwpAsanParams.sampleRate <= 0 || gwpAsanParams.maxSimutaneousAllocations <= 0) {
862 HILOG_ERROR(LOG_CORE, "sampleRate or maxSimutaneousAllocations must be greater than 0");
863 return false;
864 }
865 HILOG_DEBUG(LOG_CORE, "Parse GwpAsanOptions success, alwaysEnabled: %{public}d, sampleRate: %{public}f,"
866 " maxSimutaneousAllocations: %{public}f",
867 gwpAsanParams.alwaysEnabled, gwpAsanParams.sampleRate, gwpAsanParams.maxSimutaneousAllocations);
868 return true;
869 }
870
UpdateGwpAsanParams(napi_env env,napi_callback_info info,GwpAsanParams & gwpAsanParams,std::string & paramErrorMessage)871 bool UpdateGwpAsanParams(napi_env env, napi_callback_info info, GwpAsanParams& gwpAsanParams,
872 std::string& paramErrorMessage)
873 {
874 size_t argc = ENABLE_ARGS_TWO_PARAMS;
875 napi_value argv[ENABLE_ARGS_TWO_PARAMS] = { nullptr };
876 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
877 switch (argc) {
878 case ENABLE_ARGS_TWO_PARAMS:
879 if (!GetNapiInt32Value(env, argv[SECOND_POS], gwpAsanParams.duration) ||
880 gwpAsanParams.duration <= 0) {
881 paramErrorMessage = "Invalid parameter, set duration must be a num.";
882 return false;
883 }
884 [[fallthrough]];
885 case ENABLE_ARGS_ONE_PARAMS:
886 if (!ParseGwpAsanOptions(env, argv[FIRST_POS], gwpAsanParams)) {
887 paramErrorMessage = "Invalid parameter, parse gwpAsanOptions error.";
888 return false;
889 }
890 [[fallthrough]];
891 case ENABLE_ARGS_NO_PARAMS:
892 return true;
893 default: {
894 paramErrorMessage = "Invalid parameter, the number of parameters "
895 "cannot exceed two.";
896 return false;
897 }
898 }
899 }
900
EnableGwpAsanGrayscale(napi_env env,napi_callback_info info)901 napi_value EnableGwpAsanGrayscale(napi_env env, napi_callback_info info)
902 {
903 ApiInvokeRecorder apiInvokeRecorder("enableGwpAsanGrayscale");
904 GwpAsanParams gwpAsanParams;
905 std::string paramErrorMessage;
906 if (!UpdateGwpAsanParams(env, info, gwpAsanParams, paramErrorMessage)) {
907 HILOG_ERROR(LOG_CORE, "EnableGwpAsanGrayscale failed. Invalid params!");
908 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
909 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(),
910 paramErrorMessage.c_str());
911 return CreateUndefined(env);
912 }
913 if (!EnableGwpAsanGrayscale(gwpAsanParams.alwaysEnabled, gwpAsanParams.sampleRate,
914 gwpAsanParams.maxSimutaneousAllocations, gwpAsanParams.duration)) {
915 HILOG_ERROR(LOG_CORE, "Failed to enable gwp asan grayscale!");
916 apiInvokeRecorder.SetErrorCode(ErrorCode::OVER_ENABLE_LIMIT);
917 paramErrorMessage = "The number of GWP-ASAN applications of this device overflowed after last boot.";
918 napi_throw_error(env, std::to_string(ErrorCode::OVER_ENABLE_LIMIT).c_str(), paramErrorMessage.c_str());
919 return CreateUndefined(env);
920 }
921 return CreateUndefined(env);
922 }
923
DisableGwpAsanGrayscale(napi_env env,napi_callback_info info)924 napi_value DisableGwpAsanGrayscale(napi_env env, napi_callback_info info)
925 {
926 ApiInvokeRecorder apiInvokeRecorder("disableGwpAsanGrayscale");
927 DisableGwpAsanGrayscale();
928 return CreateUndefined(env);
929 }
930
GetGwpAsanGrayscaleState(napi_env env,napi_callback_info info)931 napi_value GetGwpAsanGrayscaleState(napi_env env, napi_callback_info info)
932 {
933 ApiInvokeRecorder apiInvokeRecorder("getGwpAsanGrayscaleState");
934 auto result = GetGwpAsanGrayscaleState();
935 napi_value ret = nullptr;
936 napi_create_uint32(env, result, &ret);
937 return ret;
938 }
939
GetJsRawHeapTrimLevelParam(napi_env env,napi_callback_info info,uint32_t & level)940 static std::string GetJsRawHeapTrimLevelParam(napi_env env, napi_callback_info info, uint32_t &level)
941 {
942 size_t argc = ENABLE_ARGS_ONE_PARAMS;
943 napi_value argv = nullptr;
944 napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
945 std::string paramErrorMessage;
946 if (argc != ENABLE_ARGS_ONE_PARAMS) {
947 paramErrorMessage = "Param type error, wrong number of parameters.";
948 HILOG_ERROR(LOG_CORE, "%{public}s", paramErrorMessage.c_str());
949 return paramErrorMessage;
950 }
951 if (!MatchValueType(env, argv, napi_number)) {
952 paramErrorMessage = "Param type error, invalid num.";
953 HILOG_ERROR(LOG_CORE, "%{public}s", paramErrorMessage.c_str());
954 return paramErrorMessage;
955 }
956 if (napi_get_value_uint32(env, argv, &level) != napi_ok ||
957 level > TRIM_LEVEL_MAX) {
958 paramErrorMessage = "Param type error, invalid an unsigned num or "
959 "exceeding the maximum value: " + std::to_string(TRIM_LEVEL_MAX);
960 HILOG_ERROR(LOG_CORE, "%{public}s", paramErrorMessage.c_str());
961 return paramErrorMessage;
962 }
963 return paramErrorMessage;
964 }
965
SetJsRawHeapTrimLevel(napi_env env,napi_callback_info info)966 napi_value SetJsRawHeapTrimLevel(napi_env env, napi_callback_info info)
967 {
968 ApiInvokeRecorder apiInvokeRecorder("setJsRawHeapTrimLevel");
969 uint32_t level = 0;
970 std::string paramErrorMessage = GetJsRawHeapTrimLevelParam(env, info, level);
971 if (!paramErrorMessage.empty()) {
972 apiInvokeRecorder.SetErrorCode(ErrorCode::PARAMETER_ERROR);
973 napi_throw_error(env, std::to_string(ErrorCode::PARAMETER_ERROR).c_str(),
974 paramErrorMessage.c_str());
975 return CreateUndefined(env);
976 }
977
978 NativeEngine *engine = reinterpret_cast<NativeEngine*>(env);
979 if (engine) {
980 engine->SetRawHeapTrimLevel(level);
981 HILOG_DEBUG(LOG_CORE, "SetRawHeapTrimLevel to level: %{public}d success", level);
982 }
983 return CreateUndefined(env);
984 }
985
DeclareHiDebugInterface(napi_env env,napi_value exports)986 napi_value DeclareHiDebugInterface(napi_env env, napi_value exports)
987 {
988 ApiRecordReporter::InitProcessor();
989 napi_property_descriptor desc[] = {
990 DECLARE_NAPI_FUNCTION("startProfiling", StartProfiling),
991 DECLARE_NAPI_FUNCTION("stopProfiling", StopProfiling),
992 DECLARE_NAPI_FUNCTION("dumpHeapData", DumpHeapData),
993 DECLARE_NAPI_FUNCTION("startJsCpuProfiling", StartJsCpuProfiling),
994 DECLARE_NAPI_FUNCTION("stopJsCpuProfiling", StopJsCpuProfiling),
995 DECLARE_NAPI_FUNCTION("dumpJsHeapData", DumpJsHeapData),
996 DECLARE_NAPI_FUNCTION("getPss", GetPss),
997 DECLARE_NAPI_FUNCTION("getSharedDirty", GetSharedDirty),
998 DECLARE_NAPI_FUNCTION("getPrivateDirty", GetPrivateDirty),
999 DECLARE_NAPI_FUNCTION("getCpuUsage", GetCpuUsage),
1000 DECLARE_NAPI_FUNCTION("getServiceDump", GetServiceDump),
1001 DECLARE_NAPI_FUNCTION("getNativeHeapSize", GetNativeHeapSize),
1002 DECLARE_NAPI_FUNCTION("getNativeHeapAllocatedSize", GetNativeHeapAllocatedSize),
1003 DECLARE_NAPI_FUNCTION("getNativeHeapFreeSize", GetNativeHeapFreeSize),
1004 DECLARE_NAPI_FUNCTION("getVss", GetVss),
1005 DECLARE_NAPI_FUNCTION("removeNapiWrap", RemoveNapiWrap),
1006 DECLARE_NAPI_FUNCTION("getAppVMMemoryInfo", GetAppVMMemoryInfo),
1007 DECLARE_NAPI_FUNCTION("getAppThreadCpuUsage", GetAppThreadCpuUsage),
1008 DECLARE_NAPI_FUNCTION("getSystemCpuUsage", GetSystemCpuUsage),
1009 DECLARE_NAPI_FUNCTION("getAppMemoryLimit", GetAppMemoryLimit),
1010 DECLARE_NAPI_FUNCTION("getAppNativeMemInfo", GetAppNativeMemInfo),
1011 DECLARE_NAPI_FUNCTION("getAppNativeMemInfoWithCache", GetAppNativeMemInfoWithCache),
1012 DECLARE_NAPI_FUNCTION("getAppNativeMemInfoAsync", GetAppNativeMemInfoAsync),
1013 DECLARE_NAPI_FUNCTION("getSystemMemInfo", GetSystemMemInfo),
1014 DECLARE_NAPI_FUNCTION("startAppTraceCapture", StartAppTraceCapture),
1015 DECLARE_NAPI_FUNCTION("stopAppTraceCapture", StopAppTraceCapture),
1016 DECLARE_NAPI_FUNCTION("getVMRuntimeStats", GetVMRuntimeStats),
1017 DECLARE_NAPI_FUNCTION("getVMRuntimeStat", GetVMRuntimeStat),
1018 DECLARE_NAPI_FUNCTION("setAppResourceLimit", SetAppResourceLimit),
1019 DECLARE_NAPI_FUNCTION("isDebugState", IsDebugState),
1020 DECLARE_NAPI_FUNCTION("getGraphicsMemory", GetGraphicsMemory),
1021 DECLARE_NAPI_FUNCTION("getGraphicsMemorySync", GetGraphicsMemorySync),
1022 DECLARE_NAPI_FUNCTION("dumpJsRawHeapData", DumpJsRawHeapData),
1023 DECLARE_NAPI_FUNCTION("enableGwpAsanGrayscale", EnableGwpAsanGrayscale),
1024 DECLARE_NAPI_FUNCTION("disableGwpAsanGrayscale", DisableGwpAsanGrayscale),
1025 DECLARE_NAPI_FUNCTION("getGwpAsanGrayscaleState", GetGwpAsanGrayscaleState),
1026 DECLARE_NAPI_FUNCTION("setJsRawHeapTrimLevel", SetJsRawHeapTrimLevel),
1027 };
1028 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1029 InitNapiClass(env, exports);
1030 return exports;
1031 }
1032
1033 static napi_module hidebugModule = {
1034 .nm_version = 1,
1035 .nm_flags = 0,
1036 .nm_filename = nullptr,
1037 .nm_register_func = HiviewDFX::DeclareHiDebugInterface,
1038 .nm_modname = "hidebug",
1039 .nm_priv = ((void *)0),
1040 .reserved = {0}
1041 };
1042
HiDebugRegisterModule(void)1043 extern "C" __attribute__((constructor)) void HiDebugRegisterModule(void)
1044 {
1045 napi_module_register(&hidebugModule);
1046 }
1047 } // HiviewDFX
1048 } // OHOS
1049