AlarmManagerService是如何工作的?

系统开发过程中,经常会遇到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<Alarm> triggerList = new ArrayList<Alarm>();
            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<jlong>(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();
}
展开阅读全文

没有更多推荐了,返回首页