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