Android下AlarmManager完整调用流程

一.首先列举下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

 





 

你可能感兴趣的:(linux层驱动,Android层)