Android学习14--charger
1 概述
最近正好在做关机充电这个,就详细看看吧。还是本着保密的原则,项目里的代码也不能直接用,这里就用的Github的。https://github.com/aosp-mirror
具体位置是:https://github.com/aosp-mirror/platform_system_core/tree/main/healthd
核心代码压缩包只有3M,比起AOSP整包的极度臃肿真是对比强烈。
2 代码框架
首先还是看BP,编译的产物是charger,但是在新版AOSP中服务却不是这个名字。新的是android.hardware.health-service.qti,此外后面带一个--charger的参数。
cc_binary {name: "charger",defaults: ["charger_defaults"],recovery_available: true,srcs: ["charger.cpp","charger_utils.cpp",],shared_libs: ["android.hardware.health@2.0","android.hardware.health@2.1",],target: {recovery: {// No UI and libsuspend for recovery charger.cflags: ["-DCHARGER_FORCE_NO_UI=1",],exclude_shared_libs: ["libpng",],exclude_static_libs: ["libhealthd_draw","libhealthd_charger","libhealthd_charger_ui","libminui","libsuspend",],}}
}
模块里面有个测试程序,可以看看整个模块的用法。
int main(int /*argc*/, char** /*argv*/) {const char* dumpFile = "/data/local/tmp/dump.txt";auto config = std::make_unique<healthd_config>();InitHealthdConfig(config.get());healthd_board_init(config.get());sp<IHealth> passthrough = new TestHealth(std::move(config));std::thread bgThread([=] {android::ChargerHidl charger(passthrough);charger.StartLoop();});// wait for healthd_init to finishif (!getUpdateNotifier().waitFor(1000 /* wait ms */, true /* updated */)) {LOG_THIS("Time out.");exit(1);}passthrough->debug(createHidlHandle(dumpFile), {} /* options */);std::string content = openToString(dumpFile);int status = expectContains(content, {"status: 4","health: 6","present: 1","level: 47","voltage: 45","temp: 987","current now: 99000","current avg: 98000","charge counter: 600","current now: 99","cycle count: 77","Full charge: 3515547"});if (status == 0) {LOG_THIS("Test success.");} else {LOG_THIS("Actual dump:\n%s", content.c_str());}exit(status); // force bgThread to exit
}
可以看到,就是
android::ChargerHidl charger(passthrough);
charger.StartLoop();
在Android的HIDL(HAL Interface Definition Language)框架中,
StartLoop
是一个用于启动HIDL服务端线程循环的方法。它允许HIDL服务端在一个独立的线程中运行,以便可以接收和处理来自客户端的请求。具体来说,StartLoop
方法会创建一个线程池,并在这个线程池中运行,使得服务端可以异步处理多个客户端请求
3 重点流程
整个其实是一个提供Hidl接口的服务。提供的接口如下:
AIDL implementation | HIDL implementation |
---|---|
Health::getChargeCounterUah | Health::getChargeCounter |
Health::getCurrentNowMicroamps | Health::getCurrentNow |
Health::getCurrentAverageMicroamps | Health::getCurrentAverage |
Health::getCapacity | Health::getCapacity |
Health::getChargeStatus | Health::getChargeStatus |
Health::getEnergyCounterNwh | Health::getEnergyCounter |
Health::getDiskStats | Health::getDiskStats |
Health::getStorageInfo | Health::getStorageInfo |
Health::BinderEvent | BinderHealth::BinderEvent |
Health::dump | Health::debug |
Health::ShouldKeepScreenOn | Health::shouldKeepScreenOn |
Health::UpdateHealthInfo | Health::UpdateHealthInfo |
类的定义如下:
namespace android {// An implementation of Charger backed by HIDL implementation. Uses HIDL health
// HAL's HalHealthLoop.
class ChargerHidl : public ::android::ChargerConfigurationInterface,public ::android::hardware::health::V2_1::implementation::HalHealthLoop {using HalHealthLoop = ::android::hardware::health::V2_1::implementation::HalHealthLoop;using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;public:explicit ChargerHidl(const sp<android::hardware::health::V2_1::IHealth>& service);std::optional<bool> ChargerShouldKeepScreenOn() override;bool ChargerIsOnline() override { return HalHealthLoop::charger_online(); }void ChargerInitConfig(healthd_config* config) override { return HalHealthLoop::Init(config); }int ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) override {return HalHealthLoop::RegisterEvent(fd, func, wakeup);}bool ChargerEnableSuspend() override;// HealthLoop overridesvoid Heartbeat() override { charger_->OnHeartbeat(); }int PrepareToWait() override { return charger_->OnPrepareToWait(); }void Init(struct healthd_config* config) override { charger_->OnInit(config); }// HalHealthLoop overridesvoid OnHealthInfoChanged(const HealthInfo_2_1& health_info) override;private:sp<android::hardware::health::V2_1::IHealth> service_;std::unique_ptr<Charger> charger_;
};
这里面有个私有变量是std::unique_ptr<Charger> charger_;,在init的时候会同时初始化charger类。ChargerHidl类很多实现还是直接调用的Charger类方法。主要的定义还是在Charger类中。
这部分主要的功能也是在Charger::OnInit里面启动的。这里有一个epoll。之前写过这部分,可以参考:小试epoll-CSDN博客
不过charger好像不是epoll,里面有一个Charger::OnHeartbeat(),在每次的心跳中处理状态和事件。包括插拔充电器和按下电源键。
大概就是这些吧,只是粗略的过了一遍,看的也不是太仔细。。。
4 题外话
对了, 从代码中可以看出,对于C++的高级应用还是很熟的。这点挺厉害的。
template <typename T>
class Atomic {public:Atomic(T&& init) : mValue(std::move(init)) {}void set(T&& newVal) {{std::lock_guard<std::mutex> lock(mMutex);mValue = std::move(newVal);}mChanged.notify_all();}bool waitFor(long ms, const T& expectVal) {std::unique_lock<std::mutex> lock(mMutex);return mChanged.wait_for(lock, std::chrono::milliseconds(ms),[this, &expectVal] { return mValue == expectVal; });}private:std::mutex mMutex;std::condition_variable mChanged;T mValue;
};Atomic<bool>& getUpdateNotifier() {static Atomic<bool> val(false);return val;
}
5 参考
https://source.android.com/docs/core/perf/health?hl=zh-cn
相关文章:

Android学习14--charger
1 概述 最近正好在做关机充电这个,就详细看看吧。还是本着保密的原则,项目里的代码也不能直接用,这里就用的Github的。https://github.com/aosp-mirror 具体位置是:https://github.com/aosp-mirror/platform_system_core/tree/mai…...
页面开发样式和布局入门:Vite + Vue 3 + Less
页面开发样式和布局入门:Vite Vue 3 Less 引言 在现代前端开发中,样式和布局是页面开发的核心部分。随着技术的不断发展,Vite、Vue 3和Less等工具和框架的出现,使得前端开发变得更加高效和灵活。然而,尽管这些工具…...

瑞芯微RK3566/RK3568开发板安卓11固件ROOT教程,Purple Pi OH演示
本文介绍RK3566/RK3568开发板Android11系统,编译ROOT权限固件的方法。触觉智能Purple Pi OH鸿蒙开发板演示,搭载了瑞芯微RK3566四核处理器,Laval鸿蒙社区推荐开发板,已适配全新OpenHarmony5.0 Release系统,SDK源码全开…...
Netty 入门应用:结合 Redis 实现服务器通信
在上篇博客中,我们了解了 Netty 的基本概念和架构。本篇文章将带你深入实践,构建一个简单的 Netty 服务端,并结合 Redis 实现一个数据存取的示例。在这个场景中,Redis 作为缓存存储,Netty 作为服务端处理客户端请求。通…...

试题转excel;pdf转excel;试卷转Excel,word试题转excel
一、问题描述 一名教师朋友,偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运,几百道题几乎需要一个下午的时间 关键这些事,枯燥无聊费眼睛,实在是看起来就很蠢的工作 就想着做一个工具,可以自动处理…...

查看网卡设备Bus号
在Linux系统中,通过ip命令能够看到网卡设备的名称,那么怎么看这个网卡设备对应的硬件设备以及Bus号? 例如在下面的虚拟机中能够看到有一个网口名为enp1s0 如何查看这个设备对应的Bus编号,可以在/sys中找到对应的设备 ll /sys/cl…...

鸿蒙Next星河版高级用例之网络请求和自适应布局以及响应式布局
目录: 1、发起网络请求的两种方式第一种使用httpRequest发送http的请求:1.1、在进行网络请求前,您需要在module.json5文件中申明网络访问权限1.2、GET 请求1.3、POST请求1.4、处理响应的结果第二种使用axios发送http的请求:1.1、在…...
鸿蒙技术分享:敲鸿蒙木鱼,积____功德——鸿蒙元服务开发:从入门到放弃(3)...
本文是系列文章,其他文章见:敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发:从入门到放弃(1)敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发&am…...

Hadoop生态圈框架部署 伪集群版(六)- MySQL安装配置
文章目录 前言一、MySQL安装与配置1. 安装MySQL2. 安装MySQL服务器3. 启动MySQL服务并设置开机自启动4. 修改MySQL初始密码登录5. 设置允许MySQL远程登录6. 登录MySQL 卸载1. 停止MySQL服务2. 卸载MySQL软件包3. 删除MySQL配置文件及数据目录 前言 在本文中,我们将…...

【Docker】创建Docker并部署Web站点
要在服务器上创建Docker容器,并在其中部署站点,你可以按照以下步骤操作。我们将以Flask应用为例来说明如何完成这一过程。 1. 准备工作 确保你的服务器已经安装了Docker。如果没有,请根据官方文档安装: Docker 安装指南 2. 创…...

实验七 用 MATLAB 设计 FIR 数字滤波器
实验目的 加深对窗函数法设计 FIR 数字滤波器的基本原理的理解。 学习用 Matlab 语言的窗函数法编写设计 FIR 数字滤波器的程序。 了解 Matlab 语言有关窗函数法设计 FIR 数字滤波器的常用函数用法。 掌握 FIR 滤波器的快速卷积实现原理。 不同滤波器的设计方法具有不同的优…...

学习ESP32开发板安装鸿蒙操作系统(新板子esp32c3不支持)
鸿蒙LiteOS网址:LiteOS: Huawei LiteOS开源代码官方主仓库.LiteOS Studio 开发工具请访问https://gitee.com/LiteOS/LiteOS_Studio 失败的实践记录见:完全按照手册win10里装Ubuntu 虚拟机然后编译ESP32(主要是想针对ESP32C3和S3)…...

asp.net core过滤器应用
筛选器类型 授权筛选器 授权过滤器是过滤器管道的第一个被执行的过滤器,用于系统授权。一般不会编写自定义的授权过滤器,而是配置授权策略或编写自定义授权策略。简单举个例子。 using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCo…...
力扣面试题 31 - 特定深度节点链表 C语言解法
题目: 给定一棵二叉树,设计一个算法,创建含有某一深度上所有节点的链表(比如,若一棵树的深度为 D,则会创建出 D 个链表)。返回一个包含所有深度的链表的数组。 示例: 输入…...
WordPress阅读文章显示太慢的处理
有两种方式, 1. 完全静态化。 动态都变成html,不再查数据库就快了。 但尝试了几个插件,都未成功。算了后面再研究。 2. cache缓存 用了WP Super Cache测试了一下,打开过一次后,文章秒开,也算达到了要求…...
关于多个线程共享一个实例对象
在多线程环境中,多个线程可能同时调用同一个对象的实例方法,这时候需要考虑如何保证线程安全。理解不同场景下的线程安全性是至关重要的,特别是当方法涉及共享状态时。 1. 共享实例与方法执行 共享实例:多个线程共享同一个实例对…...

【C++】printf 函数详解与格式化输出控制
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯printf 基础用法1.1 printf 的常见占位符1.2 占位符与参数的对应关系1.3 换行控制示例: 💯格式化输出控制2.1 输出宽度控制2.1.1 指定最小宽度 2.2 …...
HDFS 操作命令
在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在 集群上的文件系统称为 分布式文件系统 。 HDFS ( Hadoop Distributed File System )是 Apache Hadoop 项目的一个子项目, Hadoo…...
html ul li 首页渲染多条数据 但只展示八条,其余的数据全部隐藏,通过icon图标 进行展示
<div style"float: left;" id"showMore"> 展开 </div> <div style"float: left;“id"hideLess"> 收起 </div> var data document.querySelectorAll(.allbox .item h3 a); const list document.querySelectorAl…...

Facebook:筑牢隐私安全堡垒,守护社交净土
在全球社交媒体平台中,Facebook一直是风靡全球的佼佼者。然而,随着数字化信息的迅速膨胀,用户隐私保护的重要性日益凸显。面对用户对数据安全性的高度重视,Facebook致力于通过一系列措施来确保隐私保护,守护每位用户的…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...