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 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 implementationHIDL implementation
Health::getChargeCounterUahHealth::getChargeCounter
Health::getCurrentNowMicroampsHealth::getCurrentNow
Health::getCurrentAverageMicroampsHealth::getCurrentAverage
Health::getCapacityHealth::getCapacity
Health::getChargeStatusHealth::getChargeStatus
Health::getEnergyCounterNwhHealth::getEnergyCounter
Health::getDiskStatsHealth::getDiskStats
Health::getStorageInfoHealth::getStorageInfo
Health::BinderEventBinderHealth::BinderEvent
Health::dumpHealth::debug
Health::ShouldKeepScreenOnHealth::shouldKeepScreenOn
Health::UpdateHealthInfoHealth::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;
}

5 参考

https://source.android.com/docs/core/perf/health?hl=zh-cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值