您的位置:首页 > 移动开发 > Android开发

Android学习之Alarm driver

2011-11-21 23:17 393 查看
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才能把它编译出来.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: