欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PowerManagerService之亮屏流程示例分析

 更新時(shí)間:2022年10月21日 08:35:41   作者:大胃粥  
這篇文章主要為大家介紹了PowerManagerService之亮屏流程示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

亮屏的方式有很多,其中最常用的是 Power 鍵亮屏,這個(gè)流程比較簡(jiǎn)單,本文希望通過(guò)分析這個(gè)流程,從而理清操作屏幕的能用流程,為后面的文章打下基礎(chǔ)。

Power鍵亮屏

本文以 Power 鍵亮屏為例進(jìn)行分析,它會(huì)調(diào)用 PowerManagerService#wakeUp()

// PowerManagerService.java
@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
        String opPackageName) {
    // ...
    try {
        // 只能喚醒 default display group 下的顯示屏
        wakeDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, details, uid,
                opPackageName, uid);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}  
private void wakeDisplayGroup(int groupId, long eventTime, @WakeReason int reason,
        String details, int uid, String opPackageName, int opUid) {
    synchronized (mLock) {
        // 1. 更新 wakefulness 為 WAKEFULNESS_AWAKE
        // 包括更新 PowerManagerService 和 DisplayGroupPowerStateMapper 的 wakefulness
        if (wakeDisplayGroupNoUpdateLocked(groupId, eventTime, reason, details, uid,
                opPackageName, opUid)) {
            // 2. 更新電源狀態(tài)
            updatePowerStateLocked();
        }
    }
} 

注意,PowerManagerService#wakeUp() 只能操作默認(rèn)分組下的屏幕。

Android 不知何時(shí)起,對(duì)多屏幕添加了一個(gè)分組功能,手機(jī)通常只有一個(gè)屏幕,它屬于默認(rèn)分組。

亮屏的過(guò)程有兩步

  • 更新 wakefulness 為 WAKEFULNESS_AWAKE。主要是更新 PowerManagerService 和 DisplayGroupPowerStateMapper 的 wakefulness。
  • 更新電源狀態(tài)。亮屏的過(guò)程就是在這里處理的。

1. 更新 wakefulness

private boolean wakeDisplayGroupNoUpdateLocked(int groupId, long eventTime,
        @WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
    // ...
    try {
        // ...
        // 設(shè)置 wakefulness 為 WAKEFULNESS_AWAKE
        setWakefulnessLocked(groupId, WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
                opPackageName, details);
        // 更新分組顯示屏的信息
        mDisplayGroupPowerStateMapper.setLastPowerOnTimeLocked(groupId, eventTime);
        mDisplayGroupPowerStateMapper.setPoweringOnLocked(groupId, true);
    } 
    return true;
}
void setWakefulnessLocked(int groupId, int wakefulness, long eventTime, int uid, int reason,
        int opUid, String opPackageName, String details) {
    // 1. 更新 DisplayGroupPowerStateMapper 的 wakefulness
    if (mDisplayGroupPowerStateMapper.setWakefulnessLocked(groupId, wakefulness)) {
        // display group wakefulness 改變了
        mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
        // 2. 更新 PMS 的 wakefulness
        // 注意第一個(gè)參數(shù)取所有 display group 的最大的 wakefulness,優(yōu)先級(jí)如下
        //  PowerManagerInternal#WAKEFULNESS_AWAKE
        //  PowerManagerInternal#WAKEFULNESS_DREAMING
        //  PowerManagerInternal#WAKEFULNESS_DOZING
        //  PowerManagerInternal#WAKEFULNESS_ASLEEP
        // TODO: 為何 PMS 的 wakefulness 要設(shè)置為所有 display group 的最大的 wakefulness ?
        setGlobalWakefulnessLocked(mDisplayGroupPowerStateMapper.getGlobalWakefulnessLocked(),
                eventTime, reason, uid, opUid, opPackageName, details);
        if (wakefulness == WAKEFULNESS_AWAKE) {
            // Kick user activity to prevent newly awake group from timing out instantly.
            // 3. 保存用戶行為的時(shí)間
            userActivityNoUpdateLocked(
                    groupId, eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
        }
    }
}    

更新 wakefulness 為 WAKEFULNESS_AWAKE 過(guò)程如下

  • 更新 DisplayGroupPowerStateMapper 的 wakefulness 為 WAKEFULNESS_AWAKE。
  • 更新 PMS 的 wakefulness 為 WAKEFULNESS_AWAKE。這里還會(huì)通知其它系統(tǒng)組件,wakefulness/交互狀態(tài) 改變了。詳見(jiàn)【1.1 更新 PMS 的 wakefulness
  • 保存用戶行為的時(shí)間。這個(gè)時(shí)間用來(lái)決定自動(dòng)滅屏的時(shí)間。詳見(jiàn)【1.2 保存用戶行為時(shí)間

1.1 更新 PMS 的 wakefulness

// PowerManagerService.java
private void setGlobalWakefulnessLocked(int wakefulness, long eventTime, int reason, int uid,
        int opUid, String opPackageName, String details) {
    if (getWakefulnessLocked() == wakefulness) {
        return;
    }
    // Phase 1: Handle pre-wakefulness change bookkeeping.
    final String traceMethodName;
    switch (wakefulness) {
        // ...
        case WAKEFULNESS_AWAKE:
            // 保存喚醒設(shè)備的時(shí)間
            // 這個(gè)時(shí)間,后面在更新用戶行為的時(shí)候會(huì)用到
            mLastWakeTime = eventTime;
            mLastWakeReason = reason;
            break;
        // ...
    }
    try {
        // Phase 2: Handle wakefulness change and bookkeeping.
        // Under lock, invalidate before set ensures caches won't return stale values.
        mInjector.invalidateIsInteractiveCaches();
        // 更新 PMS 的 wakefulness 相關(guān)變量
        mWakefulnessRaw = wakefulness;
        mWakefulnessChanging = true;
        // mDirty 設(shè)置 DIRTY_WAKEFULNESS,表示 PMS 的 wakefulness 改變了
        mDirty |= DIRTY_WAKEFULNESS;
        mDozeStartInProgress &= (getWakefulnessLocked() == WAKEFULNESS_DOZING);
        // 通知其它組件,wakefulness改變 或者 交互狀態(tài)改變
        if (mNotifier != null) {
            mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime);
        }
        mAttentionDetector.onWakefulnessChangeStarted(wakefulness);
        // Phase 3: Handle post-wakefulness change bookkeeping.
        switch (wakefulness) {
            case WAKEFULNESS_AWAKE:
                // 記錄并檢測(cè)是否有權(quán)限
                mNotifier.onWakeUp(reason, details, uid, opPackageName, opUid);
                if (sQuiescent) {
                    mDirty |= DIRTY_QUIESCENT;
                }
                break;
            // ...
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
}

根據(jù)英文注釋,更新 PMS 的 wakefulness 過(guò)程分為三個(gè)階段,最主要的是在第二個(gè)階段,更新 wakefulness 相關(guān)變量,然后 Notifier 通知其它組件并發(fā)送亮屏通知,過(guò)程如下,大家看一下就行,這不是重點(diǎn)。

// Notifier.java
public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) {
    // 判斷新的 wakefulness 是否是交互狀態(tài)
    // WAKEFULNESS_AWAKE 是可交互狀態(tài)
    final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
    // 1. 通知 AMS wakefulness 改變了
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            mActivityManagerInternal.onWakefulnessChanged(wakefulness);
        }
    });
    // 2. 處理交互狀態(tài)改變
    // Handle any early interactive state changes.
    // Finish pending incomplete ones from a previous cycle.
    // 處理早期交互狀態(tài)改變
    if (mInteractive != interactive) {
        // Finish up late behaviors if needed.
        // mInteractiveChanging 為 true,表示上一次的處理流程還沒(méi)有執(zhí)行完
        // 這里會(huì)先執(zhí)行上一次的流程
        if (mInteractiveChanging) {
            handleLateInteractiveChange();
        }
        // 2.1 更新系統(tǒng)組件的交互狀態(tài)
        // Start input as soon as we start waking up or going to sleep.
        mInputManagerInternal.setInteractive(interactive);
        mInputMethodManagerInternal.setInteractive(interactive);
        // ...
        // Handle early behaviors.
        // 2.2 更新關(guān)于交互狀態(tài)的變量
        mInteractive = interactive;
        mInteractiveChangeReason = reason;
        mInteractiveChangeStartTime = eventTime;
        // 交互狀態(tài)正在改變
        mInteractiveChanging = true;
        // 2.3 處理早期的交互狀態(tài)改變?nèi)蝿?wù)
        handleEarlyInteractiveChange();
    }
}
private void handleEarlyInteractiveChange() {
    synchronized (mLock) {
        if (mInteractive) {
            // 通知 PhoneWindowManager,PhoneWindowManager再通知 SystemUI keyguard
            mHandler.post(() -> mPolicy.startedWakingUp(mInteractiveChangeReason));
            // 發(fā)送亮屏廣播
            mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
            mPendingWakeUpBroadcast = true;
            updatePendingBroadcastLocked();
        } else {
            // ...
        }
    }
}    

1.2 保存用戶行為時(shí)間

// PowerManagerService.java
private boolean userActivityNoUpdateLocked(int groupId, long eventTime, int event, int flags,
        int uid) {
    if (eventTime < mLastSleepTime || eventTime < mLastWakeTime || !mSystemReady) {
        return false;
    }
    Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
    try {
        if (eventTime > mLastInteractivePowerHintTime) {
            setPowerBoostInternal(Boost.INTERACTION, 0);
            mLastInteractivePowerHintTime = eventTime;
        }
        // 1. 通知系統(tǒng)組件,有用戶行為發(fā)生
        mNotifier.onUserActivity(event, uid);
        mAttentionDetector.onUserActivity(eventTime, event);
        if (mUserInactiveOverrideFromWindowManager) {
            mUserInactiveOverrideFromWindowManager = false;
            mOverriddenTimeout = -1;
        }
        final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
        if (wakefulness == WAKEFULNESS_ASLEEP
                || wakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
            return false;
        }
        maybeUpdateForegroundProfileLastActivityLocked(eventTime);
        if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
            // 這里處理延長(zhǎng)亮屏的時(shí)間的邏輯 ...
        } else {
            if (eventTime > mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(
                    groupId)) {
                // 2. 保存用戶活動(dòng)時(shí)間
                mDisplayGroupPowerStateMapper.setLastUserActivityTimeLocked(groupId, eventTime);
                // 3. mDirty 設(shè)置 DIRTY_USER_ACTIVITY 標(biāo)志位,
                // 表示用戶活動(dòng)有更新
                mDirty |= DIRTY_USER_ACTIVITY;
                if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                    mDirty |= DIRTY_QUIESCENT;
                }
                return true;
            }
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
    }
    return false;
}

PMS 更新用戶行為的過(guò)程

  • 通過(guò) Notifier 通知其它組件有用戶行為。
  • DisplayGroupPowerStateMapper 保存用戶行為的時(shí)間。這個(gè)時(shí)間會(huì)用于決定自動(dòng)滅屏的時(shí)間。
  • mDirty 設(shè)置 DIRTY_USER_ACTIVITY 標(biāo)志位,表示用戶活動(dòng)有更新,后面更新電源狀態(tài)會(huì)用到。

簡(jiǎn)單看下第一步的過(guò)程,如下

    private void sendUserActivity(int event) {
        synchronized (mLock) {
            if (!mUserActivityPending) {
                return;
            }
            mUserActivityPending = false;
        }
        // 這里暫時(shí)不知道做了什么
        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
        tm.notifyUserActivity();
        // PhoneWindowManger 會(huì)通知 SystemUI
        mPolicy.userActivity();
        // 如果 FaceDownDetector 正在執(zhí)行翻轉(zhuǎn)滅屏任務(wù),此時(shí)有用戶行為,取消這個(gè)任務(wù)
        mFaceDownDetector.userActivity(event);
    }

1.3 更新 wakefulness 小結(jié)

通過(guò)上面的分析,我們應(yīng)該看到一個(gè)本質(zhì),更新 wakefulness 流程大致如下

  • 更新 DisplayGroupPowerStateMapper 的 wakefulness,mDirty 設(shè)置標(biāo)志位 DIRTY_DISPLAY_GROUP_WAKEFULNESS。
  • 更新 PowerManagerService 的 wakefulness,mDirty 設(shè)置標(biāo)志位 DIRTY_WAKEFULNESS.
  • Notifier 通知其它組件 wakefulness/交互狀態(tài) 改變了,并發(fā)送亮屏/滅屏的廣播。

2. 更新電源狀態(tài)

// PowerManagerService.java
private void updatePowerStateLocked() {
    if (!mSystemReady || mDirty == 0) {
        return;
    }
    // 注意這里的技術(shù),線程可以判斷是否獲取了某個(gè)鎖
    if (!Thread.holdsLock(mLock)) {
        Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
    }
    Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
    try {
        // Phase 0: Basic state updates.
        // 省電模式功能
        updateIsPoweredLocked(mDirty);
        // 設(shè)置中"充電常亮功能"
        updateStayOnLocked(mDirty);
        // 亮度增加功能
        updateScreenBrightnessBoostLocked(mDirty);
        // 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;
            // 把所有的喚醒鎖歸納到 mWakeLockSummary
            updateWakeLockSummaryLocked(dirtyPhase1);
            // 1. 更新用戶行為
            updateUserActivitySummaryLocked(now, dirtyPhase1);
            updateAttentiveStateLocked(now, dirtyPhase1);
            // 決定是否進(jìn)入休眠/dream/doze狀態(tài)
            // 如果進(jìn)入某一種狀態(tài),會(huì)更新 wakefulness,因此這里要通過(guò)循環(huán)再來(lái)更新上面的東西
            if (!updateWakefulnessLocked(dirtyPhase1)) {
                break;
            }
        }
        // Phase 2: Lock profiles that became inactive/not kept awake.
        updateProfilesLocked(now);
        // Phase 3: Update display power state.
        // 2. 更新顯示屏的電源狀態(tài)
        final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
        // Phase 4: Update dream state (depends on display ready signal).
        updateDreamLocked(dirtyPhase2, displayBecameReady);
        // Phase 5: Send notifications, if needed.
        finishWakefulnessChangeIfNeededLocked();
        // 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);
    }
}

PowerManagerService 的所有功能都集中在這個(gè)函數(shù)中,但是與亮屏相關(guān)的主要有兩步

  • updateUserActivitySummaryLocked() 更新用戶行為。這個(gè)用戶行為會(huì)決定屏幕的最終亮度。詳見(jiàn)【2.1 更新用戶行為
  • updateDisplayPowerStateLocked() 更新顯示屏的電源狀態(tài),它會(huì)對(duì) DisplayManagerService 發(fā)起電源請(qǐng)求,從而決定屏幕屏的亮度。詳見(jiàn)【2.2 更新顯示屏的電源狀態(tài)

2.1 更新用戶行為

// PowerManagerService.java
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);
    // 默認(rèn)為 -1
    final long attentiveTimeout = getAttentiveTimeoutLocked();
    // 休眠超時(shí)時(shí)間,默認(rèn)為 -1
    final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
    // 屏幕超時(shí)時(shí)間
    long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
            attentiveTimeout);
    // dim duration = 20 % screen off timeout
    final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
    screenOffTimeout =
            getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
    final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
    long nextTimeout = -1;
    boolean hasUserActivitySummary = false;
    // 遍歷 display group id
    for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
        int groupUserActivitySummary = 0;
        long groupNextTimeout = 0;
        // 注意,休眠狀態(tài)是無(wú)法決定用戶行為的
        if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) {
            final long lastUserActivityTime =
                    mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId);
            final long lastUserActivityTimeNoChangeLights =
                    mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
                            groupId);
            // 1. 獲取用戶行為與超時(shí)時(shí)間
            // 上一次用戶行為的時(shí)間 >= 上一次喚醒屏幕的時(shí)間
            if (lastUserActivityTime >= mLastWakeTime) {
                groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
                if (now < groupNextTimeout) { // 沒(méi)有到 dim 時(shí)間
                    groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                } else {
                    groupNextTimeout = lastUserActivityTime + screenOffTimeout;
                    if (now < groupNextTimeout) { // 處于 dim 時(shí)間段
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                    }
                }
            }
            // 超時(shí)了,但是由于釋放了某一個(gè)鎖,需要延長(zhǎng)亮屏?xí)r間
            if (groupUserActivitySummary == 0
                    && lastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                // ...
            }
            // 一般的超時(shí)情況,
            if (groupUserActivitySummary == 0) {
                // ...
            }
            // PhoneWindowManager 處理 KeyEvent.KEYCODE_SOFT_SLEEP 時(shí),userInactiveOverride 為 true
            // KeyEvent.KEYCODE_SOFT_SLEEP 這個(gè)軟件的休眠按鍵 ?
            if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM
                    && userInactiveOverride) {
                // ...
            }
            // 用戶行為是點(diǎn)亮屏幕,并且WakeLock沒(méi)有保持屏幕常亮,用AttentionDetector再次計(jì)算屏幕超時(shí)時(shí)間
            if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
                    && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId)
                    & WAKE_LOCK_STAY_AWAKE) == 0) {
                // ...
            }
            hasUserActivitySummary |= groupUserActivitySummary != 0;
            if (nextTimeout == -1) {
                nextTimeout = groupNextTimeout;
            } else if (groupNextTimeout != -1) {
                // 這里表示 nextTimeout != -1 的情況,也說(shuō)明有多個(gè) display group 的情況
                // 從這里可以看出,多個(gè) display group 的超時(shí)時(shí)間是相同的
                nextTimeout = Math.min(nextTimeout, groupNextTimeout);
            }
        }
        // 2. DisplayGroupPowerStateMapper 保存用戶行為
        mDisplayGroupPowerStateMapper.setUserActivitySummaryLocked(groupId,
                groupUserActivitySummary);
        }
    } // 遍歷 display group id 結(jié)束
    final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
    if (nextProfileTimeout > 0) {
        nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
    }
    // 3. 定時(shí)更新電源狀態(tài)
    // 這一步?jīng)Q定自動(dòng)滅屏
    if (hasUserActivitySummary && nextTimeout >= 0) {
        scheduleUserInactivityTimeout(nextTimeout);
    }
}

這個(gè)函數(shù)不單單是用于更新用戶行為,還更新了屏幕超時(shí)時(shí)間,并且以這個(gè)時(shí)間來(lái)定時(shí)更新電源狀態(tài),以實(shí)現(xiàn)自動(dòng)滅屏的功能。

更新用戶行為在第1步,前面分析更新 wakefulness 時(shí),PMS 保存了喚醒的時(shí)間 mLastWakeTime,以及 DisplayGroupPowerStateMapper 保存了用戶行為時(shí)間。因此,對(duì)于從滅屏狀態(tài)到亮屏狀態(tài)這一過(guò)程來(lái)說(shuō),用戶行為的值現(xiàn)在是 USER_ACTIVITY_SCREEN_BRIGHT,表示用戶行為是亮屏。

2.2 更新顯示屏的電源狀態(tài)

// PowerManagerService.java
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) {
            // ...
        }
        // 遍歷 display group
        for (final int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) {
            // 1. 獲取 display group 的請(qǐng)求
            final DisplayPowerRequest displayPowerRequest =
                    mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
            // 2. 更新請(qǐng)求的各種參數(shù)
            // 更新請(qǐng)求的策略參數(shù),所謂的策略,就是亮屏,還是滅屏,或者使屏幕變暗,等等
            displayPowerRequest.policy = getDesiredScreenPolicyLocked(groupId);
            // ...省略更新其它請(qǐng)求參數(shù)的過(guò)程...
            // 3. 向 DisplayManagerService 發(fā)起請(qǐng)求
            // 如果此次請(qǐng)求與上一次的請(qǐng)求不同,那么這個(gè)請(qǐng)求的處理是一個(gè)異步處理過(guò)程,此時(shí)返回 false。
            // 否則,不用處理,直接返回 true。
            final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
                    displayPowerRequest, mRequestWaitForNegativeProximity);
            // 更新 DisplayGroupPowerStateMapper 的 ready 狀態(tài)
            final boolean displayReadyStateChanged =
                    mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
            // 如果異步請(qǐng)求處理完畢,DMS 會(huì)回調(diào)通知 PMS,PMS 再更新?tīng)顟B(tài)走到這里
            // 如果點(diǎn)亮屏幕時(shí)間過(guò)長(zhǎng),那么用log記錄下來(lái)
            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;
    }
    // 返回值表示是否從非ready狀態(tài)變?yōu)閞eady狀態(tài)
    return mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked() && !oldDisplayReady;
}

更新屏幕電源狀態(tài)的很清晰,如下

  • 首先獲取請(qǐng)求,并更新請(qǐng)求參數(shù)。請(qǐng)求參數(shù)中,主要關(guān)心的是策略參數(shù),它決定了屏幕的狀態(tài),也就是到底是亮屏還是滅屏。
  • 向 DisplayManagerService 發(fā)起請(qǐng)求。注意,如果當(dāng)前的請(qǐng)求與上一次請(qǐng)求不同,那么處理過(guò)程是異步的,并且返回的 ready 狀態(tài)為 false。否則,處理過(guò)程是同步的,返回的 ready 為 true。

我們來(lái)看下如何更新請(qǐng)求的策略

// PowerManagerService.java
 int getDesiredScreenPolicyLocked(int groupId) {
    final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId);
    final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId);
    if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
        return DisplayPowerRequest.POLICY_OFF;
    } else if (wakefulness == WAKEFULNESS_DOZING) {
        // ...
    }
    if (mIsVrModeEnabled) {
        return DisplayPowerRequest.POLICY_VR;
    }
    // 由于此時(shí)的 UserActivity 為 USER_ACTIVITY_SCREEN_BRIGHT,因此策略為 DisplayPowerRequest.POLICY_BRIGHT
    if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
            || !mBootCompleted
            || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId)
            & USER_ACTIVITY_SCREEN_BRIGHT) != 0
            || mScreenBrightnessBoostInProgress) {
        return DisplayPowerRequest.POLICY_BRIGHT;
    }
    return DisplayPowerRequest.POLICY_DIM;
}

我們剛才分析的用戶行為是 USER_ACTIVITY_SCREEN_BRIGHT,因此策略最終為 DisplayPowerRequest.POLICY_BRIGHT。當(dāng)向 DisplayManagerService 發(fā)起請(qǐng)求時(shí),最終會(huì)導(dǎo)致屏幕點(diǎn)亮。

2.3 處理屏幕狀態(tài)的更新

前面我們剛提到過(guò),處理屏幕請(qǐng)求的過(guò)程可能是一個(gè)異步,也可能是一個(gè)同步。如果從滅屏到亮屏,這個(gè)過(guò)程一定是一個(gè)異步的,那么 PowerManagerService 是如何得知 DisplayManagerService 已經(jīng)處理完成了呢? 其實(shí) PowerManagerService 向 DisplayManagerService 注冊(cè)過(guò)回調(diào)

// PowerManagerService.java
public void systemReady(IAppOpsService appOps) {
    synchronized (mLock) {
        mDisplayManagerInternal.initPowerManagement(
                mDisplayPowerCallbacks, mHandler, sensorManager);                 
    }
}
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
        new DisplayManagerInternal.DisplayPowerCallbacks() {
    @Override
    public void onStateChanged() {
        synchronized (mLock) {
            // 表示屏幕狀態(tài)更新了
            mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
            updatePowerStateLocked();
        }
    }
}    

當(dāng) PowerManagerService 通過(guò)回調(diào)得知 DisplayManagerService 已經(jīng)處理完屏幕請(qǐng)求,于是再次更新電源狀態(tài)。

此時(shí),updateDisplayPowerStateLocked() 再向 DisplayManagerService 發(fā)起請(qǐng)求,由于與上一次請(qǐng)求相同,因此 DisplayManagerService 不做處理,返回的 ready 狀態(tài)為 true。

更新電源狀態(tài)剩下的過(guò)程,就是收尾,我們大致看下

// PowerManagerService.java
private void finishWakefulnessChangeIfNeededLocked() {
    // 注意,其中一個(gè)條件就是所有 display group 要 ready
    if (mWakefulnessChanging && mDisplayGroupPowerStateMapper.areAllDisplaysReadyLocked()) {
        // ...
        // 顯示屏 ready 了, PMS 的 wakefulness 改變的工作才算處理完
        mWakefulnessChanging = false;
        // Notier 通知 wakefulness 的改變已經(jīng)完成
        mNotifier.onWakefulnessChangeFinished();
    }
}
// Notifier.java
public void onWakefulnessChangeFinished() {
    if (mInteractiveChanging) {
        mInteractiveChanging = false;
        // 處理交互狀態(tài)的后期任務(wù)
        handleLateInteractiveChange();
    }
}
private void handleLateInteractiveChange() {
    synchronized (mLock) {
        final int interactiveChangeLatency =
                (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime);
        if (mInteractive) {
            // Finished waking up...
            mHandler.post(() -> {
                // 通知 PhoneWindowManager 完成設(shè)備喚醒工作
                mPolicy.finishedWakingUp(mInteractiveChangeReason);
            });
        } else {
            // ...
        }
    }
}

2.4 小結(jié)

我們分析的是從滅屏到亮屏的過(guò)程,但是我們應(yīng)該看到一個(gè)本質(zhì)的問(wèn)題,它其實(shí)就是向 DislayManagerService 發(fā)起請(qǐng)求,來(lái)更新屏幕狀態(tài)(例如 亮屏,滅屏)。

請(qǐng)求的策略最終決定了屏幕在狀態(tài),但是影響請(qǐng)求策略的因素有很多,例如系統(tǒng)狀態(tài)(指的是PMS的wakefulness),用戶行為,喚醒鎖,等等。我們將在后面的文章中看到更多決定請(qǐng)求策略的情況。

總結(jié)

本文雖然分析的是從滅屏到亮屏的流程,但是我們要看到一個(gè)本質(zhì)的過(guò)程,其實(shí)只有兩步

  • 更新 wakefulness.
  • 向 DisplayManagerService 發(fā)起請(qǐng)求,更新屏幕狀態(tài)。

以上就是PowerManagerService之亮屏流程示例分析的詳細(xì)內(nèi)容,更多關(guān)于PowerManagerService 亮屏流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論