zoukankan      html  css  js  c++  java
  • rtc关机闹钟4 AlarmManagerService.java

    vim base/services/core/java/com/android/server/AlarmManagerService.java

    AlarmManager 调用 IAlarmManager, AlarmManagerService 是IAlarmManager的实现

    private final IBinder mService = new IAlarmManager.Stub() {
            @Override
            public void set(int type, long triggerAtTime, long windowLength, long interval, int flags,
                    PendingIntent operation, WorkSource workSource,
                    AlarmManager.AlarmClockInfo alarmClock) {
                final int callingUid = Binder.getCallingUid();
                if (workSource != null) {
                    getContext().enforcePermission(
                            android.Manifest.permission.UPDATE_DEVICE_STATS,
                            Binder.getCallingPid(), callingUid, "AlarmManager.set");
                }
    
                // No incoming callers can request either WAKE_FROM_IDLE or
                // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
                flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
                        | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
    
                // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
                // manager when to come out of idle mode, which is only for DeviceIdleController.
                if (callingUid != Process.SYSTEM_UID) {
                    flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
                }
    
                // If the caller is a core system component, and not calling to do work on behalf
                // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
                // will allow these alarms to go off as normal even while idle, with no timing
                // restrictions.
                if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
                    flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                }
    
                // If this is an exact time alarm, then it can't be batched with other alarms.
                if (windowLength == AlarmManager.WINDOW_EXACT) {
                    flags |= AlarmManager.FLAG_STANDALONE;
                }
    
                // If this alarm is for an alarm clock, then it must be standalone and we will
                // use it to wake early from idle if needed.
                if (alarmClock != null) {
                    flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
                }
    
                setImpl(type, triggerAtTime, windowLength, interval, operation,
                        flags, workSource, alarmClock, callingUid);
            }

    void setImpl(int type, long triggerAtTime, long windowLength, long interval,
                PendingIntent operation, int flags, WorkSource workSource,
                AlarmManager.AlarmClockInfo alarmClock, int callingUid) {
            if (operation == null) {
                Slog.w(TAG, "set/setRepeating ignored because there is no intent");
                return;
            }
    
            // Sanity check the window length.  This will catch people mistakenly
            // trying to pass an end-of-window timestamp rather than a duration.
            if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
                Slog.w(TAG, "Window length " + windowLength
                        + "ms suspiciously long; limiting to 1 hour");
                windowLength = AlarmManager.INTERVAL_HOUR;
            }
    
            // Sanity check the recurrence interval.  This will catch people who supply
            // seconds when the API expects milliseconds.
            final long minInterval = mConstants.MIN_INTERVAL;
            if (interval > 0 && interval < minInterval) {
                Slog.w(TAG, "Suspiciously short interval " + interval
                        + " millis; expanding to " + (minInterval/1000)
                        + " seconds");
                interval = minInterval;
            }
    
            if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
                throw new IllegalArgumentException("Invalid alarm type " + type);
            }
    
            if (triggerAtTime < 0) {
                final long what = Binder.getCallingPid();
                Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
                        + " pid=" + what);
                triggerAtTime = 0;
            }
    
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long nominalTrigger = convertToElapsed(triggerAtTime, type);
            // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
            final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
            final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
    
            final long maxElapsed;
            if (windowLength == AlarmManager.WINDOW_EXACT) {
                maxElapsed = triggerElapsed;
            } else if (windowLength < 0) {
                maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
                // Fix this window in place, so that as time approaches we don't collapse it.
                windowLength = maxElapsed - triggerElapsed;
            } else {
                maxElapsed = triggerElapsed + windowLength;
            }
    
            synchronized (mLock) {
                if (DEBUG_BATCH) {
                    Slog.v(TAG, "set(" + operation + ") : type=" + type
                            + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
                            + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
                            + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
                }
                setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                        interval, operation, flags, true, workSource, alarmClock, callingUid);
            }
        }
    
        private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
                long maxWhen, long interval, PendingIntent operation, int flags,
                boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
                int uid) {
            Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
                    operation, workSource, flags, alarmClock, uid);
            removeLocked(operation);
            setImplLocked(a, false, doValidate);
        }
    
        private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
            if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
                // This is a special alarm that will put the system into idle until it goes off.
                // The caller has given the time they want this to happen at, however we need
                // to pull that earlier if there are existing alarms that have requested to
                // bring us out of idle at an earlier time.
                if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
                    a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
                }
                // Add fuzz to make the alarm go off some time before the actual desired time.
                final long nowElapsed = SystemClock.elapsedRealtime();
                final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
                if (fuzz > 0) {
                    if (mRandom == null) {
                        mRandom = new Random();
                    }
                    final int delta = mRandom.nextInt(fuzz);
                    a.whenElapsed -= delta;
                    if (false) {
                        Slog.d(TAG, "Alarm when: " + a.whenElapsed);
                        Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
                        Slog.d(TAG, "Applied fuzz: " + fuzz);
                        Slog.d(TAG, "Final delta: " + delta);
                        Slog.d(TAG, "Final when: " + a.whenElapsed);
                    }
                    a.when = a.maxWhenElapsed = a.whenElapsed;
                }
    
            } else if (mPendingIdleUntil != null) {
                // We currently have an idle until alarm scheduled; if the new alarm has
                // not explicitly stated it wants to run while idle, then put it on hold.
                if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
                        | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
                        | AlarmManager.FLAG_WAKE_FROM_IDLE))
                        == 0) {
                    mPendingWhileIdleAlarms.add(a);
                    return;
                }
            }
    
            int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
                    ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
            if (whichBatch < 0) {
                Batch batch = new Batch(a);
                addBatchLocked(mAlarmBatches, batch);
            } else {
                Batch batch = mAlarmBatches.get(whichBatch);
                if (batch.add(a)) {
                    // The start time of this batch advanced, so batch ordering may
                    // have just been broken.  Move it to where it now belongs.
                    mAlarmBatches.remove(whichBatch);
                    addBatchLocked(mAlarmBatches, batch);
                }
            }
    
            if (a.alarmClock != null) {
                mNextAlarmClockMayChange = true;
            }
    
            boolean needRebatch = false;
    
            if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
                mPendingIdleUntil = a;
                mConstants.updateAllowWhileIdleMinTimeLocked();
                needRebatch = true;
            } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
                if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
                    mNextWakeFromIdle = a;
                    // If this wake from idle is earlier than whatever was previously scheduled,
                    // and we are currently idling, then we need to rebatch alarms in case the idle
                    // until time needs to be updated.
                    if (mPendingIdleUntil != null) {
                        needRebatch = true;
                    }
                }
            }
    
            if (!rebatching) {
                if (DEBUG_VALIDATE) {
                    if (doValidate && !validateConsistencyLocked()) {
                        Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
                                + " when(hex)=" + Long.toHexString(a.when)
                                + " whenElapsed=" + a.whenElapsed
                                + " maxWhenElapsed=" + a.maxWhenElapsed
                                + " interval=" + a.repeatInterval + " op=" + a.operation
                                + " flags=0x" + Integer.toHexString(a.flags));
                        rebatchAllAlarmsLocked(false);
                        needRebatch = false;
                    }
                }
    
                if (needRebatch) {
                    rebatchAllAlarmsLocked(false);
                }
    
                rescheduleKernelAlarmsLocked();
                updateNextAlarmClockLocked();
            }
        }
    
    
  • 相关阅读:
    对Promise的研究4
    对Promise的研究3
    对Promise的研究2
    对promise的研究1
    数据结构_栈
    数据结构_队列(普通队列和双端队列)
    数据结构_链表(单链表,单向循环链表,双链表)
    数据库进行参数化,查询一行或多行语句
    数据库基础应用
    选择排序
  • 原文地址:https://www.cnblogs.com/muhuacat/p/5258963.html
Copyright © 2011-2022 走看看