1526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil/* 2526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * Copyright (C) 2013 The Android Open Source Project 3526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * 4526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * Licensed under the Apache License, Version 2.0 (the "License"); 5526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * you may not use this file except in compliance with the License. 6526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * You may obtain a copy of the License at 7526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * 8526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * http://www.apache.org/licenses/LICENSE-2.0 9526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * 10526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * Unless required by applicable law or agreed to in writing, software 11526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * distributed under the License is distributed on an "AS IS" BASIS, 12526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * See the License for the specific language governing permissions and 14526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil * limitations under the License. 15526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil */ 16526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 17526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#define LOG_TAG "healthd-common" 18526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#define KLOG_LEVEL 6 19526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 20526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <healthd/healthd.h> 21526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <healthd/BatteryMonitor.h> 22526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 23526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <errno.h> 24526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <libgen.h> 25526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <stdio.h> 26526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <stdlib.h> 27526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <string.h> 28526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <unistd.h> 29526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <batteryservice/BatteryService.h> 30526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <cutils/klog.h> 31526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <cutils/uevent.h> 32526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <sys/epoll.h> 33526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <sys/timerfd.h> 34526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#include <utils/Errors.h> 35526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 36526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilusing namespace android; 37526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 38526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST 39526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // Periodic chores fast interval in seconds 40526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) 41526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#else 42526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST) 43526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#endif 44526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 45526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW 46526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // Periodic chores fast interval in seconds 47526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) 48526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#else 49526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW) 50526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#endif 51526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 52526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic struct healthd_config healthd_config = { 53526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST, 54526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW, 55526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryStatusPath = String8(String8::kEmptyString), 56526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryHealthPath = String8(String8::kEmptyString), 57526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryPresentPath = String8(String8::kEmptyString), 58526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryCapacityPath = String8(String8::kEmptyString), 59526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryVoltagePath = String8(String8::kEmptyString), 60526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryTemperaturePath = String8(String8::kEmptyString), 61526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryTechnologyPath = String8(String8::kEmptyString), 62526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryCurrentNowPath = String8(String8::kEmptyString), 63526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryCurrentAvgPath = String8(String8::kEmptyString), 64526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryChargeCounterPath = String8(String8::kEmptyString), 65526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryFullChargePath = String8(String8::kEmptyString), 66526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .batteryCycleCountPath = String8(String8::kEmptyString), 67526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .energyCounter = NULL, 68526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .boot_min_cap = 0, 69526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil .screen_on = NULL, 70526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil}; 71526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 72526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int eventct; 73526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int epollfd; 74526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 75526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#define POWER_SUPPLY_SUBSYSTEM "power_supply" 76526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 77526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil// epoll_create() parameter is actually unused 78526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#define MAX_EPOLL_EVENTS 40 79526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int uevent_fd; 80526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int wakealarm_fd; 81526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 82526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil// -1 for no epoll timeout 83526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int awake_poll_interval = -1; 84526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 85526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int wakealarm_wake_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST; 86526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 87526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic BatteryMonitor* gBatteryMonitor; 88526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 89526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstruct healthd_mode_ops *healthd_mode_ops; 90526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 91526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilint healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) { 92526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil struct epoll_event ev; 93526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 94526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil ev.events = EPOLLIN; 95526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 96526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (wakeup == EVENT_WAKEUP_FD) 97526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil ev.events |= EPOLLWAKEUP; 98526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 99526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil ev.data.ptr = (void *)handler; 100526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 101526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, 102526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil "epoll_ctl failed; errno=%d\n", errno); 103526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return -1; 104526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 105526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 106526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil eventct++; 107526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return 0; 108526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 109526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 110526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void wakealarm_set_interval(int interval) { 111526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil struct itimerspec itval; 112526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 113526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (wakealarm_fd == -1) 114526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 115526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 116526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil wakealarm_wake_interval = interval; 117526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 118526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (interval == -1) 119526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil interval = 0; 120526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 121526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil itval.it_interval.tv_sec = interval; 122526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil itval.it_interval.tv_nsec = 0; 123526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil itval.it_value.tv_sec = interval; 124526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil itval.it_value.tv_nsec = 0; 125526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 126526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (timerfd_settime(wakealarm_fd, 0, &itval, NULL) == -1) 127526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n"); 128526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 129526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 130526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatus_t healthd_get_property(int id, struct BatteryProperty *val) { 131526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return gBatteryMonitor->getProperty(id, val); 132526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 133526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 134526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilvoid healthd_battery_update(void) { 135526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // Fast wake interval when on charger (watch for overheat); 136526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // slow wake interval when on battery (watch for drained battery). 137526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 138526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int new_wake_interval = gBatteryMonitor->update() ? 139526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_config.periodic_chores_interval_fast : 140526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_config.periodic_chores_interval_slow; 141526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 142526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (new_wake_interval != wakealarm_wake_interval) 143526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil wakealarm_set_interval(new_wake_interval); 144526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 145526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // During awake periods poll at fast rate. If wake alarm is set at fast 146526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // rate then just use the alarm; if wake alarm is set at slow rate then 147526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // poll at fast rate while awake and let alarm wake up at slow rate when 148526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil // asleep. 149526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 150526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (healthd_config.periodic_chores_interval_fast == -1) 151526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil awake_poll_interval = -1; 152526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil else 153526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil awake_poll_interval = 154526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil new_wake_interval == healthd_config.periodic_chores_interval_fast ? 155526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil -1 : healthd_config.periodic_chores_interval_fast * 1000; 156526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 157526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 158526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilvoid healthd_dump_battery_state(int fd) { 159526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil gBatteryMonitor->dumpState(fd); 160526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil fsync(fd); 161526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 162526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 163526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void periodic_chores() { 164526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_battery_update(); 165526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 166526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 167526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil#define UEVENT_MSG_LEN 2048 168526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void uevent_event(uint32_t /*epevents*/) { 169526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil char msg[UEVENT_MSG_LEN+2]; 170526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil char *cp; 171526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int n; 172526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 173526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN); 174526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (n <= 0) 175526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 176526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ 177526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 178526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 179526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil msg[n] = '\0'; 180526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil msg[n+1] = '\0'; 181526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil cp = msg; 182526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 183526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil while (*cp) { 184526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) { 185526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_battery_update(); 186526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil break; 187526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 188526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 189526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil /* advance to after the next \0 */ 190526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil while (*cp++) 191526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil ; 192526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 193526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 194526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 195526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void uevent_init(void) { 196526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil uevent_fd = uevent_open_socket(64*1024, true); 197526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 198526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (uevent_fd < 0) { 199526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n"); 200526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 201526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 202526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 203526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil fcntl(uevent_fd, F_SETFL, O_NONBLOCK); 204526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD)) 205526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, 206526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil "register for uevent events failed\n"); 207526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 208526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 209526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void wakealarm_event(uint32_t /*epevents*/) { 210526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil unsigned long long wakeups; 211526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 212526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) { 213526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n"); 214526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 215526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 216526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 217526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil periodic_chores(); 218526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 219526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 220526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void wakealarm_init(void) { 221526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK); 222526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (wakealarm_fd == -1) { 223526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n"); 224526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 225526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 226526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 227526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD)) 228526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, 229526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil "Registration of wakealarm event failed\n"); 230526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 231526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil wakealarm_set_interval(healthd_config.periodic_chores_interval_fast); 232526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 233526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 234526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic void healthd_mainloop(void) { 235526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int nevents = 0; 236526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil while (1) { 237526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil struct epoll_event events[eventct]; 238526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int timeout = awake_poll_interval; 239526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int mode_timeout; 240526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 241526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil /* Don't wait for first timer timeout to run periodic chores */ 242526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (!nevents) 243526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil periodic_chores(); 244526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 245526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_mode_ops->heartbeat(); 246526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 247526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil mode_timeout = healthd_mode_ops->preparetowait(); 248526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) 249526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil timeout = mode_timeout; 250526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil nevents = epoll_wait(epollfd, events, eventct, timeout); 251526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (nevents == -1) { 252526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (errno == EINTR) 253526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil continue; 254526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n"); 255526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil break; 256526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 257526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 258526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil for (int n = 0; n < nevents; ++n) { 259526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (events[n].data.ptr) 260526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil (*(void (*)(int))events[n].data.ptr)(events[n].events); 261526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 262526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 263526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 264526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return; 265526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 266526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 267526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilstatic int healthd_init() { 268526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil epollfd = epoll_create(MAX_EPOLL_EVENTS); 269526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (epollfd == -1) { 270526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR(LOG_TAG, 271526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil "epoll_create failed; errno=%d\n", 272526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil errno); 273526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return -1; 274526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 275526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 276526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_board_init(&healthd_config); 277526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_mode_ops->init(&healthd_config); 278526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil wakealarm_init(); 279526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil uevent_init(); 280526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil gBatteryMonitor = new BatteryMonitor(); 281526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil gBatteryMonitor->init(&healthd_config); 282526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return 0; 283526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 284526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 285526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patilint healthd_main() { 286526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil int ret; 287526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 288526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil klog_set_level(KLOG_LEVEL); 289526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 290526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (!healthd_mode_ops) { 291526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR("healthd ops not set, exiting\n"); 292526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil exit(1); 293526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 294526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 295526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil ret = healthd_init(); 296526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil if (ret) { 297526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR("Initialization failed, exiting\n"); 298526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil exit(2); 299526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil } 300526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil 301526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil healthd_mainloop(); 302526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil KLOG_ERROR("Main loop terminated, exiting\n"); 303526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil return 3; 304526f8cf339f6c215d2d89924824b674cb99cfcc9Sandeep Patil} 305