android alarm driver &framework 关键流程

本文详细剖析了Android Alarm Driver的工作原理,包括设备初始化、注册处理函数、初始化wakeup source等核心步骤,以及上层AlarmManagerService的初始化与运行机制,展示了如何通过driver逻辑与framework对接,实现alarm事件的周期性触发与系统唤醒。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android alarm driver如下:
alarm-dev.c@\kernel\drivers\staging\android

static int __init alarm_dev_init(void)
{
    int err;
    int i;

    err = misc_register(&alarm_device);
    if (err)
        return err;

    alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm,
            ALARM_REALTIME, devalarm_alarmhandler);
    hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt,
            CLOCK_REALTIME, HRTIMER_MODE_ABS);
    alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm,
            ALARM_BOOTTIME, devalarm_alarmhandler);
    hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt,
            CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
    hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
            CLOCK_MONOTONIC, HRTIMER_MODE_ABS);

    for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
        alarms[i].type = i;
        if (!is_wakeup(i))
            alarms[i].u.hrt.function = devalarm_hrthandler;
    }

    wakeup_source_init(&alarm_wake_lock, "alarm");
    return 0;
}

driver init主要做了三件事,
1. 注册android alarm 设备:alarm_device。
2. 向linux alarm子系统注册alarm处理函数devalarm_alarmhandler,如果是允许唤醒系统的alarm,还会注册devalarm_hrthandler。当系统linux alarm到期时, 会回调这两个handler处理。
3. 初始化alarm 的wakeup source。

再细看handler里的处理:

static void devalarm_triggered(struct devalarm *alarm)
{
    unsigned long flags;
    uint32_t alarm_type_mask = 1U << alarm->type;

    alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type);
    spin_lock_irqsave(&alarm_slock, flags);
    if (alarm_enabled & alarm_type_mask) {
        __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */
        alarm_enabled &= ~alarm_type_mask;
        alarm_pending |= alarm_type_mask;
        wake_up(&alarm_wait_queue);
    }
    spin_unlock_irqrestore(&alarm_slock, flags);
}

主要做了一个动作是唤醒alarm的等待队列alarm_wait_queue, 后面分析再看如何与这里对接 。

先看上层AlarmManagerService初始化的函数,
主要有两步, 一是call native init, 二是启动thread一直等alarm消息:

public AlarmManagerService(Context context) {
        mContext = context;
        mDescriptor = init();
....
        if (mDescriptor != -1) {
            mWaitThread.start();
        } else {
            Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
        }
    }

其中AlarmManagerService是由System_server init时new出来:
initAndLoop()@SystemServer.java

            Slog.i(TAG, "Alarm Manager");
            alarm = new AlarmManagerService(context);
            ServiceManager.addService(Context.ALARM_SERVICE, alarm);

init对应初始化,完成alarm设备打开:
com_android_server_AlarmManagerService.cpp@ \frameworks\base\services\jni

static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
    return open("/dev/alarm", O_RDWR);
}

mwaitThread start后,一直循环block等待alarm driver消息, :

   public void run()
        {
            ArrayList<Alarm> triggerList = new ArrayList<Alarm>();

            while (true)
            {
                int result = waitForAlarm(mDescriptor);

native实现 :

static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
{
    int result = 0;

    do
    {
        result = ioctl(fd, ANDROID_ALARM_WAIT);
    } while (result < 0 && errno == EINTR);

    if (result < 0)
    {
        ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
        return 0;
    }

    return result;
}

ioctl对应driver逻辑:

static long alarm_do_ioctl(struct file *file, unsigned int cmd,
                            struct timespec *ts)
{
...
    case ANDROID_ALARM_WAIT:
        rv = alarm_wait();
        break;

alarm_wait实现 如下, 此处会一直wait等待wake up alarm_wait_queue状态 , 就接上了最开始提到的向linux alarm子系统注册的alarm handler来wakeup的地方. 从而完成了具体alarm到期事件 向framework的通知 。

static int alarm_wait(void)
{
    unsigned long flags;
    int rv = 0;

    spin_lock_irqsave(&alarm_slock, flags);
    alarm_dbg(IO, "alarm wait\n");
    if (!alarm_pending && wait_pending) {
        __pm_relax(&alarm_wake_lock);
        wait_pending = 0;
    }
    spin_unlock_irqrestore(&alarm_slock, flags);

    rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
    if (rv)
        return rv;

    spin_lock_irqsave(&alarm_slock, flags);
    rv = alarm_pending;
    wait_pending = 1;
    alarm_pending = 0;
    spin_unlock_irqrestore(&alarm_slock, flags);

    return rv;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值