diff options
Diffstat (limited to 'healthd')
| -rw-r--r-- | healthd/Android.mk | 151 | ||||
| -rw-r--r-- | healthd/BatteryMonitor.cpp | 1 | ||||
| -rw-r--r-- | healthd/charger.cpp | 102 | ||||
| -rw-r--r-- | healthd/healthd.cpp | 377 | ||||
| -rw-r--r-- | healthd/healthd_board_default.cpp | 29 | ||||
| -rw-r--r-- | healthd/healthd_common.cpp | 304 | ||||
| -rw-r--r-- | healthd/healthd_mode_android.cpp | 3 |
7 files changed, 557 insertions, 410 deletions
diff --git a/healthd/Android.mk b/healthd/Android.mk index b292725b9..8b5996442 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -3,16 +3,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := healthd_board_default.cpp -LOCAL_MODULE := libhealthd.default -LOCAL_CFLAGS := -Werror -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_STATIC_LIBRARIES := libbinder -LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libbinder -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) LOCAL_SRC_FILES := BatteryMonitor.cpp LOCAL_MODULE := libbatterymonitor LOCAL_C_INCLUDES := $(LOCAL_PATH)/include @@ -21,26 +11,47 @@ LOCAL_STATIC_LIBRARIES := libutils libbase libbinder include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) +LOCAL_SRC_FILES := \ + healthd_mode_android.cpp \ + BatteryPropertiesRegistrar.cpp + +LOCAL_MODULE := libhealthd_android +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/include + +LOCAL_STATIC_LIBRARIES := \ + libbatterymonitor \ + libbatteryservice \ + libutils \ + libbase \ + libcutils \ + liblog \ + libc \ + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_CFLAGS := -Werror +ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true) +LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK +endif ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true) LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND -LOCAL_SHARED_LIBRARIES += libsuspend endif + LOCAL_SRC_FILES := \ - healthd_mode_android.cpp \ healthd_mode_charger.cpp \ - AnimationParser.cpp \ - BatteryPropertiesRegistrar.cpp \ + AnimationParser.cpp -LOCAL_MODULE := libhealthd_internal -LOCAL_C_INCLUDES := bootable/recovery +LOCAL_MODULE := libhealthd_charger +LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH) \ - $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/include LOCAL_STATIC_LIBRARIES := \ - libbatterymonitor \ - libbatteryservice \ - libbinder \ libminui \ libpng \ libz \ @@ -51,11 +62,14 @@ LOCAL_STATIC_LIBRARIES := \ libm \ libc \ -include $(BUILD_STATIC_LIBRARY) +ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true) +LOCAL_STATIC_LIBRARIES += libsuspend +endif +include $(BUILD_STATIC_LIBRARY) +### charger ### include $(CLEAR_VARS) - ifeq ($(strip $(BOARD_CHARGER_NO_UI)),true) LOCAL_CHARGER_NO_UI := true endif @@ -64,80 +78,57 @@ LOCAL_CHARGER_NO_UI := true endif LOCAL_SRC_FILES := \ - healthd.cpp \ - healthd_mode_android.cpp \ - BatteryPropertiesRegistrar.cpp \ + healthd_common.cpp \ + charger.cpp \ -ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) -LOCAL_SRC_FILES += healthd_mode_charger.cpp -endif - -LOCAL_MODULE := healthd +LOCAL_MODULE := charger LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_CFLAGS := -D__STDC_LIMIT_MACROS -Werror - -ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true) -LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK -endif - -ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true) -LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND -endif - +LOCAL_CFLAGS := -Werror ifeq ($(strip $(LOCAL_CHARGER_NO_UI)),true) LOCAL_CFLAGS += -DCHARGER_NO_UI endif - -LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include - ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_FAST),) LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_FAST=$(BOARD_PERIODIC_CHORES_INTERVAL_FAST) endif - ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),) LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW) endif LOCAL_STATIC_LIBRARIES := \ - libhealthd_internal \ + libhealthd_charger \ libbatterymonitor \ - libbatteryservice \ - libbinder \ libbase \ - -ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) -LOCAL_STATIC_LIBRARIES += \ - libminui \ - libpng \ - libz \ - -endif - - -LOCAL_STATIC_LIBRARIES += \ libutils \ libcutils \ liblog \ libm \ libc \ +ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) +LOCAL_STATIC_LIBRARIES += \ + libminui \ + libpng \ + libz \ + +endif + ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true) LOCAL_STATIC_LIBRARIES += libsuspend endif LOCAL_HAL_STATIC_LIBRARIES := libhealthd -# Symlink /charger to /sbin/healthd +# Symlink /charger to /sbin/charger LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \ - && ln -sf /sbin/healthd $(TARGET_ROOT_OUT)/charger + && ln -sf /sbin/charger $(TARGET_ROOT_OUT)/charger include $(BUILD_EXECUTABLE) - ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true) define _add-charger-image include $$(CLEAR_VARS) @@ -165,3 +156,41 @@ include $(BUILD_PHONY_PACKAGE) _add-charger-image := _img_modules := endif # LOCAL_CHARGER_NO_UI + +### healthd ### +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + healthd_common.cpp \ + healthd.cpp \ + +LOCAL_MODULE := healthd +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include + +ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_FAST),) +LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_FAST=$(BOARD_PERIODIC_CHORES_INTERVAL_FAST) +endif +ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),) +LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW) +endif + +LOCAL_STATIC_LIBRARIES := \ + libhealthd_android \ + libbatterymonitor \ + libbatteryservice \ + android.hardware.health@1.0-convert \ + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libbase \ + libutils \ + libcutils \ + liblog \ + libm \ + libc \ + libhidlbase \ + libhidltransport \ + android.hardware.health@1.0 \ + +include $(BUILD_EXECUTABLE) diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 0c90a5456..369a022c9 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -141,6 +141,7 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String struct sysfsStringEnumMap supplyTypeMap[] = { { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN }, { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY }, + { "BMS", ANDROID_POWER_SUPPLY_TYPE_BATTERY }, { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC }, { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC }, { "USB", ANDROID_POWER_SUPPLY_TYPE_USB }, 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 <healthd/healthd.h> + +#include <stdlib.h> +#include <string.h> +#include <cutils/klog.h> + +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..cae6c4c3c 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,106 @@ #define KLOG_LEVEL 6 #include <healthd/healthd.h> -#include <healthd/BatteryMonitor.h> -#include <errno.h> -#include <libgen.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> -#include <batteryservice/BatteryService.h> #include <cutils/klog.h> -#include <cutils/uevent.h> -#include <sys/epoll.h> -#include <sys/timerfd.h> -#include <utils/Errors.h> -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, -}; +#include <android/hardware/health/1.0/IHealth.h> +#include <android/hardware/health/1.0/types.h> +#include <hal_conversion.h> -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; +using namespace android; -// -1 for no epoll timeout -static int awake_poll_interval = -1; +using IHealth = ::android::hardware::health::V1_0::IHealth; +using Result = ::android::hardware::health::V1_0::Result; +using HealthConfig = ::android::hardware::health::V1_0::HealthConfig; +using HealthInfo = ::android::hardware::health::V1_0::HealthInfo; -static int wakealarm_wake_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST; +using ::android::hardware::health::V1_0::hal_conversion::convertToHealthConfig; +using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthConfig; +using ::android::hardware::health::V1_0::hal_conversion::convertToHealthInfo; +using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthInfo; -static BatteryMonitor* gBatteryMonitor; +// device specific hal interface; +static sp<IHealth> gHealth; -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*/) { -} +// default energy counter property redirect to talk to device +// HAL +static int healthd_board_get_energy_counter(int64_t *energy) { -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; + if (gHealth == nullptr) { + return NAME_NOT_FOUND; } - eventct++; - return 0; -} + Result result = Result::NOT_SUPPORTED; + gHealth->energyCounter([=, &result] (Result ret, int64_t energyOut) { + result = ret; + *energy = energyOut; + }); -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"); + return result == Result::SUCCESS ? OK : NAME_NOT_FOUND; } -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); +void healthd_board_init(struct healthd_config *config) { - // 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. + // Initialize the board HAL - Equivalent of healthd_board_init(config) + // in charger/recovery mode. - 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"); + gHealth = IHealth::getService("health"); + if (gHealth == nullptr) { + KLOG_WARNING(LOG_TAG, "unable to get HAL interface, using defaults\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); + HealthConfig halConfig; + convertToHealthConfig(config, halConfig); + gHealth->init(halConfig, [=] (const auto &halConfigOut) { + convertFromHealthConfig(halConfigOut, config); + // always redirect energy counter queries + config->energyCounter = healthd_board_get_energy_counter; + }); } -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(); +int healthd_board_battery_update(struct android::BatteryProperties *props) { + int logthis = 0; - 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); - } + if (gHealth == nullptr) { + return logthis; } - 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; - } + HealthInfo info; + convertToHealthInfo(props, info); + gHealth->update(info, + [=, &logthis] (int32_t ret, const auto &infoOut) { + logthis = ret; + convertFromHealthInfo(infoOut, props); + }); - healthd_board_init(&healthd_config); - healthd_mode_ops->init(&healthd_config); - wakealarm_init(); - uevent_init(); - gBatteryMonitor = new BatteryMonitor(); - gBatteryMonitor->init(&healthd_config); - return 0; + return logthis; } -int main(int argc, char **argv) { - int ch; - int ret; +int main(int /*argc*/, char ** /*argv*/) { - 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_board_default.cpp b/healthd/healthd_board_default.cpp deleted file mode 100644 index eb55773de..000000000 --- a/healthd/healthd_board_default.cpp +++ /dev/null @@ -1,29 +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. - */ - -#include <healthd/healthd.h> - -void healthd_board_init(struct healthd_config*) -{ - // use defaults -} - - -int healthd_board_battery_update(struct android::BatteryProperties*) -{ - // return 0 to log periodic polled battery status to kernel log - return 0; -} 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 <healthd/healthd.h> +#include <healthd/BatteryMonitor.h> + +#include <errno.h> +#include <libgen.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <batteryservice/BatteryService.h> +#include <cutils/klog.h> +#include <cutils/uevent.h> +#include <sys/epoll.h> +#include <sys/timerfd.h> +#include <utils/Errors.h> + +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(); } |
