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-->