linux层驱动|Android下AlarmManager完整调用流程

一.首先列举下AlarmManager常用的api

// 取消已经注册的与参数匹配的定时器 voidcancel(PendingIntent operation) //注册一个新的延迟定时器 voidset(int type, long triggerAtTime, PendingIntent operation) //注册一个重复类型的定时器 voidsetRepeating(int type, long triggerAtTime, long interval, PendingIntent operation) //注册一个非精密的重复类型定时器 void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation) //设置时区 voidsetTimeZone(String timeZone)

这些api实现于文件:
(1)frameworks/base/core/java/android/app/IAlarmManager.aidl
(2)frameworks/base/core/java/android/app/AlarmManager.java
【linux层驱动|Android下AlarmManager完整调用流程】截取部分frameworks/base/core/java/android/app/AlarmManager.java的代码如下:
public void set(int type, long triggerAtMillis, PendingIntent operation) { try { mService.set(type, triggerAtMillis, operation); } catch (RemoteException ex) { } }


二.上面代码片段的set函数实现文件为:frameworks/base/services/java/com/android/server/AlarmManagerService.java
找到该文件中代码
protected void finalize() throws Throwable { try { close(mDescriptor); } finally { super.finalize(); } }public void set(int type, long triggerAtTime, PendingIntent operation) {// /M:add for PoerOffAlarm feature type 7 for seetings,type 8 for // deskcolck ,@{ if (type == 7 || type == 8){ if (mDescriptor == -1) { Slog.w(TAG, "alarm driver not open ,return!"); return; }

在该set函数最后调用了同一文件的函数
setRepeating(type, triggerAtTime, 0, operation);

同样在setRepeating函数中调用了同一文件中函数:
setLocked(alarm);

该函数实现如下:
private void setLocked(Alarm alarm) { if (mDescriptor != -1) { // The kernel never triggers alarms with negative wakeup times // so we ensure they are positive. long alarmSeconds, alarmNanoseconds; if (alarm.when < 0) { alarmSeconds = 0; alarmNanoseconds = 0; } else { alarmSeconds = alarm.when / 1000; alarmNanoseconds = (alarm.when % 1000) * 1000 * 1000; } Slog.v(TAG, "Native set alarm :" + alarm); set(mDescriptor, alarm.type, alarmSeconds, alarmNanoseconds); } else { Message msg = Message.obtain(); msg.what = ALARM_EVENT; mHandler.removeMessages(ALARM_EVENT); mHandler.sendMessageAtTime(msg, alarm.when); } }


三.setLocked函数中的set函数实现文件为:frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp
部分代码如下:
static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj) { return open("/dev/alarm", O_RDWR); }static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd) { close(fd); }static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds) { struct timespec ts; ts.tv_sec = seconds; ts.tv_nsec = nanoseconds; int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts); if (result < 0) { ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno)); } }


static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"init", "()I", (void*)android_server_AlarmManagerService_init}, {"close", "(I)V", (void*)android_server_AlarmManagerService_close}, {"set", "(IIJJ)V", (void*)android_server_AlarmManagerService_set}, {"waitForAlarm", "(I)I", (void*)android_server_AlarmManagerService_waitForAlarm}, {"setKernelTimezone", "(II)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, {"bootFromAlarm", "(I)Z", (void*)android_server_AlarmManagerService_bootFromAlarm}, };

在该文件中 init 打开了/dev/alarm设备驱动文件。

四.继续往下吧,linux中的alarm核心代码文件包括:
alarm-dev.calarm.cinterface.c
代码的位置可能有变化,不过文件名字应该不会变的,用find命令搜索一下就ok。
其中alarm.c实现了一个框架机制,alarm-dev.c实现了驱动程序,interface.c是linux rtc驱动的接口包装。
我们继续开始:
在frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp中,我们找到了这两个东西:
(1)交互的设备文件/dev/alarm
(2)int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
打开文件alarm-dev.c,我们发现:
static const struct file_operations alarm_fops = { .owner = THIS_MODULE, .unlocked_ioctl = alarm_ioctl, .open = alarm_open, .release = alarm_release, }; static struct miscdevice alarm_device = { .minor = MISC_DYNAMIC_MINOR, .name = "alarm", .fops = &alarm_fops, };

好了/dev/alarm找到了,一个混杂设备。
然后在alarm_ioctl中我们继续发现:
case ANDROID_ALARM_SET_OLD: case ANDROID_ALARM_SET_AND_WAIT_OLD: if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { rv = -EFAULT; goto err1; } new_alarm_time.tv_nsec = 0; goto from_old_alarm_set; case ANDROID_ALARM_SET_AND_WAIT(0): case ANDROID_ALARM_SET(0): if (copy_from_user(&new_alarm_time, (void __user *)arg, sizeof(new_alarm_time))) { rv = -EFAULT; goto err1; } from_old_alarm_set: pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, new_alarm_time.tv_sec, new_alarm_time.tv_nsec); if (alarm_type == ANDROID_ALARM_POWER_ON) { alarm_set_power_on(new_alarm_time, false); break; } if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) { alarm_set_power_on(new_alarm_time, true); break; } spin_lock_irqsave(&alarm_slock, flags); alarm_enabled |= alarm_type_mask; devalarm_start(&alarms[alarm_type], timespec_to_ktime(new_alarm_time)); spin_unlock_irqrestore(&alarm_slock, flags); if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) break;

然后进入其中的alarm_set_power_on函数(实现文件为alarm.c):
void alarm_set_power_on(struct timespec new_pwron_time, bool logo) { unsigned long pwron_time; struct rtc_wkalrm alm; #ifdef RTC_PWRON_SEC /* round down the second */ new_pwron_time.tv_sec = (new_pwron_time.tv_sec / 60) * 60; #endif if (new_pwron_time.tv_sec > 0) { pwron_time = new_pwron_time.tv_sec; #ifdef RTC_PWRON_SEC pwron_time += RTC_PWRON_SEC; #endif alm.enabled = (logo ? 3 : 2); } else { pwron_time = 0; alm.enabled = 4; } rtc_time_to_tm(pwron_time, &alm.time); rtc_set_alarm(alarm_rtc_dev, &alm); }


五.很显然,我们发现rtc_set_alarm函数,它的实现在interface.c中
我们继续寻找:
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; err = rtc_valid_tm(&alarm->time); if (err != 0) return err; err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; #ifdef RTC_LEGACY_ALARM_IMPL if (!rtc->ops) err = -ENODEV; else if (!rtc->ops->set_alarm) err = -EINVAL; else err = rtc->ops->set_alarm(rtc->dev.parent, alarm); #else if (rtc->aie_timer.enabled) { //printk("rtc_set_alarm remove\n"); rtc_timer_remove(rtc, &rtc->aie_timer); } rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); rtc->aie_timer.period = ktime_set(0, 0); if (alarm->enabled) { //printk("rtc_set_alarm enqueue\n"); err = rtc_timer_enqueue(rtc, &rtc->aie_timer); } #endif mutex_unlock(&rtc->ops_lock); return err; }


六,之后就可以进入rtc驱动找到对应真正驱动模块rtc.c:
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, };

目测流程完了,,。。
最后加一个Android AlarmManager的闹钟小程序吧,源代码如下:
http://download.csdn.net/detail/u011630458/5989449







    推荐阅读