Alarm设置流程

1. package/apps/deskclock/src/com/android/deskclock/DeskClock.java
onCreate(){
    ...
    initViews();
}

接着看

private void initViews() {
    final ImageButton alarmButton = (ImageButton) findViewById(R.id.alarm_button);
    alarmButton.setOnClickListener(alarmClickListener);
}
if (alarmClickListener == null) {
    alarmClickListener = new View.OnClickListener() {
        public void onClick(View v) {
            startActivity(new Intent(DeskClock.this, AlarmClock.class));
        }
    };
}

找AlarmClock类

2. packages/apps/deskclock/src/com/android/deskclock/AlarmClock.java

protected void onCreate(Bundle icicle) {
...
	updateLayout();
}

private void updateLayout() {
	...
	View addAlarm = findViewById(R.id.add_alarm);
        addAlarm.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    addNewAlarm();
                }
        });
}

private void addNewAlarm() {
	startActivity(new Intent(this, SetAlarm.class));
}

3. packages/apps/deskclock/src/com/android/deskclock/SetAlarm.java

protected void onCreate(Bundle icicle) {
	...
	Button b = (Button) findViewById(R.id.alarm_save);
	b.setOnClickListener(new View.OnClickListener() {
		public void onClick(View v) {
			//if there is a alarm witch has the same hour and minutes , show timepicker again
			if(Alarms.isSametimeAlarm(getContentResolver(), mHour, mMinutes,mId)){
				sameAlarmShow(mHour, mMinutes);
				return;
			}
			saveAlarm(); //修改完毕,点击‘完成 ’生效
			// Save the alarm and pop a toast.
			if(mEnabledPref.isChecked()){
				popAlarmSetToast(SetAlarm.this, mHour, mMinutes, mRepeatPref.getDaysOfWeek());
			}
			finish();
		}
	});
	...
}

private long saveAlarm() {
	if (alarm.id == -1) {
        time = Alarms.addAlarm(this, alarm);
        // addAlarm populates the alarm with the new id. Update mId so that
		// changes to other preferences update the new alarm.
		mId = alarm.id;
	} else {
		time = Alarms.setAlarm(this, alarm);
	}
}

根据time = Alarms.addAlarm(this, alarm);
4. packages/apps/deskclock/src/com/android/deskclock/Alarms.java

public static long addAlarm(Context context, Alarm alarm) {
	if (alarm.enabled) {//如果设置的闹钟为enable则
            clearSnoozeIfNeeded(context, timeInMillis);//假设设置的时间离现在最近,则清除上次设置的闹铃时间
        }
        setNextAlert(context);
}
public static void setNextAlert(final Context context) {
	Alarm alarm = calculateNextAlert(context);
    	long time = getSnoozeAlert(context);
	if ((alarm != null && alarm.time <= time) 
		|| (alarm != null && time == -1)) {     
		enableAlert(context, alarm, alarm.time);
	} 
}


private static void enableAlert(Context context, final Alarm alarm, final long atTimeInMillis) {
...
Intent intent = new Intent(ALARM_ALERT_ACTION);
...
PendingIntent sender = PendingIntent.getBroadcast(
                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am.set(AlarmManager.POWER_OFF_WAKEUP, atTimeInMillis, sender);//原生默认设置闹钟时间
        alarm_flag_setup(atTimeInMillis); //
}

private static void alarm_flag_setup(final long alarmTimeInMillis) {
	// Flag for alarm exist or not
	private static File ALARM_FLAG_FILE = new File("/productinfo/alarm_flag");
	FileWriter command = new FileWriter(ALARM_FLAG_FILE);
	try {
		command.write(String.valueOf(timeDiffInSecs));
        command.write("\n");
        command.write(String.valueOf(alarmTimeInMillis/1000));
        command.write("\n");
    } finally {
        command.close();
        Log.v(ALARM_FLAG_FILE + " write done");
    }
}

由AlarmManager am = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 可以回到AlarmManager的类5. frameworks/base/core/java/android/app/AlarmManager.java

public void set(int type, long triggerAtTime, PendingIntent operation) {
    try {
        mService.set(type, triggerAtTime, operation);
    } catch (RemoteException ex) {
    }
}

6. 接下来要找提供这个Context.ALARM_SERVICE服务的实现,通过搜索可知是在SystemServer.java中添加上这个服务
frameworks/base/services/java/com/android/server/SystemServer.java

AlarmManagerService alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);


可知实现这个服务的是类AlarmManagerService
7. frameworks/base/services/java/com/android/server/AlarmManagerService.java

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) {
	int index = addAlarmLocked(alarm);
    if (index == 0) {
        setLocked(alarm);
    } 
}

private void setLocked(Alarm alarm){
	...
	set(mDescriptor, alarm.type, alarmSeconds, alarmNanoseconds);
}

调用本地函数private native void set(int fd, int type, long seconds, long nanoseconds);


由上可知这个方法是通过JNI调用的,接下来搜索set,可知是被如下方法注册的
8. frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp

static JNINativeMethod sMethods[] = {
	/* name, signature, funcPtr */
	{"init", "()I", (void*)android_server_AlarmManagerService_init},
	{"close", "(I)V", (void*)android_server_AlarmManagerService_close},
	{"set", "(IIJJ)V", (void*)android_server_AlarmManagerService_set},
	...
}

static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
{
	#if HAVE_ANDROID_OS
	struct timespec ts;
	ts.tv_sec = seconds;
	ts.tv_nsec = nanoseconds;

	int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
	if (result < 0)
	{
		LOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
	}
	#endif
}

接下来找回过头看看传过来的fd是哪个设备文件
9. frameworks/base/services/java/com/android/server/AlarmManagerService.java
根据set(mDescriptor, alarm.type, alarmSeconds, alarmNanoseconds);找mDescriptor

mDescriptor = init();
private native int init();

10. 再回到frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp

static JNINativeMethod sMethods[] = {
	/* name, signature, funcPtr */
	{"init", "()I", (void*)android_server_AlarmManagerService_init},
	...
}

原来操作的是下面的这个函数

static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
	#if HAVE_ANDROID_OS
	return open("/dev/alarm", O_RDWR);
	#else
	return -1;
	#endif
}








   

你可能感兴趣的:(Alarm设置流程)