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 finish
if (!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 overrides
void Heartbeat() override { charger_->OnHeartbeat(); }
int PrepareToWait() override { return charger_->OnPrepareToWait(); }
void Init(struct healthd_config* config) override { charger_->OnInit(config); }
// HalHealthLoop overrides
void 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;
}
4960

被折叠的 条评论
为什么被折叠?



