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;
}