diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp index 1c455d30ae..3c5877e1da 100644 --- a/health/2.0/default/Android.bp +++ b/health/2.0/default/Android.bp @@ -31,7 +31,11 @@ cc_library_static { vendor_available: true, srcs: [ "Health.cpp", - "healthd_common.cpp", + "healthd_common_adapter.cpp", + ], + + whole_static_libs: [ + "libhealthloop", ], export_include_dirs: ["include"], diff --git a/health/2.0/default/healthd_common.cpp b/health/2.0/default/healthd_common.cpp deleted file mode 100644 index b5fdc8ecb8..0000000000 --- a/health/2.0/default/healthd_common.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#define LOG_TAG "android.hardware.health@2.0-impl" -#define KLOG_LEVEL 6 - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace android; - -// Periodic chores fast interval in seconds -#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) -// Periodic chores fast interval in seconds -#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) - -static struct healthd_config healthd_config = { - .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST, - .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW, - .batteryStatusPath = String8(String8::kEmptyString), - .batteryHealthPath = String8(String8::kEmptyString), - .batteryPresentPath = String8(String8::kEmptyString), - .batteryCapacityPath = String8(String8::kEmptyString), - .batteryVoltagePath = String8(String8::kEmptyString), - .batteryTemperaturePath = String8(String8::kEmptyString), - .batteryTechnologyPath = String8(String8::kEmptyString), - .batteryCurrentNowPath = String8(String8::kEmptyString), - .batteryCurrentAvgPath = String8(String8::kEmptyString), - .batteryChargeCounterPath = String8(String8::kEmptyString), - .batteryFullChargePath = String8(String8::kEmptyString), - .batteryCycleCountPath = String8(String8::kEmptyString), - .energyCounter = NULL, - .boot_min_cap = 0, - .screen_on = NULL, -}; - -static int eventct; -static int epollfd; - -#define POWER_SUPPLY_SUBSYSTEM "power_supply" - -static int uevent_fd; -static int wakealarm_fd; - -// -1 for no epoll timeout -static int awake_poll_interval = -1; - -static int wakealarm_wake_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST; - -using ::android::hardware::health::V2_0::implementation::Health; - -struct healthd_mode_ops* healthd_mode_ops = nullptr; - -int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) { - struct epoll_event ev; - - ev.events = EPOLLIN; - - if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP; - - ev.data.ptr = (void*)handler; - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) { - KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno); - return -1; - } - - eventct++; - return 0; -} - -static void wakealarm_set_interval(int interval) { - struct itimerspec itval; - - if (wakealarm_fd == -1) return; - - wakealarm_wake_interval = interval; - - if (interval == -1) interval = 0; - - itval.it_interval.tv_sec = interval; - itval.it_interval.tv_nsec = 0; - itval.it_value.tv_sec = interval; - itval.it_value.tv_nsec = 0; - - if (timerfd_settime(wakealarm_fd, 0, &itval, NULL) == -1) - KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n"); -} - -void healthd_battery_update_internal(bool charger_online) { - // Fast wake interval when on charger (watch for overheat); - // slow wake interval when on battery (watch for drained battery). - - int new_wake_interval = charger_online ? healthd_config.periodic_chores_interval_fast - : healthd_config.periodic_chores_interval_slow; - - if (new_wake_interval != wakealarm_wake_interval) wakealarm_set_interval(new_wake_interval); - - // During awake periods poll at fast rate. If wake alarm is set at fast - // rate then just use the alarm; if wake alarm is set at slow rate then - // poll at fast rate while awake and let alarm wake up at slow rate when - // asleep. - - if (healthd_config.periodic_chores_interval_fast == -1) - awake_poll_interval = -1; - else - awake_poll_interval = new_wake_interval == healthd_config.periodic_chores_interval_fast - ? -1 - : healthd_config.periodic_chores_interval_fast * 1000; -} - -static void healthd_battery_update(void) { - Health::getImplementation()->update(); -} - -static void periodic_chores() { - healthd_battery_update(); -} - -#define UEVENT_MSG_LEN 2048 -static void uevent_event(uint32_t /*epevents*/) { - char msg[UEVENT_MSG_LEN + 2]; - char* cp; - int n; - - n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN); - if (n <= 0) return; - if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ - return; - - msg[n] = '\0'; - msg[n + 1] = '\0'; - cp = msg; - - while (*cp) { - if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) { - healthd_battery_update(); - break; - } - - /* advance to after the next \0 */ - while (*cp++) - ; - } -} - -static void uevent_init(void) { - uevent_fd = uevent_open_socket(64 * 1024, true); - - if (uevent_fd < 0) { - KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n"); - return; - } - - fcntl(uevent_fd, F_SETFL, O_NONBLOCK); - if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD)) - KLOG_ERROR(LOG_TAG, "register for uevent events failed\n"); -} - -static void wakealarm_event(uint32_t /*epevents*/) { - unsigned long long wakeups; - - if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) { - KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n"); - return; - } - - periodic_chores(); -} - -static void wakealarm_init(void) { - wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK); - if (wakealarm_fd == -1) { - KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n"); - return; - } - - if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD)) - KLOG_ERROR(LOG_TAG, "Registration of wakealarm event failed\n"); - - wakealarm_set_interval(healthd_config.periodic_chores_interval_fast); -} - -static void healthd_mainloop(void) { - int nevents = 0; - while (1) { - struct epoll_event events[eventct]; - int timeout = awake_poll_interval; - int mode_timeout; - - /* Don't wait for first timer timeout to run periodic chores */ - if (!nevents) periodic_chores(); - - healthd_mode_ops->heartbeat(); - - mode_timeout = healthd_mode_ops->preparetowait(); - if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout; - nevents = epoll_wait(epollfd, events, eventct, timeout); - if (nevents == -1) { - if (errno == EINTR) continue; - KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n"); - break; - } - - for (int n = 0; n < nevents; ++n) { - if (events[n].data.ptr) (*(void (*)(int))events[n].data.ptr)(events[n].events); - } - } - - return; -} - -static int healthd_init() { - epollfd = epoll_create1(EPOLL_CLOEXEC); - if (epollfd == -1) { - KLOG_ERROR(LOG_TAG, "epoll_create1 failed; errno=%d\n", errno); - return -1; - } - - healthd_mode_ops->init(&healthd_config); - wakealarm_init(); - uevent_init(); - - return 0; -} - -int healthd_main() { - int ret; - - klog_set_level(KLOG_LEVEL); - - if (!healthd_mode_ops) { - KLOG_ERROR("healthd ops not set, exiting\n"); - exit(1); - } - - ret = healthd_init(); - if (ret) { - KLOG_ERROR("Initialization failed, exiting\n"); - exit(2); - } - - healthd_mainloop(); - KLOG_ERROR("Main loop terminated, exiting\n"); - return 3; -} diff --git a/health/2.0/default/healthd_common_adapter.cpp b/health/2.0/default/healthd_common_adapter.cpp new file mode 100644 index 0000000000..8fc689d50c --- /dev/null +++ b/health/2.0/default/healthd_common_adapter.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 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. + */ + +// Support legacy functions in healthd/healthd.h using healthd_mode_ops. +// New code should use HealthLoop directly instead. + +#include + +#include +#include +#include +#include + +using android::hardware::health::HealthLoop; +using android::hardware::health::V2_0::implementation::Health; + +struct healthd_mode_ops* healthd_mode_ops = nullptr; + +// Adapter of HealthLoop to use legacy healthd_mode_ops. +class HealthLoopAdapter : public HealthLoop { + public: + // Expose internal functions, assuming clients calls them in the same thread + // where StartLoop is called. + int RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) { + return HealthLoop::RegisterEvent(fd, func, wakeup); + } + void AdjustWakealarmPeriods(bool charger_online) { + return HealthLoop::AdjustWakealarmPeriods(charger_online); + } + protected: + void Init(healthd_config* config) override { healthd_mode_ops->init(config); } + void Heartbeat() override { healthd_mode_ops->heartbeat(); } + int PrepareToWait() override { return healthd_mode_ops->preparetowait(); } + void ScheduleBatteryUpdate() override { Health::getImplementation()->update(); } +}; +static std::unique_ptr health_loop; + +int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) { + auto wrapped_handler = [handler](auto*, uint32_t epevents) { handler(epevents); }; + return health_loop->RegisterEvent(fd, wrapped_handler, wakeup); +} + +void healthd_battery_update_internal(bool charger_online) { + health_loop->AdjustWakealarmPeriods(charger_online); +} + +int healthd_main() { + if (!healthd_mode_ops) { + KLOG_ERROR("healthd ops not set, exiting\n"); + exit(1); + } + + health_loop = std::make_unique(); + + int ret = health_loop->StartLoop(); + + // Should not reach here. The following will exit(). + health_loop.reset(); + + return ret; +} diff --git a/health/utils/libhealthloop/Android.bp b/health/utils/libhealthloop/Android.bp new file mode 100644 index 0000000000..de0f24fcbb --- /dev/null +++ b/health/utils/libhealthloop/Android.bp @@ -0,0 +1,35 @@ +// Copyright (C) 2019 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. + +cc_library_static { + name: "libhealthloop", + vendor_available: true, + recovery_available: true, + srcs: [ + "HealthLoop.cpp", + "utils.cpp", + ], + shared_libs: [ + "libcutils", + "libbase", + ], + header_libs: [ + "libbatteryservice_headers", + "libhealthd_headers", + "libutils_headers", + ], + export_include_dirs: [ + "include", + ], +} diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp new file mode 100644 index 0000000000..3f4b5bc596 --- /dev/null +++ b/health/utils/libhealthloop/HealthLoop.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2013 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. + */ + +#define LOG_TAG "HealthLoop" +#define KLOG_LEVEL 6 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace android; +using namespace std::chrono_literals; + +#define POWER_SUPPLY_SUBSYSTEM "power_supply" + +namespace android { +namespace hardware { +namespace health { + +HealthLoop::HealthLoop() { + InitHealthdConfig(&healthd_config_); + awake_poll_interval_ = -1; + wakealarm_wake_interval_ = healthd_config_.periodic_chores_interval_fast; +} + +HealthLoop::~HealthLoop() { + LOG(FATAL) << "HealthLoop cannot be destroyed"; +} + +int HealthLoop::RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) { + CHECK(!reject_event_register_); + + auto* event_handler = + event_handlers_ + .emplace_back(std::make_unique(EventHandler{this, fd, func})) + .get(); + + struct epoll_event ev; + + ev.events = EPOLLIN; + + if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP; + + ev.data.ptr = reinterpret_cast(event_handler); + + if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev) == -1) { + KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno); + return -1; + } + + return 0; +} + +void HealthLoop::WakeAlarmSetInterval(int interval) { + struct itimerspec itval; + + if (wakealarm_fd_ == -1) return; + + wakealarm_wake_interval_ = interval; + + if (interval == -1) interval = 0; + + itval.it_interval.tv_sec = interval; + itval.it_interval.tv_nsec = 0; + itval.it_value.tv_sec = interval; + itval.it_value.tv_nsec = 0; + + if (timerfd_settime(wakealarm_fd_, 0, &itval, NULL) == -1) + KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n"); +} + +void HealthLoop::AdjustWakealarmPeriods(bool charger_online) { + // Fast wake interval when on charger (watch for overheat); + // slow wake interval when on battery (watch for drained battery). + + int new_wake_interval = charger_online ? healthd_config_.periodic_chores_interval_fast + : healthd_config_.periodic_chores_interval_slow; + + if (new_wake_interval != wakealarm_wake_interval_) WakeAlarmSetInterval(new_wake_interval); + + // During awake periods poll at fast rate. If wake alarm is set at fast + // rate then just use the alarm; if wake alarm is set at slow rate then + // poll at fast rate while awake and let alarm wake up at slow rate when + // asleep. + + if (healthd_config_.periodic_chores_interval_fast == -1) + awake_poll_interval_ = -1; + else + awake_poll_interval_ = new_wake_interval == healthd_config_.periodic_chores_interval_fast + ? -1 + : healthd_config_.periodic_chores_interval_fast * 1000; +} + +void HealthLoop::PeriodicChores() { + ScheduleBatteryUpdate(); +} + +// TODO(b/140330870): Use BPF instead. +#define UEVENT_MSG_LEN 2048 +void HealthLoop::UeventEvent(uint32_t /*epevents*/) { + // No need to lock because uevent_fd_ is guaranteed to be initialized. + + char msg[UEVENT_MSG_LEN + 2]; + char* cp; + int n; + + n = uevent_kernel_multicast_recv(uevent_fd_, msg, UEVENT_MSG_LEN); + if (n <= 0) return; + if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ + return; + + msg[n] = '\0'; + msg[n + 1] = '\0'; + cp = msg; + + while (*cp) { + if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) { + ScheduleBatteryUpdate(); + break; + } + + /* advance to after the next \0 */ + while (*cp++) + ; + } +} + +void HealthLoop::UeventInit(void) { + uevent_fd_.reset(uevent_open_socket(64 * 1024, true)); + + if (uevent_fd_ < 0) { + KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n"); + return; + } + + fcntl(uevent_fd_, F_SETFL, O_NONBLOCK); + if (RegisterEvent(uevent_fd_, &HealthLoop::UeventEvent, EVENT_WAKEUP_FD)) + KLOG_ERROR(LOG_TAG, "register for uevent events failed\n"); +} + +void HealthLoop::WakeAlarmEvent(uint32_t /*epevents*/) { + // No need to lock because wakealarm_fd_ is guaranteed to be initialized. + + unsigned long long wakeups; + + if (read(wakealarm_fd_, &wakeups, sizeof(wakeups)) == -1) { + KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n"); + return; + } + + PeriodicChores(); +} + +void HealthLoop::WakeAlarmInit(void) { + wakealarm_fd_.reset(timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK)); + if (wakealarm_fd_ == -1) { + KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n"); + return; + } + + if (RegisterEvent(wakealarm_fd_, &HealthLoop::WakeAlarmEvent, EVENT_WAKEUP_FD)) + KLOG_ERROR(LOG_TAG, "Registration of wakealarm event failed\n"); + + WakeAlarmSetInterval(healthd_config_.periodic_chores_interval_fast); +} + +void HealthLoop::MainLoop(void) { + int nevents = 0; + while (1) { + reject_event_register_ = true; + size_t eventct = event_handlers_.size(); + struct epoll_event events[eventct]; + int timeout = awake_poll_interval_; + + int mode_timeout; + + /* Don't wait for first timer timeout to run periodic chores */ + if (!nevents) PeriodicChores(); + + Heartbeat(); + + mode_timeout = PrepareToWait(); + if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout; + nevents = epoll_wait(epollfd_, events, eventct, timeout); + if (nevents == -1) { + if (errno == EINTR) continue; + KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n"); + break; + } + + for (int n = 0; n < nevents; ++n) { + if (events[n].data.ptr) { + auto* event_handler = reinterpret_cast(events[n].data.ptr); + event_handler->func(event_handler->object, events[n].events); + } + } + } + + return; +} + +int HealthLoop::InitInternal() { + epollfd_.reset(epoll_create1(EPOLL_CLOEXEC)); + if (epollfd_ == -1) { + KLOG_ERROR(LOG_TAG, "epoll_create1 failed; errno=%d\n", errno); + return -1; + } + + // Call subclass's init for any additional init steps. + // Note that healthd_config_ is initialized before wakealarm_fd_; see + // AdjustUeventWakealarmPeriods(). + Init(&healthd_config_); + + WakeAlarmInit(); + UeventInit(); + + return 0; +} + +int HealthLoop::StartLoop() { + int ret; + + klog_set_level(KLOG_LEVEL); + + ret = InitInternal(); + if (ret) { + KLOG_ERROR(LOG_TAG, "Initialization failed, exiting\n"); + return 2; + } + + MainLoop(); + KLOG_ERROR(LOG_TAG, "Main loop terminated, exiting\n"); + return 3; +} + +} // namespace health +} // namespace hardware +} // namespace android diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h new file mode 100644 index 0000000000..693e6cbb9a --- /dev/null +++ b/health/utils/libhealthloop/include/health/HealthLoop.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019 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 +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace health { + +class HealthLoop { + public: + HealthLoop(); + + // Client is responsible for holding this forever. Process will exit + // when this is destroyed. + virtual ~HealthLoop(); + + // Initialize and start the main loop. This function does not exit unless + // the process is interrupted. + // Once the loop is started, event handlers are no longer allowed to be + // registered. + int StartLoop(); + + protected: + // healthd_mode_ops overrides. Note that healthd_mode_ops->battery_update + // is missing because it is only used by BatteryMonitor. + // Init is called right after epollfd_ is initialized (so RegisterEvent + // is allowed) but before other things are initialized (so SetChargerOnline + // is not allowed.) + virtual void Init(healthd_config* config) = 0; + virtual void Heartbeat() = 0; + virtual int PrepareToWait() = 0; + + // Note that this is NOT healthd_mode_ops->battery_update(BatteryProperties*), + // which is called by BatteryMonitor after values are fetched. This is the + // implementation of healthd_battery_update(), which calls + // the correct IHealth::update(), + // which calls BatteryMonitor::update(), which calls + // healthd_mode_ops->battery_update(BatteryProperties*). + virtual void ScheduleBatteryUpdate() = 0; + + // Register an epoll event. When there is an event, |func| will be + // called with |this| as the first argument and |epevents| as the second. + // This may be called in a different thread from where StartLoop is called + // (for obvious reasons; StartLoop never ends). + // Once the loop is started, event handlers are no longer allowed to be + // registered. + using BoundFunction = std::function; + int RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup); + + // Helper for implementing ScheduleBatteryUpdate(). An implementation of + // ScheduleBatteryUpdate should get charger_online from BatteryMonitor::update(), + // then reset wake alarm interval by calling AdjustWakealarmPeriods. + void AdjustWakealarmPeriods(bool charger_online); + + private: + struct EventHandler { + HealthLoop* object = nullptr; + int fd; + BoundFunction func; + }; + + int InitInternal(); + void MainLoop(); + void WakeAlarmInit(); + void WakeAlarmEvent(uint32_t); + void UeventInit(); + void UeventEvent(uint32_t); + void WakeAlarmSetInterval(int interval); + void PeriodicChores(); + + // These are fixed after InitInternal() is called. + struct healthd_config healthd_config_; + android::base::unique_fd wakealarm_fd_; + android::base::unique_fd uevent_fd_; + + android::base::unique_fd epollfd_; + std::vector> event_handlers_; + int awake_poll_interval_; // -1 for no epoll timeout + int wakealarm_wake_interval_; + + // If set to true, future RegisterEvent() will be rejected. This is to ensure all + // events are registered before StartLoop(). + bool reject_event_register_ = false; +}; + +} // namespace health +} // namespace hardware +} // namespace android diff --git a/health/utils/libhealthloop/include/health/utils.h b/health/utils/libhealthloop/include/health/utils.h new file mode 100644 index 0000000000..e46771c7e1 --- /dev/null +++ b/health/utils/libhealthloop/include/health/utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 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 + +namespace android { +namespace hardware { +namespace health { + +void InitHealthdConfig(struct healthd_config* healthd_config); + +} // namespace health +} // namespace hardware +} // namespace android diff --git a/health/utils/libhealthloop/utils.cpp b/health/utils/libhealthloop/utils.cpp new file mode 100644 index 0000000000..b0d153f583 --- /dev/null +++ b/health/utils/libhealthloop/utils.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 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 +namespace android { +namespace hardware { +namespace health { + +// Periodic chores fast interval in seconds +#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) +// Periodic chores fast interval in seconds +#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) + +void InitHealthdConfig(struct healthd_config* healthd_config) { + *healthd_config = { + .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST, + .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW, + .batteryStatusPath = String8(String8::kEmptyString), + .batteryHealthPath = String8(String8::kEmptyString), + .batteryPresentPath = String8(String8::kEmptyString), + .batteryCapacityPath = String8(String8::kEmptyString), + .batteryVoltagePath = String8(String8::kEmptyString), + .batteryTemperaturePath = String8(String8::kEmptyString), + .batteryTechnologyPath = String8(String8::kEmptyString), + .batteryCurrentNowPath = String8(String8::kEmptyString), + .batteryCurrentAvgPath = String8(String8::kEmptyString), + .batteryChargeCounterPath = String8(String8::kEmptyString), + .batteryFullChargePath = String8(String8::kEmptyString), + .batteryCycleCountPath = String8(String8::kEmptyString), + .energyCounter = NULL, + .boot_min_cap = 0, + .screen_on = NULL, + }; +} + +} // namespace health +} // namespace hardware +} // namespace android