1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 "napi/native_api.h"
17 #include "hicollie/hicollie.h"
18 #include <thread>
19 #include <string>
20 #include <unistd.h>
21 #include <atomic>
22 #include "hilog/log.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "testTag"
26
27 static OH_HiCollie_BeginFunc beginFunc_;
28 static OH_HiCollie_EndFunc endFunc_;
29 HiCollie_DetectionParam param {.sampleStackTriggerTime = 150, .reserved = 0};
30 int64_t lastWatchTime = 0;
31 const int64_t CHECK_INTERNAL_TIME = 3000;
32 std::shared_ptr<std::atomic<bool>> isReport = std::make_shared<std::atomic<bool>>(true);
33 int g_count = 0;
34 bool g_needReport = true;
35 int g_initResult = -1;
36 int result = 0;
37 // 自定义休眠时间,模拟卡死场景
38 const int64_t BLOCK_TIME = 5;
39 // 设置应用线程执行任务情况标志位, true-正常, false-卡死
40 std::shared_ptr<std::atomic<bool>> appThreadIsAlive_ = std::make_shared<std::atomic<bool>>(true);
41 // 设置上报应用线程卡死事件标志位
42 std::shared_ptr<std::atomic<bool>> isSixSecondEvent_ = std::make_shared<std::atomic<bool>>(false);
43
InitBeginFunc(const char * eventName)44 void InitBeginFunc(const char* eventName)
45 {
46 std::string str(eventName);
47 }
InitEndFunc(const char * eventName)48 void InitEndFunc(const char* eventName)
49 {
50 std::string str(eventName);
51 }
52
TestJankDetection()53 void TestJankDetection()
54 {
55 beginFunc_ = InitBeginFunc;
56 endFunc_ = InitEndFunc;
57 int initResult = OH_HiCollie_Init_JankDetection(&beginFunc_, &endFunc_, param);
58 int initcount = 0;
59 while (initcount < 2) { //as of 2
60 beginFunc_("TestBegin");
61 usleep(350 * 1000); //350ms转换为350*1000微秒
62 endFunc_("TestEnd");
63 initcount++;
64 }
65 }
66
TestHiCollieJankC(napi_env env,napi_callback_info info)67 static napi_value TestHiCollieJankC(napi_env env, napi_callback_info info)
68 {
69 std::thread threadObj(TestJankDetection);
70 threadObj.join();
71 napi_value sum;
72 napi_create_double(env, 0, &sum);
73 return sum;
74 }
75
GetCurrentTime()76 int64_t GetCurrentTime()
77 {
78 return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
79 system_clock::now().time_since_epoch()).count();
80 }
81
ReportEvent()82 bool ReportEvent()
83 {
84 if ((GetCurrentTime() - lastWatchTime) > CHECK_INTERNAL_TIME) {
85 return true;
86 }
87 return true;
88 }
89
TestTask()90 void TestTask()
91 {
92 if (g_needReport && ReportEvent()) {
93 bool temp = isReport->load();
94 int reportResult = OH_HiCollie_Report(&temp);
95 g_needReport = false;
96 }
97 int64_t now = GetCurrentTime();
98 if ((now - lastWatchTime) >= (CHECK_INTERNAL_TIME / 2)) { //as of 2
99 lastWatchTime = now;
100 }
101 }
102
TestStuckDetection()103 int TestStuckDetection()
104 {
105 int initResult = -1;
106 if (g_count == 0) {
107 initResult = OH_HiCollie_Init_StuckDetection(TestTask);
108 TestTask();
109 g_count++;
110 }
111 return initResult;
112 }
113
TestHiCollieStuckC(napi_env env,napi_callback_info info)114 static napi_value TestHiCollieStuckC(napi_env env, napi_callback_info info)
115 {
116 std::thread threadObj(TestStuckDetection);
117 threadObj.join();
118 napi_value sum;
119 napi_create_double(env, 0, &sum);
120 return sum;
121 }
122
TestStuckCMThread(napi_env env,napi_callback_info info)123 static napi_value TestStuckCMThread(napi_env env, napi_callback_info info)
124 {
125 napi_value sum;
126 int initResult = OH_HiCollie_Init_StuckDetection(nullptr);
127 napi_create_int32(env, initResult, &sum);
128 return sum;
129 }
130
TestJankCMThread(napi_env env,napi_callback_info info)131 static napi_value TestJankCMThread(napi_env env, napi_callback_info info)
132 {
133 napi_value sum;
134 int initResult = OH_HiCollie_Init_JankDetection(nullptr, &endFunc_, param);
135 napi_create_int32(env, initResult, &sum);
136 return sum;
137 }
138
139
TestReportCMThread(napi_env env,napi_callback_info info)140 static napi_value TestReportCMThread(napi_env env, napi_callback_info info)
141 {
142 napi_value sum;
143 int initResult = OH_HiCollie_Report(nullptr);
144 napi_create_int32(env, initResult, &sum);
145 return sum;
146 }
147
148
Test001()149 void Test001()
150 {
151 g_initResult = OH_HiCollie_Init_JankDetection(nullptr, &endFunc_, param);
152 }
153
TestJankCerr401(napi_env env,napi_callback_info info)154 static napi_value TestJankCerr401(napi_env env, napi_callback_info info)
155 {
156 napi_value sum;
157 std::thread threadObj(Test001);
158 threadObj.join();
159 napi_create_int32(env, g_initResult, &sum);
160 return sum;
161 }
162
163
Add(napi_env env,napi_callback_info info)164 static napi_value Add(napi_env env, napi_callback_info info)
165 {
166 size_t argc = 2;
167 napi_value args[2] = {nullptr};
168
169 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
170
171 napi_valuetype valuetype0;
172 napi_typeof(env, args[0], &valuetype0);
173
174 napi_valuetype valuetype1;
175 napi_typeof(env, args[1], &valuetype1);
176
177 double value0;
178 napi_get_value_double(env, args[0], &value0);
179
180 double value1;
181 napi_get_value_double(env, args[1], &value1);
182
183 napi_value sum;
184 napi_create_double(env, value0 + value1, &sum);
185 return sum;
186 }
187
CallBack(void *)188 void CallBack(void*)
189 {
190 // OH_LOG_INFO(LogType::LOG_APP, "HiCollieTimerNdk callBackParam:");
191 }
192
TestHiCollieTimerNdkErr03(napi_env env,napi_callback_info info)193 static napi_value TestHiCollieTimerNdkErr03(napi_env env, napi_callback_info info)
194 {
195 napi_value sum;
196 int id;
197 HiCollie_SetTimerParam param = {nullptr, 1, nullptr, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
198 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, &id);
199 napi_create_int32(env, errorCode, &sum);
200 return sum;
201 }
202
TestHiCollieTimerNdkErr04(napi_env env,napi_callback_info info)203 static napi_value TestHiCollieTimerNdkErr04(napi_env env, napi_callback_info info)
204 {
205 napi_value sum;
206 int id;
207 HiCollie_SetTimerParam param = {"testSetTimer", 0, nullptr, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
208 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, &id);
209 napi_create_int32(env, errorCode, &sum);
210 return sum;
211 }
212
TestHiCollieTimerNdkErr05(napi_env env,napi_callback_info info)213 static napi_value TestHiCollieTimerNdkErr05(napi_env env, napi_callback_info info)
214 {
215 napi_value sum;
216 int id;
217 HiCollie_SetTimerParam param = {"testSetTimer", 1, nullptr, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
218 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, &id);
219 napi_create_int32(env, errorCode, &sum);
220 return sum;
221 }
222
TestHiCollieTimerNdkErr06(napi_env env,napi_callback_info info)223 static napi_value TestHiCollieTimerNdkErr06(napi_env env, napi_callback_info info)
224 {
225 napi_value sum;
226 int id;
227 HiCollie_SetTimerParam param = {"testSetTimer", 1, nullptr, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
228 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, nullptr);
229 napi_create_int32(env, errorCode, &sum);
230 return sum;
231 }
232
TestHiCollieTimerNdkSetSuc(napi_env env,napi_callback_info info)233 static napi_value TestHiCollieTimerNdkSetSuc(napi_env env, napi_callback_info info)
234 {
235 napi_value sum;
236 int id;
237 HiCollie_SetTimerParam param = {"testSetTimer", 1, CallBack, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
238 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, &id);
239 // OH_LOG_INFO(LogType::LOG_APP, "HiCollieTimer taskId: %{public}d", errorCode);
240 napi_create_int32(env, errorCode, &sum);
241 return sum;
242 }
243
TestHiCollieTimerNdkCanSuc(napi_env env,napi_callback_info info)244 static napi_value TestHiCollieTimerNdkCanSuc(napi_env env, napi_callback_info info)
245 {
246 napi_value sum;
247 int id;
248 HiCollie_SetTimerParam param = {"testSetTimer", 1, CallBack, nullptr, HiCollie_Flag::HICOLLIE_FLAG_NOOP};
249 HiCollie_ErrorCode errorCode = OH_HiCollie_SetTimer(param, &id);
250 if (errorCode == HICOLLIE_SUCCESS) {
251 sleep(2);
252 OH_HiCollie_CancelTimer(id);
253 napi_create_int32(env, 0, &sum);
254 }
255 return sum;
256 }
257
SetTimeout()258 void SetTimeout()
259 {
260 int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
261 system_clock::now().time_since_epoch()).count();
262 sleep(BLOCK_TIME);
263 int64_t currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
264 system_clock::now().time_since_epoch()).count();
265 if (currentTime - now < BLOCK_TIME) {
266 appThreadIsAlive_->store(true);
267 return;
268 }
269 appThreadIsAlive_->store(false);
270 }
271
272 // 开发者可自定义周期性检测任务
Timer()273 void Timer()
274 {
275 // 每隔5s检查应用是否正常执行任务
276 if (appThreadIsAlive_->load()) {
277 OH_LOG_INFO(LogType::LOG_APP, "Check appThread isAlive.");
278 // 更新appThreadIsAlive_,正常执行下次检测时为true
279 appThreadIsAlive_->store(false);
280 // 模拟超时场景
281 SetTimeout();
282 return;
283 }
284 ReportEvent();
285 }
286
InitStuckDetectionWithTimeout()287 int InitStuckDetectionWithTimeout()
288 {
289 // 初始化线程卡死监控函数
290 int initResult = OH_HiCollie_Init_StuckDetectionWithTimeout(Timer, BLOCK_TIME);
291 // 成功结果:0
292 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_StuckDetection: %{public}d", initResult);
293 return initResult;
294 }
295
296 //HICOLLIE_WRONG_THREAD_CONTEXT 29800001 - 调用线程错误。无法从主线程调用该函数
TestHiCollieStuckWithTimeoutNdk(napi_env env,napi_callback_info info)297 static napi_value TestHiCollieStuckWithTimeoutNdk(napi_env env, napi_callback_info info)
298 {
299 napi_value sum;
300 int initResult = OH_HiCollie_Init_StuckDetectionWithTimeout(Timer, BLOCK_TIME);
301 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_StuckDetection: %{public}d", initResult);
302 napi_create_int32(env, initResult, &sum);
303 return sum;
304 }
305 //HICOLLIE_SUCCESS 0 - 成功。
TestHiCollieStuckWithTimeoutNdk1(napi_env env,napi_callback_info info)306 static napi_value TestHiCollieStuckWithTimeoutNdk1(napi_env env, napi_callback_info info)
307 {
308 napi_value sum;
309 // 创建子线程
310 std::thread threadObj(InitStuckDetectionWithTimeout);
311 // 执行任务
312 threadObj.join();
313 napi_create_int32(env, result, &sum);
314 return sum;
315 }
316 //HICOLLIE_INVALID_ARGUMENT 401 - 开始函数和结束函数两者都必须有值或为空,否则将返回该错误值;卡死时间<3s
TestHiCollieStuckWithTimeoutNdk2(napi_env env,napi_callback_info info)317 static napi_value TestHiCollieStuckWithTimeoutNdk2(napi_env env, napi_callback_info info)
318 {
319 napi_value sum;
320 // 创建子线程
321 int initResult = OH_HiCollie_Init_StuckDetectionWithTimeout(Timer, 1);
322 OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_StuckDetection: %{public}d", initResult);
323 // 执行任务
324 napi_create_int32(env, initResult, &sum);
325 return sum;
326 }
327
328 EXTERN_C_START
Init(napi_env env,napi_value exports)329 static napi_value Init(napi_env env, napi_value exports)
330 {
331 napi_property_descriptor desc[] = {
332 { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
333 { "testHiCollieJankC", nullptr, TestHiCollieJankC, nullptr, nullptr, nullptr, napi_default, nullptr },
334 { "testHiCollieStuckC", nullptr, TestHiCollieStuckC, nullptr, nullptr, nullptr, napi_default, nullptr },
335 { "testJankCMThread", nullptr, TestJankCMThread, nullptr, nullptr, nullptr, napi_default, nullptr },
336 { "testStuckCMThread", nullptr, TestStuckCMThread, nullptr, nullptr, nullptr, napi_default, nullptr },
337 { "testReportCMThread", nullptr, TestReportCMThread, nullptr, nullptr, nullptr, napi_default, nullptr },
338 { "testJankCerr401", nullptr, TestJankCerr401, nullptr, nullptr, nullptr, napi_default, nullptr },
339 { "TestHiCollieTimerNdkErr03", nullptr, TestHiCollieTimerNdkErr03, nullptr, nullptr, nullptr, napi_default, nullptr },
340 { "TestHiCollieTimerNdkErr04", nullptr, TestHiCollieTimerNdkErr04, nullptr, nullptr, nullptr, napi_default, nullptr },
341 { "TestHiCollieTimerNdkErr05", nullptr, TestHiCollieTimerNdkErr05, nullptr, nullptr, nullptr, napi_default, nullptr },
342 { "TestHiCollieTimerNdkErr06", nullptr, TestHiCollieTimerNdkErr05, nullptr, nullptr, nullptr, napi_default, nullptr },
343 { "TestHiCollieTimerNdkSetSuc", nullptr, TestHiCollieTimerNdkSetSuc, nullptr, nullptr, nullptr, napi_default, nullptr },
344 { "TestHiCollieTimerNdkCanSuc", nullptr, TestHiCollieTimerNdkCanSuc, nullptr, nullptr, nullptr, napi_default, nullptr },
345 { "testHiCollieStuckWithTimeoutNdk", nullptr, TestHiCollieStuckWithTimeoutNdk, nullptr, nullptr, nullptr, napi_default, nullptr },
346 { "testHiCollieStuckWithTimeoutNdk1", nullptr, TestHiCollieStuckWithTimeoutNdk1, nullptr, nullptr, nullptr, napi_default, nullptr },
347 { "testHiCollieStuckWithTimeoutNdk2", nullptr, TestHiCollieStuckWithTimeoutNdk2, nullptr, nullptr, nullptr, napi_default, nullptr },
348 };
349 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
350 return exports;
351 }
352 EXTERN_C_END
353
354 static napi_module demoModule = {
355 .nm_version = 1,
356 .nm_flags = 0,
357 .nm_filename = nullptr,
358 .nm_register_func = Init,
359 .nm_modname = "hicollie",
360 .nm_priv = ((void*)0),
361 .reserved = { 0 },
362 };
363
RegisterEntryModule(void)364 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
365 {
366 napi_module_register(&demoModule);
367 }
368