• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 订阅应用冻屏事件(C/C++)
2
3<!--Kit: Performance Analysis Kit-->
4<!--Subsystem: HiviewDFX-->
5<!--Owner: @rr_cn-->
6<!--Designer: @peterhuangyu-->
7<!--Tester: @gcw_KuLfPSbe-->
8<!--Adviser: @foryourself-->
9
10## 简介
11
12本文介绍如何使用HiAppEvent提供的C/C++接口订阅应用冻屏事件。接口的详细使用说明(参数限制、取值范围等)请参考[HiAppEvent C API文档](../reference/apis-performance-analysis-kit/capi-hiappevent-h.md)。
13
14## 接口说明
15
16| 接口名 | 描述 |
17| -------- | -------- |
18| int OH_HiAppEvent_AddWatcher(HiAppEvent_Watcher \*watcher) | 添加应用事件观察者,以添加对应用事件的订阅。 |
19| int OH_HiAppEvent_RemoveWatcher(HiAppEvent_Watcher \*watcher) | 移除应用事件观察者,以移除对应用事件的订阅。 |
20
21## 开发步骤
22
23### 添加事件观察者
24
25以实现对用户点击按钮触发应用无响应场景生成的应用冻屏事件订阅为例,说明开发步骤。
26
271. 新建Native C++工程,并将jsoncpp导入到新建工程内,目录结构如下。
28
29   ```yml
30   entry:
31     src:
32       main:
33         cpp:
34           json:
35             - json.h
36             - json-forwards.h
37           types:
38             libentry:
39               - index.d.ts
40           - CMakeLists.txt
41           - jsoncpp.cpp
42           - napi_init.cpp
43         ets:
44           entryability:
45             - EntryAbility.ets
46           pages:
47             - Index.ets
48   ```
49
502. 编辑“CMakeLists.txt”文件,添加源文件及动态库。
51
52   ```cmake
53   # 新增jsoncpp.cpp(解析订阅事件中的json字符串)源文件
54   add_library(entry SHARED napi_init.cpp jsoncpp.cpp)
55   # 新增动态库依赖libhiappevent_ndk.z.solibhilog_ndk.z.so(日志输出)
56   target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so)
57   ```
58
593. 编辑“napi_init.cpp”文件,导入依赖的文件,并定义LOG_TAG。
60
61   ```c++
62   #include "napi/native_api.h"
63   #include "json/json.h"
64   #include "hilog/log.h"
65   #include "hiappevent/hiappevent.h"
66
67   #undef LOG_TAG
68   #define LOG_TAG "testTag"
69   ```
70
714. 订阅系统事件。
72
73   - onReceive类型观察者
74
75      编辑“napi_init.cpp”文件,定义onReceive类型观察者相关方法:
76
77      ```c++
78      //定义一变量,用来缓存创建的观察者的指针。
79      static HiAppEvent_Watcher *systemEventWatcher;
80
81      static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
82          for (int i = 0; i < groupLen; ++i) {
83              for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
84                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
85                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
86                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
87                  if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 &&
88                      strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_APP_FREEZE) == 0) {
89                      Json::Value params;
90                      Json::Reader reader(Json::Features::strictMode());
91                      Json::FastWriter writer;
92                      if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
93                          auto time = params["time"].asInt64();
94                          auto foreground = params["foreground"].asBool();
95                          auto bundleVersion = params["bundle_version"].asString();
96                          auto bundleName = params["bundle_name"].asString();
97                          auto processName = params["process_name"].asString();
98                          auto pid = params["pid"].asInt();
99                          auto uid = params["uid"].asInt();
100                          auto uuid = params["uuid"].asString();
101                          auto exception = writer.write(params["exception"]);
102                          auto hilogSize = params["hilog"].size();
103                          auto handleSize = params["event_handler"].size();
104                          auto handleSize3s = params["event_handler_size_3s"].asString();
105                          auto handleSize6s = params["event_handler_size_6s"].asString();
106                          auto peerBindSize = params["peer_binder"].size();
107                          auto threadSize = params["threads"].size();
108                          auto memory = writer.write(params["memory"]);
109                          auto externalLog = writer.write(params["external_log"]);
110                          auto logOverLimit = params["log_over_limit"].asBool();
111                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
112                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground);
113                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
114                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
115                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.process_name=%{public}s", processName.c_str());
116                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
117                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
118                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str());
119                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str());
120                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize);
121                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler.size=%{public}d", handleSize);
122                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_3s.size=%{public}s", handleSize3s.c_str());
123                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_6s.size=%{public}s", handleSize6s.c_str());
124                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.peer_binder.size=%{public}d", peerBindSize);
125                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.threads.size=%{public}d", threadSize);
126                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str());
127                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
128                          OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit);
129                      }
130                  }
131              }
132          }
133      }
134
135      static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
136          // 开发者自定义观察者名称,系统根据不同的名称来识别不同的观察者。
137          systemEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
138          // 设置订阅的事件为EVENT_APP_FREEZE。
139          const char *names[] = {EVENT_APP_FREEZE};
140          // 开发者订阅感兴趣的事件,此处订阅了系统事件。
141          OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
142          // 开发者设置已实现的回调函数,观察者接收到事件后回立即触发OnReceive回调。
143          OH_HiAppEvent_SetWatcherOnReceive(systemEventWatcher, OnReceive);
144          // 使观察者开始监听订阅的事件。
145          OH_HiAppEvent_AddWatcher(systemEventWatcher);
146          return {};
147      }
148      ```
149
150   - onTrigger类型观察者
151
152      编辑“napi_init.cpp”文件,定义OnTrigger类型观察者相关方法:
153
154      ```c++
155      //定义一变量,用来缓存创建的观察者的指针。
156      static HiAppEvent_Watcher *systemEventWatcher;
157
158      // 开发者可以自行实现获取已监听到事件的回调函数,其中events指针指向内容仅在该函数内有效。
159      static void OnTake(const char *const *events, uint32_t eventLen) {
160          Json::Reader reader(Json::Features::strictMode());
161          Json::FastWriter writer;
162          for (int i = 0; i < eventLen; ++i) {
163              Json::Value eventInfo;
164              if (reader.parse(events[i], eventInfo)) {
165                  auto domain =  eventInfo["domain_"].asString();
166                  auto name = eventInfo["name_"].asString();
167                  auto type = eventInfo["type_"].asInt();
168                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
169                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
170                  OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
171                  if (domain ==  DOMAIN_OS && name == EVENT_APP_FREEZE) {
172                      auto time = eventInfo["time"].asInt64();
173                      auto foreground = eventInfo["foreground"].asBool();
174                      auto bundleVersion = eventInfo["bundle_version"].asString();
175                      auto bundleName = eventInfo["bundle_name"].asString();
176                      auto processName = eventInfo["process_name"].asString();
177                      auto pid = eventInfo["pid"].asInt();
178                      auto uid = eventInfo["uid"].asInt();
179                      auto uuid = eventInfo["uuid"].asString();
180                      auto exception = writer.write(eventInfo["exception"]);
181                      auto hilogSize = eventInfo["hilog"].size();
182                      auto handleSize =  eventInfo["event_handler"].size();
183                      auto handleSize3s =  eventInfo["event_handler_size_3s"].asString();
184                      auto handleSize6s =  eventInfo["event_handler_size_6s"].asString();
185                      auto peerBindSize =  eventInfo["peer_binder"].size();
186                      auto threadSize =  eventInfo["threads"].size();
187                       auto memory =  writer.write(eventInfo["memory"]);
188                      auto externalLog = writer.write(eventInfo["external_log"]);
189                      auto logOverLimit = eventInfo["log_over_limit"].asBool();
190                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
191                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground);
192                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
193                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
194                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.process_name=%{public}s", processName.c_str());
195                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
196                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
197                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str());
198                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str());
199                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize);
200                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler.size=%{public}d", handleSize);
201                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_3s.size=%{public}s", handleSize3s.c_str());
202                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_6s.size=%{public}s", handleSize6s.c_str());
203                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.peer_binder.size=%{public}d", peerBindSize);
204                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.threads.size=%{public}d", threadSize);
205                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str());
206                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
207                      OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit);
208                  }
209              }
210          }
211      }
212
213      // 开发者可以自行实现订阅回调函数,以便对获取到的事件打点数据进行自定义处理。
214      static void OnTrigger(int row, int size) {
215          // 接收回调后,获取指定数量的已接收事件。
216          OH_HiAppEvent_TakeWatcherData(systemEventWatcher, row, OnTake);
217      }
218
219      static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
220          // 开发者自定义观察者名称,系统根据不同的名称来识别不同的观察者。
221          systemEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
222          // 设置订阅的事件为EVENT_APP_FREEZE。
223          const char *names[] = {EVENT_APP_FREEZE};
224          // 开发者订阅感兴趣的事件,此处订阅了系统事件。
225          OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
226          // 开发者设置已实现的回调函数,需OH_HiAppEvent_SetTriggerCondition设置的条件满足方可触发。
227          OH_HiAppEvent_SetWatcherOnTrigger(systemEventWatcher, OnTrigger);
228          // 开发者可以设置订阅触发回调的条件,此处是设置新增事件打点数量为1个时,触发onTrigger回调。
229          OH_HiAppEvent_SetTriggerCondition(systemEventWatcher, 1, 0, 0);
230          // 使观察者开始监听订阅的事件。
231          OH_HiAppEvent_AddWatcher(systemEventWatcher);
232          return {};
233      }
234      ```
235
2365. 将RegisterWatcher注册为ArkTS接口。
237
238   编辑“napi_init.cpp”文件,将RegisterWatcher注册为ArkTS接口:
239
240   ```c++
241   static napi_value Init(napi_env env, napi_value exports)
242   {
243       napi_property_descriptor desc[] = {
244           { "registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr }
245       };
246       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
247       return exports;
248   }
249   ```
250
251   编辑“index.d.ts”文件,定义ArkTS接口:
252
253   ```typescript
254   export const registerWatcher: () => void;
255   ```
256
2576. 编辑“EntryAbility.ets”文件,在onCreate()函数中新增接口调用。
258
259   ```typescript
260   // 导入依赖模块
261   import testNapi from 'libentry.so'
262
263   // 在onCreate()函数中新增接口调用
264   // 启动时,注册系统事件观察者
265   testNapi.registerWatcher();
266   ```
267
2687. 编辑“Index.ets”文件,新增按钮触发卡顿事件。
269
270   ```typescript
271   Button("appFreeze").onClick(() => {
272     setTimeout(()=>{
273       while(true) {}
274     }, 1000)
275   })
276   ```
277
2788. 点击DevEco Studio界面中的运行按钮,运行应用工程,然后在应用界面中点击按钮“appFreeze”,触发一次应用无响应事件。
279
280### 验证观察者是否订阅到应用无响应事件
281
2821. 应用工程崩溃退出后再次运行可以在Log窗口看到对系统事件数据的处理日志。
283
284   ```text
285   HiAppEvent eventInfo.domain=OS
286   HiAppEvent eventInfo.name=APP_FREEZE
287   HiAppEvent eventInfo.eventType=1
288   HiAppEvent eventInfo.params.time=1502049167732
289   HiAppEvent eventInfo.params.foreground=1
290   HiAppEvent eventInfo.params.bundle_version=1.0.0
291   HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
292   HiAppEvent eventInfo.params.process_name=com.example.myapplication
293   HiAppEvent eventInfo.params.pid=1587
294   HiAppEvent eventInfo.params.uid=20010043
295   HiAppEvent eventInfo.params.uuid=a78a23b20f3dd9730f18a5cfa2304deac1104ac4086755c4a59cf7c72d414e2e
296   HiAppEvent eventInfo.params.exception={"message":"App main thread is not response!","name":"THREAD_BLOCK_6S"}
297   HiAppEvent eventInfo.params.hilog.size=6
298   HiAppEvent eventInfo.params.event_handler.size=16
299   HiAppEvent eventInfo.params.event_handler_3s.size=15
300   HiAppEvent eventInfo.params.event_handler_6s.size=16
301   HiAppEvent eventInfo.params.peer_binder.size=0
302   HiAppEvent eventInfo.params.threads.size=28
303   HiAppEvent eventInfo.params.memory={"pss":0,"rss":0,"sys_avail_mem":1326520,"sys_free_mem":940588,"sys_total_mem":1992340,"vss":0}
304   HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_FREEZE_1502049185239_1587.log"]
305   HiAppEvent eventInfo.params.log_over_limit=0
306   ```
307
308### 移除并销毁事件观察者
309
3101. 移除事件观察者。
311
312   ```c++
313   static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
314       // 使观察者停止监听事件
315       OH_HiAppEvent_RemoveWatcher(systemEventWatcher);
316       return {};
317   }
318   ```
319
3202. 销毁事件观察者。
321
322   ```c++
323   static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
324       // 销毁创建的观察者,并置systemEventWatcher为nullptr。
325       OH_HiAppEvent_DestroyWatcher(systemEventWatcher);
326       systemEventWatcher = nullptr;
327       return {};
328   }
329   ```
330