一.首先列举下AlarmManager常用的api
// 取消已经注册的与参数匹配的定时器
void cancel(PendingIntent operation)
//注册一个新的延迟定时器
void set(int type, long triggerAtTime, PendingIntent operation)
//注册一个重复类型的定时器
void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
//注册一个非精密的重复类型定时器
void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation)
//设置时区
void setTimeZone(String timeZone)
这些api实现于文件:
(1)frameworks/base/core/java/android/app/IAlarmManager.aidl
(2)frameworks/base/core/java/android/app/AlarmManager.java
截取部分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.c alarm.c interface.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