From 526f8cf339f6c215d2d89924824b674cb99cfcc9 Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Tue, 1 Nov 2016 16:41:56 -0700 Subject: healthd: refactor healthd code to split into 'charger' and 'healthd' This splits healthd code into 2 pieces as described below. charger - statically linked executable in /sbin - responsible for charger-mode UI - battery/charger monitoring in recovery/charger-mode. healthd - dynamically linked (*mostly*) executable in /system/bin - responsible for battery / charger monitoring in Android - runs 'batteryproperties' service. Both currently use libhealthd STATIC HALs. However, this now paves way for the healthd (android) HAL to be a shared library that can be trebelized. text data bss dec hex filename 733356 15312 33864 782532 bf0c4 root/sbin/charger 55943 10392 192 66527 103df system/bin/healthd 789299 25704 34056 849059 cf4a3 (TOTALS) Test: Tested recovery, charge-only and android boot with new binaries with and without STATIC HAL. Change-Id: I80f94948dda44d466f172d234b3fcc9064ef2476 Signed-off-by: Sandeep Patil --- healthd/Android.mk | 14 +- healthd/charger.cpp | 102 ++++++++++++ healthd/healthd.cpp | 348 +-------------------------------------- healthd/healthd_common.cpp | 304 ++++++++++++++++++++++++++++++++++ healthd/healthd_mode_android.cpp | 3 + 5 files changed, 420 insertions(+), 351 deletions(-) create mode 100644 healthd/charger.cpp create mode 100644 healthd/healthd_common.cpp (limited to 'healthd') diff --git a/healthd/Android.mk b/healthd/Android.mk index 08475f311..5a6303e32 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -88,7 +88,8 @@ LOCAL_CHARGER_NO_UI := true endif LOCAL_SRC_FILES := \ - healthd.cpp + healthd_common.cpp \ + charger.cpp \ LOCAL_MODULE := charger LOCAL_MODULE_TAGS := optional @@ -109,11 +110,8 @@ LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_IN endif LOCAL_STATIC_LIBRARIES := \ - libhealthd_android \ libhealthd_charger \ libbatterymonitor \ - libbatteryservice \ - libbinder \ libbase \ libutils \ libcutils \ @@ -173,7 +171,8 @@ endif # LOCAL_CHARGER_NO_UI include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - healthd.cpp + healthd_common.cpp \ + healthd.cpp \ LOCAL_MODULE := healthd LOCAL_MODULE_TAGS := optional @@ -188,7 +187,6 @@ endif LOCAL_STATIC_LIBRARIES := \ libhealthd_android \ - libhealthd_charger \ libbatterymonitor \ libbatteryservice \ @@ -200,10 +198,6 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libm \ libc \ - libminui \ - libpng \ - libz \ - libsuspend \ LOCAL_HAL_STATIC_LIBRARIES := libhealthd include $(BUILD_EXECUTABLE) diff --git a/healthd/charger.cpp b/healthd/charger.cpp new file mode 100644 index 000000000..5a8fe1a8b --- /dev/null +++ b/healthd/charger.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 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 "charger" +#define KLOG_LEVEL 6 + +#include + +#include +#include +#include + +using namespace android; + +// main healthd loop +extern int healthd_main(void); + +// Charger mode + +extern void healthd_mode_charger_init(struct healthd_config *config); +extern int healthd_mode_charger_preparetowait(void); +extern void healthd_mode_charger_heartbeat(void); +extern void healthd_mode_charger_battery_update( + struct android::BatteryProperties *props); + +// NOPs for modes that need no special action + +static void healthd_mode_nop_init(struct healthd_config *config); +static int healthd_mode_nop_preparetowait(void); +static void healthd_mode_nop_heartbeat(void); +static void healthd_mode_nop_battery_update( + struct android::BatteryProperties *props); + +static struct healthd_mode_ops healthd_nops = { + .init = healthd_mode_nop_init, + .preparetowait = healthd_mode_nop_preparetowait, + .heartbeat = healthd_mode_nop_heartbeat, + .battery_update = healthd_mode_nop_battery_update, +}; + +#ifdef CHARGER_NO_UI +static struct healthd_mode_ops charger_ops = healthd_nops; +#else +static struct healthd_mode_ops charger_ops = { + .init = healthd_mode_charger_init, + .preparetowait = healthd_mode_charger_preparetowait, + .heartbeat = healthd_mode_charger_heartbeat, + .battery_update = healthd_mode_charger_battery_update, +}; +#endif + +static void healthd_mode_nop_init(struct healthd_config* /*config*/) { +} + +static int healthd_mode_nop_preparetowait(void) { + return -1; +} + +static void healthd_mode_nop_heartbeat(void) { +} + +static void healthd_mode_nop_battery_update( + struct android::BatteryProperties* /*props*/) { +} + +int main(int argc, char **argv) { + int ch; + + healthd_mode_ops = &charger_ops; + + while ((ch = getopt(argc, argv, "cr")) != -1) { + switch (ch) { + case 'c': + // -c is now a noop + break; + case 'r': + // force nops for recovery + healthd_mode_ops = &healthd_nops; + break; + case '?': + default: + KLOG_ERROR(LOG_TAG, "Unrecognized charger option: %c\n", + optopt); + exit(1); + } + } + + return healthd_main(); +} diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp index aa6735d71..1ec8c2d8c 100644 --- a/healthd/healthd.cpp +++ b/healthd/healthd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2016 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. @@ -18,369 +18,35 @@ #define KLOG_LEVEL 6 #include -#include -#include -#include #include #include -#include #include -#include #include -#include -#include -#include -#include using namespace android; -#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST - // Periodic chores fast interval in seconds - #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) -#else - #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST) -#endif - -#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW - // Periodic chores fast interval in seconds - #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) -#else - #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW) -#endif - -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" - -// epoll_create() parameter is actually unused -#define MAX_EPOLL_EVENTS 40 -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; - -static BatteryMonitor* gBatteryMonitor; - -struct healthd_mode_ops *healthd_mode_ops; +// main healthd loop +extern int healthd_main(void); // Android mode extern void healthd_mode_android_init(struct healthd_config *config); extern int healthd_mode_android_preparetowait(void); +extern void healthd_mode_android_heartbeat(void); extern void healthd_mode_android_battery_update( struct android::BatteryProperties *props); -// Charger mode - -extern void healthd_mode_charger_init(struct healthd_config *config); -extern int healthd_mode_charger_preparetowait(void); -extern void healthd_mode_charger_heartbeat(void); -extern void healthd_mode_charger_battery_update( - struct android::BatteryProperties *props); - -// NOPs for modes that need no special action - -static void healthd_mode_nop_init(struct healthd_config *config); -static int healthd_mode_nop_preparetowait(void); -static void healthd_mode_nop_heartbeat(void); -static void healthd_mode_nop_battery_update( - struct android::BatteryProperties *props); - static struct healthd_mode_ops android_ops = { .init = healthd_mode_android_init, .preparetowait = healthd_mode_android_preparetowait, - .heartbeat = healthd_mode_nop_heartbeat, + .heartbeat = healthd_mode_android_heartbeat, .battery_update = healthd_mode_android_battery_update, }; -static struct healthd_mode_ops charger_ops = { -#ifdef CHARGER_NO_UI - .init = healthd_mode_nop_init, - .preparetowait = healthd_mode_nop_preparetowait, - .heartbeat = healthd_mode_nop_heartbeat, - .battery_update = healthd_mode_nop_battery_update, -#else - .init = healthd_mode_charger_init, - .preparetowait = healthd_mode_charger_preparetowait, - .heartbeat = healthd_mode_charger_heartbeat, - .battery_update = healthd_mode_charger_battery_update, -#endif -}; - -static struct healthd_mode_ops recovery_ops = { - .init = healthd_mode_nop_init, - .preparetowait = healthd_mode_nop_preparetowait, - .heartbeat = healthd_mode_nop_heartbeat, - .battery_update = healthd_mode_nop_battery_update, -}; - -static void healthd_mode_nop_init(struct healthd_config* /*config*/) { -} - -static int healthd_mode_nop_preparetowait(void) { - return -1; -} - -static void healthd_mode_nop_heartbeat(void) { -} - -static void healthd_mode_nop_battery_update( - struct android::BatteryProperties* /*props*/) { -} - -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"); -} - -status_t healthd_get_property(int id, struct BatteryProperty *val) { - return gBatteryMonitor->getProperty(id, val); -} +int main(int /*argc*/, char ** /*argv*/) { -void healthd_battery_update(void) { - // Fast wake interval when on charger (watch for overheat); - // slow wake interval when on battery (watch for drained battery). - - int new_wake_interval = gBatteryMonitor->update() ? - 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; -} - -void healthd_dump_battery_state(int fd) { - gBatteryMonitor->dumpState(fd); - fsync(fd); -} - -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_create(MAX_EPOLL_EVENTS); - if (epollfd == -1) { - KLOG_ERROR(LOG_TAG, - "epoll_create failed; errno=%d\n", - errno); - return -1; - } - - healthd_board_init(&healthd_config); - healthd_mode_ops->init(&healthd_config); - wakealarm_init(); - uevent_init(); - gBatteryMonitor = new BatteryMonitor(); - gBatteryMonitor->init(&healthd_config); - return 0; -} - -int main(int argc, char **argv) { - int ch; - int ret; - - klog_set_level(KLOG_LEVEL); healthd_mode_ops = &android_ops; - if (!strcmp(basename(argv[0]), "charger")) { - healthd_mode_ops = &charger_ops; - } else { - while ((ch = getopt(argc, argv, "cr")) != -1) { - switch (ch) { - case 'c': - healthd_mode_ops = &charger_ops; - break; - case 'r': - healthd_mode_ops = &recovery_ops; - break; - case '?': - default: - KLOG_ERROR(LOG_TAG, "Unrecognized healthd option: %c\n", - optopt); - 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; + return healthd_main(); } diff --git a/healthd/healthd_common.cpp b/healthd/healthd_common.cpp new file mode 100644 index 000000000..659991918 --- /dev/null +++ b/healthd/healthd_common.cpp @@ -0,0 +1,304 @@ +/* + * 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 "healthd-common" +#define KLOG_LEVEL 6 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace android; + +#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST + // Periodic chores fast interval in seconds + #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) +#else + #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST) +#endif + +#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW + // Periodic chores fast interval in seconds + #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) +#else + #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW) +#endif + +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" + +// epoll_create() parameter is actually unused +#define MAX_EPOLL_EVENTS 40 +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; + +static BatteryMonitor* gBatteryMonitor; + +struct healthd_mode_ops *healthd_mode_ops; + +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"); +} + +status_t healthd_get_property(int id, struct BatteryProperty *val) { + return gBatteryMonitor->getProperty(id, val); +} + +void healthd_battery_update(void) { + // Fast wake interval when on charger (watch for overheat); + // slow wake interval when on battery (watch for drained battery). + + int new_wake_interval = gBatteryMonitor->update() ? + 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; +} + +void healthd_dump_battery_state(int fd) { + gBatteryMonitor->dumpState(fd); + fsync(fd); +} + +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_create(MAX_EPOLL_EVENTS); + if (epollfd == -1) { + KLOG_ERROR(LOG_TAG, + "epoll_create failed; errno=%d\n", + errno); + return -1; + } + + healthd_board_init(&healthd_config); + healthd_mode_ops->init(&healthd_config); + wakealarm_init(); + uevent_init(); + gBatteryMonitor = new BatteryMonitor(); + gBatteryMonitor->init(&healthd_config); + 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/healthd/healthd_mode_android.cpp b/healthd/healthd_mode_android.cpp index 323ef52fd..c6123137a 100644 --- a/healthd/healthd_mode_android.cpp +++ b/healthd/healthd_mode_android.cpp @@ -42,6 +42,9 @@ int healthd_mode_android_preparetowait(void) { return -1; } +void healthd_mode_android_heartbeat(void) { +} + static void binder_event(uint32_t /*epevents*/) { IPCThreadState::self()->handlePolledCommands(); } -- cgit v1.2.3