healthd : Changes of power off charging alarm

1. Start alarm thread when device enters power off charging mode.
Reboot the device when alarm time is up during power off charging.

2. Add reboot function to event data.If the alarm event happens, call
reboot function immediately to ensure that device won't go to suspend
during calling reboot function.

3. Add alarm seconds check in case of that power off alarm time is up
when start alarm thread. If the final alarm time is less than the
estimated time of next boot completed to fire, that means it is not able
to fire the last power off alarm at the right time, so just miss it.

CRs-Fixed: 2054302
Change-Id: I40bd9c35a9e42aeabb742603e161c2049cd0b5f5
This commit is contained in:
Mao Jinlong 2017-06-12 16:09:07 +08:00 committed by Gerrit - the friendly Code Review server
parent 54529a8363
commit 7ec03e79f2
3 changed files with 52 additions and 37 deletions

View File

@ -1,16 +1,14 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := healthd_board_msm.cpp
LOCAL_SRC_FILES := healthd_board_msm.cpp healthd_msm_alarm.cpp
LOCAL_MODULE := libhealthd.msm
LOCAL_CFLAGS := -Werror
LOCAL_C_INCLUDES := \
system/core/healthd/include/healthd/ \
system/core/base/include \
bootable/recovery \
bootable/recovery/minui/include
ifneq ($(TARGET_USES_AOSP),true)
LOCAL_SRC_FILES += healthd_msm_alarm.cpp
LOCAL_CFLAGS += -DQTI_BSP=1
endif
include $(BUILD_STATIC_LIBRARY)

View File

@ -450,9 +450,7 @@ out:
void healthd_board_init(struct healthd_config*)
{
// use defaults
#if QTI_BSP
power_off_alarm_init();
#endif
healthd_batt_info_notify();
}

View File

@ -24,14 +24,14 @@
#include <time.h>
#include <unistd.h>
#include <cutils/android_reboot.h>
#include <sys/syscall.h>
#include <sys/reboot.h>
#include <sys/ioctl.h>
#include <cutils/klog.h>
#include <cutils/misc.h>
#include <cutils/uevent.h>
#include <cutils/properties.h>
#include <pthread.h>
#include <linux/android_alarm.h>
#include <linux/rtc.h>
#include <linux/time.h>
#include <sys/epoll.h>
@ -47,12 +47,6 @@ enum alarm_time_type {
RTC_TIME,
};
/*
* shouldn't be changed after
* reading from alarm register
*/
static time_t alm_secs;
static int alarm_get_time(enum alarm_time_type time_type,
time_t *secs)
{
@ -101,18 +95,11 @@ err:
return -1;
}
#define ERR_SECS 2
static int alarm_is_alm_expired()
static void alarm_reboot(void)
{
int rc;
time_t rtc_secs;
rc = alarm_get_time(RTC_TIME, &rtc_secs);
if (rc < 0)
return 0;
return (alm_secs >= rtc_secs - ERR_SECS &&
alm_secs <= rtc_secs + ERR_SECS) ? 1 : 0;
LOGI("alarm time is up, reboot the phone!\n");
syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, "rtc");
}
static int alarm_set_reboot_time_and_wait(time_t secs)
@ -136,6 +123,7 @@ static int alarm_set_reboot_time_and_wait(time_t secs)
}
event.events = EPOLLIN | EPOLLWAKEUP;
event.data.ptr = (void *)alarm_reboot;
rc = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
if (rc < 0) {
LOGE("epoll_ctl(EPOLL_CTL_ADD) failed \n");
@ -154,13 +142,13 @@ static int alarm_set_reboot_time_and_wait(time_t secs)
goto err;
}
do {
nevents = epoll_wait(epollfd, events, 1, -1);
} while ((nevents < 0) || !alarm_is_alm_expired());
nevents = epoll_wait(epollfd, events, 1, -1);
if (nevents <= 0) {
LOGE("Unable to wait on alarm\n");
goto err;
} else {
(*(void (*)())events[0].data.ptr)();
}
close(epollfd);
@ -176,10 +164,19 @@ err:
return -1;
}
/*
* 10s the estimated time from timestamp of alarm thread start
* to timestamp of android boot completed.
*/
#define TIME_DELTA 10
/* seconds of 1 minute*/
#define ONE_MINUTE 60
static void *alarm_thread(void *)
{
time_t rtc_secs, rb_secs;
time_t rtc_secs, alarm_secs;
int rc;
timespec ts;
/*
* to support power off alarm, the time
@ -188,17 +185,39 @@ static void *alarm_thread(void *)
* earlier than the actual alarm time
* set by user
*/
rc = alarm_get_time(ALARM_TIME, &alm_secs);
if (rc < 0 || !alm_secs)
rc = alarm_get_time(ALARM_TIME, &alarm_secs);
if (rc < 0 || !alarm_secs)
goto err;
rc = alarm_set_reboot_time_and_wait(alm_secs);
rc = alarm_get_time(RTC_TIME, &rtc_secs);
if (rc < 0 || !rtc_secs)
goto err;
LOGI("alarm time in rtc is %ld, rtc time is %ld\n", alarm_secs, rtc_secs);
if (alarm_secs <= rtc_secs) {
clock_gettime(CLOCK_BOOTTIME, &ts);
/*
* It is possible that last power off alarm time is up at this point.
* (alarm_secs + ONE_MINUTE) is the final alarm time to fire.
* (rtc_secs + ts.tv_sec + TIME_DELTA) is the estimated time of next
* boot completed to fire alarm.
* If the final alarm time is less than the estimated time of next boot
* completed to fire, that means it is not able to fire the last power
* off alarm at the right time, so just miss it.
*/
if (alarm_secs + ONE_MINUTE < rtc_secs + ts.tv_sec + TIME_DELTA) {
LOGE("alarm is missed\n");
goto err;
}
alarm_reboot();
}
rc = alarm_set_reboot_time_and_wait(alarm_secs);
if (rc < 0)
goto err;
LOGI("Exit from power off charging, reboot the phone!\n");
android_reboot(ANDROID_RB_RESTART2, 0, (char *)"rtc");
err:
LOGE("Exit from alarm thread\n");
return NULL;