系统开发过程中,经常会遇到Android心跳机制,待机耗流问题,几乎都跟AlarmMangerService有关,本文从应用层到kernel记录下整个处理流程。
应用层
样例代码:
AlarmManager mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
...
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent);
可以通过获取ALARM_SERVICE来设置Alarm,
第一个参数表示Alarm的类型,可选择0,1,2,3;(当系统休眠时,0和2会主动唤醒,1和3不会)
第二个参数表示Alarm到期的时间;
第三个参数表示Alarm到期时处理的intent事件。
framework层
文件frameworks/base/services/core/java/com/android/server/AlarmManagerService.java
在Alarm service运行时会启动AlarmThread线程,waitForAlarm一直等待JNI层传递闹钟到期事件。
@Override
public void onStart() {
//初始化jni层,打开alarm节点设备
mNativeData = init();
mNextWakeup = mNextNonWakeup = 0;
// We have to set current TimeZone info to kernel
// because kernel doesn't keep this after reboot
setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
//启动Alarm线程,kernel层rtc唤醒系统立即得到执行
if (mNativeData != 0) {
AlarmThread waitThread = new AlarmThread();
waitThread.start();
} else {
Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
}
...
//向SystemService注册ALARM service
publishBinderService(Context.ALARM_SERVICE, mService);
publishLocalService(LocalService.class, new LocalService());
}
//Alarm线程
private class AlarmThread extends Thread
{
public void run()
{
ArrayList triggerList = new ArrayList();
while (true)
{
int result = waitForAlarm(mNativeData);
mLastWakeup = SystemClock.elapsedRealtime();
......
}
}
}
//向jni层设置alarm
private void setLocked(int type, long when) {
if (mNativeData != 0 && mNativeData != -1) {
// The kernel never triggers alarms with negative wakeup times
// so we ensure they are positive.
long alarmSeconds, alarmNanoseconds;
if (when < 0) {
alarmSeconds = 0;
alarmNanoseconds = 0;
} else {
alarmSeconds = when / 1000;
alarmNanoseconds = (when % 1000) * 1000 * 1000;
}
Slog.d(TAG, "set alarm to RTC " + when + " Type: "+ type);
set(mNativeData, type, alarmSeconds, alarmNanoseconds);
}
}
jni层
文件frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
初始化时打开alarm节点设备,
ioctl如下方法:
ANDROID_ALARM_SET //设置alarm
ANDROID_ALARM_SET_RTC //设置系统时间
ANDROID_ALARM_WAIT //等待rtc唤醒事件
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"init", "()J", (void*)android_server_AlarmManagerService_init},
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
{"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
{"bootFromAlarm", "(I)Z", (void*)android_server_AlarmManagerService_bootFromAlarm},
};
static jlong init_alarm_driver()
{
int fd = open("/dev/alarm", O_RDWR);
if (fd < 0) {
ALOGV("opening alarm driver failed: %s", strerror(errno));
return 0;
}
AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
return reinterpret_cast(ret);
}
int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
{
return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
}
kernel层
文件kernel/drivers/staging/android/alarm-dev.c
注册alarm设备,对alarm节点的ioctrl操作处理。
static const struct file_operations alarm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = alarm_ioctl,
.open = alarm_open,
.release = alarm_release,
#ifdef CONFIG_COMPAT
.compat_ioctl = alarm_compat_ioctl,
#endif
};
static struct miscdevice alarm_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "alarm",
.fops = &alarm_fops,
};
static long alarm_do_ioctl(struct file *file, unsigned int cmd,
struct timespec *ts, struct rtc_wkalrm *alm)
{
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_CLEAR(0):
alarm_clear(alarm_type, ts);
break;
case ANDROID_ALARM_SET(0):
alarm_set(alarm_type, ts);
break;
case ANDROID_ALARM_SET_AND_WAIT(0):
alarm_set(alarm_type, ts);
/* fall though */
case ANDROID_ALARM_WAIT:
rv = alarm_wait();
break;
default:
rv = -EINVAL;
}
return rv;
}
alarm_set()
devalarm_start()
alarm_start()
然后调用rtc设备,各芯片商实现不一样,以MTK为例:
文件kernel-4.4/drivers/misc/mediatek/rtc/mtk_rtc_common.c
注册rtc设备。
static struct rtc_class_ops rtc_ops = {
.read_time = rtc_ops_read_time,
.set_time = rtc_ops_set_time,
.read_alarm = rtc_ops_read_alarm,
.set_alarm = rtc_ops_set_alarm,
.ioctl = rtc_ops_ioctl,
};
文件kernel-4.4/drivers/misc/mediatek/rtc/mtk_rtc_hal_common.c
设置rtc寄存器。
void hal_rtc_set_alarm_time(struct rtc_time *tm)
{
hal_rtc_xinfo("mon = %d, day = %d, hour = %d\n",
(rtc_read(RTC_AL_MTH) & ~(RTC_AL_MTH_MASK)) | tm->tm_mon,
(rtc_read(RTC_AL_DOM) & ~(RTC_AL_DOM_MASK)) | tm->tm_mday,
(rtc_read(RTC_AL_HOU) & ~(RTC_AL_HOU_MASK)) | tm->tm_hour);
rtc_write(RTC_AL_YEA,
(rtc_read(RTC_AL_YEA) & ~(RTC_AL_YEA_MASK)) | (tm->tm_year & RTC_AL_YEA_MASK));
rtc_write(RTC_AL_MTH,
(rtc_read(RTC_AL_MTH) & ~(RTC_AL_MTH_MASK)) | (tm->tm_mon & RTC_AL_MTH_MASK));
rtc_write(RTC_AL_DOM,
(rtc_read(RTC_AL_DOM) & ~(RTC_AL_DOM_MASK)) | (tm->tm_mday & RTC_AL_DOM_MASK));
rtc_write(RTC_AL_HOU,
(rtc_read(RTC_AL_HOU) & ~(RTC_AL_HOU_MASK)) | (tm->tm_hour & RTC_AL_HOU_MASK));
rtc_write(RTC_AL_MIN,
(rtc_read(RTC_AL_MIN) & ~(RTC_AL_MIN_MASK)) | (tm->tm_min & RTC_AL_MIN_MASK));
rtc_write(RTC_AL_SEC,
(rtc_read(RTC_AL_SEC) & ~(RTC_AL_SEC_MASK)) | (tm->tm_sec & RTC_AL_SEC_MASK));
rtc_write(RTC_AL_MASK, RTC_AL_MASK_DOW); /* mask DOW */
rtc_write_trigger();
}