Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制
来源:互联网 发布:淘宝权id 编辑:程序博客网 时间:2024/06/08 10:43
亮屏、灭屏流程整个流程涉及的模块比较多,包括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); } }
- Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制
- Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制
- Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制
- Android6.0 WMS(三) WMS窗口次序
- Android6.0 WMS(四) WMS中常用变量分析
- Android6.0 WMS(六) WMS动画管理
- Android6.0 WMS(一) WMS和应用进程的关系
- Android6.0 亮屏灭屏流程(DisplayPowerControler、WMS)(二)亮度设置
- Android6.0 亮屏灭屏流程(DisplayPowerControler、WMS)(二)亮度设置
- Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(一)应用进程
- Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(二)WMS的relayoutWindow
- Android6.0 旋转屏幕(五)WMS启动应用流程(屏幕方向相关)
- Android6.0 WMS(九) WMS切换Activity窗口(App Transition)的过程分析
- Android6.0 WMS(二) WMS创建窗口与创建Surface的关系
- Android6.0 WMS(十) WMS窗口动画从设置到显示框架
- Android6.0 WMS(十一) WMS窗口动画生成及播放
- Android6.0 旋转屏幕(一)WMS注册传感器回调
- android6.0 Activity(三) Activity与WMS通信过程
- qq 的登陆界面,它永远在z序的最前面
- JSON入门指南
- Window环境React-native环境配置步骤(Android)
- 编程命名规范
- Linux文件权限及用户组详解,必看!
- Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制
- win10+ubuntu14.04双系统硬盘安装教程
- Fragment懒加载
- 强数据类型化
- poj1000
- Android 如何实现一个平滑过渡的ViewPager广告条
- 射手Android ViewPager打造3D画廊
- 微信开发之——报警排查
- Linux 查看进程和删除进程