diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/.gitignore b/PerformanceAnalysisKit/HiAppEvent/EventSub/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/app.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..11ec180f4bdd0479c366174be005d029057fa76b --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.eventsub", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/element/string.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..5e8cd8a19f7473dae53e6273e9b38ea3e70d4f4e --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "EventSub" + } + ] +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/media/app_icon.png b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/PerformanceAnalysisKit/HiAppEvent/EventSub/AppScope/resources/base/media/app_icon.png differ diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/README_zh.md b/PerformanceAnalysisKit/HiAppEvent/EventSub/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..af5c022f9681c0c201a135ebe2adaff284b7bd2a --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/README_zh.md @@ -0,0 +1,475 @@ +# 事件订阅 + +### 介绍 + +本示例主要展示了使用HiAppEvent提供的事件订阅接口,获取本地应用事件(AppEvent),系统崩溃事件(CrashEvent),系统卡死事件(FreezeEvent),系统资源泄漏事件(PssLeakEvent),系统踩内存事件(ASANEvent)以及主线程超时事件(TimeOutEvent)。 + +该工程中的展示的代码详细描述可查如下链接: + +- [订阅应用事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-app-events-arkts.md) + +- [订阅应用事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-app-events-ndk.md) + +- [订阅崩溃事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-crash-events-arkts.md) + +- [订阅崩溃事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-crash-events-ndk.md) + +- [订阅卡死事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-freeze-events-arkts.md) + +- [订阅卡死事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-freeze-events-ndk.md) + +- [订阅资源泄漏事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-resourceleak-events-arkts.md) + +- [订阅资源泄漏事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-resourceleak-events-ndk.md) + +- [订阅踩内存事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-address-sanitizer-events-arkts.md) + +- [订阅踩内存事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-address-sanitizer-events-ndk.md) + +- [订阅主线程超时事件(ArkTS)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-mainthreadjank-events-arkts.md) + +- [订阅主线程超时事件(C/C++)](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/dfx/hiappevent-watcher-mainthreadjank-events-ndk.md) + +### 效果预览 + +| 主页 | +| :----------------------------------------------------------: | +| z | + +#### 使用说明 + +请先按照工程目录添加json相关文件,否则编译无法通过 + +##### 1.订阅应用事件(ArkTS)使用说明 + +1.在应用侧主界面,点击"writeEvent ArkTS"按钮,从ets层触发一次按钮点击事件打点; + +2.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"testTag"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=button +HiAppEvent eventInfo.name=click +HiAppEvent eventInfo.eventType=4 +readEvent C++ Success // C++读事件成功 +HiAppEvent eventInfo.params.click_time=100 +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=button +HiAppEvent eventInfo.name=click +HiAppEvent eventInfo.eventType=4 +HiAppEvent eventInfo.params.click_time=100 +writeEvent ArkTS success // ArkTS写事件成功 +HiAppEvent onTrigger: curRow=1, curSize=124 +readEvent ArkTS Success // ArkTS读事件成功 +HiAppEvent eventPkg.packageId=0 +HiAppEvent eventPkg.row=1 +HiAppEvent eventPkg.size=124 +HiAppEvent eventPkg.info={"domain_":"button","name_":"click","type_":4,"time_":1501889519611,"tz_":"+0800","pid_":2579,"tid_":2579,"click_time":100 +``` + +注意: + +1.出现C++读事件成功的原因是本示例中ArkTS和C++写的打点事件是相同的,故读取时均能读到,不影响结果。 + +2.C++读事件比ArkTS写事件先出现的原因可能是C++层的日志打印执行速度更快,不影响结果。 + +##### 2.订阅应用事件(C/C++)使用说明 + +1.在应用侧主界面,点击"writeEvent C++"按钮,从c++层触发一次按钮点击事件打点; + +2.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"testTag"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +writeEvent C++ success // C++写事件成功 +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=button +HiAppEvent eventInfo.name=click +HiAppEvent eventInfo.eventType=4 +readEvent C++ Success // C++读事件成功 +HiAppEvent eventInfo.params.click_time=1501890218 +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=button +HiAppEvent eventInfo.name=click +HiAppEvent eventInfo.eventType=4 +HiAppEvent eventInfo.params.click_time=1501890218 +HiAppEvent onTrigger: curRow=1, curSize=131 +readEvent ArkTS Success // ArkTS读事件成功 +HiAppEvent eventPkg.packageId=2 +HiAppEvent eventPkg.row=1 +HiAppEvent eventPkg.size=131 +HiAppEvent eventPkg.info={"domain_":"button","name_":"click","type_":4,"time_":1501890218641,"tz_":"+0800","pid_":2579,"tid_":2579,"click_time":1501890218} +``` + +注意: + +1.出现ArkTS读事件成功的原因是本示例中ArkTS和C++写、读的打点事件是相同的,故读取时均能读到,不影响结果。 + +##### 3.订阅崩溃事件(ArkTS&C++) + +1.在应用侧主界面,点击"appCrash ArkTS&C++"按钮触发崩溃,应用退出后重启应用; + +2.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"HiAppevent"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_CRASH +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501890680817 +HiAppEvent eventInfo.params.crash_type=JsError +HiAppEvent eventInfo.params.foreground=1 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=2579 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=114e22cab85a934b58dca7442edb14bad4301a7fe9a4f5ee5c662c557ada08b1 +HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON: Empty Text","name":"SyntaxError","stack":" at anonymous entry (entry/src/main/ets/pages/Index.ets:65:13)\n"} +HiAppEvent eventInfo.params.hilog.size=100 +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1501890680961_2579.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ onTrigger类型观察者日志输出 +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_CRASH +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501890680817 +HiAppEvent eventInfo.params.crash_type=JsError +HiAppEvent eventInfo.params.foreground=1 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=2579 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=114e22cab85a934b58dca7442edb14bad4301a7fe9a4f5ee5c662c557ada08b1 +HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON: Empty Text","name":"SyntaxError","stack":" at anonymous entry (entry/src/main/ets/pages/Index.ets:65:13)\n"} +HiAppEvent eventInfo.params.hilog.size=100 +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1501890680961_2579.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ onReceive类型观察者日志输出 +HiAppEvent onReceive: domain=OS +HiAppEvent eventName=APP_CRASH +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_CRASH +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501890680817 +HiAppEvent eventInfo.params.crash_type=JsError +HiAppEvent eventInfo.params.foreground=true +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=2579 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=114e22cab85a934b58dca7442edb14bad4301a7fe9a4f5ee5c662c557ada08b1 +HiAppEvent eventInfo.params.exception={"message":"Unexpected Text in JSON: Empty Text","name":"SyntaxError","stack":" at anonymous entry (entry/src/main/ets/pages/Index.ets:65:13)\n"} +HiAppEvent eventInfo.params.hilog.size=100 +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1501890680961_2579.log"] +HiAppEvent eventInfo.params.log_over_limit=false +HiAppEvent eventInfo.params.test_data=100 +// 以上为ArkTS onReceive类型观察者日志输出 +``` + +注意: + +1.要确认日志输出中的eventInfo.name为APP_CRASH。 + +2.C++实现了onReceive和onTrigger两种观察者,ArkTS实现了onReceive观察者。 + +##### 4.订阅卡死事件(ArkTS&C++) + +1.在应用侧主界面,点击"appFreeze ArkTS&C++"按钮触发卡死(可能需要几秒),应用退出后重启应用; + +2.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"HiAppevent"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_FREEZE +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501891964864 +HiAppEvent eventInfo.params.foreground=1 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.process_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=5105 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=c450b09dcefc0f9bd9b6cb4230e0c8f2d1b1e3c5becf82d272ef1a3241c958da +HiAppEvent eventInfo.params.exception={"message":"App main thread is not response!","name":"THREAD_BLOCK_6S"} +HiAppEvent eventInfo.params.hilog.size=88 +HiAppEvent eventInfo.params.event_handler.size=0 +HiAppEvent eventInfo.params.event_handler_3s.size=0 +HiAppEvent eventInfo.params.event_handler_6s.size=0 +HiAppEvent eventInfo.params.peer_binder.size=0 +HiAppEvent eventInfo.params.threads.size=38 +HiAppEvent eventInfo.params.memory={"pss":0,"rss":0,"sys_avail_mem":1000060,"sys_free_mem":485304,"sys_total_mem":1935816,"vss":0} +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_FREEZE_1501891977850_5105.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ onReceive类型观察者日志输出 +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_FREEZE +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501891964864 +HiAppEvent eventInfo.params.foreground=1 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.process_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=5105 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=c450b09dcefc0f9bd9b6cb4230e0c8f2d1b1e3c5becf82d272ef1a3241c958da +HiAppEvent eventInfo.params.exception={"message":"App main thread is not response!","name":"THREAD_BLOCK_6S"} +HiAppEvent eventInfo.params.hilog.size=88 +HiAppEvent eventInfo.params.event_handler.size=0 +HiAppEvent eventInfo.params.event_handler_3s.size=0 +HiAppEvent eventInfo.params.event_handler_6s.size=0 +HiAppEvent eventInfo.params.peer_binder.size=0 +HiAppEvent eventInfo.params.threads.size=38 +HiAppEvent eventInfo.params.memory={"pss":0,"rss":0,"sys_avail_mem":1000060,"sys_free_mem":485304,"sys_total_mem":1935816,"vss":0} +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_FREEZE_1501891977850_5105.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ onTrigger类型观察者日志输出 +HiAppEvent onReceive: domain=OS +HiAppEvent eventName=APP_FREEZE +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=APP_FREEZE +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1501891964864 +HiAppEvent eventInfo.params.foreground=true +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.samples.eventsub +HiAppEvent eventInfo.params.process_name=com.samples.eventsub +HiAppEvent eventInfo.params.pid=5105 +HiAppEvent eventInfo.params.uid=20010051 +HiAppEvent eventInfo.params.uuid=c450b09dcefc0f9bd9b6cb4230e0c8f2d1b1e3c5becf82d272ef1a3241c958da +HiAppEvent eventInfo.params.exception={"message":"App main thread is not response!","name":"THREAD_BLOCK_6S"} +HiAppEvent eventInfo.params.hilog.size=88 +HiAppEvent eventInfo.params.event_handler.size=0 +HiAppEvent eventInfo.params.event_handler_size_3s=0 +HiAppEvent eventInfo.params.event_handler_size_6s=0 +HiAppEvent eventInfo.params.peer_binder.size=0 +HiAppEvent eventInfo.params.threads.size=38 +HiAppEvent eventInfo.params.memory={"pss":0,"rss":0,"sys_avail_mem":1000060,"sys_free_mem":485304,"sys_total_mem":1935816,"vss":0} +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_FREEZE_1501891977850_5105.log"] +HiAppEvent eventInfo.params.log_over_limit=false +HiAppEvent eventInfo.params.test_data=100 +// 以上为ArkTS onReceive类型观察者日志输出 +``` + +注意: + +1.如果在应用重启时立即在log窗口搜索日志会出现日志暂时未出现的情况,原因是Freeze事件处理时间较长,等待10秒即可。 + +2.要确认日志输出中的eventInfo.name为APP_FREEZE。 + +3.C++实现了onReceive和onTrigger两种观察者,ArkTS实现了onReceive观察者。 + +##### 5.订阅资源泄漏事件(ArkTS&C++) + +1.先在设备“开发者选项”中打开“系统资源泄漏日志”,并重启设备; + +2.在应用侧主界面,点击"pssLeak ArkTS&C++"按钮触发资源泄露事件,等待15~30分钟,会上报应用内存泄漏事件; + +3.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"HiAppevent"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=RESOURCE_OVERLIMIT +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1502049167732 +HiAppEvent eventInfo.params.pid=1587 +HiAppEvent eventInfo.params.uid=20010043 +HiAppEvent eventInfo.params.resource_type=pss_memory +HiAppEvent eventInfo.params.bundle_name=com.example.eventsub +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.memory={"pss":2100257,"rss":1352644,"sys_avail_mem":250272,"sys_free_mem":60004,"sys_total_mem":1992340,"vss":2462936} +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572401_6808.log","/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572412_6808.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +以上为C++ OnReceive类型观察者日志输出 +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=RESOURCE_OVERLIMIT +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1502049167732 +HiAppEvent eventInfo.params.pid=1587 +HiAppEvent eventInfo.params.uid=20010043 +HiAppEvent eventInfo.params.resource_type=pss_memory +HiAppEvent eventInfo.params.bundle_name=com.example.eventsub +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.memory={"pss":2100257,"rss":1352644,"sys_avail_mem":250272,"sys_free_mem":60004,"sys_total_mem":1992340,"vss":2462936} +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572401_6808.log","/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572412_6808.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ onTrigger类型观察者日志输出 +HiAppEvent onReceive: domain=OS +HiAppEvent eventName=RESOURCE_OVERLIMIT +HiAppEvent eventInfo={"domain":"OS","name":"RESOURCE_OVERLIMIT","eventType":1,"params":{"bundle_name":"com.example.eventsub","bundle_version":"1.0.0","memory":{"pss":2100257,"rss":1352644,"sys_avail_mem":250272,"sys_free_mem":60004,"sys_total_mem":1992340,"vss":2462936},"pid":20731,"resource_type":"pss_memory","time":1502348798106,"uid":20010044,"external_log": ["/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572401_6808.log", "/data/storage/el2/log/resourcelimit/RESOURCE_OVERLIMIT_1725614572412_6808.log"], "log_over_limit": false}}eventInfo.params.bundle_version=1.0.0 +// 以上为ArkTS onReceive类型观察者日志输出 +``` + +注意: + +1.如果设备“开发者选项”中没有“系统资源泄漏日志”选项,或有该选项但重启后该选项自动关闭,则无法测试该功能。 + +2.要确认日志输出中的eventInfo.name为RESOURCE_OVERLIMIT。 + +3.C++实现了onReceive和onTrigger两种观察者,ArkTS实现了onReceive观察者。 + +##### 6.订阅踩内存事件(ArkTS&C++) + +1.点击DevEco Studio界面中的“entry”,点击“Edit Configurations”,点击“Diagnostics”,勾选“Address Sanitizer”,保存设置。 + +2.在应用侧主界面,点击"appAsanEvent ArkTS&C++"按钮触发踩内存事件,应用退出后重启应用; + +3.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"HiAppevent"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnTrigger +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=ADDRESS_SANITIZER +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1609739933049 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.example.cpp +HiAppEvent eventInfo.params.pid=6628 +HiAppEvent eventInfo.params.uid=20010050 +HiAppEvent eventInfo.params.type="stack-buffer-overflow" +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/ADDRESS_SANITIZER_1609739933234_6628.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ OnTrigger观察者日志输出 +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=ADDRESS_SANITIZER +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1609739933049 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.example.cpp +HiAppEvent eventInfo.params.pid=6628 +HiAppEvent eventInfo.params.uid=20010050 +HiAppEvent eventInfo.params.type="stack-buffer-overflow" +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/ADDRESS_SANITIZER_1609739933234_6628.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ OnReceiver观察者日志输出 +HiAppEvent onReceive: domain=OS +HiAppEvent eventName=ADDRESS_SANITIZER +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=ADDRESS_SANITIZER +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1609739473665 +HiAppEvent eventInfo.params.crash_type=JsError +HiAppEvent eventInfo.params.foreground=true +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.example.eventsub +HiAppEvent eventInfo.params.pid=4116 +HiAppEvent eventInfo.params.uid=20010053 +HiAppEvent eventInfo.type=stack-buffer-overflow +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/ADDRESS_SANITIZER_1609739473837_4116.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为ArkTS onReceive类型观察者日志输出 +``` + +注意: + +1.如果在勾选“Address Sanitizer”设置后,应用无法在设备上打开,可能是DevEco Studio和设备版本的原因,请切换版本尝试。 + +2.要确认日志输出中的eventInfo.name为ADDRESS_SANITIZER。 + +3.C++实现了onReceive和onTrigger两种观察者,ArkTS实现了onReceive观察者。 + +##### 7.订阅主线程超时事件(ArkTS&C++) + +1.测试设备应能使用开发者使用nolog版本,开发者模式处于关闭状态,可以使能主线程超时检测抓取trace的功能,建议使用真机测试; + +2.在应用侧主界面,快速连续点击两次"timeOut350 ArkTS&C++"按钮触发主线程超时事件; + +3.在DevEco Studio侧下方导航栏,切换到"Log"窗口,日志过滤选择"All log of selected app",搜索内容设置为"HiAppevent"。此时窗口仅显示符合条件的日志,打印日志结果为: + +``` +HiAppEvent eventInfo.WatcherType=OnReceive +HiAppEvent eventInfo.domain=OS +HiAppEvent eventInfo.name=MAIN_THREAD_JANK +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1609739933049 +HiAppEvent eventInfo.params.pid=6628 +HiAppEvent eventInfo.params.uid=20010050 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.example.cpp +HiAppEvent eventInfo.params.begin_time=1609739932900 +HiAppEvent eventInfo.params.end_time=1609739933049 +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/MAIN_THREAD_JANK_1609739933234_6628.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为C++ OnReceiver观察者日志输出 +HiAppEvent onReceive: domain=OS +HiAppEvent eventName=MAIN_THREAD_JANK +HiAppEvent eventInfo.eventType=1 +HiAppEvent eventInfo.params.time=1609739473665 +HiAppEvent eventInfo.params.bundle_version=1.0.0 +HiAppEvent eventInfo.params.bundle_name=com.example.eventsub +HiAppEvent eventInfo.params.pid=4116 +HiAppEvent eventInfo.params.uid=20010053 +HiAppEvent eventInfo.params.begin_time=1717593620016 +HiAppEvent eventInfo.params.end_time=1717593620518 +HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/APP_CRASH_1609739473837_4116.log"] +HiAppEvent eventInfo.params.log_over_limit=0 +// 以上为ArkTS onReceive类型观察者日志输出 +``` + +注意: + +1.如果测试设备无法达到"使用nolog版本,开发者模式处于关闭状态,可以使能主线程超时检测抓取trace的功能"的条件,无法触发回调,日志不会输出。 + +2.要确认日志输出中的eventInfo.name为MAIN_THREAD_JANK。 + +3.C++实现了onReceive观察者,ArkTS实现了onReceive观察者。 + +### 工程目录 + +``` +entry/src/main +├─cpp +│ ├─json +│ │ └─json.h // 自行添加 +│ │ └─json-forwards.h // 自行添加 +│ ├─types +│ │ └─libentry +│ │ └─Index.d.ts // 定义ArkTS接口 +│ ├─CMakeLists.txt // 导入so链接 +│ ├─napi_init.cpp // 功能函数,观察者定义 +│ └─jsoncpp.cpp // 自行添加 +└─ets + ├─entryability + │ └─EntryAbility.ets // 新增接口调用 + └─pages + └─Index.ets // 主页 +``` + +### 具体实现 + +1.在entry/src/main/cpp下添加三方库文件jsoncpp.cpp和目录"json","json"目录下添加json.h和json-forwards.h; +2.编辑"CMakeLists.txt"文件,添加源文件及动态库; +3.编辑"napi_init.cpp"文件,导入依赖的文件,定义onReceive和onTrigger类型观察者相关方法,注册为ArkTS接口; +4.编辑"index.d.ts"文件,定义ArkTS接口; +5.编辑"EntryAbility.ets"文件,在onCreate()函数中新增观察者调用(包括ArkTS添加观察者和调用C++接口从而调用观察者); +6.编辑"Index.ets"文件,新增按钮触发各种事件。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:RK3568; +2. 本示例已适配API14版本SDK,版本号:5.0.2.58,镜像版本号:OpenHarmony5.0.2.58; +3. 本示例需要使用DevEco Studio(5.0.3.910)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/PerformanceAnalysisKit/HiAppEvent/EventSub/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/openharmony/applications_app_samples.git +git pull origin master +``` \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/build-profile.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8fcacd7e6cb640f51801f20ecfe8fb9a48f25b70 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/build-profile.json5 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": 14, + "compileSdkVersion": 14, + "targetSdkVersion": 14, + "runtimeOS": "OpenHarmony" + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/.gitignore b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/build-profile.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a6a5531c56160aaacf1fb0af4365ebefb11621de --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/build-profile.json5 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": [ + "arm64-v8a", + "x86_64", + "armeabi-v7a" + ] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/hvigorfile.ts b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e042e3f963ab27941d3b34f1f027da9933b81df1 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/obfuscation-rules.txt b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..fdbb5b9852d7dd5f39bddaeb21ab5ee1f3346749 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/obfuscation-rules.txt @@ -0,0 +1,22 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/oh-package.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d55b3e8de9d84c6b79c43869a2b2f0948633f7ec --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/oh-package.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/CMakeLists.txt b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fa2f9febd17f978b15af959a2b18032d46f06a46 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,17 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(CPP) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +# 新增jsoncpp.cpp(解析订阅事件中的json字符串)源文件 +add_library(entry SHARED napi_init.cpp jsoncpp.cpp) +# 新增动态库依赖libhiappevent_ndk.z.so和libhilog_ndk.z.so(日志输出) +target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so) diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/napi_init.cpp b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d5060000c0cdea73402017d753afa7ff84ed0da --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi/native_api.h" +#include "json/json.h" +#include "hilog/log.h" +#include "hiappevent/hiappevent.h" +#include "hiappevent/hiappevent_event.h" + +#undef LOG_TAG +#define LOG_TAG "testTag" + +// 定义一变量,用来缓存创建的观察者的指针。 +static HiAppEvent_Watcher *eventWatcherR; +static HiAppEvent_Watcher *eventWatcherT; + +static void OnReceiveDottingEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, "button") == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, "click") == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + auto time = params["click_time"].asInt64(); + OH_LOG_INFO(LogType::LOG_APP, "readEvent C++ Success"); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", time); + } + } +} + +static void OnReceiveCrashEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_APP_CRASH) == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + auto time = params["time"].asInt64(); + auto crashType = params["crash_type"].asString(); + auto foreground = params["foreground"].asBool(); + auto bundleVersion = params["bundle_version"].asString(); + auto bundleName = params["bundle_name"].asString(); + auto pid = params["pid"].asInt(); + auto uid = params["uid"].asInt(); + auto uuid = params["uuid"].asString(); + auto exception = writer.write(params["exception"]); + auto hilogSize = params["hilog"].size(); + auto externalLog = writer.write(params["external_log"]); + auto logOverLimit = params["log_over_limit"].asBool(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", + crashType.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", + bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", + exception.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", + logOverLimit); + } + } +} +// OnReceiveFreezeEvent超出50行限制,将日志输出单独抽出 +static void FreezeEventOutput(Json::Value params, Json::FastWriter writer) +{ + auto time = params["time"].asInt64(); + auto foreground = params["foreground"].asBool(); + auto bundleVersion = params["bundle_version"].asString(); + auto bundleName = params["bundle_name"].asString(); + auto processName = params["process_name"].asString(); + auto pid = params["pid"].asInt(); + auto uid = params["uid"].asInt(); + auto uuid = params["uuid"].asString(); + auto exception = writer.write(params["exception"]); + auto hilogSize = params["hilog"].size(); + auto handleSize = params["event_handler"].size(); + auto handleSize3s = params["event_handler_size_3s"].asString(); + auto handleSize6s = params["event_handler_size_6s"].asString(); + auto peerBindSize = params["peer_binder"].size(); + auto threadSize = params["threads"].size(); + auto memory = writer.write(params["memory"]); + auto externalLog = writer.write(params["external_log"]); + auto logOverLimit = params["log_over_limit"].asBool(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", + bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.process_name=%{public}s", + processName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", + exception.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler.size=%{public}d", + handleSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_3s.size=%{public}s", + handleSize3s.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_6s.size=%{public}s", + handleSize6s.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.peer_binder.size=%{public}d", + peerBindSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.threads.size=%{public}d", threadSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", + logOverLimit); +} + +static void OnReceiveFreezeEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_APP_FREEZE) == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + FreezeEventOutput(params, writer); + } + } +} + +static void OnReceivePssLeakEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_RESOURCE_OVERLIMIT) == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + auto time = params["time"].asInt64(); + auto pid = params["pid"].asInt(); + auto uid = params["uid"].asInt(); + auto resourceType = params["resourceType"].asString(); + auto bundleName = params["bundle_name"].asString(); + auto bundleVersion = params["bundle_version"].asString(); + auto memory = writer.write(params["memory"]); + auto externalLog = writer.write(params["external_log"]); + std::string logOverLimit = params["log_over_limit"].asBool() ? "true" : "false"; + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.resource_type=%{public}s", + resourceType.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", + bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", + logOverLimit.c_str()); + } + } +} + +static void OnReceiveAsanEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_ADDRESS_SANITIZER) == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + auto time = params["time"].asInt64(); + auto bundleVersion = params["bundle_version"].asString(); + auto bundleName = params["bundle_name"].asString(); + auto pid = params["pid"].asInt(); + auto uid = params["uid"].asInt(); + auto type = params["type"].asString(); + auto boolFlag = params["log_over_limit"].asBool(); + std::string logOverLimit = params["log_over_limit"].asBool() ? "true" : "false"; + auto externalLog = writer.write(params["external_log"]); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", + bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.type=%{public}s", type.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}s", + logOverLimit.c_str()); + } + } +} + +static void OnReceiveTimeOutEvent(const struct HiAppEvent_AppEventGroup *appEventGroups, int i, int j) +{ + if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 && + strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_MAIN_THREAD_JANK) == 0) { + Json::Value params; + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) { + auto time = params["time"].asInt64(); + auto pid = params["pid"].asInt(); + auto uid = params["uid"].asInt(); + auto bundleName = params["bundle_name"].asString(); + auto bundleVersion = params["bundle_version"].asString(); + auto beginTime = params["begin_time"].asInt64(); + auto endTime = params["end_time"].asInt64(); + auto externalLog = writer.write(params["external_log"]); + auto logOverLimit = params["logOverLimit"].asBool(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", + bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.begin_time=%{public}lld", beginTime); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.end_time=%{public}lld", endTime); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", + logOverLimit); + } + } +} + +static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) +{ + for (int i = 0; i < groupLen; ++i) { + for (int j = 0; j < appEventGroups[i].infoLen; ++j) { + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.WatcherType=OnReceive"); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", + appEventGroups[i].appEventInfos[j].domain); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", + appEventGroups[i].appEventInfos[j].name); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", + appEventGroups[i].appEventInfos[j].type); + // 处理打点事件 + OnReceiveDottingEvent(appEventGroups, i, j); + // 处理崩溃事件 + OnReceiveCrashEvent(appEventGroups, i, j); + // 处理卡死事件 + OnReceiveFreezeEvent(appEventGroups, i, j); + // 处理内存泄漏事件 + OnReceivePssLeakEvent(appEventGroups, i, j); + // 处理ASAN事件 + OnReceiveAsanEvent(appEventGroups, i, j); + // 处理主线程卡顿事件 + OnReceiveTimeOutEvent(appEventGroups, i, j); + } + } +} + +static void OnTriggerDottingEvent(std::string domain, std::string name, Json::Value eventInfo) +{ + if (domain == "button" && name == "click") { + auto clickTime = eventInfo["click_time"].asInt64(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.click_time=%{public}lld", clickTime); + } +} + +static void OnTriggerCrashEvent(std::string domain, std::string name, Json::Value eventInfo, Json::FastWriter writer) +{ + if (domain == DOMAIN_OS && name == EVENT_APP_CRASH) { + auto time = eventInfo["time"].asInt64(); + auto crashType = eventInfo["crash_type"].asString(); + auto foreground = eventInfo["foreground"].asBool(); + auto bundleVersion = eventInfo["bundle_version"].asString(); + auto bundleName = eventInfo["bundle_name"].asString(); + auto pid = eventInfo["pid"].asInt(); + auto uid = eventInfo["uid"].asInt(); + auto uuid = eventInfo["uuid"].asString(); + auto exception = writer.write(eventInfo["exception"]); + auto hilogSize = eventInfo["hilog"].size(); + auto externalLog = writer.write(eventInfo["external_log"]); + auto logOverLimit = eventInfo["log_over_limit"].asBool(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", crashType.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit); + } +} + +static void OnTriggerFreezeEvent(std::string domain, std::string name, Json::Value eventInfo, Json::FastWriter writer) +{ + if (domain == DOMAIN_OS && name == EVENT_APP_FREEZE) { + auto time = eventInfo["time"].asInt64(); + auto foreground = eventInfo["foreground"].asBool(); + auto bundleVersion = eventInfo["bundle_version"].asString(); + auto bundleName = eventInfo["bundle_name"].asString(); + auto processName = eventInfo["process_name"].asString(); + auto pid = eventInfo["pid"].asInt(); + auto uid = eventInfo["uid"].asInt(); + auto uuid = eventInfo["uuid"].asString(); + auto exception = writer.write(eventInfo["exception"]); + auto hilogSize = eventInfo["hilog"].size(); + auto handleSize = eventInfo["event_handler"].size(); + auto handleSize3s = eventInfo["event_handler_size_3s"].asString(); + auto handleSize6s = eventInfo["event_handler_size_6s"].asString(); + auto peerBindSize = eventInfo["peer_binder"].size(); + auto threadSize = eventInfo["threads"].size(); + auto memory = writer.write(eventInfo["memory"]); + auto externalLog = writer.write(eventInfo["external_log"]); + auto logOverLimit = eventInfo["log_over_limit"].asBool(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.foreground=%{public}d", foreground); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.process_name=%{public}s", + processName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uuid=%{public}s", uuid.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.exception=%{public}s", exception.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.hilog.size=%{public}d", hilogSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler.size=%{public}d", handleSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_3s.size=%{public}s", + handleSize3s.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.event_handler_6s.size=%{public}s", + handleSize6s.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.peer_binder.size=%{public}d", peerBindSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.threads.size=%{public}d", threadSize); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", logOverLimit); + } +} + +static void OnTriggerPssLeakEvent(std::string domain, std::string name, Json::Value eventInfo, Json::FastWriter writer) +{ + if (domain == DOMAIN_OS && name == EVENT_RESOURCE_OVERLIMIT) { + auto time = eventInfo["time"].asInt64(); + auto pid = eventInfo["pid"].asInt(); + auto uid = eventInfo["uid"].asInt(); + auto resourceType = eventInfo["resourceType"].asString(); + auto bundleName = eventInfo["bundle_name"].asString(); + auto bundleVersion = eventInfo["bundle_version"].asString(); + auto memory = writer.write(eventInfo["memory"]); + auto externalLog = writer.write(eventInfo["external_log"]); + std::string logOverLimit = eventInfo["log_over_limit"].asBool() ? "true" : "false"; + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.resource_type=%{public}s", + resourceType.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.memory=%{public}s", memory.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}d", + logOverLimit.c_str()); + } +} + +static void OnTriggerAsanEvent(std::string domain, std::string name, Json::Value eventInfo, Json::FastWriter writer) +{ + if (domain == DOMAIN_OS && name == EVENT_ADDRESS_SANITIZER) { + auto time = eventInfo["time"].asInt64(); + auto bundleVersion = eventInfo["bundle_version"].asString(); + auto bundleName = eventInfo["bundle_name"].asString(); + auto pid = eventInfo["pid"].asInt(); + auto uid = eventInfo["uid"].asInt(); + auto asanType = eventInfo["type"].asString(); + auto externalLog = writer.write(eventInfo["external_log"]); + std::string logOverLimit = eventInfo["log_over_limit"].asBool() ? "true" : "false"; + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", + bundleVersion.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", asanType.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", + externalLog.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}s", + logOverLimit.c_str()); + } +} + +// 开发者可以自行实现获取已监听到事件的回调函数,其中events指针指向内容仅在该函数内有效。 +static void OnTake(const char *const *events, uint32_t eventLen) +{ + Json::Reader reader(Json::Features::strictMode()); + Json::FastWriter writer; + for (int i = 0; i < eventLen; ++i) { + Json::Value eventInfo; + if (reader.parse(events[i], eventInfo)) { + auto domain = eventInfo["domain_"].asString(); + auto name = eventInfo["name_"].asString(); + auto type = eventInfo["type_"].asInt(); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.WatcherType=OnTrigger"); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str()); + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type); + // 处理打点事件 + OnTriggerDottingEvent(domain, name, eventInfo); + // 处理崩溃事件 + OnTriggerCrashEvent(domain, name, eventInfo, writer); + // 处理卡死事件 + OnTriggerFreezeEvent(domain, name, eventInfo, writer); + // 处理内存泄漏事件 + OnTriggerPssLeakEvent(domain, name, eventInfo, writer); + // 处理ASAN事件 + OnTriggerAsanEvent(domain, name, eventInfo, writer); + } + } +} + +// 开发者可以自行实现订阅回调函数,以便对获取到的事件打点数据进行自定义处理。 +static void OnTrigger(int row, int size) +{ + // 接收回调后,获取指定数量的已接收事件。 + OH_HiAppEvent_TakeWatcherData(eventWatcherT, row, OnTake); +} + +static napi_value RegisterWatcher(napi_env env, napi_callback_info info) +{ + // 开发者自定义观察者名称,系统根据不同的名称来识别不同的观察者。 + eventWatcherT = OH_HiAppEvent_CreateWatcher("onTriggerWatcher"); + eventWatcherR = OH_HiAppEvent_CreateWatcher("onReceiverWatcher"); + // 设置订阅的事件名称为click, EVENT_APP_CRASH。 + const char *names[] = {"click", EVENT_APP_CRASH, EVENT_APP_FREEZE, EVENT_RESOURCE_OVERLIMIT, + EVENT_ADDRESS_SANITIZER, EVENT_MAIN_THREAD_JANK}; + int namesSize = sizeof(names) / sizeof(names[0]); + // 开发者订阅感兴趣的应用事件 + OH_HiAppEvent_SetAppEventFilter(eventWatcherT, "button", 0, names, namesSize); + OH_HiAppEvent_SetAppEventFilter(eventWatcherT, DOMAIN_OS, 0, names, namesSize); + // 开发者设置已实现的回调函数,需OH_HiAppEvent_SetTriggerCondition设置的条件满足方可触发。 + OH_HiAppEvent_SetWatcherOnTrigger(eventWatcherT, OnTrigger); + // 开发者可以设置订阅触发回调的条件,此处是设置新增事件打点数量为1个时,触发onTrigger回调。 + OH_HiAppEvent_SetTriggerCondition(eventWatcherT, 1, 0, 0); + // 使观察者开始监听订阅的事件。 + OH_HiAppEvent_AddWatcher(eventWatcherT); + // 开发者订阅感兴趣的应用事件 + OH_HiAppEvent_SetAppEventFilter(eventWatcherR, "button", 0, names, namesSize); + OH_HiAppEvent_SetAppEventFilter(eventWatcherR, DOMAIN_OS, 0, names, namesSize); + // 开发者设置已实现的回调函数,观察者接收到事件后回立即触发OnReceive回调。 + OH_HiAppEvent_SetWatcherOnReceive(eventWatcherR, OnReceive); + // 使观察者开始监听订阅的事件。 + OH_HiAppEvent_AddWatcher(eventWatcherR); + return {}; +} + +static napi_value RemoveWatcher(napi_env env, napi_callback_info info) +{ + // 使观察者停止监听事件 + OH_HiAppEvent_RemoveWatcher(eventWatcherT); + OH_HiAppEvent_RemoveWatcher(eventWatcherR); + return {}; +} + +static napi_value DestroyWatcher(napi_env env, napi_callback_info info) +{ + // 销毁创建的观察者,并置appEventWatcher为nullptr。 + OH_HiAppEvent_DestroyWatcher(eventWatcherT); + OH_HiAppEvent_DestroyWatcher(eventWatcherR); + eventWatcherT = nullptr; + eventWatcherR = nullptr; + return {}; +} + +static napi_value WriteAppEvent(napi_env env, napi_callback_info info) +{ + auto params = OH_HiAppEvent_CreateParamList(); + OH_HiAppEvent_AddInt64Param(params, "click_time", time(nullptr)); + OH_HiAppEvent_Write("button", "click", EventType::BEHAVIOR, params); + OH_HiAppEvent_DestroyParamList(params); + OH_LOG_INFO(LogType::LOG_APP, "writeEvent C++ success"); + return {}; +} + +static napi_value AddressTest(napi_env env, napi_callback_info info) +{ + // 任意实数 + int num = 1; + int length = 10; + // 构造数组越界写入 + int a[length]; + a[length] = num; + return {}; +} + +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + {"registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"writeAppEvent", nullptr, WriteAppEvent, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"addressTest", nullptr, AddressTest, nullptr, nullptr, nullptr, napi_default, nullptr} + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/Index.d.ts b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..4e870719082f0d84a4ae15d1c360d451680fea9b --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const registerWatcher: () => void; +export const writeAppEvent: () => void; +export const addressTest: () => void; \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/oh-package.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..88838fa0b2042f057b1d730054d5698b61c7fb58 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entryability/EntryAbility.ets b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0baefdeaf32512342d52873977a666f38e17a460 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hiAppEvent, hilog, hidebug } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { window } from '@kit.ArkUI'; +import testNapi from 'libentry.so'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + // 添加按钮事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'appEventWatcher', + // 开发者可以订阅感兴趣的应用事件,此处是订阅了按钮事件 + appEventFilters: [{ + domain: 'button' + }], + // 开发者可以设置订阅回调触发的条件,此处是设置为事件打点数量满足1个 + triggerCondition: { + row: 1 + }, + // 开发者可以自行实现订阅回调函数,以便对订阅获取到的事件打点数据进行自定义处理 + onTrigger: (curRow: number, curSize: number, holder: hiAppEvent.AppEventPackageHolder) => { + // 返回的holder对象为null,表示订阅过程发生异常,因此在记录错误日志后直接返回 + if (holder == null) { + hilog.error(0x0000, 'testTag', `HiAppEvent holder is null`); + return; + } + hilog.info(0x0000, 'testTag', `HiAppEvent onTrigger: curRow=%{public}d, curSize=%{public}d`, curRow, curSize); + let eventPkg: hiAppEvent.AppEventPackage | null = null; + // 根据设置阈值大小(默认为512KB)去获取订阅事件包,直到将订阅数据全部取出 + // 返回的事件包对象为null,表示当前订阅数据已被全部取出,此次订阅回调触发结束 + while ((eventPkg = holder.takeNext()) != null) { + // 开发者可以对事件包中的事件打点数据进行自定义处理,此处是将事件打点数据打印在日志中 + hilog.info(0x0000, 'testTag', `readEvent ArkTS Success`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.packageId=%{public}d`, eventPkg.packageId); + hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.row=%{public}d`, eventPkg.row); + hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.size=%{public}d`, eventPkg.size); + for (const eventInfo of eventPkg.data) { + hilog.info(0x0000, 'testTag', `HiAppEvent eventPkg.info=%{public}s`, eventInfo); + } + } + } + }); + // 开发者完成参数键值对赋值 + let params: Record = { + 'testData': 100, + }; + // 开发者可以设置事件的自定义参数 + hiAppEvent.setEventParam(params, hiAppEvent.domain.OS, hiAppEvent.event.APP_CRASH).then(() => { + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', `HiAppEvent code: ${err.code}, message: ${err.message}`); + }); + hiAppEvent.setEventParam(params, hiAppEvent.domain.OS, hiAppEvent.event.APP_FREEZE).then(() => { + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', `HiAppEvent code: ${err.code}, message: ${err.message}`); + }); + // 添加崩溃事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'crashEventWatcher', + // 开发者可以订阅感兴趣的系统事件,此处是订阅了崩溃事件 + appEventFilters: [ + { + domain: hiAppEvent.domain.OS, + names: [hiAppEvent.event.APP_CRASH] + } + ], + // 开发者可以自行实现订阅实时回调函数,以便对订阅获取到的事件数据进行自定义处理 + onReceive: (domain: string, appEventGroups: Array) => { + hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`); + for (const eventGroup of appEventGroups) { + // 开发者可以根据事件集合中的事件名称区分不同的系统事件 + hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`); + for (const eventInfo of eventGroup.appEventInfos) { + // 开发者可以对事件集合中的事件数据进行自定义处理,此处是将事件数据打印在日志中 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`); + // 开发者可以获取到崩溃事件发生的时间戳 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`); + // 开发者可以获取到崩溃事件发生的崩溃类型 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}`); + // 开发者可以获取到崩溃应用的前后台状态 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}`); + // 开发者可以获取到崩溃应用的版本信息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`); + // 开发者可以获取到崩溃应用的包名 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`); + // 开发者可以获取到崩溃应用的进程id + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.pid=${eventInfo.params['pid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uuid=${eventInfo.params['uuid']}`); + // 开发者可以获取到崩溃事件发生的异常类型、异常原因和异常调用栈 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}`); + // 开发者可以获取到崩溃事件发生时日志信息 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}`); + // 开发者可以获取到崩溃事件发生时的故障日志文件 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.external_log=${JSON.stringify(eventInfo.params['external_log'])}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.log_over_limit=${eventInfo.params['log_over_limit']}`); + // 开发者可以获取到崩溃事件的自定义数据test_data + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.test_data=${eventInfo.params['testData']}`); + } + } + } + }); + // 添加卡死事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'freezeEventWatcher', + // 开发者可以订阅感兴趣的系统事件,此处是订阅了卡死事件 + appEventFilters: [ + { + domain: hiAppEvent.domain.OS, + names: [hiAppEvent.event.APP_FREEZE] + } + ], + // 开发者可以自行实现订阅实时回调函数,以便对订阅获取到的事件数据进行自定义处理 + onReceive: (domain: string, appEventGroups: Array) => { + hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`); + for (const eventGroup of appEventGroups) { + // 开发者可以根据事件集合中的事件名称区分不同的系统事件 + hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`); + for (const eventInfo of eventGroup.appEventInfos) { + // 开发者可以对事件集合中的事件数据进行自定义处理,此处是将事件数据打印在日志中 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`); + // 开发者可以获取到卡死事件发生的时间戳 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`); + // 开发者可以获取到卡死应用的前后台状态 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}`); + // 开发者可以获取到卡死应用的版本信息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`); + // 开发者可以获取到卡死应用的包名 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`); + // 开发者可以获取到卡死应用的进程名称 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.process_name=${eventInfo.params['process_name']}`); + // 开发者可以获取到卡死应用的进程id + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.pid=${eventInfo.params['pid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uuid=${eventInfo.params['uuid']}`); + // 开发者可以获取到卡死事件发生的异常类型、异常原因 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}`); + // 开发者可以获取到卡死事件发生时日志信息 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}`); + // 开发者可以获取到卡死事件发生时主线程未处理消息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.event_handler.size=${eventInfo.params['event_handler'].length}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.event_handler_size_3s=${eventInfo.params['event_handler_size_3s']}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.event_handler_size_6s=${eventInfo.params['event_handler_size_6s']}`); + // 开发者可以获取到卡死事件发生时同步binder调用信息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.peer_binder.size=${eventInfo.params['peer_binder'].length}`); + // 开发者可以获取到卡死事件发生时全量线程调用栈 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.threads.size=${eventInfo.params['threads'].length}`); + // 开发者可以获取到卡死事件发生时内存信息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.memory=${JSON.stringify(eventInfo.params['memory'])}`); + // 开发者可以获取到卡死事件发生时的故障日志文件 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.external_log=${JSON.stringify(eventInfo.params['external_log'])}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.log_over_limit=${eventInfo.params['log_over_limit']}`); + // 开发者可以获取到卡死事件的自定义数据test_data + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.test_data=${eventInfo.params['testData']}`); + } + } + } + }); + // 添加资源泄露事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'pssleakwatcher', + // 开发者可以订阅感兴趣的系统事件,此处是订阅了资源泄漏事件 + appEventFilters: [ + { + domain: hiAppEvent.domain.OS, + names: [hiAppEvent.event.RESOURCE_OVERLIMIT] + } + ], + // 开发者可以自行实现订阅实时回调函数,以便对订阅获取到的事件数据进行自定义处理 + onReceive: (domain: string, appEventGroups: Array) => { + hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`); + for (const eventGroup of appEventGroups) { + // 开发者可以根据事件集合中的事件名称区分不同的系统事件 + hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`); + for (const eventInfo of eventGroup.appEventInfos) { + // 开发者可以获取到资源泄漏事件发生时内存信息 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.memory=${JSON.stringify(eventInfo)}`); + } + } + } + }); + // 添加踩地址事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'addressSanitizerWatcher', + // 开发者可以订阅感兴趣的系统事件,此处是订阅了踩内存事件 + appEventFilters: [ + { + domain: hiAppEvent.domain.OS, + names: [hiAppEvent.event.ADDRESS_SANITIZER] + } + ], + // 开发者可以自行实现订阅系统事件回调函数,以便对订阅获取到的事件数据进行自定义处理 + onReceive: (domain: string, appEventGroups: Array) => { + hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`); + for (const eventGroup of appEventGroups) { + // 开发者可以根据事件集合中的事件名称区分不同的系统事件 + hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`); + for (const eventInfo of eventGroup.appEventInfos) { + // 开发者可以对事件集合中的事件数据进行自定义处理,此处是将事件数据打印在日志中 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.time=${eventInfo.params['time']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.bundle_version=${eventInfo.params['bundle_version']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.bundle_name=${eventInfo.params['bundle_name']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.pid=${eventInfo.params['pid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.uid=${eventInfo.params['uid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.type=${eventInfo.params['type']}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.external_log=${JSON.stringify(eventInfo.params['external_log'])}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.log_over_limit=${eventInfo.params['log_over_limit']}`); + } + } + } + }); + // 添加主线程超时事件观察者 + hiAppEvent.addWatcher({ + // 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者 + name: 'timeOutWatcher', + // 开发者可以订阅感兴趣的系统事件,此处是订阅了主线程超时事件 + appEventFilters: [ + { + domain: hiAppEvent.domain.OS, + names: [hiAppEvent.event.MAIN_THREAD_JANK] + } + ], + // 开发者可以自行实现订阅实时回调函数,以便对订阅获取到的事件数据进行自定义处理 + onReceive: (domain: string, appEventGroups: Array) => { + hilog.info(0x0000, 'testTag', `HiAppEvent onReceive: domain=${domain}`); + for (const eventGroup of appEventGroups) { + // 开发者可以根据事件集合中的事件名称区分不同的系统事件 + hilog.info(0x0000, 'testTag', `HiAppEvent eventName=${eventGroup.name}`); + for (const eventInfo of eventGroup.appEventInfos) { + // 开发者可以对事件集合中的事件数据进行自定义处理,此处是将事件数据打印在日志中 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.domain=${eventInfo.domain}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.name=${eventInfo.name}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.eventType=${eventInfo.eventType}`); + // 开发者可以获取到主线程超时事件发生的时间戳 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}`); + // 开发者可以获取到主线程超时应用的版本信息 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}`); + // 开发者可以获取到主线程超时应用的包名 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}`); + // 开发者可以获取到主线程超时应用的pid、uid + hilog.info(0x0000, 'testTag', ` eventInfo.params.pid=${eventInfo.params['pid']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.uid=${eventInfo.params['uid']}`); + // 开发者可以获取主线程处理开始和结束时间 + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.begin_time=${eventInfo.params['begin_time']}`); + hilog.info(0x0000, 'testTag', `HiAppEvent eventInfo.params.end_time=${eventInfo.params['end_time']}`); + // 开发者可以获取到主线程超时事件发生时的故障日志文件 + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.external_log=${JSON.stringify(eventInfo.params['external_log'])}`); + hilog.info(0x0000, 'testTag', + `HiAppEvent eventInfo.params.log_over_limit=${eventInfo.params['log_over_limit']}`); + } + } + } + }); + // 调用C++观察者 + testNapi.registerWatcher(); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +}; diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..29feaca7669174be5c2b0e2366529ee94ab7e726 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/pages/Index.ets b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f9e0e9e5cc890c125eb1f7b2a3faa729c2c8d6e --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { BusinessError } from '@kit.BasicServicesKit'; +import { hiAppEvent, hilog } from '@kit.PerformanceAnalysisKit'; +import hidebug from '@ohos.hidebug'; +import testNapi from 'libentry.so'; + +@Entry +@Component +struct Index { + @State leakedArray: string[][] = []; + + build() { + Row() { + Column() { + Button($r('app.string.WriteEventArkTS_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + // 在按钮点击函数中进行事件打点,以记录按钮点击事件 + let eventParams: Record = {'clickTime': 100}; + let eventInfo: hiAppEvent.AppEventInfo = { + // 事件领域定义 + domain: 'button', + // 事件名称定义 + name: 'click', + // 事件类型定义 + eventType: hiAppEvent.EventType.BEHAVIOR, + // 事件参数定义 + params: eventParams, + }; + hiAppEvent.write(eventInfo).then(() => { + hilog.info(0x0000, 'testTag', `writeEvent ArkTS success`); + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', `HiAppEvent err.code: ${err.code}, err.message: ${err.message}`); + }); + }) + Button($r('app.string.Crash_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + // 在按钮点击函数中构造一个crash场景,触发应用崩溃事件 + JSON.parse(''); + }) + Button($r('app.string.Pssleak_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + // 设置一个简单的资源泄漏场景 + hidebug.setAppResourceLimit('pss_memory', 1024, true); + for (let i = 0; i < 20 * 1024; i++) { + this.leakedArray.push(new Array(1).fill('leak')); + } + }) + Button($r('app.string.TimeOut_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + let t = Date.now(); + while (Date.now() - t <= 350) { + } + }) + } + .width('50%') + + Column() { + Button($r('app.string.WriteEventCPP_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + testNapi.writeAppEvent(); + }) + Button($r('app.string.Freeze_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + setTimeout(() => { + while (true) { + } + }, 1000) + }) + Button($r('app.string.AsanEvent_Button')) + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('80%') + .height('5%') + .onClick(() => { + testNapi.addressTest(); + }) + } + .width('50%') + } + .height('100%') + } +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/module.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9f7f873fbc51484895e18fcfd60b2498521aecb0 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/module.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/color.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/string.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..3a434d5a3c1ebeba93429c665379ef216500e65e --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "EventSub" + }, + { + "name": "WriteEventArkTS_Button", + "value": "writeEvent ArkTS" + }, + { + "name": "Crash_Button", + "value": "appCrash ArkTS&C++" + }, + { + "name": "Pssleak_Button", + "value": "pssleak ArkTS&C++" + }, + { + "name": "TimeOut_Button", + "value": "timeOut350 ArkTS&C++" + }, + { + "name": "WriteEventCPP_Button", + "value": "writeEvent C++" + }, + { + "name": "Freeze_Button", + "value": "appFreeze ArkTS&C++" + }, + { + "name": "AsanEvent_Button", + "value": "appAsanEvent ArkTS&C++" + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/background.png b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/background.png differ diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/foreground.png b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/foreground.png differ diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/layered_image.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/startIcon.png b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/media/startIcon.png differ diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/backup_config.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/main_pages.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/en_US/element/string.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..3a434d5a3c1ebeba93429c665379ef216500e65e --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "EventSub" + }, + { + "name": "WriteEventArkTS_Button", + "value": "writeEvent ArkTS" + }, + { + "name": "Crash_Button", + "value": "appCrash ArkTS&C++" + }, + { + "name": "Pssleak_Button", + "value": "pssleak ArkTS&C++" + }, + { + "name": "TimeOut_Button", + "value": "timeOut350 ArkTS&C++" + }, + { + "name": "WriteEventCPP_Button", + "value": "writeEvent C++" + }, + { + "name": "Freeze_Button", + "value": "appFreeze ArkTS&C++" + }, + { + "name": "AsanEvent_Button", + "value": "appAsanEvent ArkTS&C++" + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/zh_CN/element/string.json b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..135de82be37eb2c8bbd8dc536275877670cc3e3f --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "事件订阅" + }, + { + "name": "WriteEventArkTS_Button", + "value": "writeEvent ArkTS" + }, + { + "name": "Crash_Button", + "value": "appCrash ArkTS&C++" + }, + { + "name": "Pssleak_Button", + "value": "pssleak ArkTS&C++" + }, + { + "name": "TimeOut_Button", + "value": "timeOut350 ArkTS&C++" + }, + { + "name": "WriteEventCPP_Button", + "value": "writeEvent C++" + }, + { + "name": "Freeze_Button", + "value": "appFreeze ArkTS&C++" + }, + { + "name": "AsanEvent_Button", + "value": "appAsanEvent ArkTS&C++" + } + ] +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/Libentry.mock.ets b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..37c4693badee0bced9f50f020403147ada0e8d44 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const nativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default nativeMock; \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/mock-config.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..25f4db9dcf89e656abe1a6776fe21cd00fc94dac --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/entry/src/mock/mock-config.json5 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigor/hvigor-config.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a2c44fdf8f9ac103168672568ff000ac395a2edc --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigorfile.ts b/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..79d8761856e2996edc0649eca63b96b2c883b28a --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/oh-package.json5 b/PerformanceAnalysisKit/HiAppEvent/EventSub/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b7f346f7ddb2fc98ac428c55207a63ff89ea1c70 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.18", + "@ohos/hamock": "1.0.0" + } +} diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/ohosTest.md b/PerformanceAnalysisKit/HiAppEvent/EventSub/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..fe414f3988573487d87ccc43d7f6fcf8e95e9d37 --- /dev/null +++ b/PerformanceAnalysisKit/HiAppEvent/EventSub/ohosTest.md @@ -0,0 +1,6 @@ +# EventSub测试用例归档 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------ | ------------ | ------------ | ------------ | -------- | -------- | +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 否 | Pass | +| 主页按钮点击 | 位于主页 | 依次点击按钮 | 输出预期日志 | 否 | Pass | \ No newline at end of file diff --git a/PerformanceAnalysisKit/HiAppEvent/EventSub/screenshots/Screenshot_20250219094941818.jpeg b/PerformanceAnalysisKit/HiAppEvent/EventSub/screenshots/Screenshot_20250219094941818.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7ad5f104644e23b295bace3bfea4c9274effc341 Binary files /dev/null and b/PerformanceAnalysisKit/HiAppEvent/EventSub/screenshots/Screenshot_20250219094941818.jpeg differ