亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

PowerManagerService之亮屏流程示例分析

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

前言

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

Power鍵亮屏

本文以 Power 鍵亮屏為例進(jìn)行分析,它會調(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 不知何時起,對多屏幕添加了一個分組功能,手機(jī)通常只有一個屏幕,它屬于默認(rèn)分組。

亮屏的過程有兩步

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

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
        // 注意第一個參數(shù)取所有 display group 的最大的 wakefulness,優(yōu)先級如下
        //  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. 保存用戶行為的時間
            userActivityNoUpdateLocked(
                    groupId, eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
        }
    }
}    

更新 wakefulness 為 WAKEFULNESS_AWAKE 過程如下

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

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è)備的時間
            // 這個時間,后面在更新用戶行為的時候會用到
            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:
                // 記錄并檢測是否有權(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 過程分為三個階段,最主要的是在第二個階段,更新 wakefulness 相關(guān)變量,然后 Notifier 通知其它組件并發(fā)送亮屏通知,過程如下,大家看一下就行,這不是重點。

// 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,表示上一次的處理流程還沒有執(zhí)行完
        // 這里會先執(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 保存用戶行為時間

// 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) {
            // 這里處理延長亮屏的時間的邏輯 ...
        } else {
            if (eventTime > mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(
                    groupId)) {
                // 2. 保存用戶活動時間
                mDisplayGroupPowerStateMapper.setLastUserActivityTimeLocked(groupId, eventTime);
                // 3. mDirty 設(shè)置 DIRTY_USER_ACTIVITY 標(biāo)志位,
                // 表示用戶活動有更新
                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 更新用戶行為的過程

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

簡單看下第一步的過程,如下

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

1.3 更新 wakefulness 小結(jié)

通過上面的分析,我們應(yīng)該看到一個本質(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ù),線程可以判斷是否獲取了某個鎖
    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),會更新 wakefulness,因此這里要通過循環(huán)再來更新上面的東西
            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 的所有功能都集中在這個函數(shù)中,但是與亮屏相關(guān)的主要有兩步

  • updateUserActivitySummaryLocked() 更新用戶行為。這個用戶行為會決定屏幕的最終亮度。詳見【2.1 更新用戶行為
  • updateDisplayPowerStateLocked() 更新顯示屏的電源狀態(tài),它會對 DisplayManagerService 發(fā)起電源請求,從而決定屏幕屏的亮度。詳見【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();
    // 休眠超時時間,默認(rèn)為 -1
    final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
    // 屏幕超時時間
    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)是無法決定用戶行為的
        if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) {
            final long lastUserActivityTime =
                    mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId);
            final long lastUserActivityTimeNoChangeLights =
                    mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked(
                            groupId);
            // 1. 獲取用戶行為與超時時間
            // 上一次用戶行為的時間 >= 上一次喚醒屏幕的時間
            if (lastUserActivityTime >= mLastWakeTime) {
                groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
                if (now < groupNextTimeout) { // 沒有到 dim 時間
                    groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                } else {
                    groupNextTimeout = lastUserActivityTime + screenOffTimeout;
                    if (now < groupNextTimeout) { // 處于 dim 時間段
                        groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                    }
                }
            }
            // 超時了,但是由于釋放了某一個鎖,需要延長亮屏?xí)r間
            if (groupUserActivitySummary == 0
                    && lastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                // ...
            }
            // 一般的超時情況,
            if (groupUserActivitySummary == 0) {
                // ...
            }
            // PhoneWindowManager 處理 KeyEvent.KEYCODE_SOFT_SLEEP 時,userInactiveOverride 為 true
            // KeyEvent.KEYCODE_SOFT_SLEEP 這個軟件的休眠按鍵 ?
            if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM
                    && userInactiveOverride) {
                // ...
            }
            // 用戶行為是點亮屏幕,并且WakeLock沒有保持屏幕常亮,用AttentionDetector再次計算屏幕超時時間
            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 的情況,也說明有多個 display group 的情況
                // 從這里可以看出,多個 display group 的超時時間是相同的
                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. 定時更新電源狀態(tài)
    // 這一步?jīng)Q定自動滅屏
    if (hasUserActivitySummary && nextTimeout >= 0) {
        scheduleUserInactivityTimeout(nextTimeout);
    }
}

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

更新用戶行為在第1步,前面分析更新 wakefulness 時,PMS 保存了喚醒的時間 mLastWakeTime,以及 DisplayGroupPowerStateMapper 保存了用戶行為時間。因此,對于從滅屏狀態(tài)到亮屏狀態(tài)這一過程來說,用戶行為的值現(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 的請求
            final DisplayPowerRequest displayPowerRequest =
                    mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId);
            // 2. 更新請求的各種參數(shù)
            // 更新請求的策略參數(shù),所謂的策略,就是亮屏,還是滅屏,或者使屏幕變暗,等等
            displayPowerRequest.policy = getDesiredScreenPolicyLocked(groupId);
            // ...省略更新其它請求參數(shù)的過程...
            // 3. 向 DisplayManagerService 發(fā)起請求
            // 如果此次請求與上一次的請求不同,那么這個請求的處理是一個異步處理過程,此時返回 false。
            // 否則,不用處理,直接返回 true。
            final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
                    displayPowerRequest, mRequestWaitForNegativeProximity);
            // 更新 DisplayGroupPowerStateMapper 的 ready 狀態(tài)
            final boolean displayReadyStateChanged =
                    mDisplayGroupPowerStateMapper.setDisplayGroupReadyLocked(groupId, ready);
            // 如果異步請求處理完畢,DMS 會回調(diào)通知 PMS,PMS 再更新狀態(tài)走到這里
            // 如果點亮屏幕時間過長,那么用log記錄下來
            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)的很清晰,如下

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

我們來看下如何更新請求的策略

// 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;
    }
    // 由于此時的 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ā)起請求時,最終會導(dǎo)致屏幕點亮。

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

前面我們剛提到過,處理屏幕請求的過程可能是一個異步,也可能是一個同步。如果從滅屏到亮屏,這個過程一定是一個異步的,那么 PowerManagerService 是如何得知 DisplayManagerService 已經(jīng)處理完成了呢? 其實 PowerManagerService 向 DisplayManagerService 注冊過回調(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 通過回調(diào)得知 DisplayManagerService 已經(jīng)處理完屏幕請求,于是再次更新電源狀態(tài)。

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

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

// PowerManagerService.java
private void finishWakefulnessChangeIfNeededLocked() {
    // 注意,其中一個條件就是所有 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é)

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

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

總結(jié)

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

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

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

相關(guān)文章

最新評論