6 闹钟
6.1 设置定时时间
文件:packages/apps/alarmclock/src/com/android/alarmclock/Alarms.java
private static void enableAlert(Context context, final Alarm alarm,
final long atTimeInMillis) {
AlarmManager am = (AlarmManager)
context.getSystem
Service(Context.AL
ARM_SERVICE);
...
am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender);
...
}
由闹钟管理器设置定时时间。
6.2 闹钟管理器
6.2.1 定时设置
文件:frameworks/base/core/java/android/app/AlarmManager.java
public static final int RTC_WAKEUP = 0;
public static final int RTC = 1;
public static final int ELAPSED_REALTIME_WAKEUP = 2;
public static final int ELAPSED_REALTIME = 3;
AlarmManager(IAlarmManager service) {
mService = service;
}
public void set(int type, long triggerAtTime, Pending
Intent operation) {
try {
mService.set(type, triggerAtTime, operation);
} catch (RemoteException ex) {
}
}
将type, triggerAtTime, operation等参数转向闹钟管理器服务。
6.3 闹钟管理器服务
文件:frameworks/base/services/java/com/android/server/AlarmManagerService.java
6.3.1 定时设置
public AlarmManagerService(Context context) {
mDescriptor = init();
...
}
public void set(int type, long triggerAtTime, PendingIntent operation) {
setRepeating(type, triggerAtTime, 0, operation);
}
public void setRepeating(int type, long triggerAtTime, long interval,
PendingIntent operation) {
if (operation == null) {
Log.w(TAG, "set/setRepeating ignored because there is no intent");
return;
}
synchronized (mLock) {
Alarm alarm = new Alarm();
alarm.type = type;
alarm.when = triggerAtTime;
alarm.repeatInterval = interval;
alarm.operation = operation;
// Remove this alarm if already scheduled.
removeLocked(operation);
if (localLOGV) Log.v(TAG, "set: " + alarm);
int index = addAlarmLocked(alarm);
if (index == 0) {
setLocked(alarm);
}
}
}
private void setLocked(Alarm alarm)
{
if (mDescriptor != -1)
{
set(mDescriptor, alarm.type, (alarm.when * 1000 * 1000));
}
else
{
Message msg = Message.obtain();
msg.what = ALARM_EVENT;
mHandler.removeMessages(ALARM_EVENT);
mHandler.sendMessageAtTime(msg, alarm.when);
}
}
Init,set 为底层操作函数,set(mDescriptor, alarm.type, (alarm.when * 1000 * 1000)); 由底层来完成定时设置。
6.3.2等待计时结束
private class AlarmThread extends Thread
{
public void run()
{
...
while (true)
{
int result = waitForAlarm(mDescriptor);
...
if ((result & RTC_WAKEUP_MASK) != 0)
triggerAlarmsLocked(mRtcWakeupAlarms, triggerList, nowRTC);
if ((result & RTC_MASK) != 0)
triggerAlarmsLocked(mRtcAlarms, triggerList, nowRTC);
if ((result & ELAPSED_REALTIME_WAKEUP_MASK) != 0)
triggerAlarmsLocked(mElapsedRealtimeWakeupAlarms, triggerList, nowELAPSED);
if ((result & ELAPSED_REALTIME_MASK) != 0)
triggerAlarmsLocked(mElapsedRealtimeAlarms, triggerList, nowELAPSED);
...
}
}
}
在服务里采用
线程来处理计时结束返回的信息,根据等待计时结束返回的信息触发不同的操作。
6.4 硬件调用
文件:frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp
6.4.1 定时设置
static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
#if HAVE_ANDROID_OS
return open("/dev/alarm", O_R
DWR);
#else
return -1;
#endif
}
static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
{
#if HAVE_ANDROID_OS
close(fd);
#endif
}
static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong nanoseconds)
{
#if HAVE_ANDROID_OS
struct timespec ts;
ts.tv_sec = NANOSECONDS_TO_SECONDS(nanoseconds);
ts.tv_nsec = nanoseconds - SECONDS_TO_NANOSECONDS(ts.tv_sec);
int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
if (result < 0)
{
LOGE("Unable to set alarm to %lld: %s\n", nanoseconds, strerror(errno));
}
#endif
}
以上函数的绑定如下:
{"init", "()I", (void*)android_server_AlarmManagerService_init},
{"close", "(I)V", (void*)android_server_AlarmManagerService_close},
{"set", "(IIJ)V", (void*)android_server_AlarmManagerService_set},
由上可知,通过ioctl
接口,设置定时时间。
6.4.2 等待计时结束
static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
{
#if HAVE_ANDROID_OS
int result = 0;
do
{
result = ioctl(fd, ANDROID_ALARM_WAIT);
} while (result < 0 && errno == EINTR);
if (result < 0)
{
LOGE("Unable to wait on alarm: %s\n", strerror(errno));
return 0;
}
return result;
#endif
}
以上函数的绑定如下:
{"waitForAlarm", "(I)I", (void*)android_server_AlarmManagerService_waitForAlarm},
由上可知,代码阻塞方式等待计时结束或由意外中断结束。