AlarmManagerService(一)

本篇文章主要介紹 Android
開發中的 AlarmManagerService 部分知識點,通過閱讀本篇文章,您將收穫以下內容:
1.AlarmManager的使用
2.AlarmManagerService初始化
本文轉自網路地址如下: http://www.robinheztto.com/2017/03/10/android-alarm-1/
公眾號ID:ProgramAndroid
獲取更多資訊

微信公眾號:ProgramAndroid
我們不是牛逼的程式設計師,我們只是程式開發中的墊腳石。
我們不傳送紅包,我們只是紅包的搬運工。
Android系統通過AlarmManager嚮應用提供定時/鬧鐘服務,以使應用在其生命週期之外可執行基於特定時間的操作,本篇將具體分析AlarmManager的使用及AlarmManagerService服務的初始化。
相關原始碼位於以下檔案中:
frameworks/base/core/java/android/app/AlarmManager.java frameworks/base/services/core/java/com/android/server/AlarmManagerService.java frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
AlarmManager的使用
1.獲取AlarmManager:
Alarm相關的服務介面定義在AlarmManager中,與其他系統服務一樣,通過Context獲取AlarmManager。
Context.getSystemService(Context.ALARM_SERVICE);
- Alarm的型別:
-
AlarmManager.RTC_WAKEUP
使用系統絕對時間(當前系統時間,System.currentTimeMillis()),系統休眠狀態也將喚醒系統。
-
AlarmManager.RTC
使用系統絕對時間(當前系統時間,System.currentTimeMillis()),系統休眠狀態下不可用。
-
AlarmManager.ELAPSED_REALTIME_WAKEUP
使用系統相對時間(相對系統啟動時間,SystemClock.elapsedRealtime()),系統休眠狀態也將喚醒系統。
-
AlarmManager.ELAPSED_REALTIME
使用系統相對時間(相對系統啟動時間,SystemClock.elapsedRealtime()),系統休眠狀態下不可用
RTC/RTC_WAKEUP和ELAPSED_REALTIME/ELAPSED_REALTIME_WAKEUP最大的差別就是RTC受time zone/locale的影響,可以通過修改手機時間觸發鬧鐘事件,ELAPSED_REALTIME/ELAPSED_REALTIME_WAKEUP要通過真實時間的流逝,即使在休眠狀態時間也會被計算。
WAKEUP型別的Alarm會喚醒系統,休眠狀態下會增加系統的功耗,所以在使用中應儘量避免使用該種類型的Alarm。
- Alarm的Flag:
- FLAG_STANDALONE
指定stand-alone精準alarm,該alarm不會被batch,設定WINDOW_EXACT的alarm會指定此flag。 - FLAG_WAKE_FROM_IDLE
指定alarm即使在idle模式也將喚醒系統,如alarm clock。 - FLAG_ALLOW_WHILE_IDLE
針對Doze模式,alarm即使在系統idle狀態下也會執行,但是不會使系統退出idle mode,只有特殊alarm才需要標記該Flag。 - FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
針對Doze模式,alarm即使在系統idle狀態下也會執行而且沒有時間限制,但是不會使系統退出idle mode,只有特殊alarm才需要標記該Flag。 - FLAG_IDLE_UNTIL
只有呼叫AlarmManager.setIdleUntil()接口才可能設定該flag,用來使系統進入idle mode直到marker alarm被執行,執行marker alarm時系統會退出idle mode(設定後進入DozeIdle狀態讓Alarm系統掛起,直到這個Alarm到期)。
4.Alarm的set:
非精準Alarm,其window被指定為WINDOW_HEURISTIC:
public void set(int type, long triggerAtMillis, PendingIntent operation) {} public void set(int type, long triggerAtMillis, String tag, OnAlarmListener listener,Handler targetHandler) {} public void setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation) {} public void setInexactRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation) {}// Doze模式下 public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {}
精準Alarm,其window被標記為WINDOW_EXACT
public void setWindow(int type, long windowStartMillis, long windowLengthMillis,PendingIntent operation) {} public void setWindow(int type, long windowStartMillis, long windowLengthMillis, String tag, OnAlarmListener listener, Handler targetHandler) {} public void setExact(int type, long triggerAtMillis, PendingIntent operation) {} public void setExact(int type, long triggerAtMillis, String tag, OnAlarmListener listener, Handler targetHandler) {} public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) {}// Doze模式下 public void setIdleUntil(int type, long triggerAtMillis, String tag, OnAlarmListener listener,Handler targetHandler) {} public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {}
AlarmManager中的set方法最終都是呼叫setImpl,下面是setImpl的具體實現。
frameworks/base/core/java/android/app/AlarmManager.java
private void setImpl(@AlarmType int type, long triggerAtMillis, long windowMillis, long intervalMillis, int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag, Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) { if (triggerAtMillis < 0) { /* NOTYET if (mAlwaysExact) { // Fatal error for KLP+ apps to use negative trigger times throw new IllegalArgumentException("Invalid alarm trigger time " + triggerAtMillis); } */ triggerAtMillis = 0; } // OnAlarmListener封裝到ListenerWrapper,並新增到sWrappers管理 ListenerWrapper recipientWrapper = null; if (listener != null) { synchronized (AlarmManager.class) { if (sWrappers == null) { sWrappers = new ArrayMap<OnAlarmListener, ListenerWrapper>(); } recipientWrapper = sWrappers.get(listener); // no existing wrapper => build a new one if (recipientWrapper == null) { recipientWrapper = new ListenerWrapper(listener); sWrappers.put(listener, recipientWrapper); } } final Handler handler = (targetHandler != null) ? targetHandler : mMainThreadHandler; recipientWrapper.setHandler(handler); } // 呼叫AlarmManagerService try { mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags, operation, recipientWrapper, listenerTag, workSource, alarmClock); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }
AlarmManagerService初始化
public AlarmManagerService(Context context) { super(context); mConstants = new Constants(mHandler); }
下面先看Constants類的具體實現,主要負責Alarm相關的常量的讀取及更新。
private final class Constants extends ContentObserver { // Key names stored in the settings value. private static final String KEY_MIN_FUTURITY = "min_futurity"; private static final String KEY_MIN_INTERVAL = "min_interval"; private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time"; private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time"; private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION = "allow_while_idle_whitelist_duration"; private static final String KEY_LISTENER_TIMEOUT = "listener_timeout"; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY; private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000; private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000; private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; // Minimum alarm recurrence interval public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL; // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle. public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME; // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling. public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME; // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE. public long ALLOW_WHILE_IDLE_WHITELIST_DURATION = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION; // Direct alarm listener callback timeout public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); private long mLastAllowWhileIdleWhitelistDuration = -1; public Constants(Handler handler) { super(handler); updateAllowWhileIdleMinTimeLocked(); updateAllowWhileIdleWhitelistDurationLocked(); } public void start(ContentResolver resolver) { mResolver = resolver; mResolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.ALARM_MANAGER_CONSTANTS), false, this); updateConstants(); } public void updateAllowWhileIdleMinTimeLocked() { mAllowWhileIdleMinTime = mPendingIdleUntil != null ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME; } public void updateAllowWhileIdleWhitelistDurationLocked() { if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) { mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION; BroadcastOptions opts = BroadcastOptions.makeBasic(); opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION); mIdleOptions = opts.toBundle(); } } @Override public void onChange(boolean selfChange, Uri uri) { updateConstants(); } private void updateConstants() { synchronized (mLock) { try { mParser.setString(Settings.Global.getString(mResolver, Settings.Global.ALARM_MANAGER_CONSTANTS)); } catch (IllegalArgumentException e) { // Failed to parse the settings string, log this and move on // with defaults. Slog.e(TAG, "Bad alarm manager settings", e); } MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY); MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL); ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME); ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME); ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong( KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION); LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT); updateAllowWhileIdleMinTimeLocked(); updateAllowWhileIdleWhitelistDurationLocked(); } } void dump(PrintWriter pw) { pw.println("Settings:"); pw.print(""); pw.print(KEY_MIN_FUTURITY); pw.print("="); TimeUtils.formatDuration(MIN_FUTURITY, pw); pw.println(); pw.print(""); pw.print(KEY_MIN_INTERVAL); pw.print("="); TimeUtils.formatDuration(MIN_INTERVAL, pw); pw.println(); pw.print(""); pw.print(KEY_LISTENER_TIMEOUT); pw.print("="); TimeUtils.formatDuration(LISTENER_TIMEOUT, pw); pw.println(); pw.print(""); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("="); TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw); pw.println(); pw.print(""); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("="); TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw); pw.println(); pw.print(""); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("="); TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw); pw.println(); } }
AlarmManagerService例項化後即呼叫onStart()方法。
@Override public void onStart() { // native層初始化 mNativeData = init(); mNextWakeup = mNextNonWakeup = 0; // We have to set current TimeZone info to kernel // because kernel doesn't keep this after reboot setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY)); /// M:add for PPL feature ,@{ initPpl(); ///@} /// M: For handling non-wakeup alarms while WFD is connected registerWFDStatusChangeReciever(); ///@} /// M: added for BG powerSaving feature @{ initAlarmGrouping(); ///@} // Also sure that we're booting with a halfway sensible current time if (mNativeData != 0) { final long systemBuildTime = Environment.getRootDirectory().lastModified(); if (System.currentTimeMillis() < systemBuildTime) { Slog.i(TAG, "Current time only " + System.currentTimeMillis() + ", advancing to build time " + systemBuildTime); setKernelTime(mNativeData, systemBuildTime); } } // Determine SysUI's uid final PackageManager packMan = getContext().getPackageManager(); try { PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0); ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0); if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { mSystemUiUid = sysUi.uid; } else { Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION + " defined by non-privileged app " + sysUi.packageName + " - ignoring"); } } catch (NameNotFoundException e) { } if (mSystemUiUid <= 0) { Slog.wtf(TAG, "SysUI package not found!"); } PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*"); mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0, new Intent(Intent.ACTION_TIME_TICK).addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0, UserHandle.ALL); Intent intent = new Intent(Intent.ACTION_DATE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent, Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL); // now that we have initied the driver schedule the alarm mClockReceiver = new ClockReceiver(); mClockReceiver.scheduleTimeTickEvent(); mClockReceiver.scheduleDateChangedEvent(); mInteractiveStateReceiver = new InteractiveStateReceiver(); mUninstallReceiver = new UninstallReceiver(); if (mNativeData != 0) { AlarmThread waitThread = new AlarmThread(); waitThread.start(); } else { Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler."); } try { ActivityManager.getService().registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_IDLE, ActivityManager.PROCESS_STATE_UNKNOWN, null); } catch (RemoteException e) { // ignored; both services live in system_server } publishBinderService(Context.ALARM_SERVICE, mService); publishLocalService(LocalService.class, new LocalService()); }
在onStart()後,SYSTEM_SERVICES_READY時onBootPhase()將被回撥。
@Override public void onBootPhase(int phase) { if (phase == PHASE_SYSTEM_SERVICES_READY) { mConstants.start(getContext().getContentResolver()); mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class); } }
回到onStart(),分析native層init的呼叫,下面看native init()的實現。
frameworks/base/services/core/java/com/android/server/AlarmManagerService.java private native long init();
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"init", "()J", (void*)android_server_AlarmManagerService_init}, {"close", "(J)V", (void*)android_server_AlarmManagerService_close}, {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set}, {"clear", "(JIJJ)V", (void*)android_server_AlarmManagerService_clear}, {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm}, {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime}, {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, }; int register_android_server_AlarmManagerService(JNIEnv* env) { return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService", sMethods, NELEM(sMethods)); }
register_android_server_AlarmManagerService中註冊了native方法,init()即呼叫android_server_AlarmManagerService_init。
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) { // 初始化/dev/alarm jlong ret = init_alarm_driver(); if (ret) { return ret; } // 如果初始化/dev/alarm不成功,則進入timerfd初始化,現一般採用timerfd方式採用 return init_timerfd(); }
Native Alarm初始化採用了二種方案,AlarmDriver與timerfd,當alarm_driver失敗時則使用timerfd,現在基本使用的是timerfd。如下,AlarmImpl是Native層Alarm操作的統一介面,AlarmImplAlarmDriver與AlarmImplTimerFd是AlarmDriver與timerfd二種不同方式的具體實現。
class AlarmImpl { public: AlarmImpl(int *fds, size_t n_fds); virtual ~AlarmImpl(); virtual int set(int type, struct timespec *ts) = 0; virtual int clear(int type, struct timespec *ts) = 0; virtual int setTime(struct timeval *tv) = 0; virtual int waitForAlarm() = 0; protected: int *fds; size_t n_fds; }; class AlarmImplAlarmDriver : public AlarmImpl { public: AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } int set(int type, struct timespec *ts); int clear(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); }; class AlarmImplTimerFd : public AlarmImpl { public: AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) : AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { } ~AlarmImplTimerFd(); int set(int type, struct timespec *ts); int clear(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); private: int epollfd; int rtc_id; };
下面先看AlarmDriver的方式。
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
static jlong init_alarm_driver() { // 開啟/dev/alarm,失敗則退出 int fd = open("/dev/alarm", O_RDWR); if (fd < 0) { ALOGV("opening alarm driver failed: %s", strerror(errno)); return 0; } // 根據fd建立AlarmImplAlarmDriver物件 AlarmImpl *ret = new AlarmImplAlarmDriver(fd); return reinterpret_cast<jlong>(ret); } int AlarmImplAlarmDriver::set(int type, struct timespec *ts) { return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); } int AlarmImplAlarmDriver::clear(int type, struct timespec *ts) { return ioctl(fds[0], ANDROID_ALARM_CLEAR(type), ts); } int AlarmImplAlarmDriver::setTime(struct timeval *tv) { struct timespec ts; int res; ts.tv_sec = tv->tv_sec; ts.tv_nsec = tv->tv_usec * 1000; res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts); if (res < 0) ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); return res; } int AlarmImplAlarmDriver::waitForAlarm() { return ioctl(fds[0], ANDROID_ALARM_WAIT); }
AlarmImplAlarmDriver中主要通過ioctl來實現Alarm的操作。當init_alarm_driver開啟/dev/alarm失敗時,選擇timerfd實現Alarm的操作。
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { CLOCK_REALTIME_ALARM, CLOCK_REALTIME, CLOCK_BOOTTIME_ALARM, CLOCK_BOOTTIME, CLOCK_MONOTONIC, CLOCK_POWEROFF_ALARM, CLOCK_REALTIME, }; static jlong init_timerfd() { int epollfd; int fds[N_ANDROID_TIMERFDS]; // 建立epoll控制代碼,監聽N_ANDROID_TIMERFDS個檔案描述符 epollfd = epoll_create(N_ANDROID_TIMERFDS); if (epollfd < 0) { ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS, strerror(errno)); return 0; } for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { // 建立定時器檔案 fds[i] = timerfd_create(android_alarm_to_clockid[i], 0); if (fds[i] < 0) { ALOGV("timerfd_create(%u) failed: %s",android_alarm_to_clockid[i], strerror(errno)); close(epollfd); for (size_t j = 0; j < i; j++) { close(fds[j]); } return 0; } } // 根據fds建立AlarmImplTimerFd物件,AlarmImplTimerFd也繼承於AlarmImpl AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc()); for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { epoll_event event; event.events = EPOLLIN | EPOLLWAKEUP; event.data.u32 = i; // 將建立的定時器檔案列表加入到epoll監聽中 int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event); if (err < 0) { ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); delete ret; return 0; } } struct itimerspec spec; memset(&spec, 0, sizeof(spec)); int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT], TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL); if (err < 0) { ALOGV("timerfd_settime() failed: %s", strerror(errno)); delete ret; return 0; } return reinterpret_cast<jlong>(ret); }
init_timerfd()中利用epoll+timerfd的方式,建立timerfd檔案並加入到epoll監聽中,建立的定時器檔案中,我們主要使用的是CLOCK_REALTIME_ALARM,CLOCK_BOOTTIME_ALARM,CLOCK_POWEROFF_ALARM,分別對應RTC_WAKEUP(RTC),ELAPSED_REALTIME_WAKEUP(ELAPSED_REALTIME),RTC_POWEROFF_WAKEUP。下面具體看一下AlarmImplTimerFd::set設定定時器的實現。
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
int AlarmImplTimerFd::set(int type, struct timespec *ts) { if (type > ANDROID_ALARM_TYPE_COUNT) { errno = EINVAL; return -1; } if (!ts->tv_nsec && !ts->tv_sec) { ts->tv_nsec = 1; } /* timerfd interprets 0 = disarm, so replace with a practically equivalent deadline of 1 ns */ struct itimerspec spec; memset(&spec, 0, sizeof(spec)); memcpy(&spec.it_value, ts, sizeof(spec.it_value)); // 直接呼叫timerfd_settime設定Alarm定時時間 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); }
在waitForAlarm中將等待Alarm的到來,下面看AlarmImplTimerFd::waitForAlarm的實現。
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
int AlarmImplTimerFd::waitForAlarm() { epoll_event events[N_ANDROID_TIMERFDS]; // 利用epolle_wait監聽定時器的事件 int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1); if (nevents < 0) { return nevents; } int result = 0; // 事件到來,迴圈讀取定時器檔案 for (int i = 0; i < nevents; i++) { uint32_t alarm_idx = events[i].data.u32; uint64_t unused; ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused)); if (err < 0) { if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) { // 時間改變 result |= ANDROID_ALARM_TIME_CHANGE_MASK; } else { return err; } } else { // 設定result為觸發的alarm_idx result |= (1 << alarm_idx); } } // 返回結果給AlarmManagerService return result; }
waitForAlarm中一直在epoll_wait監聽等待Alarm fd事件,當事件到來,迴圈讀取定時器檔案並向上層返回觸發的Alarm index或時間改變事件。
至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。期待您的關注,
感謝您的閱讀,謝謝!
如有侵權,請聯絡小編,小編對此深感抱歉,同時小編會立即停止侵權行為。
歡迎關注微信公眾號:程式設計師Android
公眾號ID:ProgramAndroid
獲取更多資訊

微信公眾號:ProgramAndroid
我們不是牛逼的程式設計師,我們只是程式開發中的墊腳石。
我們不傳送紅包,我們只是紅包的搬運工。

點選閱讀原文,獲取更多福利
