Android学习15--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学习15--charger
1 概述 最近正好在做关机充电这个,就详细看看吧。还是本着保密的原则,项目里的代码也不能直接用,这里就用的Github的。https://github.com/aosp-mirror 具体位置是:https://github.com/aosp-mirror/platform_system_core/tree/mai…...
顶会新宠!KAN-LSTM完美融合新方案
2024深度学习发论文&模型涨点之——KANLSTM KAN-LSTM混合预测模型是一种结合了自注意力机制(KAN, Key-attention network)和长短时记忆网络(LSTM)的深度学习模型,主要用于序列数据的预测任务,如时间序…...
JS中对象的浅拷贝,深拷贝和引用
JS中对象的浅拷贝,深拷贝和引用 浅拷贝和深拷贝的区别主要在于它们如何处理引用类型的数据(如数组和对象),而引用简而言之就是换了个变量名。 浅拷贝 引用:浅拷贝只复制对象的第一层属性,对于嵌套的对象或…...
思普企业运营平台 idsCheck Sql注入漏洞复现
0x01 产品描述: 思普企业运营平台是由贵阳思普信息技术有限公司自主研发的国内首款投融建管营云服务平台——...
FSWIND脉动风-风载时程生成器软件下载、安装及注册
1、软件下载 点击文末超链接下载 2、软件安装 以下操作,若被电脑杀毒软件提示风险,请加入白名单,软件无任何病毒和后台,请放心使用! 1)双击Fswind_setup.exe,启动安装程序 2)、点…...
spring通过RequestContextHolder获取HttpServletRequest对象
1.获取HttpServletRequest对象方法: public static HttpServletRequest getRequest() {ServletRequestAttributes attributes ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());assert attributes ! null;return attributes.getRequest(…...
STM32编码器接口及编码器测速模板代码
编码器是什么? 编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感 器,我们可以通过编码器测量到底位移或者速度信息。编码器从输出数据类型上 分,可以分为增量式编码器和绝对式编码器。 从编码器检测原理上来分࿰…...
qt QNetworkAccessManager详解
1、概述 QNetworkAccessManager是QtNetwork模块中的一个核心类,它允许应用程序发送网络请求并接收响应。该类是网络通信的基石,提供了一种方便的方式来处理常见的网络协议,如HTTP、HTTPS等。QNetworkAccessManager对象持有其发送的请求的通用…...
部署 Vue 前端项目到 Linux
看看怎么把一个 Vue 3 项目部署到 Linux 服务器上。准备好你的咖啡,让我们愉快地度过这段部署时光! 前期准备 确保你已经在本地构建了 Vue 3 项目,并生成了 dist 文件夹。 npm run build构建完成后,你将看到一个新鲜出炉的 dis…...
数据分析:探索数据背后的秘密与挑战
在当今这个数据驱动的时代,数据分析已成为各行各业不可或缺的一部分。从市场营销到金融风控,从医疗健康到智能制造,数据分析为企业决策提供了强有力的支持。然而,尽管其重要性日益凸显,数据分析的过程并非一帆风顺&…...
文本域设置高度 加上文字限制并show出来:
文本域设置高度 :rows"4" 加上文字限制并show出来: maxlength"30" show-word-limit 效果: <el-form-item label"产品备注" prop"remark"><el-input v-model"form.remark" type"textarea"…...
深入浅出:Gin框架-简介与API开发入门
深入浅出:Gin框架-简介与API开发入门 引言 Gin框架是基于Go语言的HTTP Web框架,凭借其简单易用、性能卓越和丰富的功能,成为构建高性能Web应用的理想选择。本文将深入浅出地介绍Gin框架的基础知识,并通过一个简单的案例…...
MySQL各种锁详解
什么是锁? 1.1 锁的解释 计算机协调多个进程或线程并发访问某一资源的机制。 1.2 锁的重要性 在数据库中,除传统计算资源(CPU、RAM、I/O等)的争抢,数据也是一种供多用户共享的资源。 如何保证数据并发访问的一致性&…...
海外的bug-hunters,不一样的403bypass
一种绕过403的新技术,跟大家分享一下。研究HTTP协议已经有一段时间了。发现HTTP协议的1.0版本可以绕过403。于是开始对lyncdiscover.microsoft.com域做FUZZ并且发现了几个403Forbidden的文件。 (访问fsip.svc为403) 在经过尝试后࿰…...
React 组件中 State 的定义、使用及正确更新方式
🌈个人主页:前端青山 🔥系列专栏:React篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容React 组件中 State 的定义、使用及正确更新方式 前言 在 React 应用开发中,state …...
Jenkins 的HTTP Request 插件为什么不能配置Basic认证了
本篇遇到的问题 还是因为Jenkins需要及其所在的OS需要升级,升级策略是在一台新服务器上安装和配置最新版本的Jenkins, 当前的最新版本是: 2.479.2 LTS。 如果需要这个版本的话可以在官方站点下载,也可以到如下地址下载࿱…...
8 Bellman Ford算法SPFA
图论 —— 最短路 —— Bellman-Ford 算法与 SPFA_通信网理论基础 分别使用bellman-ford算法和dijkstra算法的应用-CSDN博客 图解Bellman-Ford计算过程以及正确性证明 - 知乎 (zhihu.com) 语雀版本 1 概念 **适用场景:**单源点,可以有负边࿰…...
nginx不允许静态文件被post请求显示405 not allowed
在单独站点的配置文件中 添加error_page 405 200 $request_uri; 即可!...
【c++笔试强训】(第三十二篇)
目录 数组变换(贪⼼位运算) 题目解析 讲解算法原理 编写代码 装箱问题(动态规划-01背包) 题目解析 讲解算法原理 编写代码 数组变换(贪⼼位运算) 题目解析 1.题目链接:数组变换__牛客网…...
shell脚本实战案例
文章目录 实战第一坑功能说明脚本实现 实战第一坑 实战第一坑:在Windows系统写了一个脚本,比如上面,随后上传到服务,执行会报错 原因: 解决方案:在linux系统touch文件,并通过vim添加内容&…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
