Android學習之Alarm driver

Updated: 2013/03/18, 剛有時間瀏覽了最新的Android builder submit 2013的相關slides,其中有關於最新的android 對kernel的upstream的狀態的總結,大家可以看看
http://events.linuxfoundation.org/images/stories/slides/abs2013_stultz.pdf


Alarm正在staging中,不久應該也會進入main stream


Alarm是Android提供的一個硬件時鐘,基於內核的rtc機制完成.


相關知識點:

內核中的各種時間函數

ktime_get_ts 參見POSIX.1b clock types, 可以從<The Linux Programming Interface>的第23.5.1找到相應說明
    當應用程序希望不會受到手動的改變系統時鐘的影響時最有用.在Linux中,這個時間反應了從系統啓動開始流逝的時間.

getnstimeofday 類似與user space的gettimeofday, 反映的是從1970年開始的毫秒

還有一些各種時間格式之間的轉換函數在timer.c

一些有用的資源,在需要用到時鐘那進行控制的事情,一定要記着選擇正確的精度和函數,並多參考現有的其它driver.

Documentation/timers/timers-howto.txt

http://www.ibm.com/developerworks/linux/library/l-timers-list/index.html?ca=drs-

http://stackoverflow.com/questions/4655711/measuring-execution-time-of-a-function-inside-linux-kernel
http://stackoverflow.com/questions/6360210/androidlinux-uptime-using-clock-monotonic其中提到了最新引入內核的CLOCK_BOOTTIME.
https://lwn.net/Articles/429925/
全面介紹了最新的內核中時鐘的概念, 也提到了Android的alarm timer的實現


關於driver初始化的優先級
分爲兩個層次:initcall, Makefile.同樣的initcal中以Makefile中的順序排序,如果不在同一個initcall的層次,則以initcall的順序調用. initcal的順序參見init.h

...

#define late_initcall(fn)               __define_initcall("7",fn,7)

..

 關於alarm的一些總體認識和定義,參照include/linux/android_alarm.h中的描述:

alarm提供的接口與hrtimer的接口類似,增加了從suspend狀態wakeup的功能.並且提供了一個給週期性timer使用的遞減的實時時鐘,確保它在系統suspend的時候或者當wall time被改變的時候依然能夠繼續工作.

作爲platform驅動被platform_driver_register所註冊.
使用了WAKE_LOCK_SUSPEND的wake lock來保證在系統不會進入full的suspend狀態,從而能夠提供比較好的低延遲.

Android的alarm提供了兩個設備

一個alarm的platform driver(alarm.c)

關於platform driver的相關理解參見<Device Driver學習之platform driver是神馬>

其中值得注意的是, 它通過rtc_alarm_interface這個一個class interface,使得alarm使用了rtc提供的一些接口. 這裏使用msm_rtc這個rtc設備作爲alarm設備的時鐘源.這裏就體現了一個重要的知識點,如何使用既有的設備構建新的設備(即,使用class_interface提供的機制,使得platform alarm設備在msm_rtc設備被添加到system的時候,通過platform的core通知到platform alarm設備class_interface的add_dev,然後把platform alarm設備註冊入添加到系統中)!!!
Class Device http://www.linuxjournal.com/node/6872/print, 這篇文章雖然有點老,但是對於基本概念還是闡述的挺好的.

# dmesg | grep "using rtc device"

<6>[    7.471466] using rtc device, msm_rtc, for alarms

<6>[    7.471618] rs30000048:00010000 rs30000048:00010000: rtc core: registered msm_rtc as rtc0

一個暴露給用戶使用的接口misc的alarm接口(alarm-dev.c)

其中定義了一些列的ioctl,來操縱platform alarm driver提供的功能.

   

哪些地方使用到了alarm提供的接口:

通過grep android的代碼,如下地方使用了alarm的user接口:

development/simulator/wrapsim/FakeDev.c: *  /dev/alarm
frameworks/base/cmds/runtime/main_runtime.cpp:    fd = open("/dev/alarm", O_RDWR);
frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp:    return open("/dev/alarm", O_RDWR);
frameworks/base/libs/utils/SystemClock.cpp:    fd = open("/dev/alarm", O_RDWR);
frameworks/base/libs/utils/SystemClock.cpp:        int fd = open("/dev/alarm", O_RDONLY);

system/core/toolbox/date.c:    fd = open("/dev/alarm", O_RDWR);
system/core/toolbox/date.c:        fd = open("/dev/alarm", O_RDWR);
system/core/toolbox/uptime.c:    fd = open("/dev/alarm", O_RDONLY);
system/core/toolbox/alarm.c:    afd = open("/dev/alarm", O_RDWR);
system/core/rootdir/ueventd.rc:/dev/alarm                0664   system     radio


用戶層可以使用的由alarm驅動提供的四種硬件時鐘:

RTC_WAKEUP(ANDROID_ALARM_RTC_WAKEUP):在指定的時刻(設置Alarm的時候),喚醒設備來觸發Intent。

RTC(ANDROID_ALARM_RTC):在一個顯式的時間觸發Intent,但不喚醒設備。

ELAPSED_REALTIME(ANDROID_ALARM_ELAPSED_REALTIME):從設備啓動後,如果流逝的時間達到總時間,那麼觸發Intent,但不喚醒設備。流逝的時間包括設備睡眠的任何時間。注意一點的是,時間流逝的計算點是自從它最後一次啓動算起。

ELAPSED_REALTIME_WAKEUP(ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP):從設備啓動後,達到流逝的總時間後,如果需要將喚醒設備並觸發Intent。

以上4個時鐘都是通過alarm service提供給用戶使用的,它們通過對應的JNI側()來獲得alarm驅動提供的硬件時鐘.

還有一個在alarm驅動中定義的硬件時鐘是ANDROID_ALARM_SYSTEMTIME, 它沒有暴露給java層的用戶來使用. 它是返回上文所提到的ktime_get_ts函數返回的值.目前還沒有用戶側的程序需要使用它.

另外,值得注意的是Android提供了對alarm設備的測試程序(mydroid/system/core/toolbox/alarm.c), 但是,沒有放在編譯的Android.mk中,所以需要修改toolbox的Android.mk才能把它編譯出來.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章