Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 701ff4a1 authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge "health: handle charger in health HAL"

parents 9af94c62 a8f55cac
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -45,6 +45,52 @@ cc_defaults {
    ],
}

// Dependency to libhealthd_charger_ui. No UI in recovery.
cc_defaults {
    name: "libhealth_aidl_charger_defaults",
    shared_libs: [
        // common
        "android.hardware.health-V1-ndk",
        "libbase",
        "libcutils",
        "liblog",
        "libutils",

        // charger UI only
        "libpng",
    ],

    static_libs: [
        // common
        "libbatterymonitor",
        "libhealthloop",

        // charger UI only
        "libhealthd_draw",
        "libhealthd_charger_ui",
        "libminui",
        "libsuspend",
    ],

    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_ui",
                "libminui",
                "libsuspend",
            ],
        },
    },
}

// AIDL version of libhealth2impl.
// A helper library for health HAL implementation.
// HAL implementations can link to this library and extend the Health class.
@@ -52,12 +98,14 @@ cc_library_static {
    name: "libhealth_aidl_impl",
    defaults: [
        "libhealth_aidl_common_defaults",
        "libhealth_aidl_charger_defaults",
    ],
    export_include_dirs: ["include"],
    export_static_lib_headers: [
        "libbatterymonitor",
    ],
    srcs: [
        "ChargerUtils.cpp",
        "health-convert.cpp",
        "HalHealthLoop.cpp",
        "Health.cpp",
@@ -67,6 +115,13 @@ cc_library_static {
        ":__subpackages__",
        "//hardware/interfaces/tests/extension/health:__subpackages__",
    ],
    target: {
        recovery: {
            exclude_srcs: [
                "ChargerUtils.cpp",
            ],
        },
    },
}

// AIDL version of android.hardware.health@2.1-service.
@@ -78,9 +133,13 @@ cc_binary {
    vintf_fragments: ["android.hardware.health-service.example.xml"],
    defaults: [
        "libhealth_aidl_common_defaults",
        "libhealth_aidl_charger_defaults",
    ],
    static_libs: [
        "libhealth_aidl_impl",
    ],
    srcs: ["main.cpp"],
    overrides: [
        "charger",
    ],
}
+109 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <android-base/logging.h>
#include <health-impl/ChargerUtils.h>

namespace aidl::android::hardware::health::charger {

std::optional<bool> ChargerCallback::ChargerShouldKeepScreenOn() {
    return service_->ShouldKeepScreenOn();
}

bool ChargerCallback::ChargerIsOnline() {
    auto hal_health_loop_sp = hal_health_loop_.lock();
    if (hal_health_loop_sp == nullptr) {
        // Assume no charger
        return false;
    }
    return hal_health_loop_sp->charger_online();
}

void ChargerCallback::ChargerInitConfig(healthd_config* config) {
    auto hal_health_loop_sp = hal_health_loop_.lock();
    if (hal_health_loop_sp == nullptr) {
        return;
    }
    return service_->OnInit(hal_health_loop_sp.get(), config);
}

int ChargerCallback::ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) {
    auto hal_health_loop_sp = hal_health_loop_.lock();
    if (hal_health_loop_sp == nullptr) {
        return -1;
    }
    return hal_health_loop_sp->RegisterEvent(fd, func, wakeup);
}

void ChargerCallback::set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop) {
    hal_health_loop_ = std::move(hal_health_loop);
}

// Implements HalHealthLoopCallback for AIDL charger
// Adapter of (Charger, Health) ->  HalHealthLoopCallback
class LoopCallback : public HalHealthLoopCallback {
  public:
    LoopCallback(const std::shared_ptr<Health>& service, ChargerCallback* charger_callback)
        : service_(service), charger_(std::make_unique<::android::Charger>(charger_callback)) {}

    void OnHeartbeat() override {
        service_->OnHeartbeat();
        charger_->OnHeartbeat();
    }
    // Return the minimum timeout. Negative values are treated as no values.
    int OnPrepareToWait() override {
        int timeout1 = service_->OnPrepareToWait();
        int timeout2 = charger_->OnPrepareToWait();

        if (timeout1 < 0) return timeout2;
        if (timeout2 < 0) return timeout1;
        return std::min(timeout1, timeout2);
    }

    void OnInit(HalHealthLoop*, struct healthd_config* config) override {
        // Charger::OnInit calls ChargerInitConfig, which calls into the real Health::OnInit.
        charger_->OnInit(config);
    }

    void OnHealthInfoChanged(const HealthInfo& health_info) override {
        charger_->OnHealthInfoChanged(::android::ChargerHealthInfo{
                .battery_level = health_info.batteryLevel,
                .battery_status = health_info.batteryStatus,
        });
        service_->OnHealthInfoChanged(health_info);
    }

  private:
    std::shared_ptr<Health> service_;
    std::unique_ptr<::android::Charger> charger_;
};

int ChargerModeMain(const std::shared_ptr<Health>& binder,
                    const std::shared_ptr<ChargerCallback>& charger_callback) {
    LOG(INFO) << "Starting charger mode.";
    //   parent stack ==========================================
    //   current stack                                         ||
    //    ||                                                   ||
    //    V                                                    V
    // hal_health_loop => loop_callback => charger --(raw)--> charger_callback
    //    ^----------------(weak)---------------------------------'
    auto loop_callback = std::make_shared<LoopCallback>(binder, charger_callback.get());
    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, std::move(loop_callback));
    charger_callback->set_hal_health_loop(hal_health_loop);
    return hal_health_loop->StartLoop();
}

}  // namespace aidl::android::hardware::health::charger
+10 −0
Original line number Diff line number Diff line
@@ -4,3 +4,13 @@ service vendor.health-default /vendor/bin/hw/android.hardware.health-service.exa
    group system
    capabilities WAKE_ALARM BLOCK_SUSPEND
    file /dev/kmsg w

service vendor.charger-default /vendor/bin/hw/android.hardware.health-service.example --charger
    class charger
    user system
    group system wakelock input
    capabilities SYS_BOOT
    file /dev/kmsg w
    file /sys/fs/pstore/console-ramoops-0 r
    file /sys/fs/pstore/console-ramoops r
    file /proc/last_kmsg r
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <optional>
#include <type_traits>

#include <android/binder_auto_utils.h>
#include <charger/healthd_mode_charger.h>
#include <health-impl/Health.h>

#pragma once

namespace aidl::android::hardware::health::charger {

// Implements ChargerHalHealthLoopInterface for AIDL charger
// Adapter of (Health, HalHealthLoop) -> ChargerHalHealthLoopInterface
class ChargerCallback : public ::android::ChargerConfigurationInterface {
  public:
    ChargerCallback(const std::shared_ptr<Health>& service) : service_(service) {}
    std::optional<bool> ChargerShouldKeepScreenOn() override;
    bool ChargerIsOnline() override;
    void ChargerInitConfig(healthd_config* config) override;
    int ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) override;

    // Override to return true to replace `ro.charger.enable_suspend=true`
    bool ChargerEnableSuspend() override { return false; }

    void set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop);

  private:
    std::shared_ptr<Health> service_;
    std::weak_ptr<HalHealthLoop> hal_health_loop_;
};

int ChargerModeMain(const std::shared_ptr<Health>& binder,
                    const std::shared_ptr<ChargerCallback>& charger_callback);

}  // namespace aidl::android::hardware::health::charger
+31 −2
Original line number Diff line number Diff line
@@ -19,17 +19,46 @@
#include <health-impl/Health.h>
#include <health/utils.h>

#ifndef CHARGER_FORCE_NO_UI
#define CHARGER_FORCE_NO_UI 0
#endif

#if !CHARGER_FORCE_NO_UI
#include <health-impl/ChargerUtils.h>
#endif

using aidl::android::hardware::health::HalHealthLoop;
using aidl::android::hardware::health::Health;

#if !CHARGER_FORCE_NO_UI
using aidl::android::hardware::health::charger::ChargerCallback;
using aidl::android::hardware::health::charger::ChargerModeMain;
#endif

static constexpr const char* gInstanceName = "default";
static constexpr std::string_view gChargerArg{"--charger"};

int main() {
    // TODO(b/203246116): handle charger
int main(int argc, char** argv) {
    // make a default health service
    auto config = std::make_unique<healthd_config>();
    ::android::hardware::health::InitHealthdConfig(config.get());
    auto binder = ndk::SharedRefBase::make<Health>(gInstanceName, std::move(config));

    if (argc >= 2 && argv[1] == gChargerArg) {
        android::base::InitLogging(argv, &android::base::KernelLogger);

#if !CHARGER_FORCE_NO_UI
        // If charger shouldn't have UI for your device, simply drop the line below
        // for your service implementation. This corresponds to
        // ro.charger.no_ui=true
        return ChargerModeMain(binder, std::make_shared<ChargerCallback>(binder));
#endif

        LOG(INFO) << "Starting charger mode without UI.";
    } else {
        LOG(INFO) << "Starting health HAL.";
    }

    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
    return hal_health_loop->StartLoop();
}