640?wx_fmt=gif

640?wx_fmt=gif

极力推荐Android 开发大总结文章:欢迎收藏程序员Android 力荐 ,Android 开发者需要的必备技能

640?wx_fmt=jpeg

本篇文章主要介绍 Android 开发中的AlarmManagerService部分知识点,通过阅读本篇文章,您将收获以下内容:

1.AlarmManager的使用

本文转自网络地址如下:http://www.robinheztto.com/2017/03/10/android-alarm-1/

Android系统通过AlarmManager向应用提供定时/闹钟服务,以使应用在其生命周期之外可执行基于特定时间的操作,本篇将具体分析AlarmManager的使用及AlarmManagerService服务的初始化。

相关源码位于以下文件中:

frameworks/base/core/java/android/app/AlarmManager.javaframeworks/base/services/core/java/com/android/server/AlarmManagerService.javaframeworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp

AlarmManager的使用

1.获取AlarmManager:

Context.getSystemService(Context.ALARM_SERVICE);
  1. Alarm的类型:

  • AlarmManager.RTC_WAKEUP

  • AlarmManager.RTC

  • AlarmManager.ELAPSED_REALTIME_WAKEUP

  • AlarmManager.ELAPSED_REALTIME

WAKEUP类型的Alarm会唤醒系统,休眠状态下会增加系统的功耗,所以在使用中应尽量避免使用该种类型的Alarm。

  1. Alarm的Flag:

  • FLAG_STANDALONE

  • FLAG_WAKE_FROM_IDLE

  • FLAG_ALLOW_WHILE_IDLE

  • FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED

  • FLAG_IDLE_UNTIL

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();                }                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.javaprivate 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(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(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或时间改变事件。

640?wx_fmt=jpeg

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

640?wx_fmt=jpeg

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

Android Framework 框架系列之 AlarmManagerService(一)_第1张图片

更多相关文章

  1. 在Android中把内容写到XML文件中
  2. 【Android】volley网络框架的文件下载
  3. android 对文件的操作模式
  4. Android从网上下载文件
  5. Android遍历某个文件夹的图片并实现滑动查看的的Gallery
  6. Android SDcard目录文件操作
  7. android sdcard文件存储 + 媒体库更新方法

随机推荐

  1. Github Actions Android(安卓)CI打包配置
  2. android 学习记录
  3. Python基础——列表、元组、字典
  4. Android创建快捷方式(shortcut)
  5. Android(安卓)source code[ 源代码]下载,
  6. Android(安卓)Studio 多渠道打包遇到的问
  7. android如何取消闹铃
  8. Android(安卓)颜色代码
  9. Android(安卓)读取Assets中图片
  10. 【Android(安卓)Studio】setSupportActio