1# Subscribing to Resource Leak 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 the 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 dependency files to the **napi_init.cpp** file, and define **LOG_TAG**.
49
50   ```c++
51   # include "json/json.h"
52   # include "hilog/log.h"
53   # include "hiappevent/hiappevent.h"
54   
55   # undef LOG_TAG
56   # define LOG_TAG "testTag"
57   ```
58
594. Subscribe to application events.
60
61    - Watcher of the onReceive type:
62
63      In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type.
64
65      ```c++
66      // Define a variable to cache the pointer to the created watcher.
67      static HiAppEvent_Watcher *systemEventWatcher; 
68      
69      static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
70          for (int i = 0; i < groupLen; ++i) {
71              for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
72                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
73                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
74                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
75                  if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && 
76                      strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_RESOURCE_OVERLIMIT) == 0) {
77                      Json::Value params;
78                      Json::Reader reader(Json::Features::strictMode());
79                      Json::FastWriter writer;
80                      if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
81                          auto time = params["time"].asInt64();
82                          auto pid = params["pid"].asInt();
83                          auto uid = params["uid"].asInt();
84                          auto resourceType = params["resourceType"].asString();
85                          auto bundleName = params["bundle_name"].asString();
86                          auto bundleVersion = params["bundle_version"].asString();
87                          auto memory = writer.write(params["memory"]);
88                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
89                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
90                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
91                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.resource_type=%{public}s", resourceType.c_str());
92                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
93                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
94                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str());
95                      }
96                  }
97              }
98          }
99      }
100      
101      static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
102          // Set the watcher name. The system identifies different watchers based on their names.
103          systemEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
104          // Set the event type to EVENT_RESOURCE_OVERLIMIT.
105          const char *names[] = {EVENT_RESOURCE_OVERLIMIT};
106          // Add the system events to watch, for example, system events.
107          OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
108          // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback.
109          OH_HiAppEvent_SetWatcherOnReceive(systemEventWatcher, OnReceive);
110          // Add a watcher to listen for the specified event.
111          OH_HiAppEvent_AddWatcher(systemEventWatcher);
112          return {};
113      }
114      ```
115      
116    - Watcher of the onTrigger type:
117    
118      In the **napi_init.cpp** file, define the methods related to the watcher of the OnTrigger type.
119    
120      ```c++
121      // Implement the callback function used to return the listened events. The content pointed to by the events pointer is valid only in this function.
122      static void OnTake(const char *const *events, uint32_t eventLen) {
123          Json::Reader reader(Json::Features::strictMode());
124          Json::FastWriter writer;
125          for (int i = 0; i < eventLen; ++i) {
126              Json::Value eventInfo;
127              if (reader.parse(events[i], eventInfo)) {
128                  auto domain =  eventInfo["domain_"].asString();
129                  auto name = eventInfo["name_"].asString();
130                  auto type = eventInfo["type_"].asInt();
131                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
132                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
133                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
134                  if (domain ==  DOMAIN_OS && name == EVENT_RESOURCE_OVERLIMIT) {
135                      auto time = eventInfo["time"].asInt64();
136                      auto pid = eventInfo["pid"].asInt();
137                      auto uid = eventInfo["uid"].asInt();
138                      auto resourceType = eventInfo["resourceType"].asString();
139                      auto bundleName = eventInfo["bundle_name"].asString();
140                      auto bundleVersion = eventInfo["bundle_version"].asString();
141                      auto memory = writer.write(eventInfo["memory"]);
142                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
143                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
144                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
145                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.resource_type=%{public}s", resourceType.c_str());
146                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
147                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
148                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str());
149                  }
150              }
151          }
152      }
153      
154      // Implement the subscription callback function to apply custom processing to the obtained event logging data.
155      static void OnTrigger(int row, int size) {
156          // After the callback is received, obtain the specified number of received events.
157          OH_HiAppEvent_TakeWatcherData(systemEventWatcher, row, OnTake);
158      }
159      
160      static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
161          // Set the watcher name. The system identifies different watchers based on their names.
162          systemEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
163          // Set the event type to EVENT_RESOURCE_OVERLIMIT.
164          const char *names[] = {EVENT_RESOURCE_OVERLIMIT};
165          // Add the system events to watch, for example, system events.
166          OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
167          // Set the implemented callback function. The callback function will be triggered when the conditions set by OH_HiAppEvent_SetTriggerCondition are met.
168          OH_HiAppEvent_SetWatcherOnTrigger(systemEventWatcher, OnTrigger);
169          // Set the conditions for triggering the subscription callback. For example, trigger this onTrigger callback when the number of new event logs is 2.
170          OH_HiAppEvent_SetTriggerCondition(systemEventWatcher, 1, 0, 0);
171          // Add a watcher to listen for the specified event.
172          OH_HiAppEvent_AddWatcher(systemEventWatcher);
173          return {};
174      }
175      ```
176    
1775. Register **RegisterWatcher** as an ArkTS API.
178
179   In the **napi_init.cpp** file, register **RegisterWatcher** as an ArkTS API.
180
181   ```c++
182   static napi_value Init(napi_env env, napi_value exports)
183   {
184       napi_property_descriptor desc[] = {
185           { "registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr }
186       };
187       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
188       return exports;
189   }
190   ```
191
192   In the **index.d.ts** file, define the ArkTS API.
193
194   ```typescript
195   export const registerWatcher: () => void;
196   ```
197
1986. In the **EntryAbility.ets** file, add the following interface invocation to **onCreate()**.
199
200   ```typescript
201   import testNapi from 'libentry.so'
202   import hidebug from '@kit.PerformanceAnalysisKit'
203   export default class EntryAbility extends UIAbility {
204     onCreate(want, launchParam) {
205       // Register the system event watcher at startup.
206       testNapi.registerWatcher();
207     }
208   }
209   ```
210
2117. In the **entry/src/main/ets/pages/index.ets** file, add the **memoryleak** button and construct a scenario for triggering a resource leak event in **onClick()**.
212   In this case, use [hidebug.setAppResourceLimit](../reference/apis-performance-analysis-kit/js-apis-hidebug.md#hidebugsetappresourcelimit12) to set the memory limit to trigger a memory leak event. The sample code is as follows:
213
214   ```ts
215    Button("memoryleak").onClick(()=>{
216      // Construct a scenario for triggering a resource leak event in onClick(). The leak size is 1 MB.
217      hidebug.setAppResourceLimit("pss_memory", 1024, true);
218    })
219   ```
220
2218. Click the **Run** button in DevEco Studio to run the project, and then a memory leak event will be reported after 15 to 30 minutes.
222   For the same application, the memory leak event can be reported at most once within 24 hours. If the memory leak needs to be reported again within a shorter time, restart the device.
223
2249. After the memory leak event is reported, you can view the following event information in the **Log** window.
225
226   ```text
227   08-07 03:53:35.314 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.domain=OS
228   08-07 03:53:35.314 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.name=RESOURCE_OVERLIMIT
229   08-07 03:53:35.314 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.eventType=1
230   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.time=1502049167732
231   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.pid=1587
232   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.uid=20010043
233   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.resource_type=pss_memory
234   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
235   08-07 03:53:35.349 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.bundle_version=1.0.0
236   08-07 03:53:35.350 1719-1738/? I A00000/testTag: HiAppEvent eventInfo.params.memory={"pss":2100257,"rss":1352644,"sys_avail_mem":250272,"sys_free_mem":60004,"sys_total_mem":1992340,"vss":2462936}
237   ```
238
23910. Remove the application event watcher.
240
241    ```c++
242    static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
243        // Remove the watcher.
244        OH_HiAppEvent_RemoveWatcher(systemEventWatcher);
245        return {};
246    }
247    ```
248
24911. Destroy the application event watcher.
250
251    ```c++
252    static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
253        // Destroy the created watcher and set systemEventWatcher to nullptr.
254        OH_HiAppEvent_DestroyWatcher(systemEventWatcher);
255        systemEventWatcher = nullptr;
256        return {};
257    }
258    ```
259
260<!--no_check-->