1# Subscribing to Main Thread Jank Events (C/C++) 2 3## Main Thread Jank Event Specifications 4 5For details, see [Main Thread Jank Event Overview](./hiappevent-watcher-mainthreadjank-events.md). 6 7## Available APIs 8 9For details about how to use the APIs (such as parameter usage restrictions and value ranges), see [HiAppEvent](../reference/apis-performance-analysis-kit/_hi_app_event.md#hiappevent). 10 11**Subscription APIs** 12 13| API | Description | 14| ------------------------------------------------------------ | -------------------------------------------- | 15| int OH_HiAppEvent_AddWatcher(HiAppEvent_Watcher *watcher) | Adds a watcher to listen for application events.| 16| int OH_HiAppEvent_RemoveWatcher(HiAppEvent_Watcher *watcher) | Removes a watcher to unsubscribe from application events.| 17 18## How to Develop 19 201. Create a native C++ project and import the **jsoncpp** file to the project. The directory structure is as follows: 21 22 ```yml 23 entry: 24 src: 25 main: 26 cpp: 27 - json: 28 - json.h 29 - json-forwards.h 30 - types: 31 libentry: 32 - index.d.ts 33 - CMakeLists.txt 34 - napi_init.cpp 35 - jsoncpp.cpp 36 ets: 37 - entryability: 38 - EntryAbility.ets 39 - pages: 40 - Index.ets 41 ``` 42 432. In the **CMakeLists.txt** file, add the source file and dynamic libraries. 44 45 ```cmake 46 # Add the jsoncpp.cpp file, which is used to parse the JSON strings in the subscription events. 47 add_library(entry SHARED napi_init.cpp jsoncpp.cpp) 48 # Add libhiappevent_ndk.z.so and libhilog_ndk.z.so (log output). 49 target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so) 50 ``` 51 523. Import the dependencies to the **napi_init.cpp** file, and define **LOG_TAG**. 53 54 ```c++ 55 #include "napi/native_api.h" 56 #include "json/json.h" 57 #include "hilog/log.h" 58 #include "hiappevent/hiappevent.h" 59 #include "hiappevent/hiappevent_event.h" 60 #undef LOG_TAG 61 #define LOG_TAG "testTag" 62 ``` 63 644. Subscribe to system events. 65 66 - Watcher of the onReceive type. 67 68 In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type. 69 70 ```c++ 71 // Define a variable to cache the pointer to the created watcher. 72 static HiAppEvent_Watcher *systemEventWatcher; 73 74 static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) { 75 for (int i = 0; i < groupLen; ++i) { 76 for (int j = 0; j < appEventGroups[i].infoLen; ++j) { 77 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", 78 appEventGroups[i].appEventInfos[j].domain); 79 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", 80 appEventGroups[i].appEventInfos[j].name); 81 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", 82 appEventGroups[i].appEventInfos[j].type); 83 if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && 84 strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_MAIN_THREAD_JANK) == 0) { 85 Json::Value params; 86 Json::Reader reader(Json::Features::strictMode()); 87 Json::FastWriter writer; 88 if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { 89 auto time = params["time"].asInt64(); 90 auto pid = params["pid"].asInt(); 91 auto uid = params["uid"].asInt(); 92 auto bundleName = params["bundle_name"].asString(); 93 auto bundleVersion = params["bundle_version"].asString(); 94 auto beginTime = params["begin_time"].asInt64(); 95 auto endTime = params["end_time"].asInt64(); 96 auto externalLog = writer.write(params["external_log"]); 97 auto logOverLimit = params["logOverLimit"].asBool(); 98 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); 99 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); 100 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); 101 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", 102 bundleName.c_str()); 103 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", 104 bundleVersion.c_str()); 105 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.begin_time=%{public}lld", beginTime); 106 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.end_time=%{public}lld", endTime); 107 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str()); 108 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", 109 logOverLimit); 110 } 111 } 112 } 113 } 114 } 115 116 static napi_value RegisterWatcher(napi_env env, napi_callback_info info) { 117 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent RegisterWatcher"); 118 // Set the watcher name. The system identifies different watchers based on their names. 119 systemEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher"); 120 // Set the event to subscribe to EVENT_MAIN_THREAD_JANK. 121 const char *names[] = {EVENT_MAIN_THREAD_JANK}; 122 // Add the events to watch, for example, system events. 123 OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1); 124 // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback. 125 OH_HiAppEvent_SetWatcherOnReceive(systemEventWatcher, OnReceive); 126 // Add a watcher to listen for the specified event. 127 OH_HiAppEvent_AddWatcher(systemEventWatcher); 128 return {}; 129 } 130 ``` 131 1325. Register **RegisterWatcher** as an ArkTS API. 133 134 In the **napi_init.cpp** file, register **RegisterWatcher** as an ArkTS API. 135 136 ```c++ 137 static napi_value Init(napi_env env, napi_value exports) 138 { 139 napi_property_descriptor desc[] = { 140 { "registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr } 141 }; 142 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 143 return exports; 144 } 145 ``` 146 147 In the **index.d.ts** file, define the ArkTS API. 148 149 ```typescript 150 export const registerWatcher: () => void; 151 ``` 152 1536. In the **entry/src/main/ets/entryability/EntryAbility.ets** file, add the following interface invocation to **onCreate()**. 154 155 ```typescript 156 // Import the dependent module. 157 import testNapi from 'libentry.so' 158 159 // Add the interface invocation to onCreate(). 160 // Register the system event watcher at startup. 161 testNapi.registerWatcher(); 162 ``` 163 1647. In the **entry/src/main/ets/pages/Index.ets** file, add the **timeOut500** button with **onClick()** to trigger a main thread jank event when the button is clicked. The sample code is as follows: 165 166 ```typescript 167 Button("timeOut350") 168 .fontSize(50) 169 .fontWeight(FontWeight.Bold) 170 .onClick(() => { 171 let t = Date.now(); 172 while (Date.now() - t <= 350) {} 173 }) 174 ``` 175 1768. In DevEco Studio, click the **Run** button to run the application project. Click the **timeOut350** button twice consecutively to trigger a main thread jank event. 177 1789. After the main thread jank event is reported, you can view the following event information in the **Log** window. 179 180 ```text 181 HiAppEvent eventInfo.domain=OS 182 HiAppEvent eventInfo.name=MAIN_THREAD_JANK 183 HiAppEvent eventInfo.eventType=1 184 HiAppEvent eventInfo.params.time=1717597063727 185 HiAppEvent eventInfo.params.pid=45572 186 HiAppEvent eventInfo.params.uid=20020151 187 HiAppEvent eventInfo.params.bundle_name=com.example.nativemainthread 188 HiAppEvent eventInfo.params.bundle_version=1.0.0 189 HiAppEvent eventInfo.params.begin_time=1717597063225 190 HiAppEvent eventInfo.params.end_time=1717597063727 191 HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/watchdog/MAIN_THREAD_JANK_20240613221239_45572.txt"] 192 HiAppEvent eventInfo.params.log_over_limit=0 193 ``` 194 195 > **NOTE** 196 > For details, see [Default Main Thread Jank Event Time Specifications](./hiappevent-watcher-mainthreadjank-events.md#default-main-thread-jank-event-time-specifications) and [Main Thread Jank Event Specifications](./hiappevent-watcher-mainthreadjank-events.md#main-thread-jank-event-specifications). 197 19811. Remove the event watcher. 199 200 ```c++ 201 static napi_value RemoveWatcher(napi_env env, napi_callback_info info) { 202 // Remove the watcher. 203 OH_HiAppEvent_RemoveWatcher(systemEventWatcher); 204 return {}; 205 } 206 ``` 207 20812. Destroy the event watcher. 209 210 ```c++ 211 static napi_value DestroyWatcher(napi_env env, napi_callback_info info) { 212 // Destroy the created watcher and set systemEventWatcher to nullptr. 213 OH_HiAppEvent_DestroyWatcher(systemEventWatcher); 214 systemEventWatcher = nullptr; 215 return {}; 216 } 217 ``` 218