android 7.0 解锁亮屏,Android7.0亮屏流程分析
亮屏的本質是改變屏幕的電源狀態,經過一系列的調用會來到PowerManagerService中的updatePowerStateLocked()
1.PowerManagerService到DisplayPowerController
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
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 = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 4: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {}
}
然后經過函數updateDisplayPowerStateLocked來到DisplayPowerController的requestPowerState函數
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mLock) {
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) {
mPendingRequestLocked.copyFrom(request);
changed = true;
}
if (changed) {
mDisplayReadyLocked = false;
}
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
return mDisplayReadyLocked;
}
}
再次經過sendUpdatePowerStateLocked以及handler+meesage的消息,進入如下的switch結構
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;
case MSG_PROXIMITY_SENSOR_DEBOUNCED:
debounceProximitySensor();
break;
case MSG_SCREEN_ON_UNBLOCKED:
if (mPendingScreenOnUnblocker == msg.obj) {
unblockScreenOn();
updatePowerState();
}
break;
}
}
}
2.DisplayPowerController中的block機制
block的機制的存在是為了保證在屏幕亮時所有工作都已經準備好(如屏幕完成上電以及所有窗口繪制完成),所以前后需要執行兩次的updatePowerState()才會使屏幕真正的亮起來,從PMS傳遞過來的消息會先走到MSG_UPDATE_POWER_STATE執行第一次updatePowerState(),其核心是走到animateScreenStateChange()
private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
// If there is already an animation in progress, don't interfere with it.
if (mColorFadeOnAnimator.isStarted()
|| mColorFadeOffAnimator.isStarted()) {
if (target != Display.STATE_ON) {
return;
}
// If display state changed to on, proceed and stop the color fade and turn screen on.
mPendingScreenOff = false;
}
// If we were in the process of turning off the screen but didn't quite
// finish. Then finish up now to prevent a jarring transition back
// to screen on if we skipped blocking screen on as usual.
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
}
if (target == Display.STATE_ON) {
// Want screen on. The contents of the screen may not yet
// be visible if the color fade has not been dismissed because
// its last frame of animation is solid black.
if (!setScreenState(Display.STATE_ON)) {
return; // screen on blocked
}
if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
// Perform screen on animation.
if (mPowerState.getColorFadeLevel() == 1.0f) {
mPowerState.dismissColorFade();
} else if (mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE :
ColorFade.MODE_WARM_UP)) {
mColorFadeOnAnimator.start();
} else {
mColorFadeOnAnimator.end();
}
} else {
// Skip screen on animation.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
}
} else if (target == Display.STATE_DOZE) {
// Want screen dozing.
// Wait for brightness animation to complete beforehand when entering doze
// from screen on to prevent a perceptible jump because brightness may operate
// differently when the display is configured for dozing.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() == Display.STATE_ON) {
return;
}
// Set screen state.
if (!setScreenState(Display.STATE_DOZE)) {
return; // screen on blocked
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE_SUSPEND) {
// Want screen dozing and suspended.
// Wait for brightness animation to complete beforehand unless already
// suspended because we may not be able to change it after suspension.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
return;
}
// If not already suspending, temporarily set the state to doze until the
// screen on is unblocked, then suspend.
if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
if (!setScreenState(Display.STATE_DOZE)) {
return; // screen on blocked
}
setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else {
// Want screen off.
mPendingScreenOff = true;
if (mPowerState.getColorFadeLevel() == 0.0f) {
// Turn the screen off.
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
&& mPowerState.getScreenState() != Display.STATE_OFF) {
// Perform the screen off animation.
mColorFadeOffAnimator.start();
} else {
// Skip the screen off animation and add a black surface to hide the
// contents of the screen.
mColorFadeOffAnimator.end();
}
}
}
mColorFadeOnAnimator與亮屏動畫相關,默認是關閉的,這里不討論,對于亮屏來說target == Display.STATE_ON為true,接著看函數setScreenState
private boolean setScreenState(int state) {
if (mPowerState.getScreenState() != state) {
final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
mPowerState.setScreenState(state);
// Tell battery stats about the transition.
try {
mBatteryStats.noteScreenState(state);
} catch (RemoteException ex) {
// same process
}
}
// Tell the window manager policy when the screen is turned off or on unless it's due
// to the proximity sensor. We temporarily block turning the screen on until the
// window manager is ready by leaving a black surface covering the screen.
// This surface is essentially the final state of the color fade animation and
// it is only removed once the window manager tells us that the activity has
// finished drawing underneath.
final boolean isOff = (state == Display.STATE_OFF);
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff();
} else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn();
} else {
unblockScreenOn();
}
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
}
// Return true if the screen isn't blocked.
return mPendingScreenOnUnblocker == null;
}
2.1blockScreenOn
其中,mPowerState.setScreenState(state)與屏幕上電有關,這個放在本篇后面講,對于第一次updatePowerState,屏幕還未上電,即mPowerState.getColorFadeLevel() == 0.0f結果為true,執行blockScreenOn()
private void blockScreenOn() {
if (mPendingScreenOnUnblocker == null) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
mPendingScreenOnUnblocker = new ScreenOnUnblocker();
mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
}
}
blockscreenon的實質是new一個ScreenOnUnblocker對象,這個對象直到unblockscreen才會置為空,以此來實現block機制
2.2回調WMS
setScreenState在執行blockScreenOn之后會執行這一段話
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
WindowManagerPolicy的實現是PhoneWindowManager,所以繼續看相關代碼
@Override
public void screenTurningOn(final ScreenOnListener screenOnListener) {
updateScreenOffSleepToken(false);
synchronized (mLock) {
mScreenOnEarly = true;
mScreenOnFully = false;
mKeyguardDrawComplete = false;
mWindowManagerDrawComplete = false;
mScreenOnListener = screenOnListener;
if (mKeyguardDelegate != null) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
} else {
finishKeyguardDrawn();
}
}
}
其中,mKeyguardDelegate是用來向鎖屏傳遞消息的對象,如果鎖屏存在的話,會把mKeyguardDrawnCallback傳遞到鎖屏中去,鎖屏中進行相關判斷,滿足條件則運行callback中的方法,mKeyguardDrawnCallback中的方法最終依然是執行finishKeyguardDrawn(),所以直接看這個函數
private void finishKeyguardDrawn() {
synchronized (mLock) {
if (!mScreenOnEarly || mKeyguardDrawComplete) {
return; // We are not awake yet or we have already informed of this event.
}
mKeyguardDrawComplete = true;
if (mKeyguardDelegate != null) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
}
mWindowManagerDrawComplete = false;
}
// ... eventually calls finishWindowsDrawn which will finalize our screen turn on
// as well as enabling the orientation change logic/sensor.
mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
WAITING_FOR_DRAWN_TIMEOUT);
}
mKeyguardDrawComplete的存在是為了防止重復調用,不過多討論,finishKeyguardDrawn最后是走到了WindowManagerInternal里面,WindowManagerInternal的實現類是WindowManagerService
2.3窗口繪制檢查
public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
boolean allWindowsDrawn = false;
synchronized (mWindowMap) {
mWaitingForDrawnCallback = callback;
final WindowList windows = getDefaultWindowListLocked();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
if (win.isVisibleLw()
&& (win.mAppToken != null || isForceHiding || keyguard)) {
win.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
win.mLastContentInsets.set(-1, -1, -1, -1);
mWaitingForDrawn.add(win);
// No need to wait for the windows below Keyguard.
if (isForceHiding) {
break;
}
}
}
mWindowPlacerLocked.requestTraversal();
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
if (mWaitingForDrawn.isEmpty()) {
allWindowsDrawn = true;
} else {
mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
checkDrawnWindowsLocked();
}
}
if (allWindowsDrawn) {
callback.run();
}
}
這個函數會檢查所有的窗口是否都繪制完全,同時啟動窗口UI刷新流程,等待繪制的窗口放在mWaitingForDrawn里面,如果內容為空則表示窗口繪制完全,否則需要繼續等待,并且還會發送一個延時1秒的message,防止窗口繪制超時導致屏幕無法亮起。
如果窗口都繪制完成,則會進入傳過來的callback的run方法,具體看一下這個傳過來的callback
final Runnable mWindowManagerDrawCallback = new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
}
};
來到如下函數
private void finishWindowsDrawn() {
synchronized (mLock) {
if (!mScreenOnEarly || mWindowManagerDrawComplete) {
return; // Screen is not turned on or we did already handle this case earlier.
}
mWindowManagerDrawComplete = true;
}
finishScreenTurningOn();
}
繼續看
private void finishScreenTurningOn() {
synchronized (mLock) {
// We have just finished drawing screen content. Since the orientation listener
// gets only installed when all windows are drawn, we try to install it again.
updateOrientationListenerLp();
}
final ScreenOnListener listener;
final boolean enableScreen;
synchronized (mLock) {
if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
|| (mAwake && !mKeyguardDrawComplete)) {
return; // spurious or not ready yet
}
listener = mScreenOnListener;
mScreenOnListener = null;
mScreenOnFully = true;
// Remember the first time we draw the keyguard so we know when we're done with
// the main part of booting and can enable the screen and hide boot messages.
if (!mKeyguardDrawnOnce && mAwake) {
mKeyguardDrawnOnce = true;
enableScreen = true;
if (mBootMessageNeedsHiding) {
mBootMessageNeedsHiding = false;
hideBootMessages();
}
} else {
enableScreen = false;
}
}
if (listener != null) {
listener.onScreenOn();
}
if (enableScreen) {
try {
mWindowManager.enableScreenIfNeeded();
} catch (RemoteException unhandled) {
}
}
}
注意這里的listener,這個listener是一個ScreenOnListener對象,ScreenOnListener類的實現在DisplayPowerController中,所以通過這個listener,phoneWindowManager把窗口繪制完成的消息由傳回了DisplayPowerController
private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
@Override
public void onScreenOn() {
Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
2.4unblockScreenOn
ScreenOnUnblocker中的onScreenOn方法最終會走到unblockScreenOn方法
private void unblockScreenOn() {
if (mPendingScreenOnUnblocker != null) {
mPendingScreenOnUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
}
}
并且,unblockScreenOn之后會再一次updatePowerState(),調用DisplayPowerState中的相關方法設置亮度,屏幕最終亮起來
通過unblockScreenOn方法中的log也可以得到block的總時間,一般來說,只要blockscreen前后沒有過多的消息傳遞,可以認為block時間就是亮屏時間
3.屏幕上電
在屏幕亮起來之前需要改變屏幕的電源狀態,即給屏幕上電
前面說到,在DisplayPowerController設置電源狀態的方法開頭有這么一段
private boolean setScreenState(int state) {
if (mPowerState.getScreenState() != state) {
final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
mPowerState.setScreenState(state);
...
mPowerState是一個DisplayPowerState對象,繼續看具體的實現
public void setScreenState(int state) {
if (mScreenState != state) {
mScreenState = state;
mScreenReady = false;
scheduleScreenUpdate();
}
}
mScreenState和mScreenReady會用于狀態檢查,然后通過scheduleScreenUpdate向底層發出給屏幕上電的命令,具體的流程比較長而且復雜,不一一說明,大致的調用流程是
DisplayPowerState
-DisplayManagerService
-LocalDisplayAdapter
-SurfaceControl
-HWComposer
屏幕的上電時間與硬件的時序相關,并且是影響亮屏總時間的一個非常重要的因素,
查看屏幕的上電時間可以通過搜索trace文件中的setPowerModeInternal查看或者搜索surfaceControl的log,setPowerMode
總結
以上是生活随笔為你收集整理的android 7.0 解锁亮屏,Android7.0亮屏流程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lighttpd sqlite3 php
- 下一篇: micropython固件源码_Micr