* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "napi/native_api.h"
#include "hitrace/trace.h"
#include "hilog/log.h"
#include "hidebug/hidebug.h"
#include "hicollie/hicollie.h"
#include <thread>
#include <string>
#include <unistd.h>
#include <atomic>
#undef LOG_TAG
#define LOG_TAG "testTag"
static OH_HiCollie_BeginFunc beginFunc_;
static OH_HiCollie_EndFunc endFunc_;
HiCollie_DetectionParam param{.sampleStackTriggerTime = 150, .reserved = 0};
int64_t g_lastWatchTime = 0;
const int64_t CHECK_INTERNAL_TIME = 3000;
std::shared_ptr<std::atomic<bool>> isReport = std::make_shared<std::atomic<bool>>(false);
int g_count = 0;
bool g_needReport = false;
void InitBeginFunc(const char *eventName)
{
std::string str(eventName);
OH_LOG_INFO(LogType::LOG_APP, "InitBeginFunc eventName: %{public}s", str.c_str());
}
void InitEndFunc(const char *eventName)
{
std::string str(eventName);
OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_EndFunc eventName: %{public}s", str.c_str());
}
void TestJankDetection()
{
beginFunc_ = InitBeginFunc;
endFunc_ = InitEndFunc;
int initResult = OH_HiCollie_Init_JankDetection(&beginFunc_, &endFunc_, param);
OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_JankDetection: %{public}d", initResult);
int countOuter = 0;
const int loopLimit = 2;
const int sleepTime = 350 * 1000;
while (countOuter < loopLimit) {
beginFunc_("TestBegin");
usleep(sleepTime);
endFunc_("TestEnd");
countOuter++;
}
}
static napi_value TestHiCollieJankNdk(napi_env env, napi_callback_info info)
{
std::thread threadObj(TestJankDetection);
threadObj.join();
return 0;
}
int64_t GetCurrentTime()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
}
bool ReportEvent()
{
if ((GetCurrentTime() - g_lastWatchTime) > CHECK_INTERNAL_TIME) {
return true;
}
return false;
}
void TestTask()
{
if (g_needReport && ReportEvent()) {
bool temp = isReport->load();
int reportResult = OH_HiCollie_Report(&temp);
OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Report: %{public}d", reportResult);
OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Report isReport: %{public}d", temp);
g_needReport = false;
}
int64_t now = GetCurrentTime();
int64_t halfCheckInterval = CHECK_INTERNAL_TIME / 2;
if ((now - g_lastWatchTime) >= (halfCheckInterval)) {
g_lastWatchTime = now;
}
}
void TestStuckDetection()
{
int initResult = -1;
if (g_count == 0) {
initResult = OH_HiCollie_Init_StuckDetection(TestTask);
OH_LOG_INFO(LogType::LOG_APP, "OH_HiCollie_Init_StuckDetection: %{public}d", initResult);
g_count++;
}
}
static napi_value TestHiCollieStuckNdk(napi_env env, napi_callback_info info)
{
std::thread threadObj(TestStuckDetection);
threadObj.join();
return 0;
}
static napi_value TestHiTraceMeterNDK(napi_env env, napi_callback_info info)
{
int testNum = 123;
OH_HiTrace_StartAsyncTrace("hitraceTest", testNum);
OH_HiTrace_FinishAsyncTrace("hitraceTest", testNum);
return 0;
}
static napi_value TestHiTraceChainNDK(napi_env env, napi_callback_info info)
{
OH_HiTrace_BeginChain("hitraceTest", HITRACE_FLAG_DEFAULT);
OH_HiTrace_EndChain();
return 0;
}
static napi_value TestHidebugNdk(napi_env env, napi_callback_info info)
{
double cpuUsage = OH_HiDebug_GetSystemCpuUsage();
OH_LOG_INFO(LogType::LOG_APP, "GetSystemCpuUsage: %{public}f", cpuUsage);
return 0;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "testHidebugNdk", nullptr, TestHidebugNdk, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "testHiTraceMeterNDK", nullptr, TestHiTraceMeterNDK, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "testHiTraceChainNDK", nullptr, TestHiTraceChainNDK, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "testHiCollieJankNdk", nullptr, TestHiCollieJankNdk, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "testHiCollieStuckNdk", nullptr, TestHiCollieStuckNdk, nullptr, nullptr, nullptr, napi_default, nullptr }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void*)0),
.reserved = { 0 },
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
napi_module_register(&demoModule);
}