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致力于通过一系列措施来确保隐私保护,守护每位用户的…...
迷宫算法避坑指南:为什么你的‘流水算法’跑不出最短路径?(附Python调试技巧)
迷宫算法避坑指南:为什么你的‘流水算法’跑不出最短路径?(附Python调试技巧) 迷宫寻路算法一直是编程学习者和算法爱好者热衷探索的领域。其中,流水算法因其独特的物理模拟思路而备受关注。但在实际实现过程中&#x…...
从提示词到成片:2026年AI视频工作流效率革命——Top 5工具的Prompt工程兼容度、重绘响应延迟与跨平台资产复用率实测
更多请点击: https://intelliparadigm.com 第一章:2026年AI视频生成工具全景图谱与评测方法论 截至2026年,AI视频生成已从实验性原型迈入工业化应用阶段,工具生态呈现“三极分化”格局:消费级轻量工具专注短视频创意提…...
5分钟搞定U盘验货!这款绿色工具真香到离谱
兄弟们,你有没有买过那种“1TB只要39块还包邮”的U盘? 醒醒!那玩意儿大概率是扩容盘——实际容量可能只有64GB,超出部分写进去的数据全是空气,轻则文件损坏,重则项目代码全丢,救都救不回来&…...
一文搞懂工业机器人通讯协议:TCP/IP、Modbus与专用协议对比
在我十年的工控开发生涯中,通讯问题永远是项目延期的第一大原因。我见过太多团队花了几个月时间做运动控制和视觉算法,最后却卡在了机器人通讯上:要么是数据传输不稳定,要么是速度跟不上产线节拍,要么是换个品牌机器人就要全部重写代码。 很多新手工程师觉得通讯就是&quo…...
YOLO26优化:TIP2026 FourierSR | FourierSR引入YOLO C3k2:解决感受野局限,实现高效全局特征交互
💡💡💡现有 YOLO C3k2 模块主要基于卷积与跨阶段部分连接,虽能平衡计算与精度,但仍存在以下问题: 感受野受限:堆叠的小核卷积(如 33)感受野有限,难以捕获全局上下文,对尺度变化大或远距离依赖的目标(如小目标、遮挡目标)特征提取能力不足。 特征混合效率低:通…...
别再只用箱线图了!用R语言ggplot2绘制高颜值小提琴图,让你的SCI图表更专业
科研数据可视化进阶:用R语言打造专业级小提琴图 在生物医学领域的科研论文中,数据可视化是展示研究成果的关键环节。许多研究者习惯性地使用箱线图来呈现数据分布,却忽略了这种传统方法可能掩盖的重要信息细节。当面对复杂的数据分布模式时&…...
3步轻松延长JetBrains IDE评估期:开源工具让你的开发体验永不停歇
3步轻松延长JetBrains IDE评估期:开源工具让你的开发体验永不停歇 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter 还在为JetBrains IDE评估期结束而烦恼吗?作为开发者,我们经常…...
DDR3 颗粒信号定义解析
本文围绕 DDR3 标准信号定义、核心信号工作原理、PCB Layout 等长设计规则及行业常见误区展开,全程聚焦工程实践与底层原理。一、DDR3 标准信号完整清单(x16 位宽基准,x32 位宽对应翻倍)1. 数据信号(Data)表…...
【新手专属】OpenClaw 一键安装包:Windows 完整部署流程(含安装包)
OpenClaw 一键安装包|一键部署,告别复杂环境配置 适配系统:Windows 10/11 64 位当前版本:v2.7.5(虾壳云版)核心优势:全程可视化操作,无需命令行、无需手动配置 Python/Node.js&…...
LabVIEW图形化编程实战:从数据流原理到高效测控系统开发
1. 项目概述与核心价值今天咱们来聊聊LabVIEW这门工具。很多刚接触自动测试、数据采集或者仪器控制的朋友,可能都听说过它的大名,但上手时总觉得它和传统的文本编程语言(比如C、Python)不太一样,有点无从下手。我最早接…...
