Android 屏保時間的介紹

Android 屏保時間的介紹

屏保 當(dāng)Android 系統(tǒng)處于無操作一段時間之后就會處于一個屏保的狀態(tài)残拐,當(dāng)再過一點時間Android 就會進(jìn)入一個休眠狀體渗磅。

默認(rèn)時間的設(shè)置

SettingsProvider 里面設(shè)置默認(rèn)的超時時間。defaults.xml 里面配置的默認(rèn)值寿桨,

    <integer name="def_screen_off_timeout">60000</integer> // 1分鐘

DatabaseHelper 里面loadSystemSettings 里面對默認(rèn)值進(jìn)行設(shè)置司光。

private void loadSystemSettings(SQLiteDatabase db) {
        SQLiteStatement stmt = null;
        try {
            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
                    + " VALUES(?,?);");
            ···
            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                    R.integer.def_screen_off_timeout); // 本地化保存
            ···
        } finally {
            if (stmt != null) stmt.close();
        }
    }

如何對默認(rèn)值進(jìn)行設(shè)置琅坡。可以使用Overlay 進(jìn)行設(shè)置,Overlay怎么設(shè)置 就可以參考google/atv/overlay/TvSettingsProviderOverlay 參考google 怎么設(shè)置的残家。
我們只對TvSettingsProvider 里面的defaults 進(jìn)行重寫把需要設(shè)置的 def_screen_off_timeout 重新賦值就行榆俺。

    <integer name="def_screen_off_timeout">120000</integer> // 2分鐘

應(yīng)用的設(shè)置和使用

這種設(shè)置功能只在設(shè)置里面進(jìn)行設(shè)置,其他的應(yīng)用里面正常不會操作。

  • 獲取當(dāng)前的默認(rèn)時間
    Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT,
    DEFAULT_DREAM_TIME_MS);
  • 修改默認(rèn)時間
    Settings.System.putInt(mView.provideContext().getContentResolver(), SCREEN_OFF_TIMEOUT, time);

普通應(yīng)用 當(dāng)我們頁面不像進(jìn)入屏保是 使用 keep_screen_on茴晋。
1 manifest 里面 設(shè)置 android:keepScreenOn="true"
2 時java 代碼里面進(jìn)行設(shè)置陪捷。
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
3 是使用PowerManager WakeLock 使用,這種我沒使用過诺擅,
pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyTag");
wl.acquire();
wl.release();

屏保的計算

PowerManagerService里面
updatePowerStateLocked 這個方法是PowerManagerService 的核心方法 里面是對 屏幕的各種狀態(tài)市袖,用戶活動,電源情況等各種情況的梳理都在這個方法里面掀虎。
屬性 mScreenOffTimeoutSetting 是對屏保時間的記錄凌盯,正常應(yīng)該會有初始值的獲取和值變化的更新付枫。

 public void systemReady(IAppOpsService appOps) {
        synchronized (mLock) {
            mSystemReady = true;
            ···
            mSettingsObserver = new SettingsObserver(mHandler);
           ···
            updateSettingsLocked(); // 初始化 
            mDirty |= DIRTY_BATTERY_STATE;
            updatePowerStateLocked(); // 更新各種狀態(tài)
        }

        final ContentResolver resolver = mContext.getContentResolver();
        ···
        resolver.registerContentObserver(Settings.System.getUriFor(
                Settings.System.SCREEN_OFF_TIMEOUT),
                false, mSettingsObserver, UserHandle.USER_ALL); // 監(jiān)聽變化
      ···
    }

  private final class SettingsObserver extends ContentObserver {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            synchronized (mLock) {
                handleSettingsChangedLocked(); // 變化時候進(jìn)行
            }
        }
    }

void handleSettingsChangedLocked() {
        updateSettingsLocked(); // 監(jiān)聽變化
        updatePowerStateLocked(); // 更新各種狀態(tài)
    }

updateSettingsLocked 里面 對 mScreenOffTimeoutSetting進(jìn)行賦值烹玉。
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);

mSettingsObserver 里面監(jiān)聽到變化之后 立馬調(diào)用 updateSettingsLocked 更新值的變化,之后調(diào)用updatePowerStateLocked阐滩,根據(jù)最新的值取更新各個狀態(tài)二打。

updatePowerStateLocked 方法

/**
    * Updates the global power state based on dirty bits recorded in mDirty.
    *
    * This is the main function that performs power state transitions.
    * We centralize them here so that we can recompute the power state completely
    * each time something important changes, and ensure that we do it the same
    * way each time.  The point is to gather all of the transition logic here.
    */
   private void updatePowerStateLocked() {
    ···

       Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
// 查詢了一下 Trace   成對出現(xiàn) key 一樣 記錄 cpu 線程 耗時等信息
// 類似于 android studio 的 profile 下抓取信息

       try {
           // Phase 0: Basic state updates.
           updateIsPoweredLocked(mDirty); // 更新電源信息 是否 插入電源 電源類型 電池的狀態(tài)  有變化的話 更新mDirty 的值 。 
           updateStayOnLocked(mDirty); // 更新屏幕喚醒 
           updateScreenBrightnessBoostLocked(mDirty);// 更新屏幕亮度 時間 增強結(jié)束 里面通過 handler 發(fā)送時間

           // Phase 1: Update wakefulness.
           // Loop because the wake lock and user activity computations are influenced
           // by changes in wakefulness.
           final long now = mClock.uptimeMillis();
           int dirtyPhase2 = 0;
           for (;;) {
               int dirtyPhase1 = mDirty;
               dirtyPhase2 |= dirtyPhase1;
               mDirty = 0;
               updateWakeLockSummaryLocked(dirtyPhase1); // 更新 mWakeLockSummary 遍歷 所有的 mWakeLocks 把 WakeLock 信息都保存到 mWakeLockSummary 掂榔。
               updateUserActivitySummaryLocked(now, dirtyPhase1); // 更新用戶時間
               updateAttentiveStateLocked(now, dirtyPhase1);
               if (!updateWakefulnessLocked(dirtyPhase1)) { // 設(shè)置Wakefulness 狀態(tài) 包含dream
                   break; 
               }
           }

           // Phase 2: Lock profiles that became inactive/not kept awake.
           updateProfilesLocked(now);

           // Phase 3: Update display power state.
           final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); // 請求display 進(jìn)行變化操作

           // Phase 4: Update dream state (depends on display ready signal).
           updateDreamLocked(dirtyPhase2, displayBecameReady); // dream 操作

           // Phase 5: Send notifications, if needed.
           finishWakefulnessChangeIfNeededLocked(); // 發(fā)送通知

           // Phase 6: Update suspend blocker.
           // Because we might release the last suspend blocker here, we need to make sure
           // we finished everything else first!
           updateSuspendBlockerLocked();
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_POWER);
       }
   }

updatePowerStateLocked 方法里面有四個方法對屏保設(shè)置有關(guān)继效。
1 updateUserActivitySummaryLocked
方法 updateUserActivitySummaryLocked 更新mUserActivitySummary 用來總結(jié)用戶請求系統(tǒng)狀態(tài),比如設(shè)置屏幕 bright dream dim 等装获。
注意 nextTimeout hasUserActivitySummary 循環(huán)內(nèi)部 groupUserActivitySummary 和groupNextTimeout 內(nèi)部變量瑞信。
內(nèi)部循環(huán) 通過 groupUserActivitySummary groupNextTimeout 計算出 nextTimeout hasUserActivitySummary 。
最終調(diào)用 scheduleUserInactivityTimeout-- 》 mHandler ==〉》MSG_USER_ACTIVITY_TIMEOUT --》 handleUserActivityTimeout(){
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();}

 /**
     * Updates the value of mUserActivitySummary to summarize the user requested
     * state of the system such as whether the screen should be bright or dim.
     * Note that user activity is ignored when the system is asleep.
      
     *
     */
    private void updateUserActivitySummaryLocked(long now, int dirty) {
        // Update the status of the user activity timeout timer.
        if ((dirty & (DIRTY_DISPLAY_GROUP_WAKEFULNESS | DIRTY_WAKE_LOCKS
                | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) == 0) {
            return;
        }
        mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

        final long attentiveTimeout = getAttentiveTimeoutLocked();// 進(jìn)入Sleep 之前得提示得延時時間
     // 獲取休眠 超時時長
        final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
      // 獲取屏保超時時長
        long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
                attentiveTimeout);
// 獲取dim時長 由 休眠市場 乘以 dim 百分比 獲取再與默認(rèn)值 做對比取最大值
        final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
// 根據(jù) faceDown 標(biāo)記 重新設(shè)置 屏保超時時長  臉部朝下的判斷
        screenOffTimeout =
                getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
        final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
        long nextTimeout = -1; // 最終 nextTime  計算下面Inactivity 的時間
        boolean hasUserActivitySummary = false; // 用戶請求是否變化
        for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
            int groupUserActivitySummary = 0; // 循環(huán)內(nèi)部 用戶請求屏幕變化
            long groupNextTimeout = 0; // 循環(huán)內(nèi)部 next inactivity 的時間 
            if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) {
                final long lastUserActivityTime =
                         mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); 
                final long lastUserActivityTimeNoChangeLights =
                        mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
                                groupId);
// 判斷接下來是 繼續(xù) screen 還是 進(jìn)入 dim
                if (lastUserActivityTime >= mLastWakeTime) { // 判斷 上次用戶活動時間 大于上次wake 時間
                    groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
                    if (now < groupNextTimeout) { // 沒到dim 時間 繼續(xù) 亮屏
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        groupNextTimeout = lastUserActivityTime + screenOffTimeout;
                        if (now < groupNextTimeout) { // 到了dim 時間 標(biāo)記dim                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }

         //  根據(jù) DisplayPowerRequest 來設(shè)置 顯示類型
                if (groupUserActivitySummary == 0
                        && lastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                    groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout;
                    if (now < groupNextTimeout) {
                        final DisplayPowerRequest displayPowerRequest =
                                mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
                        if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
                                || displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                        } else if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
                            groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }

                if (groupUserActivitySummary == 0) {
                    if (sleepTimeout >= 0) { // 休眠時常 
                        final long anyUserActivity = Math.max(lastUserActivityTime,
                                lastUserActivityTimeNoChangeLights);
                        if (anyUserActivity >= mLastWakeTime) {
                            groupNextTimeout = anyUserActivity + sleepTimeout;
                            if (now < groupNextTimeout) { // 還沒超過休眠的時間
                                groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                            }
                        }
                    } else {
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;// 一直休眠
                        groupNextTimeout = -1;
                    }
                }

                if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM
                        && userInactiveOverride) {
                    if ((groupUserActivitySummary &
                            (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {// 保持 bright 或者dim
                        // Device is being kept awake by recent user activity
                        if (mOverriddenTimeout == -1) {
                            // Save when the next timeout would have occurred
                            mOverriddenTimeout = groupNextTimeout;
                        }
                    }
                    groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                    groupNextTimeout = -1;
                }

                if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
                        && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
                        & WAKE_LOCK_STAY_AWAKE) == 0) { // 保持亮度并且 沒有 STAY_AWAKE 的情況
                    groupNextTimeout = mAttentionDetector.updateUserActivity(groupNextTimeout,
                            screenDimDuration); // 獲取下次檢查dim 時間
                }

                hasUserActivitySummary |= groupUserActivitySummary != 0;

                if (nextTimeout == -1) {
                    nextTimeout = groupNextTimeout;
                } else if (groupNextTimeout != -1) {
                    nextTimeout = Math.min(nextTimeout, groupNextTimeout);
                }
            }

            mDisplayGroupPowerStateMapper.setUserActivitySummaryLocked(groupId,
                    groupUserActivitySummary);

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateUserActivitySummaryLocked: groupId=" + groupId
                        + ", mWakefulness=" + wakefulnessToString(
                        mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId))
                        + ", mUserActivitySummary=0x" + Integer.toHexString(
                        groupUserActivitySummary)
                        + ", nextTimeout=" + TimeUtils.formatUptime(groupNextTimeout));
            }
        }

        final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
        if (nextProfileTimeout > 0) {
            nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
        }

        if (hasUserActivitySummary && nextTimeout >= 0) {
            scheduleUserInactivityTimeout(nextTimeout);
        }
    }

2 updateWakefulnessLocked
方法穴豫。updateWakefulnessLocked 返回 false 退出循環(huán)
for 循環(huán)最多走一次 dirty = 0 時候 退出 有第二次的話 dirty 被重新賦值為0凡简。
里面 sleepDisplayGroupNoUpdateLocked 和sleepDisplayGroupNoUpdateLocked 更新 wakefullness 的狀態(tài)。

 private boolean updateWakefulnessLocked(int dirty) {
        boolean changed = false;
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
                | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_DOCK_STATE | DIRTY_ATTENTIVE | DIRTY_SETTINGS
                | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
            final long time = mClock.uptimeMillis();
            for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
//屏幕是喚醒狀態(tài)并且將要推出喚醒 (屏本啵或者休眠) 
                if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(id) == WAKEFULNESS_AWAKE
                        && isItBedTimeYetLocked(id)) {.
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "updateWakefulnessLocked: Bed time for group " + id);
                    }
                    if (isAttentiveTimeoutExpired(id, time)) { // 提醒時間到了
                        changed = sleepDisplayGroupNoUpdateLocked(id, time,
                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
                                PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
                    } else if (shouldNapAtBedTimeLocked()) {
//是否支持屏保
                        changed = dreamDisplayGroupNoUpdateLocked(id, time, Process.SYSTEM_UID);
                    } else {
// 正常滅屏 超市自動滅屏
                        changed = sleepDisplayGroupNoUpdateLocked(id, time,
                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
                    }
                }
            }
        }
        return changed;
    }

dreamDisplayGroupNoUpdateLocked 設(shè)置當(dāng)前之后的狀態(tài)是 dream 狀態(tài)秤涩。

 private boolean dreamDisplayGroupNoUpdateLocked(int groupId, long eventTime, int uid) {
       ···
            mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, true);
            setWakefulnessLocked(groupId, WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */
                    0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);

      ···
        return true;
    }

3 updateDisplayPowerStateLocked 方法 里面聲明了對DisplayPower 的進(jìn)行的設(shè)置 初始化 DisplayPowerRequest displayPowerRequest 然后對他進(jìn)行擱置參數(shù)的設(shè)置
然后請求請求成功后 final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
displayPowerRequest, mRequestWaitForNegativeProximity); mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
這里對setReady 對后面 更新Dream 的時候 有個使用的判斷。

 private boolean updateDisplayPowerStateLocked(int dirty) {
        final boolean oldDisplayReady = mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked();
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
                DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) != 0) {
            if ((dirty & DIRTY_QUIESCENT) != 0) {
                if (mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
                    sQuiescent = false;
                } else {
                    mDirty |= DIRTY_QUIESCENT;
                }
            }

            for (final int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
                final DisplayPowerRequest displayPowerRequest =
                        mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
                displayPowerRequest.policy = getDesiredScreenPolicyLocked(groupId);

                // Determine appropriate screen brightness and auto-brightness adjustments.
                final boolean autoBrightness;
                final float screenBrightnessOverride;
                if (!mBootCompleted) {
                    // Keep the brightness steady during boot. This requires the
                    // bootloader brightness and the default brightness to be identical.
                    autoBrightness = false;
                    screenBrightnessOverride = mScreenBrightnessDefault;
                } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                    autoBrightness = false;
                    screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
                } else {
                    autoBrightness = (mScreenBrightnessModeSetting
                            == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
                    screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
                }

                // Update display power request.
                displayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
                displayPowerRequest.useAutoBrightness = autoBrightness;
                displayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
                displayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();

                updatePowerRequestFromBatterySaverPolicy(displayPowerRequest);

                if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                    displayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
                    if ((mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
                            & WAKE_LOCK_DRAW) != 0 && !mDrawWakeLockOverrideFromSidekick) {
                        if (displayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
                            displayPowerRequest.dozeScreenState = Display.STATE_DOZE;
                        }
                        if (displayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
                            displayPowerRequest.dozeScreenState = Display.STATE_ON;
                        }
                    }
                    displayPowerRequest.dozeScreenBrightness =
                            mDozeScreenBrightnessOverrideFromDreamManagerFloat;
                } else {
                    displayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
                    displayPowerRequest.dozeScreenBrightness =
                            PowerManager.BRIGHTNESS_INVALID_FLOAT;
                }

                final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
                        displayPowerRequest, mRequestWaitForNegativeProximity);
                mNotifier.onScreenPolicyUpdate(displayPowerRequest.policy);

                final boolean displayReadyStateChanged =
                        mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
                final boolean poweringOn =
                        mDisplayGroupPowerStateMapper.isPoweringOnLocked(groupId);
                if (ready && displayReadyStateChanged && poweringOn
                        && mDisplayGroupPowerStateMapper.getWakefulnessLocked(
                        groupId) == WAKEFULNESS_AWAKE) {
                    mDisplayGroupPowerStateMapper.setPoweringOnLocked(groupId, false);
                    Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
                    final int latencyMs = (int) (mClock.uptimeMillis()
                            - mDisplayGroupPowerStateMapper.getLastPowerOnTimeLocked(groupId));
                    if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
                        Slog.w(TAG, "Screen on took " + latencyMs + " ms");
                    }
                }
            }
            mRequestWaitForNegativeProximity = false;
        }

        return mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked() && !oldDisplayReady;
    }

4 updateDreamLocked 方法

里面 調(diào)用到 scheduleSandmanLocked(); 里面 handler 發(fā)送 MSG_SANDMAN

 if (mDisplayGroupPowerStateMapper.isSandmanSupported(id)) { // 是否支持dream
                    Message msg = mHandler.obtainMessage(MSG_SANDMAN);
                    msg.arg1 = id;
                    msg.setAsynchronous(true);
                    mHandler.sendMessage(msg);
                }

handleSandman 對 是否start dream 進(jìn)行了判斷

上面 dreamDisplayGroupNoUpdateLocked 對 wakefulness 和 isSandmanSummoned 兩個條件進(jìn)行了設(shè)置
sleepDisplayGroupNoUpdateLocked 里面也對 WAKEFULNESS_DOZING 進(jìn)行了設(shè)置司抱。
mDisplayGroupPowerStateMapper.isReady(groupId))判斷 updateDisplayPowerStateLocked 對這個ready 進(jìn)行了設(shè)置

canDreamLocked對dream 的條件進(jìn)行判斷筐眷,主要是一些電量和狀態(tài),開關(guān)习柠,后面有介紹匀谣。
canDozeLocked 對Doz條件的判斷。

startDreaming 是true 的時候 DreamManager來進(jìn)行 dream 開啟资溃。

private void handleSandman(int groupId) { // runs on handler thread
        // Handle preconditions.
        final boolean startDreaming;
        final int wakefulness;
        synchronized (mLock) {
            mSandmanScheduled = false;
            final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
            if (!ArrayUtils.contains(ids, groupId)) {
                // Group has been removed.
                return;
            }
            wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
            if ((wakefulness == WAKEFULNESS_DREAMING || wakefulness == WAKEFULNESS_DOZING) &&
                    mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId)
                    && mDisplayGroupPowerStateMapper.isReady(groupId)) {
                startDreaming = canDreamLocked(groupId) || canDozeLocked();
                mDisplayGroupPowerStateMapper.setSandmanSummoned(groupId, false);
            } else {
                startDreaming = false;
            }
        }
// 上面判斷是否dream  上面 dreamDisplayGroupNoUpdateLocked 對 wakefulness 和 isSandmanSummoned 兩個條件進(jìn)行了設(shè)置武翎。

        // Start dreaming if needed.
        // We only control the dream on the handler thread, so we don't need to worry about
        // concurrent attempts to start or stop the dream.
        final boolean isDreaming;
        if (mDreamManager != null) {
            // Restart the dream whenever the sandman is summoned.
            if (startDreaming) {
                mDreamManager.stopDream(false /*immediate*/);
                mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
            }
            isDreaming = mDreamManager.isDreaming();
        } else {
            isDreaming = false;
        }

        // At this point, we either attempted to start the dream or no attempt will be made,
        // so stop holding the display suspend blocker for Doze.
        mDozeStartInProgress = false;

        // Update dream state.
        synchronized (mLock) {
            final int[] ids = mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked();
            if (!ArrayUtils.contains(ids, groupId)) {
                // Group has been removed.
                return;
            }

            // Remember the initial battery level when the dream started.
            if (startDreaming && isDreaming) {// 記錄當(dāng)前電池水平
                mBatteryLevelWhenDreamStarted = mBatteryLevel;
                if (wakefulness == WAKEFULNESS_DOZING) {
                    Slog.i(TAG, "Dozing...");
                } else {
                    Slog.i(TAG, "Dreaming...");
                }
            }

            // If preconditions changed, wait for the next iteration to determine
            // whether the dream should continue (or be restarted).
            if (mDisplayGroupPowerStateMapper.isSandmanSummoned(groupId) // 如果是 start dream 的話 上面判斷startdream 的時候 設(shè)置成false 了
                    || mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != wakefulness) { // getWakefulnessLocked 改變的話return 
                return; // wait for next cycle
            }

            // Determine whether the dream should continue.
            long now = mClock.uptimeMillis();
            if (wakefulness == WAKEFULNESS_DREAMING) {
                if (isDreaming && canDreamLocked(groupId)) {
                    // 當(dāng)前 掉電比較快  mDreamsBatteryLevelDrainCutoffConfig  掉電一個標(biāo)記 大于這個值 就要停止掉dream
                    if (mDreamsBatteryLevelDrainCutoffConfig >= 0
                            && mBatteryLevel < mBatteryLevelWhenDreamStarted
                                    - mDreamsBatteryLevelDrainCutoffConfig
                            && !isBeingKeptAwakeLocked(groupId)) {
                        // If the user activity timeout expired and the battery appears
                        // to be draining faster than it is charging then stop dreaming
                        // and go to sleep.
                        Slog.i(TAG, "Stopping dream because the battery appears to "
                                + "be draining faster than it is charging.  "
                                + "Battery level when dream started: "
                                + mBatteryLevelWhenDreamStarted + "%.  "
                                + "Battery level now: " + mBatteryLevel + "%.");
                    } else {
                        return; // continue dreaming
                    }
                }
               // 停止 dream
                // Dream has ended or will be stopped.  Update the power state.
                if (isItBedTimeYetLocked(groupId)) {
                    final int flags = isAttentiveTimeoutExpired(groupId, now)
                            ? PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE : 0;
// 休眠
                    sleepDisplayGroupNoUpdateLocked(groupId, now,
                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags, Process.SYSTEM_UID);
                } else {
//喚醒 
                    wakeDisplayGroupNoUpdateLocked(groupId, now, PowerManager.WAKE_REASON_UNKNOWN,
                            "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
                            mContext.getOpPackageName(), Process.SYSTEM_UID);
                }
                updatePowerStateLocked();
            } else if (wakefulness == WAKEFULNESS_DOZING) {
                if (isDreaming) {
                    return; // continue dozing
                }
                // 跟新 power state 
                // Doze has ended or will be stopped.  Update the power state.
                reallySleepDisplayGroupNoUpdateLocked(groupId, now, Process.SYSTEM_UID);
                updatePowerStateLocked();
            }
        }

        // Stop dream.
        if (isDreaming) {
            mDreamManager.stopDream(false /*immediate*/);
        }
    }

canDreamLocked

private boolean canDreamLocked(int groupId) {
        final DisplayPowerRequest displayPowerRequest =
                mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
        if (!mBootCompleted // 初始化走完
                || getWakefulnessLocked() != WAKEFULNESS_DREAMING // wakefullness 是 WAKEFULNESS_DREAMING
                || !mDreamsSupportedConfig  // 設(shè)備支持 
                || !mDreamsEnabledSetting // dream開關(guān)開啟
                || !displayPowerRequest.isBrightOrDim() // 沒有request Bright 或者是Dim
                || displayPowerRequest.isVr()
                || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & (
                USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM
                        | USER_ACTIVITY_SCREEN_DREAM)) == 0) {
            return false;
        }
        if (!isBeingKeptAwakeLocked(groupId)) { // 不處于喚醒狀態(tài)
            if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) { //  沒充電 電源選項沒配置 不可dream
                return false;
            }
            if (!mIsPowered
                    && mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
                    && mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) { // 沒充電 電量過低
                return false;
            }
//  1 充電 2  dream充電最小電池水平小與0  3 當(dāng)前電量水平大于dream充電最小電池水平 三個 滿足一個是true
            return !mIsPowered
                    || mDreamsBatteryLevelMinimumWhenPoweredConfig < 0
                    || mBatteryLevel >= mDreamsBatteryLevelMinimumWhenPoweredConfig;
        }
        return true;
    }

canDozeLocked 判斷就計較簡單 判斷wakefulness

  private boolean canDozeLocked() {
        return getWakefulnessLocked() == WAKEFULNESS_DOZING;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肉拓,隨后出現(xiàn)的幾起案子后频,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卑惜,死亡現(xiàn)場離奇詭異膏执,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)露久,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門更米,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毫痕,你說我怎么就攤上這事征峦。” “怎么了消请?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵栏笆,是天一觀的道長。 經(jīng)常有香客問我臊泰,道長蛉加,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任缸逃,我火速辦了婚禮针饥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘需频。我一直安慰自己丁眼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布昭殉。 她就那樣靜靜地躺著苞七,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饲化。 梳的紋絲不亂的頭發(fā)上莽鸭,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音吃靠,去河邊找鬼硫眨。 笑死,一個胖子當(dāng)著我的面吹牛巢块,可吹牛的內(nèi)容都是我干的礁阁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼族奢,長吁一口氣:“原來是場噩夢啊……” “哼姥闭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起越走,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤棚品,失蹤者是張志新(化名)和其女友劉穎靠欢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铜跑,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡门怪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锅纺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掷空。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖囤锉,靈堂內(nèi)的尸體忽然破棺而出坦弟,到底是詐尸還是另有隱情,我是刑警寧澤官地,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布酿傍,位于F島的核電站,受9級特大地震影響区丑,放射性物質(zhì)發(fā)生泄漏拧粪。R本人自食惡果不足惜修陡,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一沧侥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魄鸦,春花似錦宴杀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绢记,卻和暖如春扁达,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蠢熄。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工跪解, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人签孔。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓叉讥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饥追。 傳聞我的和親對象是個殘疾皇子图仓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 安卓電源狀態(tài) 首先安卓將電源分為以下幾種情況: 1.sleep:休眠 從代碼看,安卓將系統(tǒng)的休眠原因分為以下幾種:...
    superme_閱讀 4,996評論 0 1
  • https://juejin.cn/post/6946581970960793613 在Andorid Frame...
    superme_閱讀 1,949評論 0 1
  • 在Andorid Framework層中但绕,PowerManagerService(以下簡稱PMS)模塊負(fù)責(zé)協(xié)調(diào)救崔、管...
    Andriod采碼蜂閱讀 1,437評論 0 0
  • 我們按下電源鍵就會滅屏,再按一下就會喚醒屏幕,這個是怎樣的過程呢六孵。 電源鍵有許多額外功能碳竟,為了能讓這個主題更加清晰...
    CocoDoll閱讀 6,347評論 0 7
  • 分析了PMS部分的亮屏流程。PMS模塊中也提供了滅屏接口goTosleep()狸臣,方法給其他組件或應(yīng)用來關(guān)閉屏幕莹桅,這...
    superme_閱讀 2,924評論 1 2