亮屏、灭屏流程整个流程涉及的模块比较多,包括PowerManagerService、DisplayPowerControl、WMS、AMS。因此在分析完WMS之后,我们把这块也分析下。
DisplayPowerControl
我们知道灭屏流程的发起是在PowerManagerService中,会通过updatePowerState函数调用updateDisplayPowerStateLocked函数,再调用DisplayPowerControl的requestPowerState函数,到DisplayPowerControl中。DisplayPowerControl中后面会调用updatePowerState函数,我们也主要从这个函数开始分析:
updatePowerState会根据PowerManagerService传过来的显示状态,然后调用animateScreenStateChange函数。
animateScreenStateChange(state, performScreenOffTransition);
下面我们先来看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()) {
-
return;
-
}
-
-
// 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.
-
......
-
}
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.
-
......
-
}
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();
//关闭灭屏动画
-
}
-
}
-
}
animateScreenStateChange在亮屏的处理的时候,先会调用setScreenState(Display.STATE_ON),然后根据USE_COLOR_FADE_ON_ANIMATION 判断是否要开启亮屏动画,这里我们是没有设置的。因此直接跳过亮屏动画。灭屏的处理的话,会有一个灭屏动画(也是注册一个VSync信号回调函数处理的,这里我们不分析了),当动画结束后,直接就调用setScreenState(Display.STATE_OFF)结束。
我们再来看看setScreenState函数
-
private boolean setScreenState(int state) {
-
if (mPowerState.getScreenState() != state) {
-
final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
-
mPowerState.setScreenState(state);
-
......
-
}
-
-
// 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();
//调用PhoneWindowManager的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);
//调用PhoneWindowManager的screenTurningOn函数
-
}
-
-
// Return true if the screen isn't blocked.
-
return mPendingScreenOnUnblocker == null;
-
}
setScreenState函数,先是调用了DisplayPowerState的setScreenState函数,然后根据屏幕是灭屏还是亮屏调用PhoneWindowManager的相关函数。
PhoneWindowManager的screenTurnedOff和screenTurningOn函数
PhoneWindowManager的screenTurnedOff函数主要是通知kerguard,屏幕灭屏了。
-
@
Override
-
public
void
screenTurnedOff
() {
-
if (DEBUG_WAKEUP) Slog.i(TAG,
"Screen turned off...");
-
-
updateScreenOffSleepToken(
true);
-
synchronized (mLock) {
-
mScreenOnEarly =
false;
-
mScreenOnFully =
false;
-
mKeyguardDrawComplete =
false;
-
mWindowManagerDrawComplete =
false;
-
mScreenOnListener = null;
-
updateOrientationListenerLp();
-
-
if (mKeyguardDelegate != null) {
-
mKeyguardDelegate.onScreenTurnedOff();
-
}
-
}
-
}
我们再来看PhoneWindowManager的screenTurningOn函数。当有keyguard时,我们会先发一个延时的MSG_KEYGUARD_DRAWN_TIMEOUT信号,并且会调用keyguard的onScreenTurningOn函数,当完成会调用mKeyguardDrawnCallback回调函数。我们这里还要注意下有一个屏幕点亮后的回调。
-
@
Override
-
public
void
screenTurningOn
(final ScreenOnListener screenOnListener) {
-
if (DEBUG_WAKEUP) Slog.i(TAG,
"Screen turning on...");
-
-
updateScreenOffSleepToken(
false);
-
synchronized (mLock) {
-
mScreenOnEarly =
true;
-
mScreenOnFully =
false;
-
mKeyguardDrawComplete =
false;
-
mWindowManagerDrawComplete =
false;
-
mScreenOnListener = screenOnListener;
//屏幕点亮后的回调
-
-
if (mKeyguardDelegate != null) {
-
if (DEBUG_WAKEUP) Slog.d(TAG,
-
"send delay message MSG_KEYGUARD_DRAWN_TIMEOUT");
-
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
-
mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
1000);
-
mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
-
}
else {
-
if (DEBUG_WAKEUP) Slog.d(TAG,
-
"null mKeyguardDelegate: setting mKeyguardDrawComplete.");
-
finishKeyguardDrawn();
-
}
-
}
-
}
我们先看下mKeyguardDrawnCallback 回调,就是发送MSG_KEYGUARD_DRAWN_COMPLETE(keyguard绘制完的消息)
-
final DrawnListener mKeyguardDrawnCallback =
new DrawnListener() {
-
@Override
-
public
void onDrawn() {
-
if (DEBUG_WAKEUP) Slog.d(TAG,
"mKeyguardDelegate.ShowListener.onDrawn.");
-
mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
-
}
-
};
我们再来看看MSG_KEYGUARD_DRAWN_COMPLETE以及MSG_KEYGUARD_DRAWN_TIMEOUT信号的处理,都会调用finishKeyguardDrawn函数。
-
case MSG_KEYGUARD_DRAWN_COMPLETE:
-
if (DEBUG_WAKEUP) Slog.w(TAG,
"Setting mKeyguardDrawComplete");
-
finishKeyguardDrawn();
-
break;
-
case MSG_KEYGUARD_DRAWN_TIMEOUT:
-
Slog.w(TAG,
"Keyguard drawn timeout. Setting mKeyguardDrawComplete");
-
finishKeyguardDrawn();
-
break;
我们再来看看finishKeyguardDrawn函数,会先去除队列中的MSG_KEYGUARD_DRAWN_TIMEOUT消息(因为之前发的MSG_KEYGUARD_DRAWN_TIMEOUT消息,可能keyguard结束发送MSG_KEYGUARD_DRAWN_COMPLETE消息调用的finishKeyguardDrawn就要把MSG_KEYGUARD_DRAWN_TIMEOUT去除了)。然后会调用
-
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);
-
}
最后我们再看看WMS的waitForAllWindowsDrawn函数,以及两个参数mWindowManagerDrawCallback和一个WAITING_FOR_DRAWN_TIMEOUT(1秒)。
WMS的waitForAllWindowsDrawn函数
我们先来看看WMS的waitForAllWindowsDrawn函数,会把传进来的回调保存在mWaitingForDrawnCallback 。然后遍历所有的windows,把需要显示或者已经显示的窗口全部加入到mWaitingForDrawn,然后调用requestTraversalLocked这个函数我们之前分析过,就是发送一个消息,重新刷新UI布局。然后我们继续分析这个函数,如果mWaitingForDrawn为空,代表没啥显示的直接调用回调函数,如果mWaitingForDrawn有要显示的窗口,就要会先发送一个WAITING_FOR_DRAWN_TIMEOUT,这个timeout之前传进来的是1秒。然后调用checkDrawnWindowsLocked函数。
-
@
Override
-
public
void
waitForAllWindowsDrawn
(Runnable callback, long timeout) {
-
synchronized (mWindowMap) {
-
mWaitingForDrawnCallback = callback;
//回调保存在mWaitingForDrawnCallback
-
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);
-
Slog.i(TAG,
"In the function waitForAllWindowsDrawn");
-
if (win.isVisibleLw()
-
&& (win.mAppToken != null || isForceHiding)) {
-
Slog.i(TAG,
"In the function win.isVisibleLw()");
-
win.mWinAnimator.mDrawState = WindowStateAnimator.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;
-
}
-
}
-
}
-
requestTraversalLocked();
-
}
-
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-
if (mWaitingForDrawn.isEmpty()) {
-
callback.run();
-
Slog.i(TAG,
"In the function mWaitingForDrawn.isEmpty()");
-
}
else {
-
mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
-
checkDrawnWindowsLocked();
-
Slog.i(TAG,
"In the function checkDrawnWindowsLocked()");
-
}
-
}
我们先来看下checkDrawnWindowsLocked函数,这个函数。遍历之前加入的mWaitingForDrawn(要显示的窗口),这个时候我们把已经去除的,不需要显示的,没有surface的窗口从mWaitingForDrawn去除,还有已经绘制好的也去除。然后再当mWaitingForDrawn为空时,就发送ALL_WINDOWS_DRAWN消息。
-
void checkDrawnWindowsLocked() {
-
if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
-
return;
-
}
-
for (
int j = mWaitingForDrawn.size() -
1; j >=
0; j--) {
-
WindowState win = mWaitingForDrawn.get(j);
-
if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
-
// Window has been removed or hidden; no draw will now happen, so stop waiting.
-
if (DEBUG_SCREEN_ON) Slog.w(TAG,
"Aborted waiting for drawn: " + win);
-
mWaitingForDrawn.remove(win);
-
}
else
if (win.hasDrawnLw()) {
-
// Window is now drawn (and shown).
-
if (DEBUG_SCREEN_ON) Slog.d(TAG,
"Window drawn win=" + win);
-
mWaitingForDrawn.remove(win);
-
}
-
}
-
if (mWaitingForDrawn.isEmpty()) {
-
if (DEBUG_SCREEN_ON) Slog.d(TAG,
"All windows drawn!");
-
mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-
mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
-
}
-
}
ALL_WINDOWS_DRAWN消息的处理就是清除mWaitingForDrawnCallback ,然后调用回调。
-
case ALL_WINDOWS_DRAWN: {
-
Runnable callback;
-
synchronized (mWindowMap) {
-
callback = mWaitingForDrawnCallback;
-
mWaitingForDrawnCallback = null;
-
}
-
if (callback != null) {
-
callback.run();
-
}
-
}
还有当我们调用waitForAllWindowsDrawn一般都是有需要显示的窗口,但是我们直接调用checkDrawnWindowsLocked函数,发现有的窗口还没绘制完成。那么我们就要等,会在刷新的核心函数中performLayoutAndPlaceSurfacesLockedInner有如下代码,这个时候如果之前还没绘制完成的窗口,绘制好了。会再调用checkDrawnWindowsLocked函数,如果mWaitingForDrawn中的窗口绘制好了,会在mWaitingForDrawn中去除这个窗口。然后mWaitingForDrawn为空了,之后会发送ALL_WINDOWS_DRAWN消息,还调用mWaitingForDrawnCallback回调函数。
-
if (mWaitingForDrawnCallback != null ||
-
(mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
-
!mInnerFields.mUpdateRotation)) {
-
checkDrawnWindowsLocked();
-
}
当然如果我们之前没有把mWaitingForDrawn中的窗口清空,最后在WAITING_FOR_DRAWN_TIMEOUT(这里是1秒)时间到了也会调用回调的。
-
case WAITING_FOR_DRAWN_TIMEOUT: {
-
Runnable callback = null;
-
synchronized (mWindowMap) {
-
Slog.w(TAG,
"Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
-
mWaitingForDrawn.clear();
-
callback = mWaitingForDrawnCallback;
-
mWaitingForDrawnCallback = null;
-
}
-
if (callback != null) {
-
callback.run();
-
}
-
break;
-
}
PhoneWindowManager窗口绘制完成的回调函数
那下面我们就要继续看PhoneWindowManager中窗口绘制完成之后的回调函数。代码如下就是发送了一个消息。
-
final Runnable mWindowManagerDrawCallback =
new Runnable() {
-
@Override
-
public
void run() {
-
if (DEBUG_WAKEUP) Slog.i(TAG,
"All windows ready for display!");
-
mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
-
}
-
};
我们来看这个消息的处理
-
case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
-
if (DEBUG_WAKEUP) Slog.w(TAG,
"Setting mWindowManagerDrawComplete");
-
finishWindowsDrawn();
-
break;
finishWindowsDrawn就是把mWindowManagerDrawComplete 置为true,然后调用finishScreenTurningOn函数。
-
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();
-
}
finishScreenTurningOn函数调用了之前在DisplayPowerControl中调用screenTurningOn传入的回调,然后再调用WMS的enableScreenIfNeeded函数。
-
private void finishScreenTurningOn() {
-
synchronized (mLock) {
-
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;
-
......
-
}
-
-
if (listener != null) {
-
listener.onScreenOn();
-
}
-
-
if (enableScreen) {
-
try {
-
mWindowManager.enableScreenIfNeeded();
-
}
catch (RemoteException unhandled) {
-
}
-
}
-
}
我们先分析下WMS的enableScreenIfNeeded函数,然后再看DisplayPowerControl的回调onScreenOn函数。
WMS的enableScreenIfNeeded函数
WMS的enableScreenIfNeeded函数就是调用了enableScreenIfNeededLocked函数
-
@
Override
-
public
void
enableScreenIfNeeded
() {
-
synchronized (mWindowMap) {
-
enableScreenIfNeededLocked();
-
}
-
}
enableScreenIfNeededLocked这个函数仅仅是保证mDisplayEnabled为true,如果为true直接结束。
-
void enableScreenIfNeededLocked() {
-
if (mDisplayEnabled) {
-
return;
-
}
-
if (!mSystemBooted && !mShowingBootMessages) {
-
return;
-
}
-
mH.sendEmptyMessage(H.ENABLE_SCREEN);
-
}
mDisplayEnabled不为true,发送ENABLE_SCREEN消息
-
case ENABLE_SCREEN: {
-
performEnableScreen();
-
break;
performEnableScreen函数会让SurfaceFlinger去停止开机动画等,也会把mDisplayEnabled置为true。当然performEnableScreen在开机的时候会AMS中调用WMS的enableScreenAfterBoot函数来调用performEnableScreen函数。这个我们在博客http://blog.csdn.net/kc58236582/article/details/52921978分析过了。
-
public void performEnableScreen() {
-
synchronized(mWindowMap) {
-
if (mDisplayEnabled) {
-
return;
-
}
-
if (!mSystemBooted && !mShowingBootMessages) {
-
return;
-
}
-
-
// Don't enable the screen until all existing windows have been drawn.
-
if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
-
return;
-
}
-
-
if (!mBootAnimationStopped) {
-
// Do this one time.
-
try {
//停止开机动画
-
IBinder surfaceFlinger = ServiceManager.getService(
"SurfaceFlinger");
-
if (surfaceFlinger != null) {
-
//Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
-
Parcel data = Parcel.obtain();
-
data.writeInterfaceToken(
"android.ui.ISurfaceComposer");
-
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
// BOOT_FINISHED
-
data, null,
0);
-
data.recycle();
-
}
-
}
catch (RemoteException ex) {
-
Slog.e(TAG,
"Boot completed: SurfaceFlinger is dead!");
-
}
-
mBootAnimationStopped =
true;
-
}
-
-
if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
-
if (DEBUG_BOOT) Slog.i(TAG,
"performEnableScreen: Waiting for anim complete");
-
return;
-
}
-
-
mDisplayEnabled =
true;
//置为true
-
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG,
"******************** ENABLING SCREEN!");
-
-
// Enable input dispatch.
-
mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
-
}
-
-
try {
-
mActivityManager.bootAnimationComplete();
-
}
catch (RemoteException e) {
-
}
-
-
mPolicy.enableScreenAfterBoot();
-
-
// Make sure the last requested orientation has been applied.
-
updateRotationUnchecked(
false,
false);
-
}
窗口绘制完成后调用DisplayPowerControl中的回调
当WMS窗口绘制完成后,会在PhoneWindowManager中的finishScreenTurningOn函数调用DisplayPowerControl的回调函数。最后我们再来看看DisplayPowerControl中的回调的onScreenOn函数。只是发送了一个MSG_SCREEN_ON_UNBLOCKED消息。
-
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);
-
}
-
}
MSG_SCREEN_ON_UNBLOCKED的处理先是调用了unblockScreenOn函数,然后再调用updatePowerState更新状态。
-
case MSG_SCREEN_ON_UNBLOCKED:
-
if (mPendingScreenOnUnblocker == msg.obj) {
-
unblockScreenOn();
-
updatePowerState();
-
}
-
break;
unblockScreenOn函数,只是打印下从调用screenTurningOn开始,到窗口绘制完成在PhoneWindowManager中回调这个函数的时间差打印。
-
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);
-
}
-
}