Merge changes from topic "charger-aidl"

* changes:
  charger: Add API to replace ro.charger.enable_suspend
  charger: separate UI and HAL access.
This commit is contained in:
Yifan Hong 2021-11-02 17:58:30 +00:00 committed by Gerrit Code Review
commit 9cef8ea99a
8 changed files with 278 additions and 108 deletions

View file

@ -120,21 +120,22 @@ cc_library_static {
}
cc_library_static {
name: "libhealthd_charger",
local_include_dirs: ["include"],
export_include_dirs: [".", "include"],
name: "libhealthd_charger_ui",
export_include_dirs: [
"include",
"include_charger",
],
static_libs: [
"android.hardware.health@1.0-convert",
"android.hardware.health-V1-ndk",
"android.hardware.health-translate-ndk",
"libcharger_sysprop",
"libhealthd_draw",
"libhealthloop",
"libhealth2impl",
"libminui",
],
shared_libs: [
"android.hardware.health@2.1",
"libbase",
"libcutils",
"liblog",
@ -143,14 +144,52 @@ cc_library_static {
"libutils",
],
header_libs: [
"libhealthd_headers",
],
export_static_lib_headers: [
"android.hardware.health-V1-ndk",
],
srcs: [
"healthd_mode_charger.cpp",
"AnimationParser.cpp",
],
}
cc_library_static {
name: "libhealthd_charger",
export_include_dirs: [
"include",
"include_charger",
],
static_libs: [
"android.hardware.health@1.0-convert",
"libcharger_sysprop",
"libhealth2impl",
"libhealthd_charger_ui",
],
shared_libs: [
"android.hardware.health@2.1",
"libbase",
"libcutils",
"liblog",
"libutils",
],
srcs: [
"healthd_mode_charger_hidl.cpp",
],
}
cc_defaults {
name: "charger_defaults",
local_include_dirs: [
"include_charger",
],
cflags: [
"-Wall",
@ -174,6 +213,7 @@ cc_defaults {
static_libs: [
// common
"android.hardware.health@1.0-convert",
"android.hardware.health-V1-ndk",
"libbatterymonitor",
"libcharger_sysprop",
"libhealthd_charger_nops",
@ -183,6 +223,7 @@ cc_defaults {
// system charger only
"libhealthd_draw",
"libhealthd_charger",
"libhealthd_charger_ui",
"libminui",
"libsuspend",
],
@ -209,6 +250,7 @@ cc_binary {
exclude_static_libs: [
"libhealthd_draw",
"libhealthd_charger",
"libhealthd_charger_ui",
"libminui",
"libsuspend",
],

View file

@ -15,9 +15,9 @@
*/
#include <android-base/logging.h>
#include <charger.sysprop.h>
#include "charger.sysprop.h"
#include "healthd_mode_charger.h"
#include "healthd_mode_charger_hidl.h"
#include "healthd_mode_charger_nops.h"
#ifndef CHARGER_FORCE_NO_UI

View file

@ -31,7 +31,7 @@
#include <health/utils.h>
#include <health2impl/Health.h>
#include "healthd_mode_charger.h"
#include "healthd_mode_charger_hidl.h"
using android::hardware::health::InitHealthdConfig;
using android::hardware::health::V2_1::HealthInfo;
@ -153,7 +153,7 @@ int main(int /*argc*/, char** /*argv*/) {
sp<IHealth> passthrough = new TestHealth(std::move(config));
std::thread bgThread([=] {
android::Charger charger(passthrough);
android::ChargerHidl charger(passthrough);
charger.StartLoop();
});

View file

@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "healthd_mode_charger.h"
#include <charger/healthd_mode_charger.h>
#include <dirent.h>
#include <errno.h>
@ -51,26 +51,16 @@
#include "AnimationParser.h"
#include "charger.sysprop.h"
#include "charger_utils.h"
#include "healthd_draw.h"
#include <android/hardware/health/2.0/IHealthInfoCallback.h>
#include <health/utils.h>
#include <health2impl/HalHealthLoop.h>
#include <health2impl/Health.h>
#include <aidl/android/hardware/health/BatteryStatus.h>
#include <health/HealthLoop.h>
#include <healthd/healthd.h>
using std::string_literals::operator""s;
using namespace android;
using android::hardware::Return;
using android::hardware::health::GetHealthServiceOrDefault;
using aidl::android::hardware::health::BatteryStatus;
using android::hardware::health::HealthLoop;
using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V2_0::Result;
using android::hardware::health::V2_1::IHealth;
using IHealth_2_0 = android::hardware::health::V2_0::IHealth;
using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
// main healthd loop
extern int healthd_main(void);
@ -199,8 +189,8 @@ void Charger::InitDefaultAnimationFrames() {
};
}
Charger::Charger(const sp<IHealth>& service)
: HalHealthLoop("charger", service), batt_anim_(BASE_ANIMATION) {}
Charger::Charger(ChargerConfigurationInterface* configuration)
: batt_anim_(BASE_ANIMATION), configuration_(configuration) {}
Charger::~Charger() {}
@ -264,15 +254,18 @@ out:
LOGW("************* END LAST KMSG *************\n");
}
static int request_suspend(bool enable) {
if (!android::sysprop::ChargerProperties::enable_suspend().value_or(false)) {
int Charger::RequestEnableSuspend() {
if (!configuration_->ChargerEnableSuspend()) {
return 0;
}
return autosuspend_enable();
}
if (enable)
return autosuspend_enable();
else
return autosuspend_disable();
int Charger::RequestDisableSuspend() {
if (!configuration_->ChargerEnableSuspend()) {
return 0;
}
return autosuspend_disable();
}
static void kick_animation(animation* anim) {
@ -291,7 +284,7 @@ void Charger::UpdateScreenState(int64_t now) {
if (!batt_anim_.run || now < next_screen_transition_) return;
// If battery level is not ready, keep checking in the defined time
if (health_info_.batteryLevel == 0 && health_info_.batteryStatus == BatteryStatus::UNKNOWN) {
if (health_info_.battery_level == 0 && health_info_.battery_status == BatteryStatus::UNKNOWN) {
if (wait_batt_level_timestamp_ == 0) {
// Set max delay time and skip drawing screen
wait_batt_level_timestamp_ = now + MAX_BATT_LEVEL_WAIT_TIME;
@ -305,18 +298,15 @@ void Charger::UpdateScreenState(int64_t now) {
}
if (healthd_draw_ == nullptr) {
std::optional<bool> out_screen_on;
service()->shouldKeepScreenOn([&](Result res, bool screen_on) {
if (res == Result::SUCCESS) {
*out_screen_on = screen_on;
}
});
std::optional<bool> out_screen_on = configuration_->ChargerShouldKeepScreenOn();
if (out_screen_on.has_value()) {
if (!*out_screen_on) {
LOGV("[%" PRId64 "] leave screen off\n", now);
batt_anim_.run = false;
next_screen_transition_ = -1;
if (charger_online()) request_suspend(true);
if (configuration_->ChargerIsOnline()) {
RequestEnableSuspend();
}
return;
}
}
@ -337,7 +327,9 @@ void Charger::UpdateScreenState(int64_t now) {
healthd_draw_->blank_screen(true);
screen_blanked_ = true;
LOGV("[%" PRId64 "] animation done\n", now);
if (charger_online()) request_suspend(true);
if (configuration_->ChargerIsOnline()) {
RequestEnableSuspend();
}
return;
}
@ -351,9 +343,9 @@ void Charger::UpdateScreenState(int64_t now) {
/* animation starting, set up the animation */
if (batt_anim_.cur_frame == 0) {
LOGV("[%" PRId64 "] animation starting\n", now);
batt_anim_.cur_level = health_info_.batteryLevel;
batt_anim_.cur_status = (int)health_info_.batteryStatus;
if (health_info_.batteryLevel >= 0 && batt_anim_.num_frames != 0) {
batt_anim_.cur_level = health_info_.battery_level;
batt_anim_.cur_status = (int)health_info_.battery_status;
if (health_info_.battery_level >= 0 && batt_anim_.num_frames != 0) {
/* find first frame given current battery level */
for (int i = 0; i < batt_anim_.num_frames; i++) {
if (batt_anim_.cur_level >= batt_anim_.frames[i].min_level &&
@ -363,7 +355,7 @@ void Charger::UpdateScreenState(int64_t now) {
}
}
if (charger_online()) {
if (configuration_->ChargerIsOnline()) {
// repeat the first frame first_frame_repeats times
disp_time = batt_anim_.frames[batt_anim_.cur_frame].disp_time *
batt_anim_.first_frame_repeats;
@ -394,7 +386,7 @@ void Charger::UpdateScreenState(int64_t now) {
/* advance frame cntr to the next valid frame only if we are charging
* if necessary, advance cycle cntr, and reset frame cntr
*/
if (charger_online()) {
if (configuration_->ChargerIsOnline()) {
batt_anim_.cur_frame++;
while (batt_anim_.cur_frame < batt_anim_.num_frames &&
@ -492,13 +484,13 @@ void Charger::ProcessKey(int code, int64_t now) {
* rather than on key release
*/
kick_animation(&batt_anim_);
request_suspend(false);
RequestDisableSuspend();
}
} else {
/* if the power key got released, force screen state cycle */
if (key->pending) {
kick_animation(&batt_anim_);
request_suspend(false);
RequestDisableSuspend();
}
}
}
@ -516,8 +508,8 @@ void Charger::HandlePowerSupplyState(int64_t now) {
int timer_shutdown = UNPLUGGED_SHUTDOWN_TIME;
if (!have_battery_state_) return;
if (!charger_online()) {
request_suspend(false);
if (!configuration_->ChargerIsOnline()) {
RequestDisableSuspend();
if (next_pwr_check_ == -1) {
/* Last cycle would have stopped at the extreme top of battery-icon
* Need to show the correct level corresponding to capacity.
@ -547,7 +539,7 @@ void Charger::HandlePowerSupplyState(int64_t now) {
* Reset & kick animation to show complete animation cycles
* when charger connected again.
*/
request_suspend(false);
RequestDisableSuspend();
next_screen_transition_ = now - 1;
reset_animation(&batt_anim_);
kick_animation(&batt_anim_);
@ -557,7 +549,7 @@ void Charger::HandlePowerSupplyState(int64_t now) {
}
}
void Charger::Heartbeat() {
void Charger::OnHeartbeat() {
// charger* charger = &charger_state;
int64_t now = curr_time_ms();
@ -570,22 +562,18 @@ void Charger::Heartbeat() {
UpdateScreenState(now);
}
void Charger::OnHealthInfoChanged(const HealthInfo_2_1& health_info) {
set_charger_online(health_info);
void Charger::OnHealthInfoChanged(const ChargerHealthInfo& health_info) {
if (!have_battery_state_) {
have_battery_state_ = true;
next_screen_transition_ = curr_time_ms() - 1;
request_suspend(false);
RequestDisableSuspend();
reset_animation(&batt_anim_);
kick_animation(&batt_anim_);
}
health_info_ = health_info.legacy.legacy;
AdjustWakealarmPeriods(charger_online());
health_info_ = health_info;
}
int Charger::PrepareToWait(void) {
int Charger::OnPrepareToWait(void) {
int64_t now = curr_time_ms();
int64_t next_event = INT64_MAX;
int64_t timeout;
@ -672,7 +660,7 @@ void Charger::InitAnimation() {
}
}
void Charger::Init(struct healthd_config* config) {
void Charger::OnInit(struct healthd_config* config) {
int ret;
int i;
int epollfd;
@ -685,7 +673,7 @@ void Charger::Init(struct healthd_config* config) {
std::bind(&Charger::InputCallback, this, std::placeholders::_1, std::placeholders::_2));
if (!ret) {
epollfd = ev_get_epollfd();
RegisterEvent(epollfd, &charger_event_handler, EVENT_WAKEUP_FD);
configuration_->ChargerRegisterEvent(epollfd, &charger_event_handler, EVENT_WAKEUP_FD);
}
InitAnimation();
@ -730,7 +718,7 @@ void Charger::Init(struct healthd_config* config) {
wait_batt_level_timestamp_ = 0;
// Retrieve healthd_config from the existing health HAL.
HalHealthLoop::Init(config);
configuration_->ChargerInitConfig(config);
boot_min_cap_ = config->boot_min_cap;
}
@ -773,25 +761,3 @@ void animation::set_resource_root(const std::string& root, const std::string& ba
}
} // namespace android
int healthd_charger_main(int argc, char** argv) {
int ch;
while ((ch = getopt(argc, argv, "cr")) != -1) {
switch (ch) {
case 'c':
// -c is now a noop
break;
case 'r':
// -r is now a noop
break;
case '?':
default:
LOGE("Unrecognized charger option: %c\n", optopt);
exit(1);
}
}
Charger charger(GetHealthServiceOrDefault());
return charger.StartLoop();
}

View file

@ -0,0 +1,81 @@
/*
* 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 "healthd_mode_charger_hidl.h"
#include <android/hardware/health/2.0/types.h>
#include <charger.sysprop.h>
#include <cutils/klog.h>
#include "charger_utils.h"
using android::hardware::health::GetHealthServiceOrDefault;
using android::hardware::health::V2_0::Result;
namespace android {
ChargerHidl::ChargerHidl(const sp<android::hardware::health::V2_1::IHealth>& service)
: HalHealthLoop("charger", service), charger_(std::make_unique<Charger>(this)) {}
void ChargerHidl::OnHealthInfoChanged(const HealthInfo_2_1& health_info) {
set_charger_online(health_info);
charger_->OnHealthInfoChanged(ChargerHealthInfo{
.battery_level = health_info.legacy.legacy.batteryLevel,
.battery_status = static_cast<::aidl::android::hardware::health::BatteryStatus>(
health_info.legacy.legacy.batteryStatus),
});
AdjustWakealarmPeriods(charger_online());
}
std::optional<bool> ChargerHidl::ChargerShouldKeepScreenOn() {
std::optional<bool> out_screen_on;
service()->shouldKeepScreenOn([&](Result res, bool screen_on) {
if (res == Result::SUCCESS) {
*out_screen_on = screen_on;
}
});
return out_screen_on;
}
bool ChargerHidl::ChargerEnableSuspend() {
return android::sysprop::ChargerProperties::enable_suspend().value_or(false);
}
} // namespace android
int healthd_charger_main(int argc, char** argv) {
int ch;
while ((ch = getopt(argc, argv, "cr")) != -1) {
switch (ch) {
case 'c':
// -c is now a noop
break;
case 'r':
// -r is now a noop
break;
case '?':
default:
KLOG_ERROR("charger", "Unrecognized charger option: %c\n", optopt);
exit(1);
}
}
android::ChargerHidl charger(GetHealthServiceOrDefault());
return charger.StartLoop();
}

View file

@ -0,0 +1,55 @@
/*
* 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.
*/
#pragma once
#include <health2impl/HalHealthLoop.h>
#include <charger/healthd_mode_charger.h>
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_;
};
} // namespace android
int healthd_charger_main(int argc, char** argv);

View file

@ -23,11 +23,12 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/health/2.1/IHealth.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <health/utils.h>
#include "healthd_mode_charger.h"
#include "healthd_mode_charger_hidl.h"
using android::hardware::Return;
using android::hardware::health::InitHealthdConfig;
@ -102,12 +103,12 @@ class MockHealth : public android::hardware::health::V2_1::IHealth {
MOCK_METHOD(Return<void>, shouldKeepScreenOn, (shouldKeepScreenOn_cb _hidl_cb));
};
class TestCharger : public Charger {
class TestCharger : public ChargerHidl {
public:
// Inherit constructor.
using Charger::Charger;
using ChargerHidl::ChargerHidl;
// Expose protected functions to be used in tests.
void Init(struct healthd_config* config) override { Charger::Init(config); }
void Init(struct healthd_config* config) override { ChargerHidl::Init(config); }
MOCK_METHOD(int, CreateDisplaySurface, (const std::string& name, GRSurface** surface));
MOCK_METHOD(int, CreateMultiDisplaySurface,
(const std::string& name, int* frames, int* fps, GRSurface*** surface));

View file

@ -19,11 +19,12 @@
#include <linux/input.h>
#include <memory>
#include <optional>
#include <vector>
#include <android/hardware/health/2.0/IHealthInfoCallback.h>
#include <android/hardware/health/2.1/IHealth.h>
#include <health2impl/HalHealthLoop.h>
#include <aidl/android/hardware/health/BatteryStatus.h>
#include <health/HealthLoop.h>
#include <healthd/healthd.h>
#include "animation.h"
@ -37,22 +38,44 @@ struct key_state {
int64_t timestamp;
};
class Charger : public ::android::hardware::health::V2_1::implementation::HalHealthLoop {
public:
using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
// Health info that interests charger
struct ChargerHealthInfo {
int32_t battery_level;
aidl::android::hardware::health::BatteryStatus battery_status;
};
Charger(const sp<android::hardware::health::V2_1::IHealth>& service);
~Charger();
// Configuration interface for charger. This includes:
// - HalHealthLoop APIs that interests charger.
// - configuration values that used to be provided by sysprops
class ChargerConfigurationInterface {
public:
virtual ~ChargerConfigurationInterface() = default;
// HalHealthLoop related APIs
virtual std::optional<bool> ChargerShouldKeepScreenOn() = 0;
virtual bool ChargerIsOnline() = 0;
virtual void ChargerInitConfig(healthd_config* config) = 0;
using BoundFunction =
std::function<void(android::hardware::health::HealthLoop*, uint32_t /* epevents */)>;
virtual int ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) = 0;
// Other configuration values
virtual bool ChargerEnableSuspend() = 0;
};
// charger UI
class Charger {
public:
explicit Charger(ChargerConfigurationInterface* configuration);
virtual ~Charger();
// Hooks for ChargerConfigurationInterface
void OnHeartbeat();
int OnPrepareToWait();
// |cookie| is passed to ChargerConfigurationInterface::ChargerInitConfig
void OnInit(struct healthd_config* config);
void OnHealthInfoChanged(const ChargerHealthInfo& health_info);
protected:
// HealthLoop overrides.
void Heartbeat() override;
int PrepareToWait() override;
void Init(struct healthd_config* config) override;
// HalHealthLoop overrides
void OnHealthInfoChanged(const HealthInfo_2_1& health_info) override;
// Allowed to be mocked for testing.
virtual int CreateDisplaySurface(const std::string& name, GRSurface** surface);
virtual int CreateMultiDisplaySurface(const std::string& name, int* frames, int* fps,
@ -69,6 +92,8 @@ class Charger : public ::android::hardware::health::V2_1::implementation::HalHea
void HandlePowerSupplyState(int64_t now);
int InputCallback(int fd, unsigned int epevents);
void InitAnimation();
int RequestEnableSuspend();
int RequestDisableSuspend();
bool have_battery_state_ = false;
bool screen_blanked_ = false;
@ -83,10 +108,10 @@ class Charger : public ::android::hardware::health::V2_1::implementation::HalHea
GRSurface* surf_unknown_ = nullptr;
int boot_min_cap_ = 0;
HealthInfo_1_0 health_info_ = {};
ChargerHealthInfo health_info_ = {};
std::unique_ptr<HealthdDraw> healthd_draw_;
std::vector<animation::frame> owned_frames_;
ChargerConfigurationInterface* configuration_;
};
} // namespace android
int healthd_charger_main(int argc, char** argv);