From 93accfc09f7eb24228144a7d19f43d321d597fd5 Mon Sep 17 00:00:00 2001 From: mamingshuai Date: Wed, 2 Jun 2021 00:03:48 +0800 Subject: [PATCH] update OpenHarmony 2.0 Canary --- .gitattributes | 15 + LICENSE | 177 ++++++ README.en.md | 36 -- README.md | 56 +- README_zh.md | 45 ++ batterymgr.gni | 17 + ...ower-management-subsystem-architecture.png | Bin 0 -> 61687 bytes hdi/BUILD.gn | 21 + hdi/api/include/batteryd_api.h | 50 ++ hdi/client/BUILD.gn | 49 ++ hdi/client/include/batteryd_client.h | 43 ++ hdi/client/include/batteryd_subscriber.h | 37 ++ hdi/client/src/batteryd_client.cpp | 194 ++++++ hdi/client/src/batteryd_subscriber.cpp | 55 ++ hdi/service/BUILD.gn | 58 ++ hdi/service/include/batteryd.h | 32 + hdi/service/include/batteryd_dispatcher.h | 23 + hdi/service/include/batteryd_parser.h | 32 + hdi/service/include/batteryd_publisher.h | 28 + hdi/service/src/batteryd.c | 249 ++++++++ hdi/service/src/batteryd_dispatcher.c | 207 +++++++ hdi/service/src/batteryd_parser.c | 564 ++++++++++++++++++ hdi/service/src/batteryd_publisher.c | 68 +++ interfaces/innerkits/BUILD.gn | 52 ++ .../innerkits/native/include/battery_info.h | 305 ++++++++++ .../native/include/battery_srv_client.h | 88 +++ .../innerkits/native/include/ibattery_srv.h | 53 ++ .../native/src/battery_srv_client.cpp | 144 +++++ interfaces/kits/js/@ohos.batteryinfo.d.ts | 170 ++++++ interfaces/kits/js/napi/BUILD.gn | 47 ++ interfaces/kits/js/napi/battery_info.cpp | 288 +++++++++ interfaces/kits/js/test/battery_unit.test.js | 132 ++++ ohos.build | 33 + sa_profile/3302.xml | 24 + sa_profile/BUILD.gn | 19 + services/BUILD.gn | 62 ++ services/native/include/battery_service.h | 74 +++ .../include/battery_service_subscriber.h | 34 ++ .../native/include/batterysrv_event_handler.h | 39 ++ services/native/src/battery_service.cpp | 167 ++++++ .../native/src/battery_service_subscriber.cpp | 83 +++ .../native/src/batterysrv_event_handler.cpp | 31 + services/native/test/BUILD.gn | 21 + services/native/test/unittest/common/BUILD.gn | 63 ++ .../common/include/battery_service_test.h | 29 + .../common/src/battery_service_test.cpp | 204 +++++++ services/zidl/ibattery_srv.zidl | 19 + services/zidl/include/battery_srv_proxy.h | 46 ++ services/zidl/include/battery_srv_stub.h | 47 ++ services/zidl/src/battery_srv_proxy.cpp | 223 +++++++ services/zidl/src/battery_srv_stub.cpp | 120 ++++ utils/BUILD.gn | 21 + utils/native/include/hilog_wrapper.h | 108 ++++ utils/native/include/power_common.h | 77 +++ utils/native/include/power_mgr_errors.h | 48 ++ utils/native/include/sp_singleton.h | 74 +++ 56 files changed, 4940 insertions(+), 61 deletions(-) create mode 100644 .gitattributes create mode 100644 LICENSE delete mode 100644 README.en.md mode change 100644 => 100755 README.md create mode 100755 README_zh.md create mode 100644 batterymgr.gni create mode 100755 figures/power-management-subsystem-architecture.png create mode 100644 hdi/BUILD.gn create mode 100644 hdi/api/include/batteryd_api.h create mode 100644 hdi/client/BUILD.gn create mode 100644 hdi/client/include/batteryd_client.h create mode 100644 hdi/client/include/batteryd_subscriber.h create mode 100644 hdi/client/src/batteryd_client.cpp create mode 100644 hdi/client/src/batteryd_subscriber.cpp create mode 100644 hdi/service/BUILD.gn create mode 100644 hdi/service/include/batteryd.h create mode 100644 hdi/service/include/batteryd_dispatcher.h create mode 100644 hdi/service/include/batteryd_parser.h create mode 100644 hdi/service/include/batteryd_publisher.h create mode 100644 hdi/service/src/batteryd.c create mode 100644 hdi/service/src/batteryd_dispatcher.c create mode 100644 hdi/service/src/batteryd_parser.c create mode 100644 hdi/service/src/batteryd_publisher.c create mode 100644 interfaces/innerkits/BUILD.gn create mode 100644 interfaces/innerkits/native/include/battery_info.h create mode 100644 interfaces/innerkits/native/include/battery_srv_client.h create mode 100644 interfaces/innerkits/native/include/ibattery_srv.h create mode 100644 interfaces/innerkits/native/src/battery_srv_client.cpp create mode 100644 interfaces/kits/js/@ohos.batteryinfo.d.ts create mode 100755 interfaces/kits/js/napi/BUILD.gn create mode 100644 interfaces/kits/js/napi/battery_info.cpp create mode 100644 interfaces/kits/js/test/battery_unit.test.js create mode 100644 ohos.build create mode 100644 sa_profile/3302.xml create mode 100644 sa_profile/BUILD.gn create mode 100644 services/BUILD.gn create mode 100644 services/native/include/battery_service.h create mode 100644 services/native/include/battery_service_subscriber.h create mode 100644 services/native/include/batterysrv_event_handler.h create mode 100644 services/native/src/battery_service.cpp create mode 100644 services/native/src/battery_service_subscriber.cpp create mode 100644 services/native/src/batterysrv_event_handler.cpp create mode 100644 services/native/test/BUILD.gn create mode 100644 services/native/test/unittest/common/BUILD.gn create mode 100644 services/native/test/unittest/common/include/battery_service_test.h create mode 100644 services/native/test/unittest/common/src/battery_service_test.cpp create mode 100644 services/zidl/ibattery_srv.zidl create mode 100644 services/zidl/include/battery_srv_proxy.h create mode 100644 services/zidl/include/battery_srv_stub.h create mode 100644 services/zidl/src/battery_srv_proxy.cpp create mode 100644 services/zidl/src/battery_srv_stub.cpp create mode 100644 utils/BUILD.gn create mode 100644 utils/native/include/hilog_wrapper.h create mode 100644 utils/native/include/power_common.h create mode 100644 utils/native/include/power_mgr_errors.h create mode 100644 utils/native/include/sp_singleton.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..51c63e2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +*.tgz filter=lfs diff=lfs merge=lfs -text +*.trp filter=lfs diff=lfs merge=lfs -text +*.apk filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.asm filter=lfs diff=lfs merge=lfs -text +*.8svn filter=lfs diff=lfs merge=lfs -text +*.9svn filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.a filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4947287 --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + 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 \ No newline at end of file diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 4e0ba4b..0000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# powermgr_battery_manager - -#### Description -Battery manager | 电池服务模块 - -#### 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 old mode 100644 new mode 100755 index eac2873..3609b8f --- a/README.md +++ b/README.md @@ -1,37 +1,43 @@ -# powermgr_battery_manager +# battery\_manager -#### 介绍 -Battery manager | 电池服务模块 +- [Introduction](#section11660541593) +- [Directory Structure](#section19472752217) +- [Repositories Involved](#section63151229062) -#### 软件架构 -软件架构说明 +## Introduction +Battery Manager provides the following functionalities: -#### 安装教程 +1. Obtaining battery information +2. Obtaining the battery charging status and the remaining battery power -1. xxxx -2. xxxx -3. xxxx +**Figure 1** Power management subsystem architecture +![](figures/power-management-subsystem-architecture.png "power-management-subsystem-architecture") -#### 使用说明 +## Directory Structure -1. xxxx -2. xxxx -3. xxxx +``` +base/powermgr/battery_manager +├── hdi # HDI code +│ ├── api # HDI APIs +│ └── client # HDI client +│ └── service # HDI service +├── interfaces # APIs +│ ├── innerkits # Internal APIs +│ └── kits # External APIs +├── sa_profile # SA profile +└── services # Services +│ ├── native # Native services +│ └── zidl # zidl APIs +└── utils # Utilities and common code +``` -#### 参与贡献 +## Repositories Involved -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +Power management subsystem +**powermgr_battery_manager** -#### 特技 +powermgr_power_manager -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/) +powermgr_display_manager diff --git a/README_zh.md b/README_zh.md new file mode 100755 index 0000000..364c071 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,45 @@ +# 电池服务组件 + +- [简介](#section11660541593) +- [目录](#section19472752217) +- [相关仓](#section63151229062) + +## 简介 + +电池服务组件提供如下功能: + +1. 电池信息查询。 +2. 充放电状态查询。 + +**图 1** 电源管理子系统架构图 +![](figures/power-management-subsystem-architecture.png "电源管理子系统架构图") + +## 目录 + +``` +base/powermgr/battery_manager +├── hdi # HDI层 +│ ├── api # HDI接口 +│ └── client # HDI客户端 +│ └── service # HDI服务端 +├── interfaces # 接口层 +│ ├── innerkits # 内部接口 +│ └── kits # 外部接口 +├── sa_profile # SA配置文件 +└── services # 服务层 +│ ├── native # native层 +│ └── zidl # zidl接口层 +└── utils # 工具和通用层 +``` + + + +## 相关仓 + +电源管理子系统 + +**powermgr_battery_manager** + +powermgr_power_manager + +powermgr_display_manager diff --git a/batterymgr.gni b/batterymgr.gni new file mode 100644 index 0000000..86be394 --- /dev/null +++ b/batterymgr.gni @@ -0,0 +1,17 @@ +# Copyright (c) 2021 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") + +battery_manager_path = "//base/powermgr/battery_manager" +utils_path = "${battery_manager_path}/utils" diff --git a/figures/power-management-subsystem-architecture.png b/figures/power-management-subsystem-architecture.png new file mode 100755 index 0000000000000000000000000000000000000000..698bf197806b9e260b6919e4eaeff2a9900b2d50 GIT binary patch literal 61687 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 literal 0 HcmV?d00001 diff --git a/hdi/BUILD.gn b/hdi/BUILD.gn new file mode 100644 index 0000000..f2312e0 --- /dev/null +++ b/hdi/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2021 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") + +group("hdi_group") { + deps = [ + "client:batteryd_client", + "service:batteryd", + ] +} diff --git a/hdi/api/include/batteryd_api.h b/hdi/api/include/batteryd_api.h new file mode 100644 index 0000000..78d2733 --- /dev/null +++ b/hdi/api/include/batteryd_api.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 BATTERYD_API_H +#define BATTERYD_API_H + +#include + +enum BatterydCmd { + CMD_BIND_BATTERY_SUBSCRIBER = 0, + CMD_UNBIND_BATTERY_SUBSCRIBER, + CMD_NOTIFY_SUBSCRIBER, + CMD_GET_CAPACITY, + CMD_GET_VOLTAGE, + CMD_GET_TEMPERATURE, + CMD_GET_HEALTH_STATE, + CMD_GET_PLUGGED_TYPE, + CMD_GET_CHARGE_STATE, + CMD_GET_PRESENT, + CMD_GET_TECHNOLOGY +}; + +// Keep it same as the inner kit battery_info.h +struct BatterydInfo { + int32_t capacity_; + int32_t voltage_; + int32_t temperature_; + int32_t healthState_; + int32_t pluggedType_; + int32_t pluggedMaxCurrent_; + int32_t pluggedMaxVoltage_; + int32_t chargeState_; + int32_t chargeCounter_; + int8_t present_; + const char *technology_; +}; + +#endif // BATTERYD_API_H diff --git a/hdi/client/BUILD.gn b/hdi/client/BUILD.gn new file mode 100644 index 0000000..b5248f4 --- /dev/null +++ b/hdi/client/BUILD.gn @@ -0,0 +1,49 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +config("batteryd_client_public_config") { + include_dirs = [ + "include", + "${battery_manager_path}/hdi/api/include", + "${battery_manager_path}/interfaces/innerkits/native/include", + ] +} + +ohos_shared_library("batteryd_client") { + sources = [ + "src/batteryd_client.cpp", + "src/batteryd_subscriber.cpp", + ] + + configs = [ "${utils_path}:utils_config" ] + + public_configs = [ ":batteryd_client_public_config" ] + + deps = [ + "${hdf_uhdf_path}/hdi:libhdi", + "${hdf_uhdf_path}/host:libhdf_host", + "${hdf_uhdf_path}/osal:libhdf_utils", + "//utils/native/base:utils", + ] + + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + part_name = "battery_manager_native" +} diff --git a/hdi/client/include/batteryd_client.h b/hdi/client/include/batteryd_client.h new file mode 100644 index 0000000..2eef206 --- /dev/null +++ b/hdi/client/include/batteryd_client.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 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 BATTERYD_CLIENT_H +#define BATTERYD_CLIENT_H + +#include "battery_info.h" +#include "batteryd_subscriber.h" +#include "sp_singleton.h" + +namespace OHOS { +namespace PowerMgr { +class BatterydClient { +public: + static ErrCode BindBatterydSubscriber(const sptr &subscriber); + static ErrCode UnbindBatterydSubscriber(); + static int32_t GetCapacity(); + static int32_t GetVoltage(); + static int32_t GetTemperature(); + static BatteryHealthState GetHealthState(); + static BatteryPluggedType GetPluggedType(); + static BatteryChargeState GetChargeState(); + static bool GetPresent(); + static std::string GetTechnology(); +private: + static sptr GetBatterydService(); + static ErrCode DoDispatch(uint32_t cmd, MessageParcel &data, MessageParcel &reply); +}; +} // namespace PowerMgr +} // namespace OHOS +#endif // BATTERYD_CLIENT_H \ No newline at end of file diff --git a/hdi/client/include/batteryd_subscriber.h b/hdi/client/include/batteryd_subscriber.h new file mode 100644 index 0000000..3d792cd --- /dev/null +++ b/hdi/client/include/batteryd_subscriber.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 BATTERYD_SUBSCRIBER_H +#define BATTERYD_SUBSCRIBER_H + +#include "battery_info.h" +#include "batteryd_api.h" +#include "ipc_object_stub.h" + +namespace OHOS { +namespace PowerMgr { +class BatterydSubscriber : public IPCObjectStub { +public: + explicit BatterydSubscriber() : IPCObjectStub(u"ohos.powermgr.IBatterydSubscriber") {}; + virtual ~BatterydSubscriber() = default; + virtual int32_t Update(const BatteryInfo &info) = 0; + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +private: + static const BatteryInfo &ParserBatteryInfo(MessageParcel &data, MessageParcel &reply, MessageOption &option); +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // BATTERYD_SUBSCRIBER_H diff --git a/hdi/client/src/batteryd_client.cpp b/hdi/client/src/batteryd_client.cpp new file mode 100644 index 0000000..356d49a --- /dev/null +++ b/hdi/client/src/batteryd_client.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 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 "batteryd_client.h" +#include "batteryd_api.h" +#include "power_common.h" +#include "iservmgr_hdi.h" + +namespace OHOS { +namespace PowerMgr { +using OHOS::HDI::ServiceManager::V1_0::IServiceManager; + +namespace { +const std::string BATTERYD_SERVICE = "batteryd"; +} + +sptr BatterydClient::GetBatterydService() +{ + auto serviceManager = IServiceManager::Get(); + if (serviceManager == nullptr) { + POWER_HILOGW(MODULE_BATTERYD, "service manager is nullptr"); + return nullptr; + } + auto batterydService = serviceManager->GetService(BATTERYD_SERVICE.c_str()); + if (batterydService == nullptr) { + POWER_HILOGW(MODULE_BATTERYD, "batteryd service is nullptr"); + return nullptr; + } + return batterydService; +} + +ErrCode BatterydClient::DoDispatch(uint32_t cmd, MessageParcel &data, MessageParcel &reply) +{ + POWER_HILOGD(MODULE_BATTERYD, "Start to dispatch cmd: %{public}d", cmd); + auto batteryd = GetBatterydService(); + if (batteryd == nullptr) { + return ERR_NO_INIT; + } + + MessageOption option; + auto ret = batteryd->SendRequest(cmd, data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATTERYD, "failed to send request, cmd: %{public}d, ret: %{public}d", cmd, ret); + return ret; + } + return ERR_OK; +} + +ErrCode BatterydClient::BindBatterydSubscriber(const sptr &subscriber) +{ + POWER_HILOGD(MODULE_BATTERYD, "BindBatterydSubscriber enter"); + if (subscriber == nullptr) { + POWER_HILOGW(MODULE_BATTERYD, "subscriber is nullptr"); + return ERR_INVALID_VALUE; + } + MessageParcel data; + MessageParcel reply; + data.WriteRemoteObject(subscriber); + return DoDispatch(CMD_BIND_BATTERY_SUBSCRIBER, data, reply); +} + +ErrCode BatterydClient::UnbindBatterydSubscriber() +{ + POWER_HILOGD(MODULE_BATTERYD, "UnbindBatterydSubscriber enter"); + MessageParcel data; + MessageParcel reply; + return DoDispatch(CMD_UNBIND_BATTERY_SUBSCRIBER, data, reply); +} + +int32_t BatterydClient::GetCapacity() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetCapacity enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_CAPACITY, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_CAPACITY failed, return INVALID_BATT_INT_VALUE"); + return INVALID_BATT_INT_VALUE; + } + int32_t capacity = reply.ReadInt32(); + return capacity; +} + +int32_t BatterydClient::GetVoltage() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetVoltage enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_VOLTAGE, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_VOLTAGE failed, return INVALID_BATT_INT_VALUE"); + return INVALID_BATT_INT_VALUE; + } + int32_t voltage = reply.ReadInt32(); + return voltage; +} + +int32_t BatterydClient::GetTemperature() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetTemperature enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_TEMPERATURE, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_TEMPERATURE failed, return INVALID_BATT_TEMP_VALUE"); + return INVALID_BATT_TEMP_VALUE; + } + int32_t temperature = reply.ReadInt32(); + return temperature; +} + +BatteryHealthState BatterydClient::GetHealthState() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetHealthState enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_HEALTH_STATE, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_HEALTH_STATE failed, return HEALTH_STATE_UNKNOWN"); + return BatteryHealthState::HEALTH_STATE_UNKNOWN; + } + int32_t healthState = reply.ReadInt32(); + return (BatteryHealthState)healthState; +} + +BatteryPluggedType BatterydClient::GetPluggedType() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetPluggedType enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_PLUGGED_TYPE, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_PLUGGED_TYPE failed, return PLUGGED_TYPE_NONE"); + return BatteryPluggedType::PLUGGED_TYPE_NONE; + } + int32_t pluggedType = reply.ReadInt32(); + return (BatteryPluggedType)pluggedType; +} + +BatteryChargeState BatterydClient::GetChargeState() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetChargeState enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_CHARGE_STATE, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_CHARGE_STATE failed, return CHARGE_STATE_NONE"); + return BatteryChargeState::CHARGE_STATE_NONE; + } + int32_t chargeState = reply.ReadInt32(); + return (BatteryChargeState)chargeState; +} + +bool BatterydClient::GetPresent() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetPresent enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_PRESENT, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_PRESENT failed, return INVALID_BATT_BOOL_VALUE"); + return INVALID_BATT_BOOL_VALUE; + } + bool present = (bool)reply.ReadInt8(); + return present; +} + +std::string BatterydClient::GetTechnology() +{ + POWER_HILOGD(MODULE_BATTERYD, "GetTechnology enter"); + MessageParcel data; + MessageParcel reply; + ErrCode ret = DoDispatch(CMD_GET_TECHNOLOGY, data, reply); + if (FAILED(ret)) { + POWER_HILOGW(MODULE_BATTERYD, "CMD_GET_TECHNOLOGY failed, return INVALID_STRING_VALUE"); + return INVALID_STRING_VALUE; + } + std::string technology = reply.ReadCString(); + return technology; +} +} // namespace PowerMgr +} // namespace OHOS \ No newline at end of file diff --git a/hdi/client/src/batteryd_subscriber.cpp b/hdi/client/src/batteryd_subscriber.cpp new file mode 100644 index 0000000..84b2830 --- /dev/null +++ b/hdi/client/src/batteryd_subscriber.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 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 "batteryd_subscriber.h" +#include "power_common.h" + +namespace OHOS { +namespace PowerMgr { +int BatterydSubscriber::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + switch (code) { + case CMD_NOTIFY_SUBSCRIBER: { + const BatteryInfo &info = ParserBatteryInfo(data, reply, option); + return Update(info); + } + default: { + POWER_HILOGW(MODULE_BATTERYD, "no specific cmd for code: %{public}d", code); + return ERR_INVALID_OPERATION; + } + } +} + +const BatteryInfo &BatterydSubscriber::ParserBatteryInfo(MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + auto builder = std::make_shared(); + auto *info = builder->SetCapacity(data.ReadInt32()) + ->SetVoltage(data.ReadInt32()) + ->SetTemperature(data.ReadInt32()) + ->SetHealthState((BatteryHealthState)data.ReadInt32()) + ->SetPluggedType((BatteryPluggedType)data.ReadInt32()) + ->SetPluggedMaxCurrent(data.ReadInt32()) + ->SetPluggedMaxVoltage(data.ReadInt32()) + ->SetChargeState((BatteryChargeState)data.ReadInt32()) + ->SetChargeCounter(data.ReadInt32()) + ->SetPresent((bool)data.ReadInt8()) + ->SetTechnology(data.ReadCString()) + ->Build(); + return *info; +} +} // namespace PowerMgr +} // namespace OHOS \ No newline at end of file diff --git a/hdi/service/BUILD.gn b/hdi/service/BUILD.gn new file mode 100644 index 0000000..49ac1f3 --- /dev/null +++ b/hdi/service/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +config("batteryd_private_config") { + include_dirs = [ + "//drivers/ability/sbuf/include", + "//drivers/framework/include", + "//drivers/framework/include/core", + ] +} + +config("batteryd_public_config") { + include_dirs = [ + "include", + "${battery_manager_path}/hdi/api/include", + ] +} + +ohos_shared_library("batteryd") { + sources = [ + "src/batteryd.c", + "src/batteryd_dispatcher.c", + "src/batteryd_parser.c", + "src/batteryd_publisher.c", + ] + + configs = [ + "${utils_path}:utils_config", + ":batteryd_private_config", + ] + + public_configs = [ ":batteryd_public_config" ] + + deps = [ + "${hdf_uhdf_path}/host:libhdf_host", + "${hdf_uhdf_path}/ipc:libhdf_ipc_adapter", + "${hdf_uhdf_path}/osal:libhdf_utils", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + part_name = "battery_manager_native" +} diff --git a/hdi/service/include/batteryd.h b/hdi/service/include/batteryd.h new file mode 100644 index 0000000..19c491c --- /dev/null +++ b/hdi/service/include/batteryd.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 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 BATTERYD_H +#define BATTERYD_H + +#include "batteryd_api.h" +#include "core/hdf_device_desc.h" + +struct BatterydService { + struct IDeviceIoService ioService; + struct HdfDeviceObject *device; + struct BatterydSubscriber *subscriber; + int32_t ueventFd; +}; + +int32_t BindBatterySubscriber(struct BatterydService *service, struct BatterydSubscriber *subscriber); +int32_t UnbindBatterySubscriber(struct BatterydService *service); + +#endif // BATTERYD_H diff --git a/hdi/service/include/batteryd_dispatcher.h b/hdi/service/include/batteryd_dispatcher.h new file mode 100644 index 0000000..092b97f --- /dev/null +++ b/hdi/service/include/batteryd_dispatcher.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 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 BATTERYD_DISPATCHER_H +#define BATTERYD_DISPATCHER_H + +#include "core/hdf_device_desc.h" + +int32_t BatterydDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply); + +#endif // BATTERYD_DISPATCHER_H diff --git a/hdi/service/include/batteryd_parser.h b/hdi/service/include/batteryd_parser.h new file mode 100644 index 0000000..3481713 --- /dev/null +++ b/hdi/service/include/batteryd_parser.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 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 BATTERYD_PARSER_H +#define BATTERYD_PARSER_H + +#include "batteryd_api.h" + +int32_t InitBatterydSysfs(void); +int32_t ParseCapacity(int32_t *capacity); +int32_t ParseVoltage(int32_t *voltage); +int32_t ParseTemperature(int32_t *temperature); +int32_t ParseHealthState(int32_t *healthState); +int32_t ParsePluggedType(int32_t *pluggedType); +int32_t ParseChargeState(int32_t *chargeState); +int32_t ParsePresent(int8_t *present); +int32_t ParseTechnology(char *technology, size_t size); +void ParseUeventToBatterydInfo(const char *msg, struct BatterydInfo *info); + +#endif // BATTERYD_PARSER_H diff --git a/hdi/service/include/batteryd_publisher.h b/hdi/service/include/batteryd_publisher.h new file mode 100644 index 0000000..4adc376 --- /dev/null +++ b/hdi/service/include/batteryd_publisher.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 BATTERYD_PUBLISHER_H +#define BATTERYD_PUBLISHER_H + +#include "batteryd_api.h" +#include "batteryd.h" + +struct BatterydSubscriber { + struct HdfRemoteService *remoteService; +}; + +void NotifySubscriber(const struct BatterydSubscriber *subscriber, const struct BatterydInfo *batteryInfo); + +#endif // BATTERYD_PUBLISHER_H diff --git a/hdi/service/src/batteryd.c b/hdi/service/src/batteryd.c new file mode 100644 index 0000000..6fa65fc --- /dev/null +++ b/hdi/service/src/batteryd.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2021 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 "batteryd.h" + +#include +#include +#include + +#include "batteryd_dispatcher.h" +#include "batteryd_parser.h" +#include "batteryd_publisher.h" + +#include "osal/osal_mem.h" +#include "osal/osal_thread.h" +#include "utils/hdf_log.h" + +#define HDF_LOG_TAG batteryd +#define ERR_INVALID_FD (-1) +#define ERR_OPERATION_FAILED (-1) +#define UEVENT_BUFF_SIZE (64 * 1024) +#define UEVENT_RESERVED_SIZE (2) +#define UEVENT_MSG_LEN (2 * 1024) +#define SUBSYSTEM_POWER_SUPPLY "SUBSYSTEM=power_supply" + +static int32_t BatterydBind(struct HdfDeviceObject *device); +static int32_t BatterydInit(struct HdfDeviceObject *device); +static void BatterydRelease(struct HdfDeviceObject *device); + +struct HdfDriverEntry g_batterydEntry = { + .moduleVersion = 1, + .moduleName = "batteryd", + .Bind = BatterydBind, + .Init = BatterydInit, + .Release = BatterydRelease, +}; + +HDF_INIT(g_batterydEntry); + +static int32_t BatterydBind(struct HdfDeviceObject *device) +{ + HDF_LOGD("%{public}s enter", __func__); + struct BatterydService *service = NULL; + if (device == NULL) { + HDF_LOGW("%{public}s device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + service = (struct BatterydService *)OsalMemCalloc(sizeof(*service)); + if (service == NULL) { + HDF_LOGE("%{public}s: calloc address error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + service->device = device; + service->ioService.Dispatch = BatterydDispatch; + device->service = &(service->ioService); + return HDF_SUCCESS; +} + +static int32_t OpenUeventSocket(void) +{ + int32_t ret; + int32_t bufferSize = UEVENT_BUFF_SIZE; + struct sockaddr_nl address = { + .nl_pid = getpid(), + .nl_family = AF_NETLINK, + .nl_groups = 0xffffffff + }; + + int32_t fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT); + if (fd == ERR_INVALID_FD) { + HDF_LOGE("%{public}s open uevent socket failed, fd is invalid", __func__); + return ERR_INVALID_FD; + } + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &bufferSize, sizeof(bufferSize)); + if (ret == ERR_OPERATION_FAILED) { + HDF_LOGE("%{public}s set socket opt failed, ret: %{public}d", __func__, ret); + close(fd); + return ERR_INVALID_FD; + } + + ret = bind(fd, (struct sockaddr *)(&address), sizeof(struct sockaddr_nl)); + if (ret == ERR_OPERATION_FAILED) { + HDF_LOGE("%{public}s bind socket address failed, ret: %{public}d", __func__, ret); + close(fd); + return ERR_INVALID_FD; + } + return fd; +} + +static int32_t InitUevent(struct BatterydService *service) +{ + int32_t fd = OpenUeventSocket(); + if (fd == ERR_INVALID_FD) { + HDF_LOGE("%{public}s open uevent socket failed, fd is invalid", __func__); + return HDF_ERR_BAD_FD; + } + service->ueventFd = fd; + return HDF_SUCCESS; +} + +static bool IsPowerSupplyEvent(const char *msg) +{ + while (*msg) { + if (!strcmp(msg, SUBSYSTEM_POWER_SUPPLY)) { + return true; + } + while (*msg++) {} // move to next + } + return false; +} + +static int LoopingThreadEntry(void *arg) +{ + int32_t len; + char msg[UEVENT_MSG_LEN + UEVENT_RESERVED_SIZE] = {0}; + struct BatterydService *service = (struct BatterydService *)arg; + + HDF_LOGD("%{public}s enter, start batteryd looping", __func__); + while (true) { + do { + len = recv(service->ueventFd, msg, UEVENT_MSG_LEN, 0); + if (len < 0 || len >= UEVENT_MSG_LEN) { + HDF_LOGD("%{public}s recv return msg is invalid, len: %{public}d", __func__, len); + continue; + } + // msg separator + msg[len] = '\0'; + msg[len + 1] = '\0'; + if (!IsPowerSupplyEvent(msg)) { + continue; + } + struct BatterydInfo *batteryInfo = (struct BatterydInfo *)OsalMemCalloc(sizeof(*batteryInfo)); + if (batteryInfo == NULL) { + HDF_LOGE("%{public}s: calloc battery info error", __func__); + continue; + } + ParseUeventToBatterydInfo(msg, batteryInfo); + NotifySubscriber(service->subscriber, batteryInfo); + OsalMemFree(batteryInfo); + } while (len > 0); + HDF_LOGD("%{public}s recv error, len: %{public}d", __func__, len); + } +} + +static int32_t StartLoopingThread(struct BatterydService *service) +{ + int32_t ret; + OSAL_DECLARE_THREAD(loopingThread); + + ret = OsalThreadCreate(&loopingThread, (OsalThreadEntry)LoopingThreadEntry, service); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s osal create looping thread failed, ret: %{public}d", __func__, ret); + return ret; + } + struct OsalThreadParam threadParam = { + .name = "batteryd_looping_thread", + .stackSize = 0x4000, + .priority = OSAL_THREAD_PRI_DEFAULT + }; + ret = OsalThreadStart(&loopingThread, &threadParam); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s osal start looping thread failed, ret: %{public}d", __func__, ret); + OsalThreadDestroy(&loopingThread); + return ret; + } + return ret; +} + +static int32_t BatterydInit(struct HdfDeviceObject *device) +{ + HDF_LOGD("%{public}s enter", __func__); + int32_t ret; + if (device == NULL || device->service == NULL) { + HDF_LOGW("%{public}s device or device->service is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + struct BatterydService *service = (struct BatterydService *)device->service; + if (service == NULL) { + HDF_LOGE("%{public}s get batteryd service failed", __func__); + return HDF_ERR_INVALID_OBJECT; + } + ret = InitBatterydSysfs(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s init batteryd sysfs failed, ret: %{public}d", __func__, ret); + return ret; + } + ret = InitUevent(service); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s init uevent failed, ret: %{public}d", __func__, ret); + return ret; + } + ret = StartLoopingThread(service); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s start loop thread failed, ret: %{public}d", __func__, ret); + return ret; + } + return ret; +} + +static void BatterydRelease(struct HdfDeviceObject *device) +{ + HDF_LOGD("%{public}s enter", __func__); + if (device == NULL) { + return; + } + struct BatterydService *service = (struct BatterydService *)device->service; + if (service == NULL) { + HDF_LOGW("%{public}s batteryd service is NULL, no need to release", __func__); + return; + } + OsalMemFree(service); +} + +int32_t BindBatterySubscriber(struct BatterydService *service, struct BatterydSubscriber *subscriber) +{ + if (service == NULL) { + HDF_LOGW("%{public}s service is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + service->subscriber = subscriber; + return HDF_SUCCESS; +} + +int32_t UnbindBatterySubscriber(struct BatterydService *service) +{ + if (service == NULL) { + HDF_LOGW("%{public}s service is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (service->subscriber != NULL) { + OsalMemFree(service->subscriber); + service->subscriber = NULL; + } + return HDF_SUCCESS; +} \ No newline at end of file diff --git a/hdi/service/src/batteryd_dispatcher.c b/hdi/service/src/batteryd_dispatcher.c new file mode 100644 index 0000000..5bd6b9b --- /dev/null +++ b/hdi/service/src/batteryd_dispatcher.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 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 "batteryd_dispatcher.h" + +#include "batteryd.h" +#include "batteryd_publisher.h" +#include "batteryd_parser.h" +#include "osal/osal_mem.h" +#include "utils/hdf_log.h" + +#define HDF_LOG_TAG batteryd_dispatcher +#define MAX_BUFF_SIZE 128 + +static int32_t DispatchBindBatterySubscriber(struct BatterydService *service, struct HdfSBuf *data); +static int32_t DispatchUnbindBatterySubscriber(struct BatterydService *service); +static int32_t DispatchGetCapacity(struct HdfSBuf *reply); +static int32_t DispatchGetVoltage(struct HdfSBuf *reply); +static int32_t DispatchGetTemperature(struct HdfSBuf *reply); +static int32_t DispatchGetHealthState(struct HdfSBuf *reply); +static int32_t DispatchGetPluggedType(struct HdfSBuf *reply); +static int32_t DispatchGetChargeState(struct HdfSBuf *reply); +static int32_t DispatchGetPresent(struct HdfSBuf *reply); +static int32_t DispatchGetTechnology(struct HdfSBuf *reply); + +int32_t BatterydDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + HDF_LOGD("%{public}s enter", __func__); + if (client == NULL || client->device == NULL) { + HDF_LOGE("%{public}s: client or client->device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct BatterydService *service = (struct BatterydService *)client->device->service; + if (service == NULL) { + HDF_LOGE("%{public}s: service is NULL", __func__); + return HDF_FAILURE; + } + + switch (cmdId) { + case CMD_BIND_BATTERY_SUBSCRIBER: { + return DispatchBindBatterySubscriber(service, data); + } + case CMD_UNBIND_BATTERY_SUBSCRIBER: { + return DispatchUnbindBatterySubscriber(service); + } + case CMD_GET_CAPACITY: { + return DispatchGetCapacity(reply); + } + case CMD_GET_VOLTAGE: { + return DispatchGetVoltage(reply); + } + case CMD_GET_TEMPERATURE: { + return DispatchGetTemperature(reply); + } + case CMD_GET_HEALTH_STATE: { + return DispatchGetHealthState(reply); + } + case CMD_GET_PLUGGED_TYPE: { + return DispatchGetPluggedType(reply); + } + case CMD_GET_CHARGE_STATE: { + return DispatchGetChargeState(reply); + } + case CMD_GET_PRESENT: { + return DispatchGetPresent(reply); + } + case CMD_GET_TECHNOLOGY: { + return DispatchGetTechnology(reply); + } + default: { + HDF_LOGE("%{public}s: invalid cmdId %{public}d", __func__, cmdId); + return HDF_FAILURE; + } + } +} + +static int32_t DispatchBindBatterySubscriber(struct BatterydService *service, struct HdfSBuf *data) +{ + struct BatterydSubscriber *subscriber = NULL; + struct HdfRemoteService *remoteService = HdfSBufReadRemoteService(data); + if (remoteService == NULL) { + HDF_LOGW("%{public}s: remoteService is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + subscriber = (struct BatterydSubscriber *)OsalMemCalloc(sizeof(*subscriber)); + if (subscriber == NULL) { + HDF_LOGE("%{public}s: calloc subscriber error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + subscriber->remoteService = remoteService; + return BindBatterySubscriber(service, subscriber); +} + +static int32_t DispatchUnbindBatterySubscriber(struct BatterydService *service) +{ + return UnbindBatterySubscriber(service); +} + +static int32_t DispatchGetCapacity(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t capacity = 0; + ret = ParseCapacity(&capacity); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, capacity); + return HDF_SUCCESS; +} + +static int32_t DispatchGetVoltage(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t voltage = 0; + ret = ParseVoltage(&voltage); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, voltage); + return HDF_SUCCESS; +} + +static int32_t DispatchGetTemperature(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t temperature = 0; + ret = ParseTemperature(&temperature); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, temperature); + return HDF_SUCCESS; +} + +static int32_t DispatchGetHealthState(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t healthState = 0; + ret = ParseHealthState(&healthState); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, healthState); + return HDF_SUCCESS; +} + +static int32_t DispatchGetPluggedType(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t pluggedType = 0; + ret = ParsePluggedType(&pluggedType); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, pluggedType); + return HDF_SUCCESS; +} + +static int32_t DispatchGetChargeState(struct HdfSBuf *reply) +{ + int32_t ret; + int32_t chargeState = 0; + ret = ParseChargeState(&chargeState); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt32(reply, chargeState); + return HDF_SUCCESS; +} + +static int32_t DispatchGetPresent(struct HdfSBuf *reply) +{ + int32_t ret; + int8_t present = 0; + ret = ParsePresent(&present); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteInt8(reply, present); + return HDF_SUCCESS; +} + +static int32_t DispatchGetTechnology(struct HdfSBuf *reply) +{ + int32_t ret; + char technology[MAX_BUFF_SIZE] = {0}; + ret = ParseTechnology(technology, sizeof(technology)); + if (ret != HDF_SUCCESS) { + return ret; + } + HdfSbufWriteString(reply, technology); + return HDF_SUCCESS; +} diff --git a/hdi/service/src/batteryd_parser.c b/hdi/service/src/batteryd_parser.c new file mode 100644 index 0000000..e39e856 --- /dev/null +++ b/hdi/service/src/batteryd_parser.c @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2021 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 "batteryd_parser.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "batteryd.h" +#include "utils/hdf_log.h" +#include "osal/osal_mem.h" + +#define HDF_LOG_TAG batteryd_parser + +#define MAX_SYSFS_SIZE 64 +#define MAX_BUFF_SIZE 128 +#define INVALID_BATT_INT_VALUE (-1) + +#define POWER_SUPPLY_BASE_PATH "/sys/class/power_supply" +#define POWER_SUPPLY_BATTERY "Battery" + +#define BATTERY_KEY_CAPACITY "POWER_SUPPLY_CAPACITY=" +#define BATTERY_KEY_VOLTAGE "POWER_SUPPLY_VOLTAGE_NOW=" +#define BATTERY_KEY_TEMPERATURE "POWER_SUPPLY_TEMP=" +#define BATTERY_KEY_HEALTH "POWER_SUPPLY_HEALTH=" +#define BATTERY_KEY_CHARGE_STATUS "POWER_SUPPLY_STATUS=" +#define BATTERY_KEY_PRESENT "POWER_SUPPLY_PRESENT=" +#define BATTERY_KEY_TECHNOLOGY "POWER_SUPPLY_TECHNOLOGY=" +#define BATTERY_KEY_CHARGE_COUNTER "POWER_SUPPLY_CHARGE_COUNTER=" + +struct PowerSupplySysfsInfo { + char *name; + char typePath[PATH_MAX]; + char onlinePath[PATH_MAX]; + char currentMaxPath[PATH_MAX]; + char voltageMaxPath[PATH_MAX]; +}; + +static struct PowerSupplySysfsInfo g_powerSupplySysfsInfos[MAX_SYSFS_SIZE]; + +struct BatterySysfsInfo { + char *name; + char capacityPath[PATH_MAX]; + char voltagePath[PATH_MAX]; + char temperaturePath[PATH_MAX]; + char healthStatePath[PATH_MAX]; + char chargeStatePath[PATH_MAX]; + char presentPath[PATH_MAX]; + char technologyPath[PATH_MAX]; +}; + +static struct BatterySysfsInfo g_batterySysfsInfo; + +// Keep it same as the BatteryHealthState in battery_info.h +enum BatteryHealthState { + BATTERY_HEALTH_UNKNOWN = 0, + BATTERY_HEALTH_GOOD, + BATTERY_HEALTH_OVERHEAT, + BATTERY_HEALTH_OVERVOLTAGE, + BATTERY_HEALTH_COLD, + BATTERY_HEALTH_DEAD, + BATTERY_HEALTH_RESERVED, +}; + +// Keep it same as the BatteryChargeState in battery_info.h +enum BatteryChargeState { + CHARGE_STATE_NONE = 0, + CHARGE_STATE_ENABLE, + CHARGE_STATE_DISABLE, + CHARGE_STATE_FULL, + CHARGE_STATE_RESERVED, +}; + +// Keep it same as the BatteryPluggedType in battery_info.h +enum BatteryPluggedType { + PLUGGED_TYPE_NONE = 0, + PLUGGED_TYPE_AC, + PLUGGED_TYPE_USB, + PLUGGED_TYPE_WIRELESS, + PLUGGED_TYPE_BUTT +}; + +struct StringEnumMap { + char *str; + int32_t enumVal; +}; + +struct StringEnumMap g_healthStateEnumMap[] = { + {"Good", BATTERY_HEALTH_GOOD}, + {"Cold", BATTERY_HEALTH_COLD}, + {"Warm", BATTERY_HEALTH_GOOD}, // JEITA specification + {"Cool", BATTERY_HEALTH_GOOD}, // JEITA specification + {"Hot", BATTERY_HEALTH_OVERHEAT}, // JEITA specification + {"Overheat", BATTERY_HEALTH_OVERHEAT}, + {"Over voltage", BATTERY_HEALTH_OVERVOLTAGE}, + {"Dead", BATTERY_HEALTH_DEAD}, + {"Unknown", BATTERY_HEALTH_UNKNOWN}, + {"Unspecified failure", BATTERY_HEALTH_UNKNOWN}, + {NULL, BATTERY_HEALTH_UNKNOWN}, +}; + +struct StringEnumMap g_chargeStateEnumMap[] = { + {"Discharging", CHARGE_STATE_NONE}, + {"Charging", CHARGE_STATE_ENABLE}, + {"Full", CHARGE_STATE_FULL}, + {"Not charging", CHARGE_STATE_DISABLE}, + {"Unknown", CHARGE_STATE_RESERVED}, + {NULL, CHARGE_STATE_RESERVED}, +}; + +struct StringEnumMap g_pluggedTypeEnumMap[] = { + {"USB", PLUGGED_TYPE_USB}, + {"USB_PD_DRP", PLUGGED_TYPE_USB}, + {"Wireless", PLUGGED_TYPE_WIRELESS}, + {"Mains", PLUGGED_TYPE_AC}, + {"UPS", PLUGGED_TYPE_AC}, + {"USB_ACA", PLUGGED_TYPE_AC}, + {"USB_C", PLUGGED_TYPE_AC}, + {"USB_CDP", PLUGGED_TYPE_AC}, + {"USB_DCP", PLUGGED_TYPE_AC}, + {"USB_HVDCP", PLUGGED_TYPE_AC}, + {"USB_PD", PLUGGED_TYPE_AC}, + {"Unknown", PLUGGED_TYPE_BUTT}, + {NULL, PLUGGED_TYPE_BUTT}, +}; + +struct BatteryAssigner { + const char *prefix; + const size_t prefixLen; + void (*Assigner)(const char *, struct BatterydInfo *); +}; + +inline static int32_t ParseInt(const char *str) +{ + return strtol(str, NULL, 10); +} + +inline static void TrimNewLine(char *str) +{ + if (str == NULL) { + return; + } + str[strcspn(str, "\n")] = 0; +} + +inline static void CapacityAssigner(const char *str, struct BatterydInfo *info) +{ + info->capacity_ = ParseInt(str); // default in percent format +} + +inline static void VoltageAssigner(const char *str, struct BatterydInfo *info) +{ + info->voltage_ = ParseInt(str) / 1000; // convert to millivolt(mV) format +} + +inline static void TemperatureAssigner(const char *str, struct BatterydInfo *info) +{ + info->temperature_ = ParseInt(str); +} + +static int32_t HealthStateEnumConverter(const char *str) +{ + for (int i = 0; g_healthStateEnumMap[i].str; ++i) { + if (strcmp(str, g_healthStateEnumMap[i].str) == 0) { + return g_healthStateEnumMap[i].enumVal; + } + } + return BATTERY_HEALTH_UNKNOWN; +} + +inline static void HealthStateAssigner(const char *str, struct BatterydInfo *info) +{ + info->healthState_ = HealthStateEnumConverter(str); +} + +static int32_t ChargeStateEnumConverter(const char *str) +{ + for (int i = 0; g_chargeStateEnumMap[i].str; ++i) { + if (strcmp(str, g_chargeStateEnumMap[i].str) == 0) { + return g_chargeStateEnumMap[i].enumVal; + } + } + return CHARGE_STATE_RESERVED; +} + +inline static void ChargeStateAssigner(const char *str, struct BatterydInfo *info) +{ + info->chargeState_ = ChargeStateEnumConverter(str); +} + +inline static void PresentAssigner(const char *str, struct BatterydInfo *info) +{ + info->present_ = ParseInt(str); +} + +inline static void TechnologyAssigner(const char *str, struct BatterydInfo *info) +{ + info->technology_ = str; +} + +inline static void ChargeCounterAssigner(const char *str, struct BatterydInfo *info) +{ + info->chargeCounter_ = ParseInt(str); +} + +static struct BatteryAssigner g_batteryAssigners[] = { + {BATTERY_KEY_CAPACITY, sizeof(BATTERY_KEY_CAPACITY) - 1, CapacityAssigner}, + {BATTERY_KEY_VOLTAGE, sizeof(BATTERY_KEY_VOLTAGE) - 1, VoltageAssigner}, + {BATTERY_KEY_TEMPERATURE, sizeof(BATTERY_KEY_TEMPERATURE) - 1, TemperatureAssigner}, + {BATTERY_KEY_HEALTH, sizeof(BATTERY_KEY_HEALTH) - 1, HealthStateAssigner}, + {BATTERY_KEY_CHARGE_STATUS, sizeof(BATTERY_KEY_CHARGE_STATUS) - 1, ChargeStateAssigner}, + {BATTERY_KEY_PRESENT, sizeof(BATTERY_KEY_PRESENT) - 1, PresentAssigner}, + {BATTERY_KEY_TECHNOLOGY, sizeof(BATTERY_KEY_TECHNOLOGY) - 1, TechnologyAssigner}, + {BATTERY_KEY_CHARGE_COUNTER, sizeof(BATTERY_KEY_CHARGE_COUNTER) - 1, ChargeCounterAssigner}, + {NULL, 0, NULL} // end of the array +}; + +static void FormatPath(char *path, size_t size, const char *format, const char *basePath, const char *name) +{ + int ret = snprintf_s(path, PATH_MAX, size - 1, format, basePath, name); + if (ret == -1) { + HDF_LOGW("%{public}s: failed to format path of %{public}s", __func__, name); + } +} + +static void FormatSysfsPaths(struct PowerSupplySysfsInfo *info) +{ + // Format paths for plugged power supply types + FormatPath(info->typePath, sizeof(info->typePath), "%s/%s/type", POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(info->onlinePath, sizeof(info->onlinePath), "%s/%s/online", POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(info->currentMaxPath, sizeof(info->currentMaxPath), "%s/%s/current_max", POWER_SUPPLY_BASE_PATH, + info->name); + FormatPath(info->voltageMaxPath, sizeof(info->voltageMaxPath), "%s/%s/voltage_max", POWER_SUPPLY_BASE_PATH, + info->name); + if (strcmp(info->name, POWER_SUPPLY_BATTERY) != 0) { + return; + } + // Format paths for battery only + g_batterySysfsInfo.name = info->name; + FormatPath(g_batterySysfsInfo.capacityPath, sizeof(g_batterySysfsInfo.capacityPath), "%s/%s/capacity", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.voltagePath, sizeof(g_batterySysfsInfo.voltagePath), "%s/%s/voltage_now", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.temperaturePath, sizeof(g_batterySysfsInfo.temperaturePath), "%s/%s/temp", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.healthStatePath, sizeof(g_batterySysfsInfo.healthStatePath), "%s/%s/health", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.chargeStatePath, sizeof(g_batterySysfsInfo.chargeStatePath), "%s/%s/status", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.presentPath, sizeof(g_batterySysfsInfo.presentPath), "%s/%s/present", + POWER_SUPPLY_BASE_PATH, info->name); + FormatPath(g_batterySysfsInfo.technologyPath, sizeof(g_batterySysfsInfo.technologyPath), "%s/%s/technology", + POWER_SUPPLY_BASE_PATH, info->name); +} + +int32_t InitBatterydSysfs(void) +{ + DIR *dir = NULL; + struct dirent *entry = NULL; + int32_t index = 0; + + dir = opendir(POWER_SUPPLY_BASE_PATH); + if (dir == NULL) { + HDF_LOGE("%{public}s: cannot open POWER_SUPPLY_BASE_PATH", __func__); + return HDF_ERR_IO; + } + + while (true) { + entry = readdir(dir); + if (entry == NULL) { + break; + } + + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) { + struct PowerSupplySysfsInfo sysfsInfo = {0}; + sysfsInfo.name = entry->d_name; + HDF_LOGD("%{public}s: init sysfs info of %{public}s", __func__, sysfsInfo.name); + if (index >= MAX_SYSFS_SIZE) { + HDF_LOGE("%{public}s: too many plugged types", __func__); + break; + } + FormatSysfsPaths(&sysfsInfo); + g_powerSupplySysfsInfos[index] = sysfsInfo; + index++; + } + } + closedir(dir); + return HDF_SUCCESS; +} + +static int32_t ReadSysfsFile(const char *path, char *buf, size_t size) +{ + int32_t ret; + int fd = open(path, O_RDONLY); + if (fd < HDF_SUCCESS) { + HDF_LOGE("%{public}s: failed to open %{private}s", __func__, path); + return HDF_ERR_IO; + } + ret = read(fd, buf, size); + if (ret < HDF_SUCCESS) { + HDF_LOGE("%{public}s: failed to read %{private}s", __func__, path); + close(fd); + return HDF_ERR_IO; + } + close(fd); + buf[size - 1] = '\0'; + return HDF_SUCCESS; +} + +static int32_t ReadBatterySysfsToBuff(const char *path, char *buf, size_t size) +{ + int32_t ret; + if (g_batterySysfsInfo.name == NULL) { + HDF_LOGW("%{public}s: battery sysfs info is not exist", __func__); + return HDF_ERR_INVALID_OBJECT; + } + ret = ReadSysfsFile(path, buf, size); + if (ret != HDF_SUCCESS) { + HDF_LOGW("%{public}s: read path %{private}s failed, ret: %{public}d", __func__, path, ret); + return ret; + } + return HDF_SUCCESS; +} + +int32_t ParseCapacity(int32_t *capacity) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.capacityPath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: capacity is %{public}d", __func__, value); + *capacity = value; + return HDF_SUCCESS; +} + +int32_t ParseVoltage(int32_t *voltage) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.voltagePath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: voltage is %{public}d", __func__, value); + *voltage = value; + return HDF_SUCCESS; +} + +int32_t ParseTemperature(int32_t *temperature) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.temperaturePath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: temperature is %{public}d", __func__, value); + *temperature = value; + return HDF_SUCCESS; +} + +int32_t ParseHealthState(int32_t *healthState) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.healthStatePath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: healthState is %{public}d", __func__, value); + *healthState = value; + return HDF_SUCCESS; +} + +void GetPluggedTypeName(char *buf, size_t size) +{ + int32_t ret; + int32_t online; + for (int i = 0; i < MAX_SYSFS_SIZE && g_powerSupplySysfsInfos[i].name; ++i) { + if (strcmp(g_powerSupplySysfsInfos[i].name, POWER_SUPPLY_BATTERY) == 0) { + // ignore the battery type + continue; + } + ret = ReadSysfsFile(g_powerSupplySysfsInfos[i].onlinePath, buf, size); + if (ret != HDF_SUCCESS) { + HDF_LOGW("%{public}s: read online path failed, ret: %{public}d", __func__, ret); + continue; + } + online = ParseInt(buf); + if (!online) { + continue; + } + HDF_LOGD("%{public}s: %{public}s is online", __func__, g_powerSupplySysfsInfos[i].name); + ret = ReadSysfsFile(g_powerSupplySysfsInfos[i].typePath, buf, size); + if (ret != HDF_SUCCESS) { + HDF_LOGW("%{public}s: read type path failed, ret: %{public}d", __func__, ret); + continue; + } + TrimNewLine(buf); + break; + } +} + +static int32_t PluggedTypeEnumConverter(const char *str) +{ + for (int i = 0; g_pluggedTypeEnumMap[i].str; ++i) { + if (strcmp(str, g_pluggedTypeEnumMap[i].str) == 0) { + return g_pluggedTypeEnumMap[i].enumVal; + } + } + return PLUGGED_TYPE_BUTT; +} + +int32_t ParsePluggedType(int32_t *pluggedType) +{ + int32_t type; + char buf[MAX_BUFF_SIZE] = {0}; + GetPluggedTypeName(buf, sizeof(buf)); + type = PluggedTypeEnumConverter(buf); + if (type == PLUGGED_TYPE_BUTT) { + HDF_LOGW("%{public}s: not support the online type %{public}s", __func__, buf); + return HDF_ERR_NOT_SUPPORT; + } + HDF_LOGD("%{public}s: return online plugged type %{public}d", __func__, type); + *pluggedType = type; + return HDF_SUCCESS; +} + +int32_t ParseChargeState(int32_t *chargeState) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.chargeStatePath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: chargeState is %{public}d", __func__, value); + *chargeState = value; + return HDF_SUCCESS; +} + +int32_t ParsePresent(int8_t *present) +{ + int32_t ret; + int8_t value; + char buf[MAX_BUFF_SIZE] = {0}; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.presentPath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = (int8_t)ParseInt(buf); + HDF_LOGD("%{public}s: present is %{public}d", __func__, value); + *present = value; + return HDF_SUCCESS; +} + +int32_t ParseTechnology(char *buf, size_t size) +{ + int32_t ret; + ret = ReadBatterySysfsToBuff(g_batterySysfsInfo.technologyPath, buf, size); + if (ret != HDF_SUCCESS) { + return ret; + } + HDF_LOGD("%{public}s: technology is %{public}s", __func__, buf); + return HDF_SUCCESS; +} + +int32_t ParsePluggedMaxCurrent(int32_t *maxCurrent) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + GetPluggedTypeName(buf, sizeof(buf)); + for (int i = 0; i < MAX_SYSFS_SIZE && g_powerSupplySysfsInfos[i].name; ++i) { + if (strcmp(buf, g_powerSupplySysfsInfos[i].name) != 0) { + continue; + } + ret = ReadBatterySysfsToBuff(g_powerSupplySysfsInfos[i].currentMaxPath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: maxCurrent is %{public}d", __func__, value); + *maxCurrent = value; + return HDF_SUCCESS; + } + return HDF_ERR_NOT_SUPPORT; +} + +int32_t ParsePluggedMaxVoltage(int32_t *maxVoltage) +{ + int32_t ret; + int32_t value; + char buf[MAX_BUFF_SIZE] = {0}; + GetPluggedTypeName(buf, sizeof(buf)); + for (int i = 0; i < MAX_SYSFS_SIZE && g_powerSupplySysfsInfos[i].name; ++i) { + if (strcmp(buf, g_powerSupplySysfsInfos[i].name) != 0) { + continue; + } + ret = ReadBatterySysfsToBuff(g_powerSupplySysfsInfos[i].voltageMaxPath, buf, sizeof(buf)); + if (ret != HDF_SUCCESS) { + return ret; + } + value = ParseInt(buf); + HDF_LOGD("%{public}s: maxCurrent is %{public}d", __func__, value); + *maxVoltage = value; + return HDF_SUCCESS; + } + return HDF_ERR_NOT_SUPPORT; +} + +void ParseUeventToBatterydInfo(const char *msg, struct BatterydInfo *info) +{ + while (*msg) { + for (int i = 0; g_batteryAssigners[i].prefix; ++i) { + if (!strncmp(msg, g_batteryAssigners[i].prefix, g_batteryAssigners[i].prefixLen)) { + HDF_LOGD("%{public}s: msg: %{public}s", __func__, msg); + msg += g_batteryAssigners[i].prefixLen; + g_batteryAssigners[i].Assigner(msg, info); + break; + } + } + while (*msg++) {} // move to next + } + info->pluggedType_ = PLUGGED_TYPE_NONE; + ParsePluggedType(&info->pluggedType_); + info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE; + ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_); + info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE; + ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_); +} \ No newline at end of file diff --git a/hdi/service/src/batteryd_publisher.c b/hdi/service/src/batteryd_publisher.c new file mode 100644 index 0000000..fb34a82 --- /dev/null +++ b/hdi/service/src/batteryd_publisher.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 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 "batteryd_publisher.h" + +#include "hdf_remote_service.h" +#include "utils/hdf_log.h" + +#define HDF_LOG_TAG batteryd_publisher + +void NotifySubscriber(const struct BatterydSubscriber *subscriber, const struct BatterydInfo *batteryInfo) +{ + HDF_LOGD("%{public}s: enter", __func__); + if (subscriber == NULL) { + HDF_LOGD("%{public}s: subscriber is NULL", __func__); + return; + } + int ret; + struct HdfRemoteService *service = subscriber->remoteService; + struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC); + struct HdfSBuf *reply = HdfSBufTypedObtain(SBUF_IPC); + if (data == NULL || reply == NULL) { + HDF_LOGE("%{public}s failed to obtain hdf sbuf", __func__); + HdfSBufRecycle(data); + HdfSBufRecycle(reply); + return; + } + HDF_LOGD("%{public}s BatteryInfo: capacity=%{public}d, voltage=%{public}d, temperature=%{public}d, " \ + "healthState=%{public}d, pluggedType=%{public}d, pluggedMaxCurrent=%{public}d, " \ + "pluggedMaxVoltage=%{public}d, chargeState=%{public}d, chargeCounter=%{public}d, present=%{public}d, " \ + "technology=%{public}s", __func__, batteryInfo->capacity_, batteryInfo->voltage_, + batteryInfo->temperature_, batteryInfo->healthState_, batteryInfo->pluggedType_, + batteryInfo->pluggedMaxCurrent_, batteryInfo->pluggedMaxVoltage_, batteryInfo->chargeState_, + batteryInfo->chargeCounter_, batteryInfo->present_, batteryInfo->technology_); + + HdfSbufWriteInt32(data, batteryInfo->capacity_); + HdfSbufWriteInt32(data, batteryInfo->voltage_); + HdfSbufWriteInt32(data, batteryInfo->temperature_); + HdfSbufWriteInt32(data, batteryInfo->healthState_); + HdfSbufWriteInt32(data, batteryInfo->pluggedType_); + HdfSbufWriteInt32(data, batteryInfo->pluggedMaxCurrent_); + HdfSbufWriteInt32(data, batteryInfo->pluggedMaxVoltage_); + HdfSbufWriteInt32(data, batteryInfo->chargeState_); + HdfSbufWriteInt32(data, batteryInfo->chargeCounter_); + HdfSbufWriteInt8(data, batteryInfo->present_); + HdfSbufWriteString(data, batteryInfo->technology_); + + ret = service->dispatcher->Dispatch(service, CMD_NOTIFY_SUBSCRIBER, data, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed to notify subscriber, ret: %{public}d", __func__, ret); + } else { + HDF_LOGD("%{public}s: succeed to notify subscriber", __func__); + } + HdfSBufRecycle(data); + HdfSBufRecycle(reply); +} \ No newline at end of file diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn new file mode 100644 index 0000000..0cd5244 --- /dev/null +++ b/interfaces/innerkits/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") + +config("batterysrv_private_config") { + include_dirs = [ + "${battery_manager_path}/services/zidl/include", + "//utils/system/safwk/native/include", + ] +} + +config("batterysrv_public_config") { + include_dirs = [ "native/include" ] +} + +ohos_shared_library("batterysrv_client") { + sources = [ + "${battery_manager_path}/services/zidl/src/battery_srv_proxy.cpp", + "native/src/battery_srv_client.cpp", + ] + + configs = [ + "${utils_path}:utils_config", + ":batterysrv_private_config", + ":batterysrv_public_config", + ] + + public_configs = [ ":batterysrv_public_config" ] + + deps = [ "//utils/native/base:utils" ] + + external_deps = [ + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_L2:samgr_proxy", + ] + + part_name = "battery_manager_native" +} diff --git a/interfaces/innerkits/native/include/battery_info.h b/interfaces/innerkits/native/include/battery_info.h new file mode 100644 index 0000000..4720159 --- /dev/null +++ b/interfaces/innerkits/native/include/battery_info.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 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 BATTERY_SRV_BATERY_INFO_H +#define BATTERY_SRV_BATERY_INFO_H + +#include + +namespace OHOS { +namespace PowerMgr { +static constexpr int32_t INVALID_BATT_INT_VALUE = -1; +static constexpr int32_t INVALID_BATT_TEMP_VALUE = 100; +static const std::string INVALID_STRING_VALUE = "Invalid"; +static constexpr bool INVALID_BATT_BOOL_VALUE = true; + +/** + * Type for acquire BatteryChargeState. + */ +enum class BatteryChargeState : uint32_t { + /** + * Battery is discharge. + */ + CHARGE_STATE_NONE, + + /** + * Battery is charging. + */ + CHARGE_STATE_ENABLE, + + /** + * Battery is not charging. + */ + CHARGE_STATE_DISABLE, + + /** + * Battery charge full. + */ + CHARGE_STATE_FULL, + + /** + * The bottom of the enum. + */ + CHARGE_STATE_BUTT +}; + +/** + * Type for acquire BatteryHealthState. + */ +enum class BatteryHealthState : uint32_t { + /** + * Health Status: unknown. + */ + HEALTH_STATE_UNKNOWN, + + /** + * Health Status: good. + */ + HEALTH_STATE_GOOD, + + /** + * Health Status: over heat. + */ + HEALTH_STATE_OVERHEAT, + + /** + * Health Status: over voltage. + */ + HEALTH_STATE_OVERVOLTAGE, + + /** + * Health Status: COLD. + */ + HEALTH_STATE_COLD, + + /** + * Health Status: Dead. + */ + HEALTH_STATE_DEAD, + + /** + * The bottom of the enum. + */ + HEALTH_STATE_BUTT +}; + +/** + * Type for acquire BatteryPluggedType. + */ +enum class BatteryPluggedType : uint32_t { + /** + * Power source is unplugged. + */ + PLUGGED_TYPE_NONE, + + /** + * Power source is an AC charger. + */ + PLUGGED_TYPE_AC, + + /** + * Power source is a USB DC charger. + */ + PLUGGED_TYPE_USB, + + /** + * Power source is wireless charger. + */ + PLUGGED_TYPE_WIRELESS, + + /** + * The bottom of the enum. + */ + PLUGGED_TYPE_BUTT +}; + +class BatteryInfo { +public: + enum { + COMMON_EVENT_CODE_CAPACITY = 0, + COMMON_EVENT_CODE_VOLTAGE = 1, + COMMON_EVENT_CODE_TEMPERATURE = 2, + COMMON_EVENT_CODE_HEALTH_STATE = 3, + COMMON_EVENT_CODE_PLUGGED_TYPE = 4, + COMMON_EVENT_CODE_PLUGGED_MAX_CURRENT = 5, + COMMON_EVENT_CODE_PLUGGED_MAX_VOLTAGE = 6, + COMMON_EVENT_CODE_CHARGE_STATE = 7, + COMMON_EVENT_CODE_CHARGE_COUNTER = 8, + COMMON_EVENT_CODE_PRESENT = 9, + COMMON_EVENT_CODE_TECHNOLOGY = 10, + }; + + class Builder { + public: + Builder() + { + this->info_ = new BatteryInfo; + }; + + ~Builder() + { + delete info_; + }; + + Builder *SetCapacity(int32_t capacity) + { + this->info_->capacity_ = capacity; + return this; + } + + Builder *SetVoltage(int32_t voltage) + { + this->info_->voltage_ = voltage; + return this; + } + + Builder *SetTemperature(int32_t temperature) + { + this->info_->temperature_ = temperature; + return this; + } + + Builder *SetHealthState(BatteryHealthState healthState) + { + this->info_->healthState_ = healthState; + return this; + } + + Builder *SetPluggedType(BatteryPluggedType pluggedType) + { + this->info_->pluggedType_ = pluggedType; + return this; + } + + Builder *SetPluggedMaxCurrent(int32_t maxCurrent) + { + this->info_->pluggedMaxCurrent_ = maxCurrent; + return this; + } + + Builder *SetPluggedMaxVoltage(int32_t maxVoltage) + { + this->info_->pluggedMaxVoltage_ = maxVoltage; + return this; + } + + Builder *SetChargeState(BatteryChargeState chargeState) + { + this->info_->chargeState_ = chargeState; + return this; + } + + Builder *SetChargeCounter(int32_t chargeCounter) + { + this->info_->chargeCounter_ = chargeCounter; + return this; + } + + Builder *SetPresent(bool present) + { + this->info_->present_ = present; + return this; + } + + Builder *SetTechnology(const std::string &technology) + { + this->info_->technology_ = technology; + return this; + } + + const BatteryInfo *Build() + { + return info_; + } + + private: + BatteryInfo *info_; + }; + + BatteryInfo() = default; + ~BatteryInfo() = default; + + const int32_t &GetCapacity() const + { + return capacity_; + } + + const int32_t &GetVoltage() const + { + return voltage_; + } + + const int32_t &GetTemperature() const + { + return temperature_; + } + + BatteryHealthState GetHealthState() const + { + return healthState_; + } + + BatteryPluggedType GetPluggedType() const + { + return pluggedType_; + } + + const int32_t &GetPluggedMaxCurrent() const + { + return pluggedMaxCurrent_; + } + + const int32_t &GetPluggedMaxVoltage() const + { + return pluggedMaxVoltage_; + } + + BatteryChargeState GetChargeState() const + { + return chargeState_; + } + + const int32_t &GetChargeCounter() const + { + return chargeCounter_; + } + + bool IsPresent() const + { + return present_; + } + + const std::string &GetTechnology() const + { + return technology_; + } + +private: + int32_t capacity_ = INVALID_BATT_INT_VALUE; + int32_t voltage_ = INVALID_BATT_INT_VALUE; + int32_t temperature_ = INVALID_BATT_TEMP_VALUE; + BatteryHealthState healthState_ = BatteryHealthState::HEALTH_STATE_BUTT; + BatteryPluggedType pluggedType_ = BatteryPluggedType::PLUGGED_TYPE_BUTT; + int32_t pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE; + int32_t pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE; + BatteryChargeState chargeState_ = BatteryChargeState::CHARGE_STATE_BUTT; + int32_t chargeCounter_ = INVALID_BATT_INT_VALUE; + bool present_ = INVALID_BATT_BOOL_VALUE; + std::string technology_ = INVALID_STRING_VALUE; +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // BATTERY_SRV_BATERY_INFO_H \ No newline at end of file diff --git a/interfaces/innerkits/native/include/battery_srv_client.h b/interfaces/innerkits/native/include/battery_srv_client.h new file mode 100644 index 0000000..0aa13a9 --- /dev/null +++ b/interfaces/innerkits/native/include/battery_srv_client.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 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 POWERMGR_BATTERY_SRV_CLIENT_H +#define POWERMGR_BATTERY_SRV_CLIENT_H + +#include +#include +#include +#include "iremote_object.h" +#include "ibattery_srv.h" + +namespace OHOS { +namespace PowerMgr { +class BatterySrvClient final : public DelayedRefSingleton { + DECLARE_DELAYED_REF_SINGLETON(BatterySrvClient) + +public: + DISALLOW_COPY_AND_MOVE(BatterySrvClient); + + /** + * Return the capacity of the battery, in mAh. + */ + int32_t GetCapacity(); + /** + * Return the charging status, such as CHARGE_STATE_NONE, CHARGE_STATE_ENABLE, + * CHARGE_STATE_DISABLE, CHARGE_STATE_FULL,... + */ + BatteryChargeState GetChargingStatus(); + /** + * Return the Health state of the battery, such as HEALTH_STATE_UNKNOWN, + * HEALTH_STATE_GOOD, HEALTH_STATE_OVERHEAT,.... + */ + BatteryHealthState GetHealthStatus(); + /** + * Return the charger type plugged, such as PLUGGED_TYPE_NONE, + * PLUGGED_TYPE_AC, PLUGGED_TYPE_USB,.... + */ + BatteryPluggedType GetPluggedType(); + /** + * Return the voltage of the battery, in mv. + */ + int32_t GetVoltage(); + /** + * Return the present state of the battery, true or false. + */ + bool GetPresent(); + /** + * Return the technology of the battery, such as Li-ion. + */ + std::string GetTechnology(); + /** + * Return the temperature of the battery, in 0.1℃. + */ + int32_t GetBatteryTemperature(); + +private: + class BatterySrvDeathRecipient : public IRemoteObject::DeathRecipient { + public: + BatterySrvDeathRecipient() = default; + ~BatterySrvDeathRecipient() = default; + void OnRemoteDied(const wptr& remote); + private: + DISALLOW_COPY_AND_MOVE(BatterySrvDeathRecipient); + }; + + ErrCode Connect(); + sptr proxy_ {nullptr}; + sptr deathRecipient_ {nullptr}; + void ResetProxy(const wptr& remote); + std::mutex mutex_; +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // BATTERY_SRV_CLIENT_H \ No newline at end of file diff --git a/interfaces/innerkits/native/include/ibattery_srv.h b/interfaces/innerkits/native/include/ibattery_srv.h new file mode 100644 index 0000000..5208f70 --- /dev/null +++ b/interfaces/innerkits/native/include/ibattery_srv.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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 POWERMGR_INNERKITS_IBATTERY_SRV_H +#define POWERMGR_INNERKITS_IBATTERY_SRV_H + +#include +#include "iremote_broker.h" +#include "iremote_object.h" +#include "battery_info.h" + +namespace OHOS { +namespace PowerMgr { +class IBatterySrv : public IRemoteBroker { +public: + enum { + BATT_GET_CAPACITY = 0, + BATT_GET_CHARGING_STATUS, + BATT_GET_HEALTH_STATUS, + BATT_GET_PLUG_TYPE, + BATT_GET_VOLTAGE, + BATT_GET_PRESENT, + BATT_GET_TEMPERATURE, + BATT_GET_TECHNOLOGY, + }; + + virtual int32_t GetCapacity() = 0; + virtual BatteryChargeState GetChargingStatus() = 0; + virtual BatteryHealthState GetHealthStatus() = 0; + virtual BatteryPluggedType GetPluggedType() = 0; + virtual int32_t GetVoltage() = 0; + virtual bool GetPresent() = 0; + virtual std::string GetTechnology() = 0; + virtual int32_t GetBatteryTemperature() = 0; +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.powermgr.IBatterySrv"); +}; +} // space PowerMgr +} // namespace OHOS + +#endif // POWERMGR_INNERKITS_IBATTERY_SRV_H \ No newline at end of file diff --git a/interfaces/innerkits/native/src/battery_srv_client.cpp b/interfaces/innerkits/native/src/battery_srv_client.cpp new file mode 100644 index 0000000..ab703c7 --- /dev/null +++ b/interfaces/innerkits/native/src/battery_srv_client.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 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 "battery_srv_client.h" +#include "string_ex.h" +#include "datetime_ex.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "if_system_ability_manager.h" +#include "system_ability_definition.h" +#include "power_common.h" + +namespace OHOS { +namespace PowerMgr { +BatterySrvClient::BatterySrvClient() {} +BatterySrvClient::~BatterySrvClient() {} + +ErrCode BatterySrvClient::Connect() +{ + std::lock_guard lock(mutex_); + if (proxy_ != nullptr) { + return ERR_OK; + } + sptr sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sm == nullptr) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "%{public}s:fail to get Registry", __func__); + return E_GET_SYSTEM_ABILITY_MANAGER_FAILED; + } + sptr remoteObject_ = sm->CheckSystemAbility(POWER_MANAGER_BATT_SERVICE_ID); + if (remoteObject_ == nullptr) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "GetSystemAbility failed."); + return E_GET_POWER_SERVICE_FAILED; + } + proxy_ = iface_cast(remoteObject_); + POWER_HILOGI(MODULE_BATT_INNERKIT, "%{public}s :Connect PowerMgrService ok.", __func__); + return ERR_OK; +} + +void BatterySrvClient::ResetProxy(const wptr& remote) +{ + std::lock_guard lock(mutex_); + RETURN_IF(proxy_ == nullptr); + auto serviceRemote = proxy_->AsObject(); + if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) { + serviceRemote->RemoveDeathRecipient(deathRecipient_); + proxy_ = nullptr; + } +} + +void BatterySrvClient::BatterySrvDeathRecipient::OnRemoteDied(const wptr& remote) +{ + if (remote == nullptr) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvDeathRecipient::OnRemoteDied failed, remote is nullptr."); + return; + } + BatterySrvClient::GetInstance().ResetProxy(remote); + POWER_HILOGI(MODULE_BATT_INNERKIT, "BatterySrvDeathRecipient::Recv death notice."); +} + +int32_t BatterySrvClient::GetCapacity() +{ + int32_t capacity = INVALID_BATT_INT_VALUE; + RETURN_IF_WITH_RET(Connect() != ERR_OK, capacity); + capacity = proxy_->GetCapacity(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetCapacity Success!"); + return capacity; +} + +BatteryChargeState BatterySrvClient::GetChargingStatus() +{ + BatteryChargeState chargingstate = BatteryChargeState::CHARGE_STATE_BUTT; + RETURN_IF_WITH_RET(Connect() != ERR_OK, chargingstate); + chargingstate = proxy_->GetChargingStatus(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetChargingStatus Success!"); + return chargingstate; +} + +BatteryHealthState BatterySrvClient::GetHealthStatus() +{ + BatteryHealthState healthState = BatteryHealthState::HEALTH_STATE_BUTT; + RETURN_IF_WITH_RET(Connect() != ERR_OK, healthState); + healthState = proxy_->GetHealthStatus(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetHealthStatus Success!"); + return healthState; +} + +BatteryPluggedType BatterySrvClient::GetPluggedType() +{ + BatteryPluggedType pluggedType = BatteryPluggedType::PLUGGED_TYPE_BUTT; + RETURN_IF_WITH_RET(Connect() != ERR_OK, pluggedType); + pluggedType = proxy_->GetPluggedType(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetPluggedType Success!"); + return pluggedType; +} + +int32_t BatterySrvClient::GetVoltage() +{ + int32_t voltage = INVALID_BATT_INT_VALUE; + RETURN_IF_WITH_RET(Connect() != ERR_OK, voltage); + voltage = proxy_->GetVoltage(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetVoltage Success!"); + return voltage; +} + +bool BatterySrvClient::GetPresent() +{ + bool present = INVALID_BATT_BOOL_VALUE; + RETURN_IF_WITH_RET(Connect() != ERR_OK, present); + present = proxy_->GetPresent(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetPresent Success!"); + return present; +} + +std::string BatterySrvClient::GetTechnology() +{ + std::string technology; + RETURN_IF_WITH_RET(Connect() != ERR_OK, technology); + technology = proxy_->GetTechnology(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetTechnology Success!"); + return technology; +} + +int32_t BatterySrvClient::GetBatteryTemperature() +{ + int32_t temperature = INVALID_BATT_TEMP_VALUE; + RETURN_IF_WITH_RET(Connect() != ERR_OK, temperature); + temperature = proxy_->GetBatteryTemperature(); + POWER_HILOGI(MODULE_BATT_INNERKIT, " Calling GetBatteryTemperature Success!"); + return temperature; +} +} // namespace PowerMgr +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/@ohos.batteryinfo.d.ts b/interfaces/kits/js/@ohos.batteryinfo.d.ts new file mode 100644 index 0000000..7682dc8 --- /dev/null +++ b/interfaces/kits/js/@ohos.batteryinfo.d.ts @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021 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. + */ + +/** + * Obtains battery information of a device. + * + *

Battery information includes the remaining battery power, + * voltage, temperature, model, and charger type. + * + * @SysCap SystemCapability.PowerMgr.BatteryManager + * @devices phone, tablet + * @since 6 + */ +declare namespace batteryInfo { + /** + * Battery state of charge (SoC) of the current device. + * @devices phone, tablet + */ + const batterySOC: number; + + /** + * Battery charging status of the current device. + * @devices phone, tablet + */ + const chargingStatus: BatteryChargeState; + + /** + * Battery health state of the current device. + * @devices phone, tablet + */ + const healthStatus: BatteryHealthState; + + /** + * Charger type of the current device. + * @devices phone, tablet + */ + const pluggedType: BatteryPluggedType; + + /** + * Battery voltage of the current device. + * @devices phone, tablet + */ + const voltage: number; + + /** + * Battery technology of the current device. + * @devices phone, tablet + */ + const technology: string; + + /** + * Battery temperature of the current device. + * @devices phone, tablet + */ + const batteryTemperature: number; + + /** + * Indicates the charger type of a device. + * + * @SysCap SystemCapability.PowerMgr.BatteryManager + * @devices phone, tablet + * @since 6 + */ + export enum BatteryPluggedType { + /** + * Unknown type + * @devices phone, tablet + */ + NONE, + /** + * AC charger + * @devices phone, tablet + */ + AC, + /** + * USB charger + * @devices phone, tablet + */ + USB, + /** + * Wireless charger + * @devices phone, tablet + */ + WIRELESS + } + + /** + * Indicates the battery charging status of a device. + * + * @SysCap SystemCapability.PowerMgr.BatteryManager + * @devices phone, tablet + * @since 6 + */ + export enum BatteryChargeState { + /** + * Unknown state. + * @devices phone, tablet + */ + NONE, + /** + * The battery is being charged. + * @devices phone, tablet + */ + ENABLE, + /** + * The battery is not being charged. + * @devices phone, tablet + */ + DISABLE, + /** + * The battery is fully charged. + * @devices phone, tablet + */ + FULL + } + + /** + * Indicates the battery health status of a device. + * + * @SysCap SystemCapability.PowerMgr.BatteryManager + * @devices phone, tablet + * @since 6 + */ + export enum BatteryHealthState { + /** + * Unknown state. + * @devices phone, tablet + */ + UNKNOWN, + /** + * The battery is in healthy state. + * @devices phone, tablet + */ + GOOD, + /** + * The battery is overheated. + * @devices phone, tablet + */ + OVERHEAT, + /** + * The battery voltage is over high. + * @devices phone, tablet + */ + OVERVOLTAGE, + /** + * The battery temperature is low. + * @devices phone, tablet + */ + COLD, + /** + * The battery is dead. + * @devices phone, tablet + */ + DEAD + } +} +export default batteryInfo; + diff --git a/interfaces/kits/js/napi/BUILD.gn b/interfaces/kits/js/napi/BUILD.gn new file mode 100755 index 0000000..1aac457 --- /dev/null +++ b/interfaces/kits/js/napi/BUILD.gn @@ -0,0 +1,47 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") + +config("batterynapi_private_config") { + include_dirs = [ + "//foundation/ace/napi/native_engine", + "//foundation/ace/napi/interfaces/kits", + "//utils/system/safwk/native/include", + "//third_party/node/src", + "//base/powermgr/battery_manager/interfaces/innerkits/native/include", + "//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include", + "//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include", + ] +} + +ohos_shared_library("batteryinfo") { + sources = [ "battery_info.cpp" ] + configs = [ + "${utils_path}:utils_config", + ":batterynapi_private_config", + ] + deps = [ + "//base/powermgr/battery_manager/interfaces/innerkits:batterysrv_client", + "//foundation/ace/napi:ace_napi", + ] + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + + relative_install_dir = "module" + + subsystem_name = "powermgr" + part_name = "battery_manager_native" +} diff --git a/interfaces/kits/js/napi/battery_info.cpp b/interfaces/kits/js/napi/battery_info.cpp new file mode 100644 index 0000000..185d65f --- /dev/null +++ b/interfaces/kits/js/napi/battery_info.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2021 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 +#include +#include +#include "battery_info.h" +#include "battery_srv_client.h" +#include "hilog_wrapper.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +using namespace OHOS::PowerMgr; + +static BatterySrvClient &g_battClient = BatterySrvClient::GetInstance(); + +static napi_value BatterySOC(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t capacity = g_battClient.GetCapacity(); + + NAPI_CALL(env, napi_create_int32(env, capacity, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "capacity %{public}d", capacity); + return napiValue; +} + +static napi_value GetChargingState(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t chargeState = (int32_t)g_battClient.GetChargingStatus(); + + NAPI_CALL(env, napi_create_int32(env, chargeState, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "chargeState %{public}d", chargeState); + + return napiValue; +} + +static napi_value GetHealthState(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t healthStatus = (int32_t)g_battClient.GetHealthStatus(); + + NAPI_CALL(env, napi_create_int32(env, healthStatus, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "healthStatus %{public}d", healthStatus); + + return napiValue; +} + +static napi_value GetPluggedType(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t pluggedType = (int32_t)g_battClient.GetPluggedType(); + + NAPI_CALL(env, napi_create_int32(env, pluggedType, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "pluggedType %{public}d", pluggedType); + + return napiValue; +} + +static napi_value GetVoltage(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t voltage = g_battClient.GetVoltage(); + + NAPI_CALL(env, napi_create_int32(env, voltage, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "%{public}d", voltage); + + return napiValue; +} + +static napi_value GetTechnology(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + auto technology = g_battClient.GetTechnology(); + const char *technologyStr = technology.c_str(); + + NAPI_CALL(env, napi_create_string_utf8(env, technologyStr, strlen(technologyStr), &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "technology %{public}s", technologyStr); + return napiValue; +} + +static napi_value GetBatteryTemperature(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int32_t temperature = g_battClient.GetBatteryTemperature(); + + NAPI_CALL(env, napi_create_int32(env, temperature, &napiValue)); + + POWER_HILOGD(MODULE_JS_NAPI, "%{public}d", temperature); + + return napiValue; +} + +static napi_value EnumHealthClassConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisArg = nullptr; + void *data = nullptr; + + napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data); + + napi_value global = nullptr; + napi_get_global(env, &global); + + return thisArg; +} + +static napi_value CreateEnumHealthState(napi_env env, napi_value exports) +{ + napi_value unknown = nullptr; + napi_value good = nullptr; + napi_value overheat = nullptr; + napi_value overvoltage = nullptr; + napi_value cold = nullptr; + napi_value dead = nullptr; + + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_UNKNOWN, &unknown); + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_GOOD, &good); + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_OVERHEAT, &overheat); + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_OVERVOLTAGE, &overvoltage); + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_COLD, &cold); + napi_create_int32(env, (int32_t)BatteryHealthState::HEALTH_STATE_DEAD, &dead); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY("UNKNOWN", unknown), + DECLARE_NAPI_STATIC_PROPERTY("GOOD", good), + DECLARE_NAPI_STATIC_PROPERTY("OVERHEAT", overheat), + DECLARE_NAPI_STATIC_PROPERTY("OVERVOLTAGE", overvoltage), + DECLARE_NAPI_STATIC_PROPERTY("COLD", cold), + DECLARE_NAPI_STATIC_PROPERTY("DEAD", dead), + }; + napi_value result = nullptr; + napi_define_class(env, "BatteryHealthState", NAPI_AUTO_LENGTH, EnumHealthClassConstructor, nullptr, + sizeof(desc) / sizeof(*desc), desc, &result); + + napi_set_named_property(env, exports, "BatteryHealthState", result); + + return exports; +} + +static napi_value EnumChargeClassConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisArg = nullptr; + void *data = nullptr; + + napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data); + + napi_value global = nullptr; + napi_get_global(env, &global); + + return thisArg; +} + +static napi_value CreateEnumChargeState(napi_env env, napi_value exports) +{ + napi_value none = nullptr; + napi_value enable = nullptr; + napi_value disable = nullptr; + napi_value full = nullptr; + + napi_create_int32(env, (int32_t)BatteryChargeState::CHARGE_STATE_NONE, &none); + napi_create_int32(env, (int32_t)BatteryChargeState::CHARGE_STATE_ENABLE, &enable); + napi_create_int32(env, (int32_t)BatteryChargeState::CHARGE_STATE_DISABLE, &disable); + napi_create_int32(env, (int32_t)BatteryChargeState::CHARGE_STATE_FULL, &full); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY("NONE", none), + DECLARE_NAPI_STATIC_PROPERTY("ENABLE", enable), + DECLARE_NAPI_STATIC_PROPERTY("DISABLE", disable), + DECLARE_NAPI_STATIC_PROPERTY("FULL", full), + }; + + napi_value result = nullptr; + napi_define_class(env, "BatteryChargeState", NAPI_AUTO_LENGTH, EnumChargeClassConstructor, nullptr, + sizeof(desc) / sizeof(*desc), desc, &result); + + napi_set_named_property(env, exports, "BatteryChargeState", result); + + return exports; +} + +static napi_value EnumPluggedClassConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisArg = nullptr; + void *data = nullptr; + + napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data); + + napi_value global = nullptr; + napi_get_global(env, &global); + + return thisArg; +} + +static napi_value CreateEnumPluggedType(napi_env env, napi_value exports) +{ + napi_value none = nullptr; + napi_value ac = nullptr; + napi_value usb = nullptr; + napi_value wireless = nullptr; + + napi_create_int32(env, (int32_t)BatteryPluggedType::PLUGGED_TYPE_NONE, &none); + napi_create_int32(env, (int32_t)BatteryPluggedType::PLUGGED_TYPE_AC, &ac); + napi_create_int32(env, (int32_t)BatteryPluggedType::PLUGGED_TYPE_USB, &usb); + napi_create_int32(env, (int32_t)BatteryPluggedType::PLUGGED_TYPE_WIRELESS, &wireless); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY("NONE", none), + DECLARE_NAPI_STATIC_PROPERTY("AC", ac), + DECLARE_NAPI_STATIC_PROPERTY("USB", usb), + DECLARE_NAPI_STATIC_PROPERTY("WIRELESS", wireless), + }; + + napi_value result = nullptr; + napi_define_class(env, "BatteryPluggedType", NAPI_AUTO_LENGTH, EnumPluggedClassConstructor, nullptr, + sizeof(desc) / sizeof(*desc), desc, &result); + + napi_set_named_property(env, exports, "BatteryPluggedType", result); + + return exports; +} + +EXTERN_C_START +/* + * function for module exports + */ +static napi_value BatteryInit(napi_env env, napi_value exports) +{ + POWER_HILOGD(MODULE_JS_NAPI, "enter"); + + napi_property_descriptor desc[] = { + DECLARE_NAPI_GETTER("batterySOC", BatterySOC), + DECLARE_NAPI_GETTER("chargingStatus", GetChargingState), + DECLARE_NAPI_GETTER("healthStatus", GetHealthState), + DECLARE_NAPI_GETTER("pluggedType", GetPluggedType), + DECLARE_NAPI_GETTER("voltage", GetVoltage), + DECLARE_NAPI_GETTER("technology", GetTechnology), + DECLARE_NAPI_GETTER("batteryTemperature", GetBatteryTemperature), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + + CreateEnumPluggedType(env, exports); + CreateEnumChargeState(env, exports); + CreateEnumHealthState(env, exports); + + POWER_HILOGD(MODULE_JS_NAPI, "return"); + + return exports; +} +EXTERN_C_END + +/* + * Module definition + */ +static napi_module g_module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = "batteryInfo", + .nm_register_func = BatteryInit, + .nm_modname = "batteryInfo", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +/* + * Module registration + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&g_module); +} diff --git a/interfaces/kits/js/test/battery_unit.test.js b/interfaces/kits/js/test/battery_unit.test.js new file mode 100644 index 0000000..f64ee0a --- /dev/null +++ b/interfaces/kits/js/test/battery_unit.test.js @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2021 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 app from '@system.app' +import Context from '@ohos.napi_context' +import batteryInfo from '@ohos.batteryInfo'; + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' + +describe('appInfoTest', function () { + console.log("*************Battery Unit Test Begin*************"); + it('battery_soc_test', 0, function () { + var batterySoc = batteryInfo.batterySOC; + console.info('batterySoc = ' + batterySoc); + expect(batterySoc >= 0 && batterySoc <= 100).assertEqual('1') + }) + it('charging_status_test', 0, function () { + var chargingStatus = batteryInfo.chargingStatus; + console.info('chargingStatus = ' + chargingStatus); + expect(chargingStatus >= 0 && chargingStatus <= 3).assertEqual('1') + }) + it('health_status_test', 0, function () { + var healthStatus = batteryInfo.healthStatus; + console.info('healthStatus = ' + healthStatus); + expect(healthStatus >= 0 && healthStatus <= 5).assertEqual('1') + }) + it('plugged_type_test', 0, function () { + var pluggedType = batteryInfo.pluggedType; + console.info('pluggedType = ' + pluggedType); + expect(pluggedType >= 0 && pluggedType <= 3).assertEqual('1') + }) + it('voltage_test', 0, function () { + var voltage = batteryInfo.voltage; + console.info('voltage = ' + voltage); + expect(voltage >= 0).assertEqual('1') + }) + it('technology_test', 0, function () { + var technology = batteryInfo.technology; + console.info('technology = ' + technology); + expect(0).assertEqual('0') + }) + it('battery_temperature_test', 0, function () { + var batteryTemperature = batteryInfo.batteryTemperature; + console.info('batteryTemperature = ' + batteryTemperature); + expect(batteryTemperature <= 100).assertEqual('1') + }) + + it('enum_health_state_test_unknown', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.UNKNOWN; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 0).assertEqual('1') + }) + it('enum_health_state_test_good', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.GOOD; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 1).assertEqual('1') + }) + it('enum_health_state_test_overheat', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.OVERHEAT; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 2).assertEqual('1') + }) + it('enum_health_state_test_overvoltage', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.OVERVOLTAGE; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 3).assertEqual('1') + }) + it('enum_health_state_test_cold', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.COLD; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 4).assertEqual('1') + }) + it('enum_health_state_test_dead', 0, function () { + var batteryHealthState = batteryInfo.BatteryHealthState.DEAD; + console.info('batteryHealthState = ' + batteryHealthState); + expect(batteryHealthState == 5).assertEqual('1') + }) + + it('enum_charge_state_test_none', 0, function () { + var batteryChargeState = batteryInfo.BatteryChargeState.NONE; + console.info('batteryChargeState = ' + batteryChargeState); + expect(batteryChargeState == 0).assertEqual('1') + }) + it('enum_charge_state_test_enable', 0, function () { + var batteryChargeState = batteryInfo.BatteryChargeState.ENABLE; + console.info('batteryChargeState = ' + batteryChargeState); + expect(batteryChargeState == 1).assertEqual('1') + }) + it('enum_charge_state_test_disable', 0, function () { + var batteryChargeState = batteryInfo.BatteryChargeState.DISABLE; + console.info('batteryChargeState = ' + batteryChargeState); + expect(batteryChargeState == 2).assertEqual('1') + }) + it('enum_charge_state_test_full', 0, function () { + var batteryChargeState = batteryInfo.BatteryChargeState.FULL; + console.info('batteryChargeState = ' + batteryChargeState); + expect(batteryChargeState == 3).assertEqual('1') + }) + + it('enum_plugged_type_test_none', 0, function () { + var batteryPluggedType = batteryInfo.BatteryPluggedType.NONE; + console.info('batteryPluggedType = ' + batteryPluggedType); + expect(batteryPluggedType == 0).assertEqual('1') + }) + it('enum_plugged_type_test_ac', 0, function () { + var batteryPluggedType = batteryInfo.BatteryPluggedType.AC; + console.info('batteryPluggedType = ' + batteryPluggedType); + expect(batteryPluggedType == 1).assertEqual('1') + }) + it('enum_plugged_type_test_usb', 0, function () { + var batteryPluggedType = batteryInfo.BatteryPluggedType.USB; + console.info('batteryPluggedType = ' + batteryPluggedType); + expect(batteryPluggedType == 2).assertEqual('1') + }) + it('enum_plugged_type_test_wireless', 0, function () { + var batteryPluggedType = batteryInfo.BatteryPluggedType.WIRELESS; + console.info('batteryPluggedType = ' + batteryPluggedType); + expect(batteryPluggedType == 3).assertEqual('1') + }) +}) \ No newline at end of file diff --git a/ohos.build b/ohos.build new file mode 100644 index 0000000..27ff947 --- /dev/null +++ b/ohos.build @@ -0,0 +1,33 @@ +{ + "subsystem": "powermgr", + "parts": { + "battery_manager_native": { + "system_capabilities": [ + "SystemCapability.PowerMgr.BatteryManager" + ], + "module_list": [ + "//base/powermgr/battery_manager/hdi:hdi_group", + "//base/powermgr/battery_manager/interfaces/innerkits:batterysrv_client", + "//base/powermgr/battery_manager/sa_profile:batterymgr_sa_profile", + "//base/powermgr/battery_manager/services:batteryservice", + "//base/powermgr/battery_manager/interfaces/kits/js/napi:batteryinfo" + ], + "inner_kits": [ + { + "name": "//base/powermgr/battery_manager/interfaces/innerkits:batterysrv_client", + "header": { + "header_files": [ + "battery_srv_client.h", + "ibattery_srv.h", + "battery_info.h" + ], + "header_base": "//base/powermgr/battery_manager/interfaces/innerkits/native/include" + } + } + ], + "test_list": [ + "//base/powermgr/battery_manager/services/native/test:unittest" + ] + } + } +} \ No newline at end of file diff --git a/sa_profile/3302.xml b/sa_profile/3302.xml new file mode 100644 index 0000000..7c88e43 --- /dev/null +++ b/sa_profile/3302.xml @@ -0,0 +1,24 @@ + + + + foundation + + 3302 + libbatteryservice.z.so + true + false + 1 + + diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn new file mode 100644 index 0000000..aae91a9 --- /dev/null +++ b/sa_profile/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2021 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/sa_profile/sa_profile.gni") + +ohos_sa_profile("batterymgr_sa_profile") { + sources = [ "3302.xml" ] + part_name = "battery_manager_native" +} diff --git a/services/BUILD.gn b/services/BUILD.gn new file mode 100644 index 0000000..cca21fc --- /dev/null +++ b/services/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") + +config("batterysrv_private_config") { + include_dirs = [ "//utils/system/safwk/native/include" ] +} + +config("batterysrv_public_config") { + include_dirs = [ + "native/include", + "${battery_manager_path}/services/zidl/include", + ] +} + +ohos_shared_library("batteryservice") { + sources = [ + "${battery_manager_path}/services/zidl/src/battery_srv_stub.cpp", + "native/src/battery_service.cpp", + "native/src/battery_service_subscriber.cpp", + "native/src/batterysrv_event_handler.cpp", + ] + + configs = [ + "${utils_path}:utils_config", + ":batterysrv_private_config", + ] + + public_configs = [ ":batterysrv_public_config" ] + + deps = [ + "${battery_manager_path}/hdi/client:batteryd_client", + "${battery_manager_path}/interfaces/innerkits:batterysrv_client", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:base", + "aafwk_standard:want", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:libeventhandler", + "ces_standard:cesfwk_innerkits", + "ces_standard:cesfwk_kits", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr_L2:samgr_proxy", + ] + + part_name = "battery_manager_native" +} diff --git a/services/native/include/battery_service.h b/services/native/include/battery_service.h new file mode 100644 index 0000000..12229c1 --- /dev/null +++ b/services/native/include/battery_service.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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 POWERMGR_BATTERY_SERVICE_H +#define POWERMGR_BATTERY_SERVICE_H + +#include "sp_singleton.h" +#include "system_ability.h" +#include "iremote_object.h" +#include "ibattery_srv.h" +#include "batteryd_api.h" +#include "batteryd_client.h" +#include "batteryd_subscriber.h" +#include "battery_service_subscriber.h" +#include "battery_srv_stub.h" +#include "batterysrv_event_handler.h" + +namespace OHOS { +namespace PowerMgr { +class BatteryService final : public SystemAbility, + public BatterySrvStub { +DECLARE_SYSTEM_ABILITY(BatteryService) + +DECLARE_DELAYED_SP_SINGLETON(BatteryService); +public: + virtual void OnStart() override; + virtual void OnStop() override; + + bool IsServiceReady() const + { + return ready_; + } + + std::shared_ptr GetHandler() const + { + return handler_; + } + + int32_t GetCapacity() override; + BatteryChargeState GetChargingStatus() override; + BatteryHealthState GetHealthStatus() override; + BatteryPluggedType GetPluggedType() override; + int32_t GetVoltage() override; + bool GetPresent() override; + std::string GetTechnology() override; + int32_t GetBatteryTemperature() override; + +private: + bool Init(); + bool InitBatteryd(); + bool IsCommonEventServiceAbilityExist(); + bool ready_ {false}; + int32_t commEventRetryTimes_ {0}; + std::mutex mutex_; + std::shared_ptr eventRunner_; + std::shared_ptr handler_; + sptr batterydSubscriber_; +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // POWERMGR_BATTERY_SERVICE_H diff --git a/services/native/include/battery_service_subscriber.h b/services/native/include/battery_service_subscriber.h new file mode 100644 index 0000000..76bcc3f --- /dev/null +++ b/services/native/include/battery_service_subscriber.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 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 BATTERY_SERVICE_SUBSCRIBER_H +#define BATTERY_SERVICE_SUBSCRIBER_H + +#include "batteryd_subscriber.h" + +namespace OHOS { +namespace PowerMgr { +class BatteryServiceSubscriber : public BatterydSubscriber { +public: + BatteryServiceSubscriber(); + ~BatteryServiceSubscriber() = default; + int32_t Update(const BatteryInfo &info) override; + +private: + static bool HandleBatteryChangedEvent(const BatteryInfo &info); +}; +} // namespace PowerMgr +} // namespace OHOS +#endif // BATTERY_SERVICE_SUBSCRIBER_H \ No newline at end of file diff --git a/services/native/include/batterysrv_event_handler.h b/services/native/include/batterysrv_event_handler.h new file mode 100644 index 0000000..768ac41 --- /dev/null +++ b/services/native/include/batterysrv_event_handler.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 POWERMGR_BATTERYSRV_EVENT_HANDLER_H +#define POWERMGR_BATTERYSRV_EVENT_HANDLER_H + +#include "refbase.h" +#include "event_handler.h" + +namespace OHOS { +namespace PowerMgr { +class BatteryService; + +class BatterysrvEventHandler : public AppExecFwk::EventHandler { +public: + BatterysrvEventHandler(const std::shared_ptr &runner, + const wptr &service); + ~BatterysrvEventHandler() = default; + void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; + +private: + wptr service_; +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // POWERMGR_BATTERYSRV_EVENT_HANDLER_H \ No newline at end of file diff --git a/services/native/src/battery_service.cpp b/services/native/src/battery_service.cpp new file mode 100644 index 0000000..57b8d8c --- /dev/null +++ b/services/native/src/battery_service.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021 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 "battery_service.h" + +#include +#include "file_ex.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "power_common.h" + +namespace OHOS { +namespace PowerMgr { +namespace { +const std::string BATTERY_SERVICE_NAME = "BatteryService"; +constexpr int32_t COMMEVENT_REGISTER_RETRY_TIMES = 10; +constexpr int32_t COMMEVENT_REGISTER_WAIT_DELAY_US = 20000; +} + +const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility( + DelayedSpSingleton::GetInstance().GetRefPtr()); + +BatteryService::BatteryService() + : SystemAbility(POWER_MANAGER_BATT_SERVICE_ID, true) {} + +BatteryService::~BatteryService() {} + +void BatteryService::OnStart() +{ + POWER_HILOGI(MODULE_BATT_SERVICE, "OnStart enter"); + if (ready_) { + POWER_HILOGE(MODULE_BATT_SERVICE, "OnStart is ready, nothing to do"); + return; + } + if (!(Init())) { + POWER_HILOGE(MODULE_BATT_SERVICE, "OnStart call init fail"); + return; + } + if (!(InitBatteryd())) { + POWER_HILOGE(MODULE_BATT_SERVICE, "OnStart call initBatteryd fail"); + return; + } + ready_ = true; + POWER_HILOGI(MODULE_BATT_SERVICE, "OnStart and add system ability success"); +} + +bool BatteryService::Init() +{ + POWER_HILOGI(MODULE_BATT_SERVICE, "Init start"); + if (!eventRunner_) { + eventRunner_ = AppExecFwk::EventRunner::Create(BATTERY_SERVICE_NAME); + if (eventRunner_ == nullptr) { + POWER_HILOGE(MODULE_BATT_SERVICE, "Init failed due to create EventRunner"); + return false; + } + } + if (!handler_) { + handler_ = std::make_shared(eventRunner_, + DelayedSpSingleton::GetInstance()); + if (handler_ == nullptr) { + POWER_HILOGE(MODULE_BATT_SERVICE, "Init failed due to create handler error"); + return false; + } + } + while (commEventRetryTimes_ <= COMMEVENT_REGISTER_RETRY_TIMES) { + if (!IsCommonEventServiceAbilityExist()) { + commEventRetryTimes_++; + usleep(COMMEVENT_REGISTER_WAIT_DELAY_US); + } else { + commEventRetryTimes_ = 0; + break; + } + } + POWER_HILOGI(MODULE_BATT_SERVICE, "Init success"); + return true; +} + +bool BatteryService::InitBatteryd() +{ + batterydSubscriber_ = new BatteryServiceSubscriber(); + ErrCode ret = BatterydClient::BindBatterydSubscriber(batterydSubscriber_); + POWER_HILOGD(MODULE_BATT_SERVICE, "InitBatteryd ret: %{public}d", ret); + return SUCCEEDED(ret); +} + +void BatteryService::OnStop() +{ + POWER_HILOGI(MODULE_BATT_SERVICE, "stop service"); + if (!ready_) { + return; + } + eventRunner_.reset(); + handler_.reset(); + ready_ = false; + BatterydClient::UnbindBatterydSubscriber(); +} + +bool BatteryService::IsCommonEventServiceAbilityExist() +{ + sptr sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!sm) { + POWER_HILOGI(MODULE_BATT_SERVICE, + "IsCommonEventServiceAbilityExist Get ISystemAbilityManager failed, no SystemAbilityManager"); + return false; + } + sptr remote = sm->CheckSystemAbility(COMMON_EVENT_SERVICE_ABILITY_ID); + if (!remote) { + POWER_HILOGE(MODULE_BATT_SERVICE, "No CesServiceAbility"); + return false; + } + return true; +} + +int32_t BatteryService::GetCapacity() +{ + return BatterydClient::GetCapacity(); +} + +BatteryChargeState BatteryService::GetChargingStatus() +{ + return BatterydClient::GetChargeState(); +} + +BatteryHealthState BatteryService::GetHealthStatus() +{ + return BatterydClient::GetHealthState(); +} + +BatteryPluggedType BatteryService::GetPluggedType() +{ + return BatterydClient::GetPluggedType(); +} + +int32_t BatteryService::GetVoltage() +{ + return BatterydClient::GetVoltage(); +} + +bool BatteryService::GetPresent() +{ + return BatterydClient::GetPresent(); +} + +std::string BatteryService::GetTechnology() +{ + return BatterydClient::GetTechnology(); +} + +int32_t BatteryService::GetBatteryTemperature() +{ + return BatterydClient::GetTemperature(); +} +} // namespace PowerMgr +} // namespace OHOS diff --git a/services/native/src/battery_service_subscriber.cpp b/services/native/src/battery_service_subscriber.cpp new file mode 100644 index 0000000..fae0b6e --- /dev/null +++ b/services/native/src/battery_service_subscriber.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 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 "battery_service_subscriber.h" + +#include "common_event_data.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "ohos/aafwk/content/want.h" +#include "power_common.h" +#include "string_ex.h" + +using namespace OHOS::AAFwk; +using namespace OHOS::EventFwk; + +namespace OHOS { +namespace PowerMgr { +BatteryServiceSubscriber::BatteryServiceSubscriber() {} + +int32_t BatteryServiceSubscriber::Update(const BatteryInfo &info) +{ + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryInfo: capacity=%{public}d, voltage=%{public}d, " \ + "temperature=%{public}d, healthState=%{public}d, pluggedType=%{public}d, " \ + "pluggedMaxCurrent=%{public}d, pluggedMaxVoltage=%{public}d, " \ + "chargeState=%{public}d, chargeCounter=%{public}d, present=%{public}d, " \ + "technology=%{public}s", + info.GetCapacity(), info.GetVoltage(), info.GetTemperature(), info.GetHealthState(), + info.GetPluggedType(), info.GetPluggedMaxCurrent(), info.GetPluggedMaxVoltage(), info.GetChargeState(), + info.GetChargeCounter(), info.IsPresent(), info.GetTechnology().c_str()); + bool ret = HandleBatteryChangedEvent(info); + return ret ? ERR_OK : ERR_NO_INIT; +} + +bool BatteryServiceSubscriber::HandleBatteryChangedEvent(const BatteryInfo &info) +{ + Want want; + want.SetAction(CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED); + CommonEventData data; + data.SetWant(want); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_CAPACITY); + data.SetData(ToString(info.GetCapacity())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_VOLTAGE); + data.SetData(ToString(info.GetVoltage())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_TEMPERATURE); + data.SetData(ToString(info.GetTemperature())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_HEALTH_STATE); + data.SetData(ToString(static_cast(info.GetHealthState()))); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_PLUGGED_TYPE); + data.SetData(ToString(static_cast(info.GetPluggedType()))); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_PLUGGED_MAX_CURRENT); + data.SetData(ToString(info.GetPluggedMaxCurrent())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_PLUGGED_MAX_VOLTAGE); + data.SetData(ToString(info.GetPluggedMaxVoltage())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_CHARGE_STATE); + data.SetData(ToString(static_cast(info.GetChargeState()))); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_CHARGE_COUNTER); + data.SetData(ToString(info.GetChargeCounter())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_PRESENT); + data.SetData(ToString(info.IsPresent())); + data.SetCode(BatteryInfo::COMMON_EVENT_CODE_TECHNOLOGY); + data.SetData(info.GetTechnology()); + CommonEventPublishInfo publishInfo; + publishInfo.SetOrdered(true); + bool isSuccess = CommonEventManager::PublishCommonEvent(data, publishInfo); + if (!isSuccess) { + POWER_HILOGD(MODULE_BATT_SERVICE, "failed to publish BATTERY_CHANGED event"); + } + return isSuccess; +} +} // namespace PowerMgr +} // namespace OHOS diff --git a/services/native/src/batterysrv_event_handler.cpp b/services/native/src/batterysrv_event_handler.cpp new file mode 100644 index 0000000..f054fe4 --- /dev/null +++ b/services/native/src/batterysrv_event_handler.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 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 "batterysrv_event_handler.h" +#include "power_common.h" +#include "battery_service.h" + +namespace OHOS { +namespace PowerMgr { +BatterysrvEventHandler::BatterysrvEventHandler(const std::shared_ptr &runner, + const wptr &service) + : AppExecFwk::EventHandler(runner), service_(service) +{ + POWER_HILOGD(MODULE_BATT_SERVICE, "BatterysrvEventHandler::BatterysrvEventHandler instance created."); +} + +void BatterysrvEventHandler::ProcessEvent([[maybe_unused]] const AppExecFwk::InnerEvent::Pointer &event) {} +} // namespace PowerMgr +} // namespace OHOS \ No newline at end of file diff --git a/services/native/test/BUILD.gn b/services/native/test/BUILD.gn new file mode 100644 index 0000000..788191d --- /dev/null +++ b/services/native/test/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2021 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/test.gni") + +group("unittest") { + testonly = true + if (is_large_system) { + deps = [ "unittest/common:unittest" ] + } +} diff --git a/services/native/test/unittest/common/BUILD.gn b/services/native/test/unittest/common/BUILD.gn new file mode 100644 index 0000000..d01bf44 --- /dev/null +++ b/services/native/test/unittest/common/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") +import("//build/test.gni") + +module_output_path = "battery_manager_native/batterysrv" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "//utils/system/safwk/native/include", + ] +} + +##############################unittest########################################## +ohos_unittest("test_batterysrv") { + module_out_path = module_output_path + + sources = [ "src/battery_service_test.cpp" ] + + configs = [ + "${utils_path}:utils_config", + ":module_private_config", + ] + + deps = [ + "${battery_manager_path}/interfaces/innerkits:batterysrv_client", + "${battery_manager_path}/services:batteryservice", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "aafwk_standard:base", + "aafwk_standard:intent", + "appexecfwk_standard:appexecfwk_base", + "appexecfwk_standard:libeventhandler", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_L2:samgr_proxy", + ] +} + +group("unittest") { + testonly = true + deps = [] + + deps += [ ":test_batterysrv" ] +} diff --git a/services/native/test/unittest/common/include/battery_service_test.h b/services/native/test/unittest/common/include/battery_service_test.h new file mode 100644 index 0000000..6925227 --- /dev/null +++ b/services/native/test/unittest/common/include/battery_service_test.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 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 BATTERY_SERVICE_TEST_H +#define BATTERY_SERVICE_TEST_H + +#include + +class BatteryServiceTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + bool IsBatterySupported(); +}; +#endif // BATTERY_SERVICE_TEST_H \ No newline at end of file diff --git a/services/native/test/unittest/common/src/battery_service_test.cpp b/services/native/test/unittest/common/src/battery_service_test.cpp new file mode 100644 index 0000000..29ac47f --- /dev/null +++ b/services/native/test/unittest/common/src/battery_service_test.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021 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 "battery_service_test.h" +#include +#include "battery_srv_client.h" +#include "battery_service.h" +#include "power_common.h" +#include "iservice_registry.h" +#include "if_system_ability_manager.h" +#include "system_ability_definition.h" +#include "ipc_skeleton.h" +#include "string_ex.h" +#include "sys_param.h" +#include + +using namespace testing::ext; +using namespace OHOS::PowerMgr; +using namespace OHOS; +using namespace std; + +void BatteryServiceTest::SetUpTestCase(void) +{ +} + +void BatteryServiceTest::TearDownTestCase(void) +{ +} + +void BatteryServiceTest::SetUp(void) +{ +} + +void BatteryServiceTest::TearDown(void) +{ +} + +bool BatteryServiceTest::IsBatterySupported() +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto presentState = BatterySrvClient.GetPresent(); + auto isCar = SysParam::IsDeviceType(DeviceType::DEVICE_CAR); + auto isTv = SysParam::IsDeviceType(DeviceType::DEVICE_TV); + + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::isCar = %{public}d, isTv = %{public}d, present=%{public}d", + isCar, isTv, presentState); + if (!presentState || isCar || isTv) { + return false; + } + + return true; +} + +/** + * @tc.name: BatteryService001 + * @tc.desc: Test functions to get status of Present + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService001, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto present = BatterySrvClient.GetPresent(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::present=%{public}d", present); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(present); + } else { + ASSERT_FALSE(present); + } + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService001 end."); +} + +/** + * @tc.name: BatteryService002 + * @tc.desc: Test functions to get status of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService002, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto chargingStatus = BatterySrvClient.GetChargingStatus(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::status=%{public}d", chargingStatus); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(chargingStatus != BatteryChargeState::CHARGE_STATE_BUTT); + } else { + POWER_HILOGE(MODULE_BATT_SERVICE, "BatteryServiceTest::test is disabled, do nothing"); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService002 end."); +} + +/** + * @tc.name: BatteryService003 + * @tc.desc: Test functions to get value of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService003, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto healthStatus = BatterySrvClient.GetHealthStatus(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::health=%{public}d", healthStatus); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(healthStatus != BatteryHealthState::HEALTH_STATE_BUTT); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService003 end."); +} + +/** + * @tc.name: BatteryService004 + * @tc.desc: Test functions of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService004, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto capacity = BatterySrvClient.GetCapacity(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::soc=%{public}d", capacity); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(capacity != INVALID_BATT_INT_VALUE); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService004 end."); +} + +/** + * @tc.name: BatteryService005 + * @tc.desc: Test functions of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService005, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto voltage = BatterySrvClient.GetVoltage(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::voltage=%{public}d", voltage); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(voltage != INVALID_BATT_INT_VALUE); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService005 end."); +} + +/** + * @tc.name: BatteryService006 + * @tc.desc: Test functions of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService006, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto temp = BatterySrvClient.GetBatteryTemperature(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::temp=%{public}d", temp); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(temp != INVALID_BATT_TEMP_VALUE); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService006 end."); +} + +/** + * @tc.name: BatteryService007 + * @tc.desc: Test functions of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService007, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto technology = BatterySrvClient.GetTechnology(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::technology=%{public}s", technology.c_str()); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(technology != INVALID_STRING_VALUE); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService007 end."); +} + +/** + * @tc.name: BatteryService008 + * @tc.desc: Test functions of BatteryService + * @tc.type: FUNC + */ +HWTEST_F (BatteryServiceTest, BatteryService008, TestSize.Level1) +{ + auto& BatterySrvClient = BatterySrvClient::GetInstance(); + auto type = BatterySrvClient.GetPluggedType(); + POWER_HILOGI(MODULE_BATT_SERVICE, "BatteryServiceTest::type=%{public}d", type); + if (BatteryServiceTest::IsBatterySupported()) { + ASSERT_TRUE(type != BatteryPluggedType::PLUGGED_TYPE_BUTT); + } + + POWER_HILOGD(MODULE_BATT_SERVICE, "BatteryService::BatteryService008 end."); +} + diff --git a/services/zidl/ibattery_srv.zidl b/services/zidl/ibattery_srv.zidl new file mode 100644 index 0000000..a2783b9 --- /dev/null +++ b/services/zidl/ibattery_srv.zidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 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. + */ + +interface OhOs.PowerMgr.IBatterySrv { + /* the function about BatteryService */ +} \ No newline at end of file diff --git a/services/zidl/include/battery_srv_proxy.h b/services/zidl/include/battery_srv_proxy.h new file mode 100644 index 0000000..b70986b --- /dev/null +++ b/services/zidl/include/battery_srv_proxy.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 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 BATTERY_SRV_PROXY_H +#define BATTERY_SRV_PROXY_H + +#include "ibattery_srv.h" +#include "nocopyable.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace PowerMgr { +class BatterySrvProxy : public IRemoteProxy { +public: + explicit BatterySrvProxy(const sptr& impl) + : IRemoteProxy(impl) {} + ~BatterySrvProxy() = default; + DISALLOW_COPY_AND_MOVE(BatterySrvProxy); + + virtual int32_t GetCapacity() override; + virtual BatteryChargeState GetChargingStatus() override; + virtual BatteryHealthState GetHealthStatus() override; + virtual BatteryPluggedType GetPluggedType() override; + virtual int32_t GetVoltage() override; + virtual bool GetPresent() override; + virtual std::string GetTechnology() override; + virtual int32_t GetBatteryTemperature() override; +private: + static inline BrokerDelegator delegator_; +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // BATTERY_SRV_PROXY_H \ No newline at end of file diff --git a/services/zidl/include/battery_srv_stub.h b/services/zidl/include/battery_srv_stub.h new file mode 100644 index 0000000..639eb97 --- /dev/null +++ b/services/zidl/include/battery_srv_stub.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 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 BATTERY_SRV_STUB_H +#define BATTERY_SRV_STUB_H + +#include "ibattery_srv.h" +#include "nocopyable.h" +#include "iremote_stub.h" + +namespace OHOS { +namespace PowerMgr { +class BatterySrvStub : public IRemoteStub { +public: + DISALLOW_COPY_AND_MOVE(BatterySrvStub); + + BatterySrvStub() = default; + + virtual ~BatterySrvStub() = default; + + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + +private: + int32_t GetCapacityStub(MessageParcel& reply); + int32_t GetChargingStatusStub(MessageParcel& reply); + int32_t GetHealthStatusStub(MessageParcel& reply); + int32_t GetPluggedTypeStub(MessageParcel& reply); + int32_t GetVoltageStub(MessageParcel& reply); + int32_t GetPresentStub(MessageParcel& reply); + int32_t GetTechnologyStub(MessageParcel& reply); + int32_t GetBatteryTemperatureStub(MessageParcel& reply); +}; +} // namespace PowerMgr +} // namespace OHOS +#endif // BATTERY_SRV_STUB_H \ No newline at end of file diff --git a/services/zidl/src/battery_srv_proxy.cpp b/services/zidl/src/battery_srv_proxy.cpp new file mode 100644 index 0000000..7bc11c1 --- /dev/null +++ b/services/zidl/src/battery_srv_proxy.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2021 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 "battery_srv_proxy.h" +#include "ipc_types.h" +#include "message_parcel.h" +#include "power_common.h" + +namespace OHOS { +namespace PowerMgr { +int32_t BatterySrvProxy::GetCapacity() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, INVALID_BATT_INT_VALUE); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return INVALID_BATT_INT_VALUE; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_CAPACITY), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return INVALID_BATT_INT_VALUE; + } + int32_t capacity = INVALID_BATT_INT_VALUE; + READ_PARCEL_WITH_RET(reply, Int32, capacity, INVALID_BATT_INT_VALUE); + return capacity; +} + +BatteryChargeState BatterySrvProxy::GetChargingStatus() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, BatteryChargeState::CHARGE_STATE_BUTT); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return BatteryChargeState::CHARGE_STATE_BUTT; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_CHARGING_STATUS), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return BatteryChargeState::CHARGE_STATE_BUTT; + } + uint32_t chargingState = static_cast(BatteryChargeState::CHARGE_STATE_BUTT); + READ_PARCEL_WITH_RET(reply, Uint32, chargingState, BatteryChargeState::CHARGE_STATE_BUTT); + return static_cast(chargingState); +} + +BatteryHealthState BatterySrvProxy::GetHealthStatus() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, BatteryHealthState::HEALTH_STATE_BUTT); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return BatteryHealthState::HEALTH_STATE_BUTT; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_HEALTH_STATUS), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return BatteryHealthState::HEALTH_STATE_BUTT; + } + uint32_t healthStatus = static_cast(BatteryHealthState::HEALTH_STATE_BUTT); + READ_PARCEL_WITH_RET(reply, Uint32, healthStatus, BatteryHealthState::HEALTH_STATE_BUTT); + return static_cast(healthStatus); +} + +BatteryPluggedType BatterySrvProxy::GetPluggedType() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, BatteryPluggedType::PLUGGED_TYPE_BUTT); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return BatteryPluggedType::PLUGGED_TYPE_BUTT; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_PLUG_TYPE), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return BatteryPluggedType::PLUGGED_TYPE_BUTT; + } + uint32_t pluggedType = static_cast(BatteryPluggedType::PLUGGED_TYPE_BUTT); + READ_PARCEL_WITH_RET(reply, Uint32, pluggedType, BatteryPluggedType::PLUGGED_TYPE_BUTT); + return static_cast(pluggedType); +} + +int32_t BatterySrvProxy::GetVoltage() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, INVALID_BATT_INT_VALUE); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return INVALID_BATT_INT_VALUE; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_VOLTAGE), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return INVALID_BATT_INT_VALUE; + } + int32_t voltage = INVALID_BATT_INT_VALUE; + READ_PARCEL_WITH_RET(reply, Int32, voltage, INVALID_BATT_INT_VALUE); + return voltage; +} + +bool BatterySrvProxy::GetPresent() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, INVALID_BATT_BOOL_VALUE); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return INVALID_BATT_BOOL_VALUE; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_PRESENT), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return INVALID_BATT_BOOL_VALUE; + } + bool present = INVALID_BATT_BOOL_VALUE; + READ_PARCEL_WITH_RET(reply, Bool, present, INVALID_BATT_BOOL_VALUE); + return present; +} + +std::string BatterySrvProxy::GetTechnology() +{ + std::string technology = INVALID_STRING_VALUE; + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, INVALID_STRING_VALUE); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return INVALID_STRING_VALUE; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_TECHNOLOGY), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return INVALID_STRING_VALUE; + } + READ_PARCEL_WITH_RET(reply, String, technology, INVALID_STRING_VALUE); + return technology; +} + +int32_t BatterySrvProxy::GetBatteryTemperature() +{ + sptr remote = Remote(); + RETURN_IF_WITH_RET(remote == nullptr, INVALID_BATT_TEMP_VALUE); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(BatterySrvProxy::GetDescriptor())) { + POWER_HILOGE(MODULE_INNERKIT, "BatterySrvProxy::%{public}s write descriptor failed!", __func__); + return INVALID_BATT_TEMP_VALUE; + } + + int ret = remote->SendRequest(static_cast(IBatterySrv::BATT_GET_TEMPERATURE), + data, reply, option); + if (ret != ERR_OK) { + POWER_HILOGE(MODULE_BATT_INNERKIT, "BatterySrvProxy::%{public}s SendRequest is failed, error code: %d", + __func__, ret); + return INVALID_BATT_TEMP_VALUE; + } + int32_t temperature = INVALID_BATT_TEMP_VALUE; + READ_PARCEL_WITH_RET(reply, Int32, temperature, INVALID_BATT_TEMP_VALUE); + return temperature; +} +} // namespace PowerMgr +} // namespace OHOS diff --git a/services/zidl/src/battery_srv_stub.cpp b/services/zidl/src/battery_srv_stub.cpp new file mode 100644 index 0000000..b45cb13 --- /dev/null +++ b/services/zidl/src/battery_srv_stub.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 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 "battery_srv_stub.h" +#include "message_parcel.h" +#include "power_common.h" +#include "battery_srv_proxy.h" + +namespace OHOS { +namespace PowerMgr { +int BatterySrvStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + POWER_HILOGD(MODULE_BATT_SERVICE, "BatterySrvStub::OnRemoteRequest, cmd = %d, flags = %d", code, option.GetFlags()); + std::u16string descriptor = BatterySrvStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + POWER_HILOGE(MODULE_SERVICE, "BatterySrvStub::OnRemoteRequest failed, descriptor is not matched!"); + return E_GET_POWER_SERVICE_FAILED; + } + + switch (code) { + case static_cast(IBatterySrv::BATT_GET_CAPACITY): { + return GetCapacityStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_CHARGING_STATUS): { + return GetChargingStatusStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_HEALTH_STATUS): { + return GetHealthStatusStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_PLUG_TYPE): { + return GetPluggedTypeStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_VOLTAGE): { + return GetVoltageStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_PRESENT): { + return GetPresentStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_TEMPERATURE): { + return GetBatteryTemperatureStub(reply); + } + case static_cast(IBatterySrv::BATT_GET_TECHNOLOGY): { + return GetTechnologyStub(reply); + } + default: { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } +} + +int32_t BatterySrvStub::GetCapacityStub(MessageParcel &reply) +{ + int32_t ret = GetCapacity(); + WRITE_PARCEL_WITH_RET(reply, Int32, ret, E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetChargingStatusStub(MessageParcel &reply) +{ + BatteryChargeState ret = GetChargingStatus(); + WRITE_PARCEL_WITH_RET(reply, Uint32, static_cast(ret), E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetHealthStatusStub(MessageParcel &reply) +{ + BatteryHealthState ret = GetHealthStatus(); + WRITE_PARCEL_WITH_RET(reply, Uint32, static_cast(ret), E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetPluggedTypeStub(MessageParcel &reply) +{ + BatteryPluggedType ret = GetPluggedType(); + WRITE_PARCEL_WITH_RET(reply, Uint32, static_cast(ret), E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetVoltageStub(MessageParcel &reply) +{ + int32_t ret = GetVoltage(); + WRITE_PARCEL_WITH_RET(reply, Int32, ret, E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetPresentStub(MessageParcel &reply) +{ + bool ret = GetPresent(); + WRITE_PARCEL_WITH_RET(reply, Bool, ret, E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetTechnologyStub(MessageParcel &reply) +{ + std::string ret = GetTechnology(); + WRITE_PARCEL_WITH_RET(reply, String, ret, E_WRITE_PARCEL_ERROR); + return ERR_OK; +} + +int32_t BatterySrvStub::GetBatteryTemperatureStub(MessageParcel &reply) +{ + int32_t ret = GetBatteryTemperature(); + WRITE_PARCEL_WITH_RET(reply, Int32, ret, E_WRITE_PARCEL_ERROR); + return ERR_OK; +} +} // namespace PowerMgr +} // namespace OHOS diff --git a/utils/BUILD.gn b/utils/BUILD.gn new file mode 100644 index 0000000..7990a8e --- /dev/null +++ b/utils/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2021 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("//base/powermgr/battery_manager/batterymgr.gni") + +config("utils_config") { + include_dirs = [ + "native/include", + "//utils/native/base/include", + ] +} diff --git a/utils/native/include/hilog_wrapper.h b/utils/native/include/hilog_wrapper.h new file mode 100644 index 0000000..25795a7 --- /dev/null +++ b/utils/native/include/hilog_wrapper.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021 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 HILOG_WRAPPER_H +#define HILOG_WRAPPER_H + +#define CONFIG_HILOG +#ifdef CONFIG_HILOG +#include "hilog/log.h" +namespace OHOS { +namespace PowerMgr { +#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) +#define __FORMATED(fmt, ...) "[%{public}s] %{public}s# " fmt, __FILENAME__, __FUNCTION__, ##__VA_ARGS__ + +#ifdef POWER_HILOGF +#undef POWER_HILOGF +#endif + +#ifdef POWER_HILOGE +#undef POWER_HILOGE +#endif + +#ifdef POWER_HILOGW +#undef POWER_HILOGW +#endif + +#ifdef POWER_HILOGI +#undef POWER_HILOGI +#endif + +#ifdef POWER_HILOGD +#undef POWER_HILOGD +#endif + +// param of log interface, such as POWER_HILOGF. +enum PowerMgrSubModule { + MODULE_INNERKIT = 0, + MODULE_SERVICE, + MODULE_JAVAKIT, // java kit used, define to avoid repeat used domain + MODULE_JNI, + MODULE_BATT_INNERKIT, // below used by battery service + MODULE_BATT_SERVICE, + MODULE_BATTERYD, + MODULE_COMMON, // used both by battery and powermgr + MODULE_JS_NAPI, + POWERMGR_MODULE_BUTT, +}; + +// 0xD002900: subsystem:PowerMgr module:PowerMgr, reserved 8 bit. +static constexpr unsigned int BASE_POWERMGR_DOMAIN_ID = 0xD002900; + +enum PowerMgrDomainId { + POWERMGR_INNERKIT_DOMAIN = BASE_POWERMGR_DOMAIN_ID + MODULE_INNERKIT, + POWERMGR_SERVICE_DOMAIN, + POWERMGR_JAVAKIT_DOMAIN, // 0xD002902 + BATT_INNERKIT_DOMAIN, + BATT_SERVICE_DOMAIN, + BATTERYD_DOMAIN, + COMMON_DOMAIN, + POWERMGR_JS_NAPI, + POWERMGR_BUTT, +}; + +static constexpr OHOS::HiviewDFX::HiLogLabel POWER_MGR_LABEL[POWERMGR_MODULE_BUTT] = { + {LOG_CORE, POWERMGR_INNERKIT_DOMAIN, "PowerMgrClient"}, + {LOG_CORE, POWERMGR_SERVICE_DOMAIN, "PowerMgrService"}, + {LOG_CORE, POWERMGR_JAVAKIT_DOMAIN, "PowerMgrJavaService"}, + {LOG_CORE, POWERMGR_INNERKIT_DOMAIN, "PowerMgrJni"}, + {LOG_CORE, BATT_INNERKIT_DOMAIN, "BatterySrvClient"}, + {LOG_CORE, BATT_SERVICE_DOMAIN, "BatteryService"}, + {LOG_CORE, BATTERYD_DOMAIN, "Batteryd"}, + {LOG_CORE, COMMON_DOMAIN, "PowerMgrCommon"}, + {LOG_CORE, POWERMGR_JS_NAPI, "PowerMgrJSNAPI"}, +}; + +// In order to improve performance, do not check the module range, module should less than POWERMGR_MODULE_BUTT. +#define POWER_HILOGF(module, ...) (void)OHOS::HiviewDFX::HiLog::Fatal(POWER_MGR_LABEL[module], __FORMATED(__VA_ARGS__)) +#define POWER_HILOGE(module, ...) (void)OHOS::HiviewDFX::HiLog::Error(POWER_MGR_LABEL[module], __FORMATED(__VA_ARGS__)) +#define POWER_HILOGW(module, ...) (void)OHOS::HiviewDFX::HiLog::Warn(POWER_MGR_LABEL[module], __FORMATED(__VA_ARGS__)) +#define POWER_HILOGI(module, ...) (void)OHOS::HiviewDFX::HiLog::Info(POWER_MGR_LABEL[module], __FORMATED(__VA_ARGS__)) +#define POWER_HILOGD(module, ...) (void)OHOS::HiviewDFX::HiLog::Debug(POWER_MGR_LABEL[module], __FORMATED(__VA_ARGS__)) + +} // namespace PowerMgr +} // namespace OHOS + +#else + +#define POWER_HILOGF(...) +#define POWER_HILOGE(...) +#define POWER_HILOGW(...) +#define POWER_HILOGI(...) +#define POWER_HILOGD(...) + +#endif // CONFIG_HILOG + +#endif // HILOG_WRAPPER_H diff --git a/utils/native/include/power_common.h b/utils/native/include/power_common.h new file mode 100644 index 0000000..78599ce --- /dev/null +++ b/utils/native/include/power_common.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 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 POWER_COMMON_H +#define POWER_COMMON_H + +#include +#include + +#include "hilog_wrapper.h" +#include "power_mgr_errors.h" + +namespace OHOS { +namespace PowerMgr { +#define RETURN_IF_WITH_RET(cond, retval) if (cond) {return (retval);} +#define RETURN_IF(cond) if (cond) {return;} +#define RETURN_IF_WITH_LOG(cond, loginfo) \ + do { \ + if (cond) { \ + POWER_HILOGE(MODULE_COMMON, "%{public}s "#loginfo" ", __func__); \ + return; \ + } \ + } while (0) \ + +#define READ_PARCEL_NO_RET(parcel, type, out) \ + do { \ + if (!(parcel).Read##type(out)) { \ + POWER_HILOGE(MODULE_COMMON, "%{public}s read "#out" failed", __func__); \ + return; \ + } \ + } while (0) \ + +#define WRITE_PARCEL_NO_RET(parcel, type, data) \ + do { \ + if (!(parcel).Write##type(data)) { \ + POWER_HILOGE(MODULE_COMMON, "%{public}s write "#data" failed", __func__); \ + return; \ + } \ + } while (0) \ + +#define READ_PARCEL_WITH_RET(parcel, type, out, retval) \ + do { \ + if (!(parcel).Read##type(out)) { \ + POWER_HILOGE(MODULE_COMMON, "%{public}s read "#out" failed", __func__); \ + return (retval); \ + } \ + } while (0) \ + +#define WRITE_PARCEL_WITH_RET(parcel, type, data, retval) \ + do { \ + if (!(parcel).Write##type(data)) { \ + POWER_HILOGE(MODULE_COMMON, "%{public}s write "#data" failed", __func__); \ + return (retval); \ + } \ + } while (0) + +template +constexpr auto ToUnderlying(E e) noexcept +{ + return static_cast>(e); +} +} // namespace PowerMgr +} // namespace OHOS + +#endif // POWER_COMMON_H diff --git a/utils/native/include/power_mgr_errors.h b/utils/native/include/power_mgr_errors.h new file mode 100644 index 0000000..b2d67c0 --- /dev/null +++ b/utils/native/include/power_mgr_errors.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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 POWER_MGR_ERRORS_H +#define POWER_MGR_ERRORS_H + +#include + +namespace OHOS { +namespace PowerMgr { +enum { + /** + * Module type: Power Manager Service + */ + POWER_MODULE_TYPE_SERVICE = 0, + /** + * Module type: Power Manager Kit + */ + POWER_MODULE_TYPE_KIT = 1 +}; + +// offset of powermgr error, only be used in this file. +constexpr ErrCode POWERFWK_SERVICE_ERR_OFFSET = ErrCodeOffset(SUBSYS_POWERMNG, POWER_MODULE_TYPE_SERVICE); + +enum { + E_WRITE_PARCEL_ERROR = POWERFWK_SERVICE_ERR_OFFSET, + E_READ_PARCEL_ERROR, + E_GET_SYSTEM_ABILITY_MANAGER_FAILED, + E_GET_POWER_SERVICE_FAILED, + E_ADD_DEATH_RECIPIENT_FAILED, + E_INNER_ERR +}; +} // namespace PowerMgr +} // namespace OHOS + +#endif // POWER_MGR_ERRORS_H \ No newline at end of file diff --git a/utils/native/include/sp_singleton.h b/utils/native/include/sp_singleton.h new file mode 100644 index 0000000..56811de --- /dev/null +++ b/utils/native/include/sp_singleton.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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 SP_SINGLETON_H +#define SP_SINGLETON_H + +#include "nocopyable.h" +#include +#include +#include + +namespace OHOS { +namespace PowerMgr { +#define DECLARE_DELAYED_SP_SINGLETON(MyClass) \ +public: \ + ~MyClass(); \ +private: \ + friend DelayedSpSingleton; \ + MyClass(); + +template +class DelayedSpSingleton : public NoCopyable { +public: + static sptr GetInstance(); + static void DestroyInstance(); + +private: + static sptr instance_; + static std::mutex mutex_; +}; + +template +sptr DelayedSpSingleton::instance_ = nullptr; + +template +std::mutex DelayedSpSingleton::mutex_; + +template +sptr DelayedSpSingleton::GetInstance() +{ + if (!instance_) { + std::lock_guard lock(mutex_); + if (instance_ == nullptr) { + instance_ = new T(); + } + } + + return instance_; +} + +template +void DelayedSpSingleton::DestroyInstance() +{ + std::lock_guard lock(mutex_); + if (instance_) { + instance_.clear(); + instance_ = nullptr; + } +} +} // namespace PowerMgr +} // namespace OHOS +#endif // SP_SINGLETON_H