From b1a1190bd4e7a46460e69c3e13650f73125a96ec Mon Sep 17 00:00:00 2001 From: rongkunshi Date: Mon, 14 Feb 2022 17:50:26 +0800 Subject: [PATCH 1/2] frameaware code 20220214 Signed-off-by: rongkunshi --- BUILD.gn | 24 + LICENSE | 178 +++++++ OAT.xml | 85 +++ README.en.md | 36 -- README.md | 39 -- README_ZH.md | 124 +++++ bundle.json | 67 +++ common/include/frame_info_const.h | 59 +++ common/include/rme_constants.h | 56 ++ common/include/rme_log_domain.h | 72 +++ common/include/rtg_interface.h | 112 ++++ common/include/single_instance.h | 49 ++ figures/zh-cn_image_fwk.png | Bin 0 -> 209521 bytes frameaware.gni | 18 + .../include/frame_msg_mgr.h | 53 ++ .../include/frame_scene_sched.h | 50 ++ .../include/frame_window_mgr.h | 39 ++ .../include/intelli_sense_sched.h | 41 ++ .../include/rme_core_sched.h | 59 +++ .../include/rme_scene_sched.h | 60 +++ .../src/frame_msg_mgr.cpp | 150 ++++++ .../src/frame_window_mgr.cpp | 51 ++ .../src/rme_core_sched.cpp | 107 ++++ .../src/rme_scene_sched.cpp | 146 ++++++ .../frame_aware_policy/include/app_info.h | 64 +++ .../frame_aware_policy/include/app_info_mgr.h | 53 ++ .../include/intellisense_server.h | 57 ++ .../frame_aware_policy/include/para_config.h | 74 +++ .../frame_aware_policy/include/rtg_msg_mgr.h | 44 ++ .../core/frame_aware_policy/src/app_info.cpp | 97 ++++ .../frame_aware_policy/src/app_info_mgr.cpp | 168 ++++++ .../src/intellisense_server.cpp | 149 ++++++ .../frame_aware_policy/src/para_config.cpp | 215 ++++++++ .../frame_aware_policy/src/rtg_msg_mgr.cpp | 96 ++++ interfaces/innerkits/BUILD.gn | 23 + interfaces/innerkits/frameintf/BUILD.gn | 123 +++++ .../innerkits/frameintf/frame_msg_intf.cpp | 103 ++++ .../innerkits/frameintf/frame_msg_intf.h | 48 ++ .../innerkits/frameintf/frame_ui_intf.cpp | 168 ++++++ .../innerkits/frameintf/frame_ui_intf.h | 49 ++ .../innerkits/frameintf/rtg_interface.cpp | 491 ++++++++++++++++++ profiles/BUILD.gn | 21 + profiles/hwrme.xml | 28 + test/BUILD.gn | 101 ++++ test/unittest/phone/frame_msg_intf_test.cpp | 144 +++++ test/unittest/phone/frame_ui_intf_test.cpp | 51 ++ test/unittest/phone/rtg_interface_test.cpp | 485 +++++++++++++++++ 47 files changed, 4452 insertions(+), 75 deletions(-) create mode 100644 BUILD.gn create mode 100644 LICENSE create mode 100644 OAT.xml delete mode 100644 README.en.md delete mode 100644 README.md create mode 100644 README_ZH.md create mode 100644 bundle.json create mode 100644 common/include/frame_info_const.h create mode 100644 common/include/rme_constants.h create mode 100644 common/include/rme_log_domain.h create mode 100644 common/include/rtg_interface.h create mode 100644 common/include/single_instance.h create mode 100644 figures/zh-cn_image_fwk.png create mode 100644 frameaware.gni create mode 100644 frameworks/core/frame_aware_collector/include/frame_msg_mgr.h create mode 100644 frameworks/core/frame_aware_collector/include/frame_scene_sched.h create mode 100644 frameworks/core/frame_aware_collector/include/frame_window_mgr.h create mode 100644 frameworks/core/frame_aware_collector/include/intelli_sense_sched.h create mode 100644 frameworks/core/frame_aware_collector/include/rme_core_sched.h create mode 100644 frameworks/core/frame_aware_collector/include/rme_scene_sched.h create mode 100644 frameworks/core/frame_aware_collector/src/frame_msg_mgr.cpp create mode 100644 frameworks/core/frame_aware_collector/src/frame_window_mgr.cpp create mode 100644 frameworks/core/frame_aware_collector/src/rme_core_sched.cpp create mode 100644 frameworks/core/frame_aware_collector/src/rme_scene_sched.cpp create mode 100644 frameworks/core/frame_aware_policy/include/app_info.h create mode 100644 frameworks/core/frame_aware_policy/include/app_info_mgr.h create mode 100644 frameworks/core/frame_aware_policy/include/intellisense_server.h create mode 100644 frameworks/core/frame_aware_policy/include/para_config.h create mode 100644 frameworks/core/frame_aware_policy/include/rtg_msg_mgr.h create mode 100644 frameworks/core/frame_aware_policy/src/app_info.cpp create mode 100644 frameworks/core/frame_aware_policy/src/app_info_mgr.cpp create mode 100644 frameworks/core/frame_aware_policy/src/intellisense_server.cpp create mode 100644 frameworks/core/frame_aware_policy/src/para_config.cpp create mode 100644 frameworks/core/frame_aware_policy/src/rtg_msg_mgr.cpp create mode 100644 interfaces/innerkits/BUILD.gn create mode 100644 interfaces/innerkits/frameintf/BUILD.gn create mode 100644 interfaces/innerkits/frameintf/frame_msg_intf.cpp create mode 100644 interfaces/innerkits/frameintf/frame_msg_intf.h create mode 100644 interfaces/innerkits/frameintf/frame_ui_intf.cpp create mode 100644 interfaces/innerkits/frameintf/frame_ui_intf.h create mode 100644 interfaces/innerkits/frameintf/rtg_interface.cpp create mode 100644 profiles/BUILD.gn create mode 100644 profiles/hwrme.xml create mode 100644 test/BUILD.gn create mode 100644 test/unittest/phone/frame_msg_intf_test.cpp create mode 100644 test/unittest/phone/frame_ui_intf_test.cpp create mode 100644 test/unittest/phone/rtg_interface_test.cpp diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000..bed0e84 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (C) 2022 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("//build/ohos.gni") +import("//foundation/resourceschedule/frame_aware_sched/frameaware.gni") + + +group("libintellisensesched_intf") { + public_deps = [ + "${innerkits_path}/frameintf:frame_msg_intf", + "${innerkits_path}/frameintf:frame_ui_intf", + ] +} + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4909afd --- /dev/null +++ b/LICENSE @@ -0,0 +1,178 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + diff --git a/OAT.xml b/OAT.xml new file mode 100644 index 0000000..7ece961 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 21a74bc..0000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# frame_aware_sched - -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md deleted file mode 100644 index 7611f38..0000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# frame_aware_sched - -#### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} - -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 0000000..b13bc5c --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,124 @@ +# 智能感知调度 + +- [简介](#section_introduction) + +- [目录](#section_catalogue) + +- [框架](#section_framework) + + - [绘帧信息收集](#section_strategy) + + - [帧感知调度机制](#section_mechanism) + +- [相关仓](#related_repositories) + + + +## 简介 + +智能感知调度部件位于全局资源调度管控子系统中,基于应用的生命周期状态、绘帧信息等,更新进程调度分组,通过设置进程组、线程优先级及其他内核调度参数等手段管理系统调度,保障系统进程调度供给。 + + + +## 目录 + +``` +//foundation/resourceschedule/plugins/frame_aware_sched +├── common # 部件通用工具类 +│ └── include +│ ├── frame_info_const.h # UI及render绘帧过程信息 +│ ├── frame_aware_constants.h # 通用参数配置 +│ ├── frame_aware_log_domain.h # 封装hilog,用于日志打印 +│ └── single_instance.h # 封装单例类,方便实现单例 +│ +├── interfaces +│ └── innerkits # 对内接口目录 +│ └── frameintf # 感知调度专用接口 +│ +├── frameworks +│ └── core +│ ├── frame_aware_collector # 应用绘帧信息收集组件 +│ └── frame_aware_policy # 帧感知调度机制组件 +│ +├── profiles # 组件配置文件 +└── test # 自测试用例目录 +``` + + +## 框架 + +智能感知调度部件根据执行时所属线程进行划分,可包含两大组件,即运行在App进程的绘帧信息收集器组件和运行在系统服务进程的帧感知调度机制组件,每个组件分为若干模块。 + +- **绘帧信息收集组件**:主要分为绘帧事件处理模块、滑动场景策略模块以及模型处理模块,三者构成绘帧核心策略。其中: + + 消息处理模块负责统筹JS-UI子系统及Graphic子系统的绘帧子过程的消息信息并分发; + + 帧事件处理模块主要负责提供各个子过程的调节调度算法; + + 滑动场景策略模块主要负责针对滑动场景,使用帧事件处理模块的算法接口提供应用主线程绘帧策略,进行场景化精细调度。 + +- **帧感知调度机制组件**:主要分为场景处理模块、应用管控模块、调度参数管控模块和RTG(Related-Thread-Group)分组管理模块,四者构成应用线程调度机制。其中: + + 场景处理模块主要负责注册接收来自全局资源管控子系统的消息,诸如应用前后台切换、窗口焦点变化等,并分发消息给应用管控模块和RTG分组模块; + + 应用管控模块,主要负责把维护接收到的消息,形成应用消息管理; + + RTG分组管理模块即调用内核接口设置,根据应用状态设置RTG分组实现线程调度管理; + + 调度参数管控模块主要负责读取默认调度参数配置。 + +两个组件中的事件处理模块,均统筹了智能感知调度部件所要对外相应的事件,而调度特性内核接口模块则负责将管控调度命令以帧的频率下发,两个组件相互合作,共同保障系统线程的性能供给。 + +![](figures/zh-cn_image_fwk.png) + + + +### 绘帧信息收集 + +应用绘帧感知主要负责调节内核调度的参数,进行线程负载的缩放。当用户在APP界面滑动时,识别出应用的关键线程(诸如绘帧主线程、渲染线程),感知应用绘帧子过程的执行情况,根据是否超时来判断是否调整内核调度参数,进行实时的资源供给,进行优先调度。 + +- 根据屏幕刷新率,判断当前帧率信息。根据越接近绘帧结束时刻,越加大关键线程的资源供给 + + +- 根据界面绘帧图形渲染过程中的各个子阶段的时长,调节资源供给。 + + +- 对可能发生丢帧卡顿的高概率事件,增加资源供给 + + + + +### 帧感知调度机制 + +应用线程调度机制,作为应用绘帧感知实现的基础,主要负责管控线程组及线程优先级,实现应用线程的统一管理,保证整个系统性能。 + +**核心思想**:分组,即根据不同线程组提供不同的供给能力。把用户敏感度线程添加进同一个线程组,在应用启动、前后台切换等多个应用变化场景,提供资源优先供给。 + + + +### 使用说明 + +系统开发者可以通过配置productdefine/common/products下的产品定义json文件,增加或移除本部件,来启用或停用本部件 + +"resourceschedule:frame_aware_sched":{} + + + +### 相关仓 + +- resource_schedule_service + +- ace_ace_engine + +- graphic_standard + +- aafwk_standard + +- **frame_aware_sched** + + + + + + + diff --git a/bundle.json b/bundle.json new file mode 100644 index 0000000..a51bb73 --- /dev/null +++ b/bundle.json @@ -0,0 +1,67 @@ +{ + "name": "@ohos/resource_schedule_service", + "description": "resource_schedule_service", + "version": "3.1", + "license": "Apache License 2.0", + "publishAs": "code-segment", + "segment": { + "destPath": "foundation/resourceschedule/plugins/frame_aware_sched" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "frame_aware_sched", + "subsystem": "resourceschedule", + "syscap": [], + "features": [], + "adapted_system_type": [ + "mini", + "small", + "standard" + ], + "rom": "2048KB", + "ram": "10240KB", + "deps": { + "components": [ + "libeventhandler", + "ipc_core", + "samgr_proxy", + "system_ability_fwk" + ], + "third_party": [ + "xml2" + ] + }, + "build": { + "sub_component": [ + "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf:frame_ui_intf", + "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf:frame_msg_intf", + "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf:rtg_interface", + "//foundation/resourceschedule/plugins/frame_aware_sched/profiles:frame_aware_sched_config" + ], + "inner_kits": [ + { + "header": { + "header_base": "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf", + "header_files": [ + "frame_ui_intf.h" + ] + }, + "name": "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf:frame_ui_intf" + }, + { + "header": { + "header_base": "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf", + "header_files": [ + "frame_msg_intf.h" + ] + }, + "name": "//foundation/resourceschedule/plugins/frame_aware_sched/interfaces/innerkits/frameintf:frame_msg_intf" + } + ], + "test": [ + "//foundation/resourceschedule/plugins/frame_aware_sched/test:frame_unittest" + ] + } + } +} diff --git a/common/include/frame_info_const.h b/common/include/frame_info_const.h new file mode 100644 index 0000000..2b941e6 --- /dev/null +++ b/common/include/frame_info_const.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_INFO_CONST_H +#define FRAME_INFO_CONST_H + +namespace OHOS { +namespace RME { + +enum class FrameEvent { + FLUSH_ANIMATION, + FLUSH_BUILD, + FLUSH_LAYOUT, + FLUSH_RENDER, + FLUSH_RENDER_FINISH, // to add, do not realize + PROCESS_POST_FLUSH, + PROCESS_COMMANDS, + ANIMATE, + RENDER, + SEND_COMMANDS, + EVENT_SET_PARAM, + EVENT_RTG_ENABLE, + EVENT_BUFFER_COUNT, + UNKNOWN, +}; + +enum class EventState { + EVENT_ENTER, + EVENT_CONSUMED, + EVENT_EXIT, + ENABLE, + DISABLE, +}; + +enum class SceneEvent { + SCENE_INVALID = 0, + VIDEO, + SLIDE, + GAME, + CLICK, + SCENE_MAX, +}; + +} // namespace RME +} // namespace OHOS + +#endif diff --git a/common/include/rme_constants.h b/common/include/rme_constants.h new file mode 100644 index 0000000..d35086b --- /dev/null +++ b/common/include/rme_constants.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef RME_CONSTANTS_H +#define RME_CONSTANTS_H + +namespace OHOS { +namespace RME { + +enum class AppStateUpdateReason { + APP_FOREGROUND, + APP_BACKGROUND, + APP_TERMINATED, + PROCESS_CREATE, + PROCESS_READY, + PROCESS_SUSPEND, + PROCESS_DIED, + REASON_UNKNOWN, +}; + +enum class ThreadType { + UI, + RENDER, +}; + +enum class ThreadState { + CREATE = 0, + DIED, +}; + +enum class WindowState { + FOCUS_YES = 0, + FOCUS_NO, +}; + +enum class ErrorCode { + FAIL, + SUCC, +}; + +} // namespace RME +} // namespace OHOS + +#endif diff --git a/common/include/rme_log_domain.h b/common/include/rme_log_domain.h new file mode 100644 index 0000000..09b78d0 --- /dev/null +++ b/common/include/rme_log_domain.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef RME_LOG_DOMAIN_H +#define RME_LOG_DOMAIN_H + +#include +#include "hilog/log.h" + +namespace OHOS { +namespace RmeLogDomain { + +constexpr uint32_t COMMON = 0xD006600; +constexpr uint32_t RME_SERVICE = 0xD006601; +constexpr uint32_t RME_TEST = 0xD006602; +constexpr uint32_t RME_INTELLISENSE = 0xD006604; + +/* +#ifdef RME_LOGF +#undef RME_LOGF +#endif + +#ifdef RME_LOGE +#undef RME_LOGE +#endif + +#ifdef RME_LOGW +#undef RME_LOGW +#endif + +#ifdef RME_LOGI +#undef RME_LOGI +#endif + +#ifdef RME_LOGD +#undef RME_LOGD +#endif +*/ + +#define DEFINE_RMELOG_LABEL(name) \ + static constexpr OHOS::HiviewDFX::HiLogLabel RME_LOG_LABEL = {LOG_CORE, OHOS::RmeLogDomain::COMMON, name}; +#define DEFINE_RMELOG_INTELLISENSE(name) \ + static constexpr OHOS::HiviewDFX::HiLogLabel RME_LOG_LABEL = {LOG_CORE, OHOS::RmeLogDomain::RME_INTELLISENSE, name}; +#define DEFINE_RMELOG_SERVICE(name) \ + static constexpr OHOS::HiviewDFX::HiLogLabel RME_LOG_LABEL = {LOG_CORE, OHOS::RmeLogDomain::RME_SERVICE, name}; +#define DEFINE_RMELOG_TEST(name) \ + static constexpr OHOS::HiviewDFX::HiLogLabel RME_LOG_LABEL = {LOG_CORE, OHOS::RmeLogDomain::RME_TEST, name}; + + +#define RME_LOGF(...) (void)OHOS::HiviewDFX::HiLog::Fatal(RME_LOG_LABEL, ##__VA_ARGS__) +#define RME_LOGE(...) (void)OHOS::HiviewDFX::HiLog::Error(RME_LOG_LABEL, ##__VA_ARGS__) +#define RME_LOGW(...) (void)OHOS::HiviewDFX::HiLog::Warn(RME_LOG_LABEL, ##__VA_ARGS__) +#define RME_LOGI(...) (void)OHOS::HiviewDFX::HiLog::Info(RME_LOG_LABEL, ##__VA_ARGS__) +#define RME_LOGD(...) (void)OHOS::HiviewDFX::HiLog::Debug(RME_LOG_LABEL, ##__VA_ARGS__) + + +} // namespace RmeLogDomain +} // namespace OHOS + +#endif // RME_LOG_DOMAIN_H diff --git a/common/include/rtg_interface.h b/common/include/rtg_interface.h new file mode 100644 index 0000000..f6e07d8 --- /dev/null +++ b/common/include/rtg_interface.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef OHOS_FRAME_AWARE_SCHED_COMMON_INCLUDE_RTG_INTERFACE_H +#define OHOS_FRAME_AWARE_SCHED_COMMON_INCLUDE_RTG_INTERFACE_H + + +#include +#include + +namespace OHOS { +namespace RME { + +using namespace std; + +#define MAX_TID_NUM 5 +#define MAX_SUBPROCESS_NUM 8 +#define MULTI_FRAME_NUM 5 + +typedef int pid_t; + +struct rtg_enable_data { + int enable; + int len; + char *data; +}; + +struct rtg_str_data { + int type; + int len; + char *data; +}; + +struct proc_state_data { + int grp_id; + int state_param; +}; + +enum grp_ctrl_cmd { + CMD_CREATE_RTG_GRP, + CMD_ADD_RTG_THREAD, + CMD_REMOVE_RTG_THREAD, + CMD_CLEAR_RTG_GRP, + CMD_DESTROY_RTG_GRP +}; + +struct rtg_grp_data { + int rtg_cmd; + int grp_id; + int prio_type; + int rt_cnt; + int tid_num; + int tids[MAX_TID_NUM]; +}; + +struct rtg_info { + int rtg_num; + int rtgs[MULTI_FRAME_NUM]; +}; + +enum rtg_sched_cmdid { + SET_ENABLE = 1, + SET_RTG, + SET_CONFIG, + SET_RTG_ATTR, + BEGIN_FRAME_FREQ = 5, + END_FRAME_FREQ, + END_SCENE, + SET_MIN_UTIL, + SET_MARGIN, + LIST_RTG, + LIST_RTG_THREAD, + SEARCH_RTG, + RTG_CTRL_MAX_NR, +}; + +extern "C"{ + int EnableRtg(bool flag); + //-----for frame rtg-----// + int CreateNewRtgGrp(int prioType = 0, int rtNum = 0); // Return GrpId if success + int AddThreadToRtg(int tid, int grpId); + int AddThreadsToRtg(vector tids, int grpId); + int RemoveRtgThread(int tid); + int ClearRtgGrp(int grpId); + int DestroyRtgGrp(int grpId); + int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType); + int SetMaxVipRtgs(int rtframe); + int BeginFrameFreq(int grpId, int stateParam); + int EndFrameFreq(int grpId, int stateParam); + int EndScene(int rtgId); + int SetMinUtil(int grpId, int stateParam); + int SetMargin(int grpId, int stateParam); + int ListRtgThread(int grpId, vector *rs); // list all tasks of grpId; + int ListRtgGroup(vector *rs); + int SearchRtgForTid(int stateParam); +} + +} // namespace RME +} // namespace OHOS +#endif // OHOS_FRAME_AWARE_SCHED_COMMON_INCLUDE_RTG_INTERFACE_H \ No newline at end of file diff --git a/common/include/single_instance.h b/common/include/single_instance.h new file mode 100644 index 0000000..37d765f --- /dev/null +++ b/common/include/single_instance.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef SINGLE_INSTANCE_H +#define SINGLE_INSTANCE_H + +namespace OHOS { +namespace RME { + +#define DECLARE_SINGLE_INSTANCE_BASE(className) \ +public: \ + static className& GetInstance(); \ +private: \ + className(const className&) = delete; \ + className& operator=(const className &) = delete; \ + className(className&&) = delete; \ + className& operator=(className&&) = delete; \ + + +#define DECLARE_SINGLE_INSTANCE(className) \ + DECLARE_SINGLE_INSTANCE_BASE(className) \ +private: \ + className() = default; \ + ~className() = default; \ + + +#define IMPLEMENT_SINGLE_INSTANCE(className) \ +className& className::GetInstance() \ +{ \ + static auto instance = new className(); \ + return *instance; \ +} + +} // namespace RME +} // namespace OHOS + +#endif // SINGLE_INSTANCE_H diff --git a/figures/zh-cn_image_fwk.png b/figures/zh-cn_image_fwk.png new file mode 100644 index 0000000000000000000000000000000000000000..c9fda7b34b8bc376d66ac03e7e69502218c43dc5 GIT binary patch literal 209521 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%0D80G;Mabn3^29R6z5X*LhA+binYP` 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%0AxDxm0Sq+AhjRVc&4f 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 z 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

^k}{v>p0iXgklZuhUp$5#0Z~ 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 z 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 literal 0 HcmV?d00001 diff --git a/frameaware.gni b/frameaware.gni new file mode 100644 index 0000000..b4eba46 --- /dev/null +++ b/frameaware.gni @@ -0,0 +1,18 @@ +# Copyright (C) 2022 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. + +frame_aware_path = "//foundation/resourceschedule/plugins/frame_aware_sched" +service_path = "${frame_aware_path}/services" +innerkits_path = "${frame_aware_path}/interfaces/innerkits" + +framework_path = "${frame_aware_path}/frameworks/core" diff --git a/frameworks/core/frame_aware_collector/include/frame_msg_mgr.h b/frameworks/core/frame_aware_collector/include/frame_msg_mgr.h new file mode 100644 index 0000000..4d51e30 --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/frame_msg_mgr.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_MSG_MGR_H +#define FRAME_MSG_MGR_H + +#include + +#include "rme_log_domain.h" +#include "frame_info_const.h" +#include "rme_scene_sched.h" + +namespace OHOS { +namespace RME { + +class RmeSceneSched; + +class FrameMsgMgr { + DECLARE_SINGLE_INSTANCE_BASE(FrameMsgMgr); +public: + FrameMsgMgr(); + ~FrameMsgMgr(); + bool Init(); + void EventUpdate(FrameEvent eventType, EventState state); + +private: + void UpdateScene(SceneEvent scene); + + void HandleDefaultEvent(FrameEvent event, EventState state); + void SetSchedParam(); + FrameSceneSched *GetSceneHandler() const; + + SceneEvent sceneType; + RmeSceneSched *rmeScene; + +}; + + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_collector/include/frame_scene_sched.h b/frameworks/core/frame_aware_collector/include/frame_scene_sched.h new file mode 100644 index 0000000..03398e3 --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/frame_scene_sched.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_SCENE_SCHED_H +#define FRAME_SCENE_SCHED_H + +#include "rme_log_domain.h" + +namespace OHOS { +namespace RME { + +class FrameSceneSched { +public: + FrameSceneSched() {}; + virtual ~FrameSceneSched() = default; + +// virtual void UpdateBufferCount(int count); + virtual void BeginFlushAnimation() = 0; + virtual void EndFlushAnimation() = 0; + virtual void BeginFlushBuild() = 0; + virtual void EndFlushBuild() = 0; + virtual void BeginFlushLayout() = 0; + virtual void EndFlushLayout() = 0; + virtual void BeginFlushRender() = 0; + virtual void EndFlushRender() = 0; + virtual void BeginProcessPostFlush() = 0; + virtual void ProcessCommandsStart() = 0; + virtual void AnimateStart() = 0; + virtual void RenderStart() = 0; + virtual void SendCommandsStart() = 0; + +}; + +} // namespace RME + +} // namespace OHOS + +#endif diff --git a/frameworks/core/frame_aware_collector/include/frame_window_mgr.h b/frameworks/core/frame_aware_collector/include/frame_window_mgr.h new file mode 100644 index 0000000..04fd7ec --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/frame_window_mgr.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_WINDOW_MGR_H +#define FRAME_WINDOW_MGR_H + +#include +#include "single_instance.h" + +namespace OHOS { +namespace RME { + +class FrameWindowMgr { + DECLARE_SINGLE_INSTANCE(FrameWindowMgr); +public: + int GetEnable(); + void SetStartFlag(bool flag); + bool GetStartFlag(); +private: + int m_enable = -1; + bool m_startFlag; +// static int m_propName; +}; + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_collector/include/intelli_sense_sched.h b/frameworks/core/frame_aware_collector/include/intelli_sense_sched.h new file mode 100644 index 0000000..a2cb0b4 --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/intelli_sense_sched.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef INTELLI_SENSE_SCHED_H +#define INTELLI_SENSE_SCHED_H + +#include +#include + + +namespace OHOS { + +namespace RME { + +class IntelliSenseSched { +public: + IntelliSenseSched(); + ~IntelliSenseSched(); + + static IntelliSenseSched &GetInstance(); + static bool IsSoLoaded(); + + +} + + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_collector/include/rme_core_sched.h b/frameworks/core/frame_aware_collector/include/rme_core_sched.h new file mode 100644 index 0000000..cec215a --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/rme_core_sched.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef RME_CORE_SCHED_H +#define RME_CORE_SCHED_H + +#include "rme_log_domain.h" + +namespace OHOS { +namespace RME { + +class RmeCoreSched { +public: + RmeCoreSched(); + ~RmeCoreSched(); + + void Init(); + + void BeginFlushAnimation(); + void EndFlushAnimation(); + + void BeginFlushBuild(); + void EndFlushBuild(); + + void BeginFlushLayout(); + void EndFlushLayout(); + + void BeginFlushRender(); + void EndFlushRender(); + + void BeginProcessPostFlush(); + void ProcessCommandsStart(); + void AnimateStart(); + void RenderStart(); + void SendCommandsStart(); + + RmeCoreSched(const RmeCoreSched &) = delete; + RmeCoreSched &operator=(const RmeCoreSched &) = delete; + +private: + int m_flushAnimationPeriod = 3; + +}; + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_collector/include/rme_scene_sched.h b/frameworks/core/frame_aware_collector/include/rme_scene_sched.h new file mode 100644 index 0000000..4a301f0 --- /dev/null +++ b/frameworks/core/frame_aware_collector/include/rme_scene_sched.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef RME_SCENE_SCHED_H +#define RME_SCENE_SCHED_H + +#include "frame_scene_sched.h" +#include "frame_window_mgr.h" +#include "rme_core_sched.h" +#include "rme_log_domain.h" + +namespace OHOS { +namespace RME { + +class RmeSceneSched : public FrameSceneSched { +public: + RmeSceneSched(); + ~RmeSceneSched() override; + + void BeginFlushAnimation() override; + void EndFlushAnimation() override; + + void BeginFlushBuild() override; + void EndFlushBuild() override; + + void BeginFlushLayout() override; + void EndFlushLayout() override; + + void BeginFlushRender() override; + void EndFlushRender() override; + + void BeginProcessPostFlush() override; + void ProcessCommandsStart() override; + void AnimateStart() override; + void RenderStart() override; + void SendCommandsStart() override; + + bool Init(); + +private: + int curWorkingStatus; + RmeCoreSched *rmeCoreSched; +}; + + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_collector/src/frame_msg_mgr.cpp b/frameworks/core/frame_aware_collector/src/frame_msg_mgr.cpp new file mode 100644 index 0000000..751f495 --- /dev/null +++ b/frameworks/core/frame_aware_collector/src/frame_msg_mgr.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2022 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 "frame_msg_mgr.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("ueaClient-FrameMsgMgr"); +IMPLEMENT_SINGLE_INSTANCE(FrameMsgMgr); + +FrameMsgMgr::FrameMsgMgr() + : sceneType(SceneEvent::SLIDE), rmeScene(nullptr) +{ +} + +FrameMsgMgr::~FrameMsgMgr() +{ + if (rmeScene != nullptr) { + delete rmeScene; + } +} + +bool FrameMsgMgr::Init() +{ + if (rmeScene == nullptr) { + rmeScene = new RmeSceneSched(); + } + + if (!rmeScene->Init()) { + RME_LOGE("[Init]:inited success!"); + return false; + } + RME_LOGI("[Init]:inited success!"); + return true; +} + +void FrameMsgMgr::EventUpdate(FrameEvent event, EventState value) +{ + switch (event) { + case FrameEvent::EVENT_SET_PARAM: + SetSchedParam(); + break; + case FrameEvent::EVENT_RTG_ENABLE: + RME_LOGI("[EventUpdate]:rtg enable!"); + break; + default: + HandleDefaultEvent(event, value); + break; + } + return; +} + +void FrameMsgMgr::UpdateScene(SceneEvent scene) +{ + if (scene < SceneEvent::SCENE_INVALID || scene >= SceneEvent::SCENE_MAX) { + scene = SceneEvent::SCENE_INVALID; + } + + sceneType = scene; +} + +void FrameMsgMgr::HandleDefaultEvent(FrameEvent event, EventState value) +{ + FrameSceneSched *scene = GetSceneHandler(); + if (scene == nullptr) { + RME_LOGE("[HandleDefaultEvent]:scene nullptr"); + return; + } + + switch (event) { + case FrameEvent::FLUSH_ANIMATION: + if (value == EventState::EVENT_ENTER) { + scene->BeginFlushAnimation(); + } else { + scene->EndFlushAnimation(); + } + break; + case FrameEvent::FLUSH_BUILD: + if (value == EventState::EVENT_ENTER) { + scene->BeginFlushBuild(); + } else { + scene->EndFlushBuild(); + } + break; + case FrameEvent::FLUSH_LAYOUT: + if (value == EventState::EVENT_ENTER) { + scene->BeginFlushLayout(); + } else { + scene->EndFlushLayout(); + } + break; + case FrameEvent::FLUSH_RENDER: + if (value == EventState::EVENT_ENTER) { + scene->BeginFlushRender(); + } else { + scene->EndFlushRender(); + } + break; + case FrameEvent::PROCESS_POST_FLUSH: + scene->BeginProcessPostFlush(); + break; + case FrameEvent::PROCESS_COMMANDS: + scene->ProcessCommandsStart(); + break; + case FrameEvent::ANIMATE: + scene->AnimateStart(); + break; + case FrameEvent::RENDER: + scene->RenderStart(); + break; + case FrameEvent::SEND_COMMANDS: + scene->SendCommandsStart(); + break; + default: + RME_LOGE("[HandleDefaultEvent]: unknown event id: %{public}d, event state:%{public}d\n", static_cast(event), static_cast(value)); + return; + } +} + +void FrameMsgMgr::SetSchedParam() +{ + RME_LOGI("[SetSchedParam]: set default sched param!"); +} + +FrameSceneSched *FrameMsgMgr::GetSceneHandler() const +{ + + if (sceneType == SceneEvent::SCENE_INVALID) { + RME_LOGE("[GetSceneHandler]:get nullptr sceneType %{public}d,", static_cast(sceneType)); + return nullptr; + } + return rmeScene; +} + + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_collector/src/frame_window_mgr.cpp b/frameworks/core/frame_aware_collector/src/frame_window_mgr.cpp new file mode 100644 index 0000000..87ce0ff --- /dev/null +++ b/frameworks/core/frame_aware_collector/src/frame_window_mgr.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 "frame_window_mgr.h" + +namespace OHOS { +namespace RME { +namespace { + +const std::string SCHEME_SWITCH_PROP = ""; // to add prop +} + +IMPLEMENT_SINGLE_INSTANCE(FrameWindowMgr); + +int FrameWindowMgr::GetEnable() +{ + if (m_enable == -1) { + bool prop = true; + if (prop) { + m_enable = 1; + } else { + m_enable = 0; + } + } + return m_enable; +} + +void FrameWindowMgr::SetStartFlag(bool flag) +{ + m_startFlag = flag; +} + +bool FrameWindowMgr::GetStartFlag() +{ + return m_startFlag; +} + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_collector/src/rme_core_sched.cpp b/frameworks/core/frame_aware_collector/src/rme_core_sched.cpp new file mode 100644 index 0000000..573d716 --- /dev/null +++ b/frameworks/core/frame_aware_collector/src/rme_core_sched.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 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 "rme_core_sched.h" +#include "rtg_interface.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("ueaClient-RmeCoreSched"); + +RmeCoreSched::RmeCoreSched() +{ + return; +} + +RmeCoreSched::~RmeCoreSched() +{ + return; +} + +void RmeCoreSched::Init() +{ + int ret = EnableRtg(true); + if (ret < 0) { + RME_LOGE("[Init]: enableRtg failed!"); + } + return; +} + +void RmeCoreSched::BeginFlushAnimation() +{ + int ret = BeginFrameFreq(2 ,0); + RME_LOGI("[BeginFlushAnimation]: set BeginFrameFreq(2, 0), ret: %{public}d!", ret); + int flushAnimationTime = 1; // TO DO + if (flushAnimationTime >= m_flushAnimationPeriod) { + flushAnimationTime = 2; + } else { + flushAnimationTime = 3; + } + return; +} + +void RmeCoreSched::EndFlushAnimation() +{ +} + +void RmeCoreSched::BeginFlushBuild() +{ +} + +void RmeCoreSched::EndFlushBuild() +{ +} + +void RmeCoreSched::BeginFlushLayout() +{ +} + +void RmeCoreSched::EndFlushLayout() +{ +} + +void RmeCoreSched::BeginFlushRender() +{ +} + +void RmeCoreSched::EndFlushRender() +{ +} + +void RmeCoreSched::BeginProcessPostFlush() +{ +} + +void RmeCoreSched::ProcessCommandsStart() +{ +} + +void RmeCoreSched::AnimateStart() +{ +} + +void RmeCoreSched::RenderStart() +{ +} + +void RmeCoreSched::SendCommandsStart() +{ + int ret = EndFrameFreq(2, 16); + RME_LOGI("[SendCommandsStart]: set EndFrameFreq(2, 16), ret: %{public}d!", ret); +} + +} // namespace RME +} // OHOS diff --git a/frameworks/core/frame_aware_collector/src/rme_scene_sched.cpp b/frameworks/core/frame_aware_collector/src/rme_scene_sched.cpp new file mode 100644 index 0000000..3698942 --- /dev/null +++ b/frameworks/core/frame_aware_collector/src/rme_scene_sched.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2022 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 "rme_scene_sched.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("ueaClient-RmeSceneSched"); + +RmeSceneSched::RmeSceneSched() + :curWorkingStatus(0), rmeCoreSched(nullptr) +{ +} + +RmeSceneSched::~RmeSceneSched() +{ + if (rmeCoreSched != nullptr) { + delete rmeCoreSched; + } +} + +bool RmeSceneSched::Init() +{ + if (rmeCoreSched == nullptr) { + rmeCoreSched = new RmeCoreSched(); + } + + curWorkingStatus = 1; + if (rmeCoreSched == nullptr) { + return false; + } + RME_LOGI("[Init]:RmeSceneSched init success!"); + return true; +} + +void RmeSceneSched::BeginFlushAnimation() +{ + if (!FrameWindowMgr::GetInstance().GetEnable()) { + return; + } + if (curWorkingStatus == 1) { + rmeCoreSched->BeginFlushAnimation(); + RME_LOGI("[BeginFlushAnimation]:RmeSceneSched send msg success!"); + } +} + +void RmeSceneSched::EndFlushAnimation() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->EndFlushAnimation(); + } +} + +void RmeSceneSched::BeginFlushBuild() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->BeginFlushBuild(); + } +} + +void RmeSceneSched::EndFlushBuild() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->EndFlushBuild(); + } +} + +void RmeSceneSched::BeginFlushLayout() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->BeginFlushLayout(); + } +} + +void RmeSceneSched::EndFlushLayout() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->EndFlushLayout(); + } +} + +void RmeSceneSched::BeginFlushRender() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->BeginFlushRender(); + } +} + +void RmeSceneSched::EndFlushRender() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->EndFlushRender(); + } +} + +void RmeSceneSched::BeginProcessPostFlush() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->BeginProcessPostFlush(); + } +} + +void RmeSceneSched::ProcessCommandsStart() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->ProcessCommandsStart(); + } +} + +void RmeSceneSched::AnimateStart() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->AnimateStart(); + } +} + +void RmeSceneSched::RenderStart() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->RenderStart(); + } +} + +void RmeSceneSched::SendCommandsStart() +{ + if (curWorkingStatus == 1) { + rmeCoreSched->SendCommandsStart(); + RME_LOGI("[SendCommandsStart]:RmeSceneSched send msg success!"); + } +} + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_policy/include/app_info.h b/frameworks/core/frame_aware_policy/include/app_info.h new file mode 100644 index 0000000..c7eee02 --- /dev/null +++ b/frameworks/core/frame_aware_policy/include/app_info.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef APP_INFO_H +#define APP_INFO_H + +#include + +namespace OHOS { +namespace RME { + +enum class AppState { + APP_FOREGROUND, + APP_BACKGROUND, + APP_TERMINATED, + APP_UNKNOWN, +}; + + +class AppInfo { +public: + AppInfo(std::string appName, int pid, int uiTid, int renderTid, int isFocus, AppState state); + ~AppInfo() = default; + + void SetRenderTid(const int tid); + int GetRenderTid(); + void SetUiTid(const int tid); + int GetUiTid(); + void SetAppName(const std::string appName); + void SetAppState(AppState appState); + AppState GetAppState(); + void SetFocusState(const int isFocus); + int GetFocusState(); + void SetAppPid(const int pid); + int GetAppPid(); + void SetRtgrp(const int grpNum); + int GetRtgrp(); + +private: + std::string m_appName; + int m_pid; + int m_uiTid; + int m_renderTid; + int m_isFocus; + int m_rtgrp; + AppState m_appState; +}; + + +} // RME +} // OHOS +#endif diff --git a/frameworks/core/frame_aware_policy/include/app_info_mgr.h b/frameworks/core/frame_aware_policy/include/app_info_mgr.h new file mode 100644 index 0000000..25b8778 --- /dev/null +++ b/frameworks/core/frame_aware_policy/include/app_info_mgr.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef APP_INFO_MGR_H +#define APP_INFO_MGR_H + +#include + +#include "app_info.h" +#include "rme_log_domain.h" +#include "single_instance.h" + +namespace OHOS { +namespace RME { + +class AppInfoMgr { + DECLARE_SINGLE_INSTANCE(AppInfoMgr); + +public: + std::map> GetForegroundApp() const; + void OnForegroundChanged(const int pid, const std::string appName, const int rtGrp); + void OnBackgroundChanged(const int pid, const std::string appName); + void OnAppTerminateChanged(const int pid, const std::string appName); + void OnWindowFocus(const int pid, bool isFocus); + void OnUiProcessStart(const int pid, const int tid); + void OnRenderProcessStart(const int pid, const int tid); + bool OnProcessDied(const int pid, const int tid); + std::shared_ptr GetFocusApp() const; + void SetFocusApp(const int pid); + int GetAppRtgrp(const int pid); + +private: + std::map> mForegroundAppList; + std::map> mBackgroundAppList; + std::shared_ptr mFocusApp; +}; + + +} // namespace RME +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_policy/include/intellisense_server.h b/frameworks/core/frame_aware_policy/include/intellisense_server.h new file mode 100644 index 0000000..2b0fa24 --- /dev/null +++ b/frameworks/core/frame_aware_policy/include/intellisense_server.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef INTELLI_SENSE_SERVER_H +#define INTELLI_SENSE_SERVER_H + +#include +#include +#include +#include +#include + +#include "rme_constants.h" +#include "single_instance.h" +#include "event_handler.h" + +namespace OHOS { +namespace RME { + +using namespace std; + +class IntelliSenseServer { + DECLARE_SINGLE_INSTANCE(IntelliSenseServer); +public: + void Init(); + void ReportMessage(std::string appName, std::string processName, int pid, + AppStateUpdateReason reason); + void ReportWindowFocus(const int pid, int isFocus); + void ReportProcessInfo(const int pid, const int tid, ThreadState state); + bool ReadXml(); + void SetPara(const int32_t currentFps, const int32_t currentRenderType); + +private: + std::map m_generalPara {}; + std::map> m_subEventPara {}; + std::vector m_fpsList {}; + std::vector m_renderTypeList {}; + + bool m_readXmlSuc = false; + bool m_needReadXml = true; +}; + +} // namespace RME +} // namesapce OHOS +#endif diff --git a/frameworks/core/frame_aware_policy/include/para_config.h b/frameworks/core/frame_aware_policy/include/para_config.h new file mode 100644 index 0000000..a2e7aa6 --- /dev/null +++ b/frameworks/core/frame_aware_policy/include/para_config.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef PARA_CONFIG_H +#define PARA_CONFIG_H + +#include +#include +#include +#include + +#include + +#include "third_party/libxml2/include/libxml/parser.h" +#include "third_party/libxml2/include/libxml/tree.h" +#include "third_party/libxml2/include/libxml/xpath.h" +#include "rme_log_domain.h" +#include "single_instance.h" + +namespace OHOS { +namespace RME { + +class ParaConfig { +public: + ParaConfig(); + ~ParaConfig(); + + ParaConfig(const ParaConfig&) = delete; + ParaConfig& operator=(const ParaConfig&) = delete; + ParaConfig(ParaConfig&&) = delete; + ParaConfig& operator=(const ParaConfig&&) = delete; + + static bool IsXmlPrepared(const std::string& filePath); // input parameters need gaurantee + static std::map GetGeneralConfig(); + static std::map> GetSubEventConfig(); + static std::vector GetFpsList(); + static std::vector GetRenderTypeList(); +// static bool GetSwitchEnable(); + +private: + static std::map m_generalConfig; + static std::map> m_subEventConfig; + static std::vector m_fpsList; + static std::vector m_renderTypeList; +// static bool m_switchEnable; + + static void ReadAttr(xmlNodePtr& root, const std::string& attrName, std::string& res); + static void ReadFrameConfig(const xmlNodePtr& root); + static void ReadConfigInfo(const xmlNodePtr& root); + static void ReadFpsConfig(const xmlNodePtr& root); + static void ReadRenderType(const xmlNodePtr& root); + static void SplitString(const std::string& context, const std::string& character, + std::vector &mList, const int maxVal, const std::string& attrName); + static bool IsValidNode(const xmlNode& currNode); + +}; + + +} // namespace RME + +} // namespace OHOS +#endif diff --git a/frameworks/core/frame_aware_policy/include/rtg_msg_mgr.h b/frameworks/core/frame_aware_policy/include/rtg_msg_mgr.h new file mode 100644 index 0000000..e94761d --- /dev/null +++ b/frameworks/core/frame_aware_policy/include/rtg_msg_mgr.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef RTG_MSG_MGR_H +#define RTG_MSG_MGR_H + +#include +#include + +#include "rme_log_domain.h" +#include "rtg_interface.h" +#include "single_instance.h" + + +namespace OHOS { +namespace RME { + +class RtgMsgMgr { + DECLARE_SINGLE_INSTANCE(RtgMsgMgr); +public: + void Init(); + int OnForeground(const std::string appName, const int pid); + void OnBackground(const std::string appName, const int pid, const int grpId); + void ProcessStart(const int tid, const int grpId); + void ProcessDied(const int pid, const int tid); + void FpsChanged(); + void FocusChanged(const int pid, bool isFocus); // for multiwindow +}; + +} // RME +} // OHOS +#endif diff --git a/frameworks/core/frame_aware_policy/src/app_info.cpp b/frameworks/core/frame_aware_policy/src/app_info.cpp new file mode 100644 index 0000000..864d6a6 --- /dev/null +++ b/frameworks/core/frame_aware_policy/src/app_info.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 "app_info.h" + +namespace OHOS { +namespace RME { + +AppInfo::AppInfo(std::string appName, int pid, int uiTid, int renderTid, int isFocus, AppState state) + : m_appName(appName), + m_pid(pid), + m_uiTid(uiTid), + m_renderTid(renderTid), + m_isFocus(isFocus), + m_appState(state) +{} + +void AppInfo::SetRenderTid(const int tid) +{ + this->m_renderTid = tid; +} + +int AppInfo::GetRenderTid() +{ + return m_renderTid; +} + +void AppInfo::SetUiTid(const int tid) +{ + this->m_uiTid = tid; +} + +int AppInfo::GetUiTid() +{ + return m_uiTid; +} + +void AppInfo::SetAppName(const std::string appName) +{ + this->m_appName = appName; +} + +void AppInfo::SetFocusState(const int isFocus) +{ + this->m_isFocus = isFocus; +} + +int AppInfo::GetFocusState() +{ + return m_isFocus; +} + +void AppInfo::SetAppState(AppState appState) +{ + this->m_appState = appState; +} + +void AppInfo::SetAppPid(const int pid) +{ + this->m_pid = pid; +} + +int AppInfo::GetAppPid() +{ + return m_pid; +} + +AppState AppInfo::GetAppState() +{ + return m_appState; +} + +void AppInfo::SetRtgrp(const int grpNum) +{ + this->m_rtgrp = grpNum; +} + +int AppInfo::GetRtgrp() +{ + return m_rtgrp; +} + + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp b/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp new file mode 100644 index 0000000..432bfb1 --- /dev/null +++ b/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2022 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 "app_info_mgr.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_SERVICE("ueaServer-AppInfoMgr"); + +namespace { + constexpr int INIT_VAL = -1; +} + +IMPLEMENT_SINGLE_INSTANCE(AppInfoMgr); + +void AppInfoMgr::OnForegroundChanged(const int pid, const std::string appName, const int rtGrp) +{ + RME_LOGI("[OnForegroundChanged]:pid %{public}d, appname:%{public}s", pid, appName.c_str()); + std::map>::iterator it = mForegroundAppList.find(pid); + if (it != mForegroundAppList.end()) { + mForegroundAppList[pid]->SetAppName(appName); + mForegroundAppList[pid]->SetAppState(AppState::APP_FOREGROUND); + } else { + std::map>::iterator itB = mBackgroundAppList.find(pid); + if (itB != mBackgroundAppList.end()) { + mBackgroundAppList[pid]->SetAppName(appName); + mBackgroundAppList[pid]->SetAppState(AppState::APP_FOREGROUND); + mForegroundAppList[pid] = mBackgroundAppList[pid]; + mBackgroundAppList.erase(pid); + } else { + auto appInfo = std::make_shared(appName, pid, INIT_VAL, INIT_VAL, INIT_VAL, AppState::APP_FOREGROUND); + mForegroundAppList[pid] = appInfo; + } + } + mForegroundAppList[pid]->SetRtgrp(rtGrp); + RME_LOGI("[OnForegroundChanged]rtgrp:%{public}d:", rtGrp); +} + +void AppInfoMgr::OnBackgroundChanged(const int pid, const std::string appName) +{ + RME_LOGI("[OnBackgroundChanged]:pid:%{public}d, appName:%{public}s", pid, appName.c_str()); + std::map>::iterator it = mForegroundAppList.find(pid); + if (it != mForegroundAppList.end()) { + mForegroundAppList[pid]->SetAppState(AppState::APP_BACKGROUND); + mBackgroundAppList[pid] = mForegroundAppList[pid]; + mForegroundAppList.erase(pid); + } else { + RME_LOGE("[OnBackgroundChanged]:unfind appName in foreground app when go to background!"); + } +} + +void AppInfoMgr::OnAppTerminateChanged(const int pid, const std::string appName) +{ + RME_LOGI("[OnAppTerminatedChanged]: pid: %{public}d, appName: %{public}s:", pid, appName.c_str()); + mForegroundAppList.erase(pid); + mBackgroundAppList.erase(pid); +} + +void AppInfoMgr::OnWindowFocus(const int pid, bool isFocus) +{ + RME_LOGI("[OnAppFocus]: pid:%{public}d, isFocus:%{public}d", pid, isFocus); + std::shared_ptr appInfo = nullptr; + if (mForegroundAppList.find(pid) != mForegroundAppList.end()) { + appInfo = mForegroundAppList[pid]; + mForegroundAppList.erase(pid); + } else if (mBackgroundAppList.find(pid) != mBackgroundAppList.end()) { + appInfo = mBackgroundAppList[pid]; + mBackgroundAppList.erase(pid); + } else { + appInfo = std::make_shared("", pid, INIT_VAL, INIT_VAL, isFocus, AppState::APP_FOREGROUND); + } + appInfo->SetFocusState(isFocus); + if (isFocus) { + mForegroundAppList[pid] = appInfo; + SetFocusApp(pid); + } else { + mBackgroundAppList[pid] = appInfo; + } +} + +void AppInfoMgr::OnUiProcessStart(const int pid, const int tid) +{ + RME_LOGI("[OnUiProcessStart]:pid:%{public}d, uitid:%{public}d.\n", pid, tid); + std::shared_ptr appInfo = nullptr; + if (mForegroundAppList.find(pid) != mForegroundAppList.end()) { + appInfo = mForegroundAppList[pid]; + mForegroundAppList.erase(pid); + } else if (mBackgroundAppList.find(pid) != mBackgroundAppList.end()) { + appInfo = mBackgroundAppList[pid]; + mBackgroundAppList.erase(pid); + } else { + appInfo = std::make_shared("", pid, tid, INIT_VAL, INIT_VAL, AppState::APP_UNKNOWN); + } + appInfo->SetUiTid(tid); +} + +bool AppInfoMgr::OnProcessDied(const int pid, const int tid) +{ + bool deleted = false; + if (mForegroundAppList.find(pid) != mForegroundAppList.end()) { + mForegroundAppList.erase(pid); + deleted = true; + } else if (mBackgroundAppList.find(pid) != mBackgroundAppList.end()) { + mBackgroundAppList.erase(pid); + } + RME_LOGI("[OnProcessDied]: pid: %{public}d, tid:%{public}d, deleted:%{public}d.\n", pid, tid, deleted); + return deleted; +} + +void AppInfoMgr::OnRenderProcessStart(const int pid, const int tid) +{ + RME_LOGI("[OnRenderProcessStart]:pid:%{public}d, tid:%{public}d.\n", pid, tid); + std::shared_ptr appInfo = nullptr; + if (mForegroundAppList.find(pid) != mForegroundAppList.end()) { + appInfo = mForegroundAppList[pid]; + mForegroundAppList.erase(pid); + } else if (mBackgroundAppList.find(pid) != mBackgroundAppList.end()) { + appInfo = mBackgroundAppList[pid]; + mBackgroundAppList.erase(pid); + } else { + appInfo = std::make_shared("", pid, INIT_VAL, tid, INIT_VAL, AppState::APP_UNKNOWN); + } + appInfo->SetUiTid(tid); +} + +void AppInfoMgr::SetFocusApp(const int pid) +{ + mFocusApp = mForegroundAppList[pid]; +} + +std::shared_ptr AppInfoMgr::GetFocusApp() const +{ + return mFocusApp; +} + +int AppInfoMgr::GetAppRtgrp(const int pid) +{ + int rtGrp = -1; + if (mForegroundAppList.count(pid) != 0) { + rtGrp = mForegroundAppList[pid]->GetRtgrp(); + } else if (mBackgroundAppList.count(pid) != 0) { + rtGrp = mBackgroundAppList[pid]->GetRtgrp(); + } else { + RME_LOGI("[GetAppRtgrp]: do not have this pid, please add!"); + } + return rtGrp; +} + +std::map> AppInfoMgr::GetForegroundApp() const +{ + return mForegroundAppList; +} + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_policy/src/intellisense_server.cpp b/frameworks/core/frame_aware_policy/src/intellisense_server.cpp new file mode 100644 index 0000000..aff8579 --- /dev/null +++ b/frameworks/core/frame_aware_policy/src/intellisense_server.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2022 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 "intellisense_server.h" + +#include + +#include "para_config.h" +#include "rtg_msg_mgr.h" +#include "rme_log_domain.h" +#include "app_info_mgr.h" + +namespace OHOS { +namespace RME { + +using namespace std; + +static std::string configFilePath = "/system/etc/frame_aware_sched/hwrme.xml"; // need To check the exact file path. + +DEFINE_RMELOG_INTELLISENSE("ueaServer-IntelliSenseServer"); + +IMPLEMENT_SINGLE_INSTANCE(IntelliSenseServer); + +void IntelliSenseServer::Init() +{ + RtgMsgMgr::GetInstance().Init(); + RME_LOGI("[Init]:Init rtg and readXml finish!"); +} + +bool IntelliSenseServer::ReadXml() +{ + if (!m_needReadXml) { // do this value really need? + return false; + } + m_needReadXml = false; + if (ParaConfig::IsXmlPrepared(configFilePath)) { + m_generalPara = ParaConfig::GetGeneralConfig(); + m_subEventPara = ParaConfig::GetSubEventConfig(); + m_fpsList = ParaConfig::GetFpsList(); + m_renderTypeList = ParaConfig::GetRenderTypeList(); + if (!m_generalPara.empty() && !m_subEventPara.empty() && !m_fpsList.empty() && !m_renderTypeList.empty()) { + m_readXmlSuc = true; + RME_LOGI("[ReadXml]: read slide scene xml success!"); + return true; + } + } + RME_LOGE("[ReadXml]: read slide scene xml not success!"); + return false; +} + +void IntelliSenseServer::ReportMessage(std::string appName, std::string processName, int pid, AppStateUpdateReason reason) +{ + + int rtGrp = AppInfoMgr::GetInstance().GetAppRtgrp(pid); + switch (reason) { + case AppStateUpdateReason::APP_FOREGROUND: + rtGrp = RtgMsgMgr::GetInstance().OnForeground(appName, pid); + AppInfoMgr::GetInstance().OnForegroundChanged(pid, appName, rtGrp); + RME_LOGI("[ReportMessage]: App_foreground!"); + break; + case AppStateUpdateReason::APP_BACKGROUND: + RtgMsgMgr::GetInstance().OnBackground(appName, pid, rtGrp); + AppInfoMgr::GetInstance().OnBackgroundChanged(pid, appName); + RME_LOGI("[ReportMessage]: App_background!"); + break; + case AppStateUpdateReason::APP_TERMINATED: + RtgMsgMgr::GetInstance().ProcessDied(pid, -1); + AppInfoMgr::GetInstance().OnAppTerminateChanged(pid, appName); + RME_LOGI("[ReportMessage]: App terminated!"); + break; + default: + RME_LOGI("[ReportMessage]: get unuse app state msg!"); + break; + } + return; +} + +void IntelliSenseServer::ReportWindowFocus(const int pid, int isFocus) +{ + int rtGrp = AppInfoMgr::GetInstance().GetAppRtgrp(pid); + switch (isFocus) { + case static_cast(WindowState::FOCUS_YES): + { + rtGrp = RtgMsgMgr::GetInstance().OnForeground("", pid); + AppInfoMgr::GetInstance().OnForegroundChanged(pid, "", rtGrp); + RME_LOGI("[ReportWindowFocus]: Focus yes!"); + } + break; + case static_cast(WindowState::FOCUS_NO): + { + RtgMsgMgr::GetInstance().OnBackground("", pid, rtGrp); + AppInfoMgr::GetInstance().OnBackgroundChanged(pid, ""); + RME_LOGI("[ReportWindowFocus]: Focus No!"); + } + break; + default: + RME_LOGI("[ReportWindowFocus]:unknown msg!"); + + } + AppInfoMgr::GetInstance().OnWindowFocus(pid, isFocus); + RtgMsgMgr::GetInstance().FocusChanged(pid, isFocus); +} + +void IntelliSenseServer::ReportProcessInfo(const int pid, const int tid, ThreadState state) +{ + switch (state) { + case ThreadState::DIED: + { + int ret = AppInfoMgr::GetInstance().OnProcessDied(pid, tid); + if (ret) { + RtgMsgMgr::GetInstance().ProcessDied(pid, tid); + RME_LOGI("process died, need to delete the rtgrp."); + } + RME_LOGI("process died, do not need to delete the rtgrp:pid:%{public}d, tid: %{public}d, threadstate: %{public}d", pid, tid, static_cast(state)); + } + break; + case ThreadState::CREATE: + RME_LOGI("process create, pid: %{public}d, tid: %{public}d, threadstate: %{public}d", pid, tid, static_cast(state)); + break; + default: + RME_LOGI("unknown state : %{public}d", static_cast(state)); + break; + } + return; +} + +void IntelliSenseServer::SetPara(const int32_t currentFps, const int32_t currentRenderType) +{ + RME_LOGI("[SetPara]:ioctl SetPara!\n"); + std::string key = std::to_string(currentRenderType) + " " + std::to_string(currentFps); + map tempMap = m_subEventPara[key]; + +} + + +} // namespace RME +} // namesapce OHOS diff --git a/frameworks/core/frame_aware_policy/src/para_config.cpp b/frameworks/core/frame_aware_policy/src/para_config.cpp new file mode 100644 index 0000000..7c54cc0 --- /dev/null +++ b/frameworks/core/frame_aware_policy/src/para_config.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2022 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 "para_config.h" + +namespace OHOS { +namespace RME { + +namespace { +constexpr int FPS_MAX_VALUE = 120; +constexpr int RENDER_TYPE_MAX_VALUE = 2; +} + +DEFINE_RMELOG_INTELLISENSE("ueaServer-ParaConfig"); + +std::map ParaConfig::m_generalConfig; +std::map> ParaConfig::m_subEventConfig; +std::vector ParaConfig::m_fpsList; +std::vector ParaConfig::m_renderTypeList; + +bool ParaConfig::IsXmlPrepared(const std::string& filePath) +{ + RME_LOGI("[IsXmlPrepared]:begin!"); + xmlDocPtr docPtr; + docPtr = xmlReadFile(filePath.c_str(), nullptr, XML_PARSE_NOBLANKS); + RME_LOGI("[IsXmlPrepared]:filePath:%{public}s", filePath.c_str()); + if (docPtr == nullptr) { + RME_LOGE("[IsXmlPrepared]:load xml error!"); + return false; + } + + xmlNodePtr rootPtr; + rootPtr = xmlDocGetRootElement(docPtr); + if (rootPtr == nullptr || rootPtr->name == nullptr) { + RME_LOGE("[IsXmlPrepared]: get root element failed!"); + xmlFreeDoc(docPtr); + return false; + } + for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) { + if (IsValidNode(*curNodePtr)) { + RME_LOGE("[IsXmlPrepared]: invalid node!"); + continue; + } + auto nodeName = curNodePtr->name; // char* to string + if (!xmlStrcmp(nodeName, reinterpret_cast("log_open")) || + !xmlStrcmp(nodeName, reinterpret_cast("enable")) || + !xmlStrcmp(nodeName, reinterpret_cast("SOC")) || + !xmlStrcmp(nodeName, reinterpret_cast("frame_sched_reset_count"))) { + ReadConfigInfo(curNodePtr); // is this transform ok? + continue; + } + if (!xmlStrcmp(nodeName, reinterpret_cast("fps_list"))) { + ReadFpsConfig(curNodePtr); + continue; + } + if (!xmlStrcmp(nodeName, reinterpret_cast("render_type"))) { + ReadFpsConfig(curNodePtr); + continue; + } + if (!xmlStrcmp(nodeName, reinterpret_cast("framedetect"))) { + ReadFrameConfig(curNodePtr); + continue; + } + } + xmlFreeDoc(docPtr); + return true; +} + +bool ParaConfig::IsValidNode(const xmlNode& currNode) +{ + if (currNode.name == nullptr || currNode.type == XML_COMMENT_NODE) { + return true; + } + return false; +} + +void ParaConfig::ReadConfigInfo(const xmlNodePtr& root) +{ + xmlChar* context = nullptr; + context = xmlNodeGetContent(root); + if (context == nullptr) { + RME_LOGE("[GetConfigInfo]:read xml node error: nodeName:(%{public}s)", root->name); + return; + } + std::string nodeName = reinterpret_cast(root->name); + m_generalConfig[nodeName] = std::string(reinterpret_cast(context)); + xmlFree(context); +} + +void ParaConfig::ReadFpsConfig(const xmlNodePtr& root) +{ + xmlChar* context = xmlNodeGetContent(root); + if (context == nullptr) { + RME_LOGE("[GetFpsConfig]: fps read failed!"); + return; + } + + SplitString(std::string(reinterpret_cast(context)), " ", m_fpsList, FPS_MAX_VALUE, "fpsList"); + xmlFree(context); +} + +void ParaConfig::ReadRenderType(const xmlNodePtr& root) +{ + xmlChar* context = xmlNodeGetContent(root); + if (context == nullptr) { + RME_LOGE("[GetRenderType]: renderType read failed!"); + return; + } + SplitString(std::string(reinterpret_cast(context)), " ", m_renderTypeList, RENDER_TYPE_MAX_VALUE, "renderType"); + xmlFree(context); +} + +void ParaConfig::SplitString(const std::string& context, const std::string& character,std::vector &mList, + const int maxVal, const std::string& attrName) +{ + if (context == "") { + return; + } + + std::string toSplitStr = context + character; + size_t pos = toSplitStr.find(character); + + while (pos != toSplitStr.npos) { + int curVal = atoi(toSplitStr.substr(0, pos).c_str()); + if (curVal <= 0 && curVal > maxVal) { + RME_LOGI("[SplitString]:get data error! attr name:%{public}s", attrName.c_str()); + return; + } + mList.push_back(curVal); + + toSplitStr = toSplitStr.substr(pos + 1,toSplitStr.size()); + pos = toSplitStr.find(character); + } + RME_LOGI("[SplitString]:get data success!attr name:%{public}s", attrName.c_str()); +} + +void ParaConfig::ReadFrameConfig(const xmlNodePtr& root) +{ + // TODO: need abnormal process! what if the xml has problem when traversal? + for (xmlNodePtr curNode = root->xmlChildrenNode; curNode != nullptr; curNode = curNode->next) { + if (IsValidNode(*curNode)) { + RME_LOGE("[IsXmlPrepared]: invalid node!"); + continue; + } + std::string key1 = ""; + std::string key2 = ""; + ReadAttr(curNode, "renderType", key1); + ReadAttr(curNode, "fps_list", key2); + std::string key = key1 + " " + key2; + + std::map frameConfigTmp; + xmlNodePtr curSubNode = curNode->xmlChildrenNode; + for (; curSubNode != nullptr; curSubNode = curSubNode->next) { + std::string nodeName = reinterpret_cast(curSubNode->name); // char* to string + xmlChar* context = xmlNodeGetContent(curSubNode); + if (context == nullptr) { // if one config wrong then this config dilscard. + RME_LOGE("[GetFrameConfig]: frame config get error! nodeName:%{public}s, key:%{public}s", nodeName.c_str(), key.c_str()); + xmlFree(context); + break; + } + frameConfigTmp[nodeName] = atoi(reinterpret_cast(context)); + RME_LOGI("[GetFrameConfig]: nodeName:%{public}s, val:%{public}s", nodeName.c_str(), reinterpret_cast(context)); + xmlFree(context); + } + m_subEventConfig[key] = frameConfigTmp; + } + RME_LOGI("[GetFrameConfig]:read frameconfig success!"); +} + +void ParaConfig::ReadAttr(xmlNodePtr& root, const std::string& attrName, std::string& res) +{ + xmlChar* attr = nullptr; + attr = xmlGetProp(root, reinterpret_cast(attrName.c_str())); + if (attr == nullptr) { + RME_LOGE("[ReadAttr]: attr <%{public}s> read error!", attrName.c_str()); + } + const char* tmp = reinterpret_cast(attr); // char* to string + res = tmp; + xmlFree(attr); +} + +std::map ParaConfig::GetGeneralConfig() +{ + return m_generalConfig; +} + +std::map> ParaConfig::GetSubEventConfig() +{ + return m_subEventConfig; +} + +std::vector ParaConfig::GetFpsList() +{ + return m_fpsList; +} + +std::vector ParaConfig::GetRenderTypeList() +{ + return m_renderTypeList; +} + +} // namespace RME +} // namespace OHOS diff --git a/frameworks/core/frame_aware_policy/src/rtg_msg_mgr.cpp b/frameworks/core/frame_aware_policy/src/rtg_msg_mgr.cpp new file mode 100644 index 0000000..b8392cf --- /dev/null +++ b/frameworks/core/frame_aware_policy/src/rtg_msg_mgr.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022 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 "rtg_msg_mgr.h" + +namespace OHOS { +namespace RME { +namespace { +const int PRIO_TYPE = 0; +const int RT_NUM = 0; +} + +DEFINE_RMELOG_INTELLISENSE("ueaServer-RtgMsgMgr"); + +IMPLEMENT_SINGLE_INSTANCE(RtgMsgMgr); + +void RtgMsgMgr::Init() +{ + int ret = EnableRtg(true); + if (ret < 0) { + RME_LOGE("[Init]: enable rtg failed!"); + } +} + +int RtgMsgMgr::OnForeground(const std::string appName, const int pid) +{ // for multiwindow + RME_LOGI("[OnForeground]:pid:%{public}d:", pid); + int rtGrp = CreateNewRtgGrp(PRIO_TYPE, RT_NUM); + RME_LOGI("[OnForeground]: createNewRtgGroup begin! rtGrp:%{public}d, pid: %{public}d", rtGrp, pid); + if (rtGrp < 0) { + RME_LOGI("[OnForeground]: createNewRtgGroup failed! rtGrp:%{public}d, pid: %{public}d", rtGrp, pid); + rtGrp = -1; + return rtGrp; + } + AddThreadToRtg(pid, rtGrp); // add ui thread + return rtGrp; +} + +void RtgMsgMgr::OnBackground(const std::string appName, const int pid, const int grpId) +{ + RME_LOGI("[OnBackground]:pid:%{public}d", pid); + if (grpId <= 0) { + RME_LOGI("[OnBackground]:do not find grpid, pid:%{public}d, grpId:%{public}d", pid, grpId); + return; + } + DestroyRtgGrp(grpId); +} + +void RtgMsgMgr::ProcessStart(const int tid, const int grpId) +{ + if (grpId <= 0) { + RME_LOGI("[ProcessStart]:do not find grpid, tid:%{public}d, grpId:%{public}d", tid, grpId); + return; + } + AddThreadToRtg(tid, grpId); +} + +void RtgMsgMgr::ProcessDied(const int pid, const int tid) +{ + int removeTid = -1; + if (tid == -1) { + removeTid = pid; + } else { + removeTid = tid; + } + int ret = RemoveRtgThread(removeTid); + if (ret < 0) { + RME_LOGI("[ProcessDied]: removeRtgGroup failed!pid:%{public}d, tid:%{public}d", pid, tid); + } + RME_LOGI("[ProcessDied]: removeRtgGroup success! pid:%{public}d, tid:%{public}d:tid", pid, tid); +} + +void RtgMsgMgr::FpsChanged() +{ + RME_LOGI("[FpsChanged]: need to change fps for rtggrp!"); +} + +void RtgMsgMgr::FocusChanged(const int pid, bool isFocus) +{ + RME_LOGI("[FocusChanged]: need to change prio for rtggrp"); +} + +} // RME +} // OHOS diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn new file mode 100644 index 0000000..329c869 --- /dev/null +++ b/interfaces/innerkits/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (C) 2022 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("//build/ohos.gni") +import("//foundation/resourceschedule/frame_aware_sched/frame_aware_sched.gni") + +group("innerkits_target") { + deps = [ + "frameintf:frame_ui_intf", + "frameintf:frame_msg_intf", + "frameintf:rtg_interface", + ] +} diff --git a/interfaces/innerkits/frameintf/BUILD.gn b/interfaces/innerkits/frameintf/BUILD.gn new file mode 100644 index 0000000..1882f27 --- /dev/null +++ b/interfaces/innerkits/frameintf/BUILD.gn @@ -0,0 +1,123 @@ +# Copyright (C) 2022 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("//build/ohos.gni") +import("//foundation/resourceschedule/plugins/frame_aware_sched/frameaware.gni") + + +config("frame_ui_intf_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${innerkits_path}/frameintf", + "${frame_aware_path}/common/include", + "${framework_path}/frame_aware_collector/include", + "//utils/native/base/include", + "//utils/system/safwk/native/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + "//base/hiviewdfx/interfaces/innerkits/libhitrace/include", + ] +} + +ohos_shared_library("frame_ui_intf") { + sources = [ + "frame_ui_intf.cpp", + "${framework_path}/frame_aware_collector/src/frame_msg_mgr.cpp", + "${framework_path}/frame_aware_collector/src/frame_window_mgr.cpp", + "${framework_path}/frame_aware_collector/src/rme_core_sched.cpp", + "${framework_path}/frame_aware_collector/src/rme_scene_sched.cpp", + "${frame_aware_path}/interfaces/innerkits/frameintf/rtg_interface.cpp", + ] + + configs = [ ":frame_ui_intf_config" ] + + deps = [ + "//utils/native/base:utils", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + ] + + public_deps = [ + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "bytrace_standard:bytrace_core", + "dsoftbus_standard:softbus_client", + "ipc:ipc_core", + ] + + subsystem_name = "resourceschedule" + part_name = "frame_aware_sched" +} + +config("frame_msg_intf_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${innerkits_path}/frameintf", + "//third_party/libxml2/include", + "${framework_path}/frame_aware_policy/include", + "${frame_aware_path}/common/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + "//base/hiviewdfx/interfaces/innerkits/libhitrace/include", + ] +} + +ohos_shared_library("frame_msg_intf") { + sources = [ + "frame_msg_intf.cpp", + "${framework_path}/frame_aware_policy/src/intellisense_server.cpp", + "${framework_path}/frame_aware_policy/src/app_info.cpp", + "${framework_path}/frame_aware_policy/src/app_info_mgr.cpp", + "${framework_path}/frame_aware_policy/src/para_config.cpp", + "${framework_path}/frame_aware_policy/src/rtg_msg_mgr.cpp", + "${frame_aware_path}/interfaces/innerkits/frameintf/rtg_interface.cpp", + ] + + configs = [ ":frame_msg_intf_config" ] + + deps = [ + "//third_party/libxml2:xml2", + "//utils/native/base:utils", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", + ] + + external_deps = [ + "bytrace_standard:bytrace_core", + "hiviewdfx_hilog_native:libhilog", + "dsoftbus_standard:softbus_client", + "ipc:ipc_core", + ] + + subsystem_name = "resourceschedule" + part_name = "frame_aware_sched" +} + + +ohos_shared_library("rtg_interface") { + sources = [ + "rtg_interface.cpp" + ] + + include_dirs = [ + "${frame_aware_path}/common/include", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + ] + + install_enable = true + part_name = "frame_aware_sched" +} diff --git a/interfaces/innerkits/frameintf/frame_msg_intf.cpp b/interfaces/innerkits/frameintf/frame_msg_intf.cpp new file mode 100644 index 0000000..4b7df62 --- /dev/null +++ b/interfaces/innerkits/frameintf/frame_msg_intf.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 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 "frame_msg_intf.h" +#include "intellisense_server.h" +#include "event_handler.h" +#include "rme_log_domain.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("ueaServer-FrameMsgIntf"); + +FrameMsgIntf& FrameMsgIntf::GetInstance() +{ + static FrameMsgIntf instance; + return instance; +} + +bool FrameMsgIntf::Init() +{ + RME_LOGI("init begin!"); + if (!GetThreadHandler()) { + return false; + } + threadHandler_->PostTask([] { + IntelliSenseServer::GetInstance().Init(); + }); + return true; +} + +bool FrameMsgIntf::GetThreadHandler() +{ + if (threadHandler_ == nullptr) { + threadHandler_ = std::make_shared(AppExecFwk::EventRunner::Create()); + if (threadHandler_ == nullptr) { + RME_LOGI("failed to create thread handler!"); + return false; + } + } + RME_LOGI("Init process success!"); + return true; +} + + +void FrameMsgIntf::ReportAppInfo(std::string appName, std::string processName, int pid, AppStateUpdateReason reason) +{ + if (threadHandler_ == nullptr) { + RME_LOGI("[ReportAppInfo]:threandHandler none!"); + return; + } + threadHandler_->PostTask([appName, processName, pid, reason] { + IntelliSenseServer::GetInstance().ReportMessage(appName, processName, pid, reason); + }); +} + +void FrameMsgIntf::ReportWindowFocus(const int pid, const int isFocus) +{ + if (threadHandler_ == nullptr) { + RME_LOGI("[ReportWindowFocus]:threandHandler none!"); + return; + } + threadHandler_->PostTask([pid, isFocus] { + IntelliSenseServer::GetInstance().ReportWindowFocus(pid, isFocus); + }); +} + +void FrameMsgIntf::ReportProcessInfo(const int pid, const int tid, ThreadState state) +{ + + if (threadHandler_ == nullptr) { + RME_LOGI("[ReportWindowFocus]:threandHandler none!"); + return; + } + threadHandler_->PostTask([pid, tid, state] { + IntelliSenseServer::GetInstance().ReportProcessInfo(pid, tid, state); + }); +} + +void FrameMsgIntf::Stop() +{ + if (threadHandler_ != nullptr) { + threadHandler_->RemoveAllEvents(); + threadHandler_ = nullptr; + } + RME_LOGI("stop eventRunner success!"); +} + +} // namespace RME +} // namespace OHOS + diff --git a/interfaces/innerkits/frameintf/frame_msg_intf.h b/interfaces/innerkits/frameintf/frame_msg_intf.h new file mode 100644 index 0000000..de317e1 --- /dev/null +++ b/interfaces/innerkits/frameintf/frame_msg_intf.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_MSG_INTF_H +#define FRAME_MSG_INTF_H + +#include "rme_constants.h" +#include "single_instance.h" +#include "event_handler.h" + +namespace OHOS { +namespace RME { + +class FrameMsgIntf { +public: + static FrameMsgIntf& GetInstance(); + bool Init(); + bool GetThreadHandler(); + void ReportAppInfo(std::string appName, std::string processName, int pid, AppStateUpdateReason reason); + void ReportWindowFocus(const int pid, const int isFocus); + void ReportProcessInfo(const int pid, const int tid, ThreadState state); + void Stop(); + +protected: + FrameMsgIntf() = default; + virtual ~FrameMsgIntf() = default; + std::shared_ptr threadHandler_; + +private: + DISALLOW_COPY_AND_MOVE(FrameMsgIntf); + +}; + +} // namespace RME +} // namespace OHOS +#endif diff --git a/interfaces/innerkits/frameintf/frame_ui_intf.cpp b/interfaces/innerkits/frameintf/frame_ui_intf.cpp new file mode 100644 index 0000000..b9ca253 --- /dev/null +++ b/interfaces/innerkits/frameintf/frame_ui_intf.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2022 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 "frame_ui_intf.h" + +#include "frame_info_const.h" +#include "rme_constants.h" +#include "frame_msg_mgr.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("ueaCleint-FrameUiIntf"); + +//TO DO: need to check the init logic. + +FrameUiIntf& FrameUiIntf::GetInstance() +{ + static FrameUiIntf instance; + return instance; +} + +void FrameUiIntf::Init() +{ + if (inited) { + return; + } + int ret = FrameMsgMgr::GetInstance().Init(); + if (!ret) { + inited = false; + } else { + inited = true; + } + RME_LOGI("[Init]:ret:%{public}d, inited:%{public}d", ret, inited); +} + +int FrameUiIntf::GetSenseSchedEnable() +{ + if (!inited) { + return static_cast(ErrorCode::FAIL); + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::EVENT_RTG_ENABLE, EventState::ENABLE); + return static_cast(ErrorCode::SUCC); +} + +void FrameUiIntf::BeginFlushAnimation() +{ + + RME_LOGI("[BeginFlushAnimation]:start"); + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_ANIMATION, EventState::EVENT_ENTER); +} + +void FrameUiIntf::EndFlushAnimation() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_BUILD, EventState::EVENT_EXIT); +} + +void FrameUiIntf::BeginFlushBuild() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_BUILD, EventState::EVENT_ENTER); + RME_LOGI("[BeginFlushBuild]:success"); +} + +void FrameUiIntf::EndFlushBuild() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_BUILD, EventState::EVENT_EXIT); +} + +void FrameUiIntf::BeginFlushLayout() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_LAYOUT, EventState::EVENT_ENTER); +} + +void FrameUiIntf::EndFlushLayout() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_LAYOUT, EventState::EVENT_EXIT); +} + +void FrameUiIntf::BeginFlushRender() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_RENDER, EventState::EVENT_ENTER); +} + +void FrameUiIntf::EndFlushRender() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::FLUSH_RENDER, EventState::EVENT_EXIT); +} + +void FrameUiIntf::BeginProcessPostFlush() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::PROCESS_POST_FLUSH, EventState::EVENT_ENTER); +} + +void FrameUiIntf::ProcessCommandsStart() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::PROCESS_COMMANDS, EventState::EVENT_ENTER); +} + +void FrameUiIntf::AnimateStart() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::ANIMATE, EventState::EVENT_ENTER); +} + +void FrameUiIntf::RenderStart() +{ + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::RENDER, EventState::EVENT_ENTER); +} + +void FrameUiIntf::SendCommandsStart() +{ + RME_LOGI("[SendCommandsStart]:start"); + if (!inited) { + return; + } + FrameMsgMgr::GetInstance().EventUpdate(FrameEvent::SEND_COMMANDS, EventState::EVENT_ENTER); + RME_LOGI("[SendCommandsStart]:success"); +} + +} // namespace RME +} // namespace OHOS diff --git a/interfaces/innerkits/frameintf/frame_ui_intf.h b/interfaces/innerkits/frameintf/frame_ui_intf.h new file mode 100644 index 0000000..284d8f1 --- /dev/null +++ b/interfaces/innerkits/frameintf/frame_ui_intf.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAME_UI_INTF_H +#define FRAME_UI_INTF_H + +namespace OHOS { +namespace RME { + +class FrameUiIntf { +public: + static FrameUiIntf& GetInstance(); + void Init(); + int GetSenseSchedEnable(); + void BeginFlushAnimation(); + void EndFlushAnimation(); + + void BeginFlushBuild(); + void EndFlushBuild(); + void BeginFlushLayout(); + void EndFlushLayout(); + + void BeginFlushRender(); + void EndFlushRender(); + + void BeginProcessPostFlush(); + void ProcessCommandsStart(); + void AnimateStart(); + void RenderStart(); + void SendCommandsStart(); + + bool inited = false; +}; + +} // namespace RME +} // namespace OHOS +#endif diff --git a/interfaces/innerkits/frameintf/rtg_interface.cpp b/interfaces/innerkits/frameintf/rtg_interface.cpp new file mode 100644 index 0000000..9df25a1 --- /dev/null +++ b/interfaces/innerkits/frameintf/rtg_interface.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2022 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 "rtg_interface.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rme_log_domain.h" + +namespace OHOS { +namespace RME { + +DEFINE_RMELOG_INTELLISENSE("rtg_interface"); + +#define MAX_LENGTH 100 +#define MAX_STR_LEN 100 +#define MAX_PATH_LEN 100 + +#define RTG_SCHED_IPC_MAGIC 0xAB + +#define CMD_ID_SET_ENABLE \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct rtg_enable_data) +#define CMD_ID_SET_RTG \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data) +#define CMD_ID_SET_CONFIG \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct rtg_str_data) +#define CMD_ID_SET_RTG_ATTR \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct rtg_str_data) +#define CMD_ID_BEGIN_FRAME_FREQ \ + _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct proc_state_data) +#define CMD_ID_END_FRAME_FREQ \ + _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct proc_state_data) +#define CMD_ID_END_SCENE \ + _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct proc_state_data) +#define CMD_ID_SET_MIN_UTIL \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct proc_state_data) +#define CMD_ID_SET_MARGIN \ + _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct proc_state_data) +#define CMD_ID_LIST_RTG \ + _IOWR(RTG_SCHED_IPC_MAGIC, LIST_RTG, struct rtg_info) +#define CMD_ID_LIST_RTG_THREAD \ + _IOWR(RTG_SCHED_IPC_MAGIC, LIST_RTG_THREAD, struct rtg_grp_data) +#define CMD_ID_SEARCH_RTG \ + _IOWR(RTG_SCHED_IPC_MAGIC, SEARCH_RTG, struct proc_state_data) + +int BasicOpenRtgNode(int pid) +{ + char fileName[MAX_PATH_LEN] = {0}; + snprintf(fileName, MAX_PATH_LEN, "/proc/%d/rtg", pid); + int fd = open(fileName, O_RDWR); + if (fd < 0) { + RME_LOGE("Open fail, errno = %{public}d(%{public}s), dev = %{public}s", errno, strerror(errno), fileName); + } + return fd; +} + +enum rtg_type { + VIP = 0, + TOP_TASK_KEY, + TOP_TASK, + NORMAL_TASK, + RTG_TYPE_MAX, +}; + +int EnableRtg(bool flag) +{ + struct rtg_enable_data enableData; + char configStr[] = "load_freq_switch:1;sched_cycle:1"; + int pid = getpid(); + + enableData.enable = flag; + enableData.len = sizeof(configStr); + enableData.data = configStr; + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + if (ioctl(fd, CMD_ID_SET_ENABLE, &enableData)) { + RME_LOGE("set rtg config enable failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set rtg config enable success."); + } + close(fd); + return 0; +}; + +int CreateNewRtgGrp(int prioType, int rtNum) +{ + struct rtg_grp_data grp_data; + int ret; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) { + grp_data.prio_type = prioType; + } + if (rtNum > 0) { + grp_data.rt_cnt = rtNum; + } + grp_data.rtg_cmd = CMD_CREATE_RTG_GRP; + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("create rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("create rtg grp success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +} + +int AddThreadToRtg(int tid, int grpId) +{ + struct rtg_grp_data grp_data; + int ret; + int fd = BasicOpenRtgNode(tid); + if (fd < 0) { + RME_LOGE("open node failed."); + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + grp_data.tid_num = 1; + grp_data.tids[0] = tid; + grp_data.grp_id = grpId; + grp_data.rtg_cmd = CMD_ADD_RTG_THREAD; + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("add rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("add rtg grp success"); + } + close(fd); + return ret; +} + +int AddThreadsToRtg(vector tids, int grpId) +{ + struct rtg_grp_data grp_data; + int ret; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + int num = tids.size(); + if (num > MAX_TID_NUM) { + return -1; + } + grp_data.tid_num = num; + grp_data.grp_id = grpId; + grp_data.rtg_cmd = CMD_ADD_RTG_THREAD; + for (int i = 0; i < num; i++) { + if (tids[i] < 0) { + return -1; + } + grp_data.tids[i] = tids[i]; + } + + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("add rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("add rtg grp success"); + } + close(fd); + return ret; +}; + +int RemoveRtgThread(int tid){ + struct rtg_grp_data grp_data; + int ret; + int fd = BasicOpenRtgNode(tid); + if (fd < 0) { + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + grp_data.tid_num = 1; + grp_data.tids[0] = tid; + grp_data.rtg_cmd = CMD_REMOVE_RTG_THREAD; + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("remove grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("remove grp success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +}; + +int ClearRtgGrp(int GrpId){ + struct rtg_grp_data grp_data; + int ret; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + grp_data.rtg_cmd = CMD_CLEAR_RTG_GRP; + grp_data.grp_id = GrpId; + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("clear rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("clear rtg grp success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +}; + +int DestroyRtgGrp(int GrpId){ + struct rtg_grp_data grp_data; + int ret; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + grp_data.rtg_cmd = CMD_DESTROY_RTG_GRP; + grp_data.grp_id = GrpId; + ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data); + if ( ret < 0) { + RME_LOGE("create rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("create rtg grp success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +}; + + +int SetMaxVipRtgs(int rtframe){ + int ret = 0; + char str_data[MAX_STR_LEN] = {}; + snprintf(str_data, MAX_STR_LEN, "rtframe:%d", rtframe); + struct rtg_str_data strData; + strData.len = strlen(str_data); + strData.data = str_data; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_SET_CONFIG, &strData); + if ( ret < 0) { + RME_LOGE("set single config failed, ret = %{public}d", ret); + } else { + RME_LOGI("set single config success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +} + +int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType){ + int ret = 0; + char str_data[MAX_LENGTH] = {}; + snprintf(str_data, MAX_LENGTH, "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType); + struct rtg_str_data strData; + strData.len = strlen(str_data); + strData.data = str_data; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_SET_RTG_ATTR, &strData); + if ( ret < 0) { + RME_LOGE("set rtg attr failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set rtg attr success, get rtg id %{public}d.", ret); + } + close(fd); + return ret; +} + +int BeginFrameFreq(int grpId, int stateParam){ + int ret = 0; + struct proc_state_data state_data; + state_data.grp_id = grpId; + state_data.state_param = stateParam; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_BEGIN_FRAME_FREQ, &state_data); + if ( ret < 0) { + RME_LOGE("set BeginFrameFreq failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set BeginFrameFreq success, get ret %{public}d.", ret); + } + close(fd); + return ret; +} + +int EndFrameFreq(int grpId, int stateParam){ + int ret = 0; + struct proc_state_data state_data; + state_data.grp_id = grpId; + state_data.state_param = stateParam; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_END_FRAME_FREQ, &state_data); + if ( ret < 0) { + RME_LOGE("set EndFrameFreq failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set EndFrameFreq success, get ret %{public}d.", ret); + } + close(fd); + + return ret; +} + +int EndScene(int rtgId){ + int ret = 0; + struct proc_state_data state_data; + state_data.grp_id = rtgId; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_END_SCENE, &state_data); + if ( ret < 0) { + RME_LOGE("set EndScene failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set EndScene success, get ret %{public}d.", ret); + } + close(fd); + + return ret; +} + +int SetMinUtil(int grpId, int stateParam){ + int ret = 0; + struct proc_state_data state_data; + state_data.grp_id = grpId; + state_data.state_param = stateParam; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_SET_MIN_UTIL, &state_data); + if ( ret < 0) { + RME_LOGE("set min util failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set min util success, get ret %{public}d.", ret); + } + close(fd); + + return ret; +} + +int SetMargin(int grpId, int stateParam) { + int ret = 0; + struct proc_state_data state_data; + state_data.grp_id = grpId; + state_data.state_param = stateParam; + + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + ret = ioctl(fd, CMD_ID_SET_MARGIN, &state_data); + if ( ret < 0) { + RME_LOGE("set margin failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("set margin success, get ret %{public}d.", ret); + } + close(fd); + + return ret; +} + +int ListRtgGroup(vector *rs) +{ + int ret = 0; + struct rtg_info rtg_info; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + if (!rs) { + return -1; + } + memset(&rtg_info, 0, sizeof(struct rtg_info)); + ret = ioctl(fd, CMD_ID_LIST_RTG, &rtg_info); + if ( ret < 0) { + RME_LOGE("list rtg group failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("list rtg group success with num %{public}d", rtg_info.rtg_num); + rs->clear(); + for (int i = 0; i < rtg_info.rtg_num; i++) { + rs->push_back(rtg_info.rtgs[i]); + } + } + close(fd); + return ret; +} + +int ListRtgThread(int grpId, vector *rs) +{ + int ret = 0; + struct rtg_grp_data grp_data; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + if (!rs) { + return -1; + } + memset(&grp_data, 0, sizeof(struct rtg_grp_data)); + grp_data.grp_id = grpId; + ret = ioctl(fd, CMD_ID_LIST_RTG_THREAD, &grp_data); + if ( ret < 0) { + RME_LOGE("list rtg thread failed, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("list rtg thread success with tid num %{public}d", grp_data.tid_num); + rs->clear(); + for (int i = 0; i < grp_data.tid_num; i++) { + rs->push_back(grp_data.tids[i]); + } + } + close(fd); + return ret; +} + +int SearchRtgForTid(int stateParam) +{ + int ret = 0; + struct proc_state_data search_data; + int pid = getpid(); + int fd = BasicOpenRtgNode(pid); + if (fd < 0) { + return fd; + } + if (stateParam <= 0) { + RME_LOGI("Search tid err: invalid tid."); + return -1; + } + memset(&search_data, 0, sizeof(struct proc_state_data)); + search_data.state_param = stateParam; + ret = ioctl(fd, CMD_ID_SEARCH_RTG, &search_data); + if ( ret < 0) { + RME_LOGE("Search tid fail, errno = %{public}d (%{public}s)", errno, strerror(errno)); + } else { + RME_LOGI("Search tid %{public}d success with rtg_grp %{public}d", stateParam, ret); + } + close(fd); + return ret; +} + +} // namespace RME +} // namespace OHOS diff --git a/profiles/BUILD.gn b/profiles/BUILD.gn new file mode 100644 index 0000000..9c5c6cd --- /dev/null +++ b/profiles/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2022 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("//build/ohos.gni") + +ohos_prebuilt_etc("frame_aware_sched_config") { + source = "hwrme.xml" + subsystem_name = "resourceschedule" + part_name = "frame_aware_sched" + module_install_dir = "etc/frame_aware_sched" +} diff --git a/profiles/hwrme.xml b/profiles/hwrme.xml new file mode 100644 index 0000000..49c6c78 --- /dev/null +++ b/profiles/hwrme.xml @@ -0,0 +1,28 @@ + + + + 1.0 + -1 + 1 + 990 + 1 + 60 90 + 0 1 2 + + + 600 + + + diff --git a/test/BUILD.gn b/test/BUILD.gn new file mode 100644 index 0000000..2ce9368 --- /dev/null +++ b/test/BUILD.gn @@ -0,0 +1,101 @@ +# Copyright (C) 2022 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("//build/ohos.gni") +import("//build/ohos_var.gni") +import("//build/test.gni") +import("//foundation/resourceschedule/plugins/frame_aware_sched/frameaware.gni") + +module_output_path = "frameawareschedtest/" + +frame_aware_sched_configs = [ "${innerkits_path}/frameintf:frame_msg_intf_config" ] + +frame_aware_sched_deps = [ + "//utils/native/base:utils", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "${innerkits_path}/frameintf:frame_ui_intf", + "${innerkits_path}/frameintf:frame_msg_intf", + "//foundation/appexecfwk/standard/interfaces/innerkits/libeventhandler:libeventhandler", +] + +frame_aware_sched_external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", +] + +frame_aware_sched_public_deps = [ "//third_party/googletest:gtest_main" ] + + +ohos_unittest("frame_ui_intf_test") { + module_out_path = module_output_path + configs = frame_aware_sched_configs + + sources = [ "unittest/phone/frame_ui_intf_test.cpp" ] + + deps = frame_aware_sched_deps + + if (is_standard_system) { + external_deps = frame_aware_sched_external_deps + public_deps = frame_aware_sched_public_deps + } + part_name = "frame_aware_sched" + subsystem_name = "resourceschedule" + +} + +ohos_unittest("frame_msg_intf_test") { + module_out_path = module_output_path + + sources = [ "unittest/phone/frame_msg_intf_test.cpp" ] + + configs = frame_aware_sched_configs + + deps = frame_aware_sched_deps + + if (is_standard_system) { + external_deps = frame_aware_sched_external_deps + public_deps = frame_aware_sched_public_deps + } + + part_name = "frame_aware_sched" + subsystem_name = "resourceschedule" +} + +ohos_unittest("rtg_interface_test") { + module_out_path = module_output_path + + sources = [ "unittest/phone/rtg_interface_test.cpp" ] + + include_dirs = [ + "${frame_aware_path}/common/include", + ] + + deps = frame_aware_sched_deps + + if (is_standard_system) { + external_deps = frame_aware_sched_external_deps + public_deps = frame_aware_sched_public_deps + } + + part_name = "frame_aware_sched" + subsystem_name = "resourceschedule" + +} + +group("frame_unittest") { + testonly = true + deps = [ + ":frame_msg_intf_test", + ":rtg_interface_test", + ] +} diff --git a/test/unittest/phone/frame_msg_intf_test.cpp b/test/unittest/phone/frame_msg_intf_test.cpp new file mode 100644 index 0000000..2161920 --- /dev/null +++ b/test/unittest/phone/frame_msg_intf_test.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022 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 "gtest/gtest.h" + +#define private public +#define protected public +#include "frame_msg_intf.h" +#include "app_info_mgr.h" +#include "app_info.h" +#undef private +#undef protected + +namespace OHOS { +namespace RME { +using namespace testing; +using namespace testing::ext; + +class FrameMsgIntfTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void FrameMsgIntfTest::SetUpTestCase() +{ +} + +void FrameMsgIntfTest::TearDownTestCase() +{ +} + +void FrameMsgIntfTest::SetUp() +{ +} + +void FrameMsgIntfTest::TearDown() +{ +} + +HWTEST_F(FrameMsgIntfTest, FrameMsgIntfInit, TestSize.Level1) +{ + bool ret = FrameMsgIntf::GetInstance().Init(); + EXPECT_EQ(ret, true); +} + +HWTEST_F(FrameMsgIntfTest, FrameMsgIntfReportAppInfo, TestSize.Level1) +{ + int pid_1 = 12315; + std::string appName_1 = "com.ohos.frameaware.test1"; + int pid_2 = 12366; + std::string appName_2 = "com.ohos.frameaware.test2"; + + // app foreground + FrameMsgIntf::GetInstance().ReportAppInfo(appName_1, appName_1, pid_1, AppStateUpdateReason::APP_FOREGROUND); + FrameMsgIntf::GetInstance().ReportAppInfo(appName_2, appName_2, pid_2, AppStateUpdateReason::APP_FOREGROUND); + + // app background + FrameMsgIntf::GetInstance().ReportAppInfo(appName_2, appName_2, pid_2, AppStateUpdateReason::APP_BACKGROUND); + + + bool isAppPidExist = AppInfoMgr::GetInstance().GetForegroundApp().count(pid_1); + bool isAppPidExist2 = AppInfoMgr::GetInstance().GetForegroundApp().count(pid_2); + + EXPECT_EQ(isAppPidExist, true); + EXPECT_EQ(isAppPidExist2, false); + + // app terminated + FrameMsgIntf::GetInstance().ReportAppInfo(appName_1, appName_1, pid_1, AppStateUpdateReason::APP_TERMINATED); + isAppPidExist = AppInfoMgr::GetInstance().GetForegroundApp().count(pid_1); + EXPECT_EQ(isAppPidExist, false); +} + +HWTEST_F(FrameMsgIntfTest, FrameMsgIntfReportWindowFocus, TestSize.Level1) +{ + + int pid_1 = 12234; + int pid_2 = 23134; + int pid_3 = 8912; + + std::string appName_1 = "com.ohos.frameaware.test1"; + std::string appName_2 = "com.ohos.frameaware.test2"; + std::string appName_3 = "com.ohos.frameaware.test3"; + + // app focus + FrameMsgIntf::GetInstance().ReportAppInfo(appName_1, appName_1, pid_1, AppStateUpdateReason::APP_FOREGROUND); + FrameMsgIntf::GetInstance().ReportAppInfo(appName_2, appName_2, pid_2, AppStateUpdateReason::APP_FOREGROUND); + FrameMsgIntf::GetInstance().ReportWindowFocus(pid_1, 1); + + // app Unfocus + FrameMsgIntf::GetInstance().ReportAppInfo(appName_3, appName_3, pid_3, AppStateUpdateReason::APP_FOREGROUND); + FrameMsgIntf::GetInstance().ReportWindowFocus(pid_3, 0); + + std::shared_ptr app_1 = AppInfoMgr::GetInstance().GetFocusApp(); + bool focusSta_1 = app_1->GetFocusState(); + std::shared_ptr app_2 = AppInfoMgr::GetInstance().GetFocusApp(); + bool focusSta_2 = app_2->GetFocusState(); + + EXPECT_EQ(focusSta_1, true); + EXPECT_EQ(focusSta_2, false); +} + +HWTEST_F(FrameMsgIntfTest, FrameMsgIntfReportProcessInfo, TestSize.Level1) +{ + //process died + int pid_1 = 12435; + int pid_2 = 12436; + int ui_tid = 12435; + int render_tid = 13332; + + FrameMsgIntf::GetInstance().ReportWindowFocus(pid_1, 1); + FrameMsgIntf::GetInstance().ReportWindowFocus(pid_2, 1); + + FrameMsgIntf::GetInstance().ReportProcessInfo(pid_1, ui_tid, ThreadState::DIED); + FrameMsgIntf::GetInstance().ReportProcessInfo(pid_1, render_tid, ThreadState::DIED); + + std::shared_ptr app_1 = AppInfoMgr::GetInstance().mForegroundAppList[pid_1]; + EXPECT_EQ(app_1->GetUiTid(), ui_tid); + EXPECT_EQ(app_1->GetRenderTid(), render_tid); +} + +HWTEST_F(FrameMsgIntfTest, FrameMsgIntfStop, TestSize.Level1) +{ + FrameMsgIntf::GetInstance().Stop(); + std::shared_ptr thread = FrameMsgIntf::GetInstance().threadHandler_; + EXPECT_TRUE(thread == nullptr); +} + +} // namespace RME +} // namespace OHOS diff --git a/test/unittest/phone/frame_ui_intf_test.cpp b/test/unittest/phone/frame_ui_intf_test.cpp new file mode 100644 index 0000000..d9f4d24 --- /dev/null +++ b/test/unittest/phone/frame_ui_intf_test.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 "gtest/gtest.h" + +#define private public +#define protected public +#include "frame_ui_intf.h" +#undef private +#undef protected + +namespace OHOS { +namespace RME { +using namespace testing; +using namespace testing::ext; + +class FrameUIIntfTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void FrameUIIntfTest::SetUpTestCase() +{ +} + +void FrameUIIntfTest::TearDownTestCase() +{ +} + +void FrameUIIntfTest::SetUp() +{ +} + +void FrameUIIntfTest::TearDown() +{ +} diff --git a/test/unittest/phone/rtg_interface_test.cpp b/test/unittest/phone/rtg_interface_test.cpp new file mode 100644 index 0000000..d0e53cc --- /dev/null +++ b/test/unittest/phone/rtg_interface_test.cpp @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2022 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 "gtest/gtest.h" + +#define private public +#define protected public +#include "rtg_interface.h" +#undef private +#undef protected + +namespace OHOS { +namespace RME { +using namespace testing; +using namespace testing::ext; + +#define RTG_INTERFACE_SO_PATH "/system/lib/librtg_interface.z.so" + +enum rtg_type { + VIP = 0, + TOP_TASK_KEY, + TOP_TASK, + NORMAL_TASK, + RTG_TYPE_MAX, +}; + +class RtgInterfaceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void RtgInterfaceTest::SetUpTestCase() +{ +} + +void RtgInterfaceTest::TearDownTestCase() +{ +} + +void RtgInterfaceTest::SetUp() +{ + // must enable rtg before use the interface + bool ret = EnableRtg(true); + EXPECT_EQ(ret, false); +} + +void RtgInterfaceTest::TearDown() +{ + // disable rtg after use the interface + bool ret = EnableRtg(false); + EXPECT_EQ(ret, false); +} + +/** + * @tc.name: RtgInterfaceCreateAndDestroy + * @tc.desc: Verify the CreateAndDestroy function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceCreateAndDestroy, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceDestroyErrorGroup + * @tc.desc: Verify Destroy function with error param. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceDestroyErrorGroup, TestSize.Level1) +{ + int ret = 0; + ret = DestroyRtgGrp(-1); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceAddRtg + * @tc.desc: Verify Rtg add function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceAddRtg, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + int pid = getpid(); + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = AddThreadToRtg(pid, grpId); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceAddErrorThread + * @tc.desc: Verify Rtg add function with error pid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceAddErrorThread, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = AddThreadToRtg(-1, grpId); + EXPECT_NE(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceAddErrorGroup + * @tc.desc: Verify Rtg add function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceAddErrorGroup, TestSize.Level1) +{ + int ret = 0; + int pid = getpid(); + ret = AddThreadToRtg(pid, -1); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceAddRtgs + * @tc.desc: Verify Rtg add multiple thread function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceAddRtgs, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + int pid = getpid(); + vector pids = {}; + pids.push_back(pid); + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = AddThreadsToRtg(pids, grpId); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceClearRtg + * @tc.desc: Verify Rtg clear function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceClearRtg, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + int pid = getpid(); + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = AddThreadToRtg(pid, grpId); + EXPECT_EQ(ret, 0); + ret = ClearRtgGrp(grpId); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceClearErrorGroup + * @tc.desc: Verify Rtg clear function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceClearErrorGroup, TestSize.Level1) +{ + int ret = 0; + ret = ClearRtgGrp(-1); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceBeginFrameFreq + * @tc.desc: Verify rtg frame start function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceBeginFrameFreq, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = BeginFrameFreq(grpId, 0); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceBeginFrameFreqWithErrorGrp + * @tc.desc: Verify rtg frame start function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceBeginFrameFreqWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + ret = BeginFrameFreq(-1, 0); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceEndFrameFreq + * @tc.desc: Verify rtg frame end function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceEndFrameFreq, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = EndFrameFreq(grpId, 0); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceEndFrameFreqWithErrorGrp + * @tc.desc: Verify rtg frame end function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceEndFrameFreqWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + ret = EndFrameFreq(-1, 0); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceEndScene + * @tc.desc: Verify rtg frame scene end function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceEndScene, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = EndScene(grpId); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceEndSceneWithErrorGrp + * @tc.desc: Verify rtg frame scene end function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceEndSceneWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + ret = EndScene(-1); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetMinUtil + * @tc.desc: Verify rtg minUtil set function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetMinUtil, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = SetMinUtil(grpId, 0); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetMinUtilWithErrorGrp + * @tc.desc: Verify rtg minUtil set function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetMinUtilWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + ret = SetMinUtil(-1, 0); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetMargin + * @tc.desc: Verify rtg margin set function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetMargin, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = SetMargin(grpId, 0); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetMarginWithErrorGrp + * @tc.desc: Verify rtg margin set function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetMarginWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + ret = SetMargin(-1, 0); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceListRtgThread + * @tc.desc: Verify rtg list function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceListRtgThread, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + vector rs; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = ListRtgThread(grpId, &rs); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceListRtgThreadWithNullRes + * @tc.desc: Verify rtg thread list function with null vector input. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceListRtgThreadWithNullRes, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = ListRtgThread(grpId, nullptr); + EXPECT_NE(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceListRtgThreadWithErrorGrp + * @tc.desc: Verify rtg thread list function with error groupid. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceListRtgThreadWithErrorGrp, TestSize.Level1) +{ + int ret = 0; + vector rs; + ret = ListRtgThread(-1, &rs); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceListRtgGroup + * @tc.desc: Verify rtg list function. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceListRtgGroup, TestSize.Level1) +{ + int ret = 0; + vector rs; + ret = ListRtgGroup(&rs); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceListRtgGroupWithNullRes + * @tc.desc: Verify rtg list function with null vector input. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceListRtgGroupWithNullRes, TestSize.Level1) +{ + int ret = 0; + ret = ListRtgGroup(nullptr); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetAttr + * @tc.desc: Verify rtg attr set funtion. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetAttr, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = SetFrameRateAndPrioType(grpId, 60, VIP); + EXPECT_EQ(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetErrorAttr + * @tc.desc: Verify rtg attr set funtion with error attr param. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetErrorAttr, TestSize.Level1) +{ + int ret = 0; + int grpId = 0; + grpId = CreateNewRtgGrp(VIP, 0); + EXPECT_GT(grpId, 0); + ret = SetFrameRateAndPrioType(grpId, 90, -1); + EXPECT_NE(ret, 0); + ret = DestroyRtgGrp(grpId); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetMaxVips + * @tc.desc: Verify rtg max vip num set funtion. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetMaxVips, TestSize.Level1) +{ + int ret = 0; + ret = SetMaxVipRtgs(2); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetErrorMaxVips + * @tc.desc: Verify rtg max vip num set funtion with 0 vip nums. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetErrorMaxVips, TestSize.Level1) +{ + int ret = 0; + ret = SetMaxVipRtgs(0); + EXPECT_NE(ret, 0); +} + +/** + * @tc.name: RtgInterfaceSetLargeMaxVips + * @tc.desc: Verify rtg max vip num set funtion with too large vip nums. + * @tc.type: FUNC + */ +HWTEST_F(RtgInterfaceTest, RtgInterfaceSetLargeMaxVips, TestSize.Level1) +{ + int ret = 0; + ret = SetMaxVipRtgs(50000); + EXPECT_NE(ret, 0); +} + +} // namespace RME +} // namespace OHOS \ No newline at end of file -- Gitee From b1f9562002a9a17eb832eeff66c48fde5702a642 Mon Sep 17 00:00:00 2001 From: rongkunshi Date: Mon, 14 Feb 2022 18:36:11 +0800 Subject: [PATCH 2/2] fix the code for code quality Signed-off-by: rongkunshi --- frameworks/core/frame_aware_policy/src/app_info_mgr.cpp | 4 ++-- .../core/frame_aware_policy/src/intellisense_server.cpp | 2 +- frameworks/core/frame_aware_policy/src/para_config.cpp | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp b/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp index 432bfb1..7533b37 100644 --- a/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp +++ b/frameworks/core/frame_aware_policy/src/app_info_mgr.cpp @@ -110,10 +110,10 @@ void AppInfoMgr::OnUiProcessStart(const int pid, const int tid) bool AppInfoMgr::OnProcessDied(const int pid, const int tid) { bool deleted = false; - if (mForegroundAppList.find(pid) != mForegroundAppList.end()) { + if (mForegroundAppList.count(pid)) { mForegroundAppList.erase(pid); deleted = true; - } else if (mBackgroundAppList.find(pid) != mBackgroundAppList.end()) { + } else if (mBackgroundAppList.count(pid)) { mBackgroundAppList.erase(pid); } RME_LOGI("[OnProcessDied]: pid: %{public}d, tid:%{public}d, deleted:%{public}d.\n", pid, tid, deleted); diff --git a/frameworks/core/frame_aware_policy/src/intellisense_server.cpp b/frameworks/core/frame_aware_policy/src/intellisense_server.cpp index aff8579..1400ad2 100644 --- a/frameworks/core/frame_aware_policy/src/intellisense_server.cpp +++ b/frameworks/core/frame_aware_policy/src/intellisense_server.cpp @@ -141,7 +141,7 @@ void IntelliSenseServer::SetPara(const int32_t currentFps, const int32_t current RME_LOGI("[SetPara]:ioctl SetPara!\n"); std::string key = std::to_string(currentRenderType) + " " + std::to_string(currentFps); map tempMap = m_subEventPara[key]; - + RME_LOGI("[SetPara]:subEventPara map size: %{public}d", tempMap.size()); } diff --git a/frameworks/core/frame_aware_policy/src/para_config.cpp b/frameworks/core/frame_aware_policy/src/para_config.cpp index 7c54cc0..4e2fdf3 100644 --- a/frameworks/core/frame_aware_policy/src/para_config.cpp +++ b/frameworks/core/frame_aware_policy/src/para_config.cpp @@ -88,8 +88,7 @@ bool ParaConfig::IsValidNode(const xmlNode& currNode) void ParaConfig::ReadConfigInfo(const xmlNodePtr& root) { - xmlChar* context = nullptr; - context = xmlNodeGetContent(root); + xmlChar* context = xmlNodeGetContent(root); if (context == nullptr) { RME_LOGE("[GetConfigInfo]:read xml node error: nodeName:(%{public}s)", root->name); return; @@ -181,8 +180,7 @@ void ParaConfig::ReadFrameConfig(const xmlNodePtr& root) void ParaConfig::ReadAttr(xmlNodePtr& root, const std::string& attrName, std::string& res) { - xmlChar* attr = nullptr; - attr = xmlGetProp(root, reinterpret_cast(attrName.c_str())); + xmlChar* attr = xmlGetProp(root, reinterpret_cast(attrName.c_str())); if (attr == nullptr) { RME_LOGE("[ReadAttr]: attr <%{public}s> read error!", attrName.c_str()); } -- Gitee