Android7.0 PowerManagerService亮灭屏分析(二)

  • 3029

在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerRequest中传入DisplayPowerController中进一步处理。在亮屏过程中DisplayPowerController会根据传过来的数值来设置新的电源状态为亮屏,然后调用DisplayPowerState来对状态进行设置,在分析DisplayPowerState时会具体讲解。由于此时ColorFade level(就是在手机屏幕的一层surface,当level为0是为一层黑帧,level为1.0时为透明)的值为0,表示屏幕还没有绘制好,所以此时需要block screen直到window界面绘制完成。当需要亮屏时调用PhoneWindowManager的screenTurningOn函数,通知window屏幕就要点亮了。然后调用WMS中函数waitForAllWindowsDrawn函数等待将所有需要绘制的window绘制完成后回调回来,超时时间为1000ms。在WMS中获取需要绘制的window将其加入mWaitingForDrawn中等待绘制,通过检查mWaitingForDrawn是否为空来判断,window是否绘制完成。此时screenTurningOn函数就执行完了,剩下的就是等待windows绘制完成。

DisplayManagerService.java中的LocalService继承了DisplayManagerInternal.java, 所以就会调用LocalService的requestPowerState函数请求电源状态.

[java] view plain copy
  1. private final class LocalService extends DisplayManagerInternal {
  2. @Override
  3. public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
  4. SensorManager sensorManager) {    //初始化函数在PowerManagerService的systemReady函数中调用
  5. synchronized (mSyncRoot) {
  6. DisplayBlanker blanker = new DisplayBlanker() {   //创建blanker对象
  7. @Override
  8. public void requestDisplayState(int state, int brightness) {
  9. // The order of operations is important for legacy reasons.
  10. if (state == Display.STATE_OFF) {
  11. requestGlobalDisplayStateInternal(state, brightness);
  12. }
  13. callbacks.onDisplayStateChange(state);
  14. if (state != Display.STATE_OFF) {
  15. requestGlobalDisplayStateInternal(state, brightness);
  16. }
  17. }
  18. };
  19. mDisplayPowerController = new DisplayPowerController(    //创建DisplayPowerController对象
  20. mContext, callbacks, handler, sensorManager, blanker);
  21. }
  22. }
  23. @Override
  24. public boolean requestPowerState(DisplayPowerRequest request,
  25. boolean waitForNegativeProximity) {
  26. return mDisplayPowerController.requestPowerState(request,
  27. waitForNegativeProximity);     //调用DisplayPowerController请求电源状态
  28. }
  29. //.....

在DisplayPowerController中通过Handler发送MSG_UPDATE_POWER_STATE消息调用updatePowerState来更新电源状态. updatePowerState也是一个非常核心的函数,在该函数中将PowerManagerService中传过来的参数获取出来根据policy获取设备的请求状态是ON, OFF还是DOZE, 应用距离传感器, 将最终的请求状态调用DisplayPowerState进行设置. 判断设备是否打开了自动亮度调节, 计算最终屏幕要达到的目标亮度并通过亮度渐变动画慢慢的点亮屏幕,最终变为高亮.

[java] view plain copy
  1. private void updatePowerState() {
  2. // Update the power state request.
  3. final boolean mustNotify;
  4. boolean mustInitialize = false;
  5. boolean autoBrightnessAdjustmentChanged = false;
  6. synchronized (mLock) {
  7. mPendingUpdatePowerStateLocked = false;
  8. if (mPendingRequestLocked == null) {
  9. return; // wait until first actual power request
  10. }
  11. if (mPowerRequest == null) { //判断mPowerRequest是否为NULL,如果为空新创建一个, 否则直接将mPendingRequestLocked复制给他
  12. mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
  13. mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
  14. mPendingWaitForNegativeProximityLocked = false;
  15. mPendingRequestChangedLocked = false;
  16. mustInitialize = true;
  17. } else if (mPendingRequestChangedLocked) {
  18. autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
  19. != mPendingRequestLocked.screenAutoBrightnessAdjustment);
  20. mPowerRequest.copyFrom(mPendingRequestLocked);
  21. mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
  22. mPendingWaitForNegativeProximityLocked = false;
  23. mPendingRequestChangedLocked = false;
  24. mDisplayReadyLocked = false;
  25. }
  26. mustNotify = !mDisplayReadyLocked;
  27. }
  28. // Initialize things the first time the power state is changed.
  29. if (mustInitialize) {
  30. initialize();//power state第一次发生变化时需要做一些初始化,如:创建DisplayPowerState, 亮灭屏动画,亮度渐变动画实例等
  31. }
  32. // Compute the basic display state using the policy.
  33. // We might override this below based on other factors.
  34. int state;
  35. int brightness = PowerManager.BRIGHTNESS_DEFAULT;//设置屏幕默认亮度
  36. boolean performScreenOffTransition = false;
  37. switch (mPowerRequest.policy) {
  38. case DisplayPowerRequest.POLICY_OFF: //设置设备状态为OFF
  39. state = Display.STATE_OFF;
  40. performScreenOffTransition = true; //灭屏有过渡动画
  41. break;
  42. case DisplayPowerRequest.POLICY_DOZE:  //设置设备状态为DOZE
  43. if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
  44. state = mPowerRequest.dozeScreenState;
  45. } else {
  46. state = Display.STATE_DOZE;
  47. }
  48. if (!mAllowAutoBrightnessWhileDozingConfig) {
  49. brightness = mPowerRequest.dozeScreenBrightness;//如果在xml文件中配置了相关属性,就将dozeScreenBrightness赋给亮度值
  50. }
  51. break;
  52. case DisplayPowerRequest.POLICY_DIM:
  53. case DisplayPowerRequest.POLICY_BRIGHT:
  54. default:
  55. state = Display.STATE_ON;//如果policy为DIM, BRIGHT的话,设备状态都为ON
  56. break;
  57. }
  58. assert(state != Display.STATE_UNKNOWN);
  59. // Apply the proximity sensor.
  60. if (mProximitySensor != null) {  //距离传感器相关处理
  61. if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
  62. setProximitySensorEnabled(true);
  63. if (!mScreenOffBecauseOfProximity
  64. && mProximity == PROXIMITY_POSITIVE) {
  65. mScreenOffBecauseOfProximity = true;
  66. sendOnProximityPositiveWithWakelock();
  67. }
  68. } else if (mWaitingForNegativeProximity
  69. && mScreenOffBecauseOfProximity
  70. && mProximity == PROXIMITY_POSITIVE
  71. && state != Display.STATE_OFF) {
  72. setProximitySensorEnabled(true);
  73. } else {
  74. setProximitySensorEnabled(false);
  75. mWaitingForNegativeProximity = false;
  76. }
  77. if (mScreenOffBecauseOfProximity
  78. && mProximity != PROXIMITY_POSITIVE) {
  79. mScreenOffBecauseOfProximity = false;
  80. sendOnProximityNegativeWithWakelock();
  81. }
  82. } else {
  83. mWaitingForNegativeProximity = false;
  84. }
  85. if (mScreenOffBecauseOfProximity) {
  86. state = Display.STATE_OFF;//如果因为距离传感器灭屏设置设备状态为OFF
  87. }
  88. // Animate the screen state change unless already animating.
  89. // The transition may be deferred, so after this point we will use the
  90. // actual state instead of the desired one.
  91. animateScreenStateChange(state, performScreenOffTransition);//处理屏幕状态改变
  92. state = mPowerState.getScreenState();//获取新的屏幕状态
  93. // Use zero brightness when screen is off.
  94. if (state == Display.STATE_OFF) {
  95. brightness = PowerManager.BRIGHTNESS_OFF; //如果新的状态是灭屏的话设置brightness为0
  96. }
  97. // Configure auto-brightness.
  98. boolean autoBrightnessEnabled = false;
  99. if (mAutomaticBrightnessController != null) {
  100. final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
  101. && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
  102. autoBrightnessEnabled = mPowerRequest.useAutoBrightness
  103. && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
  104. && brightness < 0;
  105. final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
  106. && mPowerRequest.brightnessSetByUser;
  107. mAutomaticBrightnessController.configure(autoBrightnessEnabled,
  108. mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
  109. userInitiatedChange, mPowerRequest.useTwilight);//配置控制自动亮度设置的对象
  110. }
  111. // Apply brightness boost.
  112. // We do this here after configuring auto-brightness so that we don't
  113. // disable the light sensor during this temporary state.  That way when
  114. // boost ends we will be able to resume normal auto-brightness behavior
  115. // without any delay.
  116. if (mPowerRequest.boostScreenBrightness
  117. && brightness != PowerManager.BRIGHTNESS_OFF) {
  118. brightness = PowerManager.BRIGHTNESS_ON;
  119. }
  120. // Apply auto-brightness.
  121. boolean slowChange = false;
  122. if (brightness < 0) {
  123. if (autoBrightnessEnabled) {
  124. brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();//获取自动亮度值
  125. }
  126. if (brightness >= 0) {
  127. // Use current auto-brightness value and slowly adjust to changes.
  128. brightness = clampScreenBrightness(brightness);//保证亮度值的有效性,不能在0~255之外
  129. if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
  130. slowChange = true; // slowly adapt to auto-brightness
  131. }
  132. mAppliedAutoBrightness = true;//使用了自动亮度
  133. } else {
  134. mAppliedAutoBrightness = false;//没有使用自动亮度
  135. }
  136. } else {
  137. mAppliedAutoBrightness = false;
  138. }
  139. // Use default brightness when dozing unless overridden.
  140. if (brightness < 0 && (state == Display.STATE_DOZE
  141. || state == Display.STATE_DOZE_SUSPEND)) {
  142. brightness = mScreenBrightnessDozeConfig;
  143. }
  144. // Apply manual brightness.
  145. // Use the current brightness setting from the request, which is expected
  146. // provide a nominal default value for the case where auto-brightness
  147. // is not ready yet.
  148. if (brightness < 0) {
  149. brightness = clampScreenBrightness(mPowerRequest.screenBrightness);//如果亮度值小于0的话,就是用setting中设置的亮度值
  150. }
  151. // Apply dimming by at least some minimum amount when user activity
  152. // timeout is about to expire.
  153. if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
  154. if (brightness > mScreenBrightnessRangeMinimum) {
  155. brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
  156. mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
  157. }
  158. if (!mAppliedDimming) {
  159. slowChange = false;
  160. }
  161. mAppliedDimming = true;
  162. } else if (mAppliedDimming) {
  163. slowChange = false;
  164. mAppliedDimming = false;
  165. }
  166. // If low power mode is enabled, cut the brightness level by half
  167. // as long as it is above the minimum threshold.
  168. if (mPowerRequest.lowPowerMode) {
  169. if (brightness > mScreenBrightnessRangeMinimum) {
  170. brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);//低电模式, 亮度是目标亮度的1/2
  171. }
  172. if (!mAppliedLowPower) {
  173. slowChange = false;
  174. }
  175. mAppliedLowPower = true;
  176. } else if (mAppliedLowPower) {
  177. slowChange = false;
  178. mAppliedLowPower = false;
  179. }
  180. // Animate the screen brightness when the screen is on or dozing.
  181. // Skip the animation when the screen is off or suspended.
  182. if (!mPendingScreenOff) {
  183. if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
  184. animateScreenBrightness(brightness,
  185. slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);//使用亮度渐变动画设置亮度, 渐变速度依赖于rate
  186. } else {
  187. animateScreenBrightness(brightness, 0);//动画速率为0, 没有动画
  188. }
  189. }
  190. //..........
  191. }

根据上面代码分析在updatePowerState中主要做的事情主要有两件事:
1.调用animateScreenStateChange函数处理屏幕状态变化
2.调用animateScreenBrightness函数设置屏幕亮度
下面将详细讲解这两件事情: 
animateScreenStateChange函数处理屏幕状态变化

[java] view plain copy
  1. private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
  2. // If there is already an animation in progress, don't interfere with it.
  3. if (mColorFadeOnAnimator.isStarted()
  4. || mColorFadeOffAnimator.isStarted()) {
  5. if (target != Display.STATE_ON) {
  6. return;    //如果此时有亮灭屏动画, 并且目标状态不是ON,就返回.
  7. }
  8. // If display state changed to on, proceed and stop the color fade and turn screen on.
  9. mPendingScreenOff = false;
  10. }
  11. // If we were in the process of turning off the screen but didn't quite
  12. // finish.  Then finish up now to prevent a jarring transition back
  13. // to screen on if we skipped blocking screen on as usual.
  14. if (mPendingScreenOff && target != Display.STATE_OFF) {
  15. setScreenState(Display.STATE_OFF);
  16. mPendingScreenOff = false;
  17. mPowerState.dismissColorFadeResources();
  18. }
  19. if (target == Display.STATE_ON) {    //亮屏
  20. // Want screen on.  The contents of the screen may not yet
  21. // be visible if the color fade has not been dismissed because
  22. // its last frame of animation is solid black.
  23. if (!setScreenState(Display.STATE_ON)) {    //设置屏幕状态,如果返回false就blocked亮屏, 不能往下执行
  24. return; // screen on blocked
  25. }
  26. if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
  27. // Perform screen on animation.
  28. if (mPowerState.getColorFadeLevel() == 1.0f) {   //执行亮屏动画, 将Color Fade level渐变为1.0f
  29. mPowerState.dismissColorFade();
  30. } else if (mPowerState.prepareColorFade(mContext,
  31. mColorFadeFadesConfig ?
  32. ColorFade.MODE_FADE :
  33. ColorFade.MODE_WARM_UP)) {
  34. mColorFadeOnAnimator.start();
  35. } else {
  36. mColorFadeOnAnimator.end();
  37. }
  38. } else {
  39. // Skip screen on animation.
  40. mPowerState.setColorFadeLevel(1.0f);   //跳过亮屏, 直接设置Color Fade level为1.0f
  41. mPowerState.dismissColorFade();
  42. }
  43. //...........
  44. } else {
  45. // Want screen off.   //灭屏
  46. mPendingScreenOff = true;
  47. if (mPowerState.getColorFadeLevel() == 0.0f) {
  48. // Turn the screen off.
  49. // A black surface is already hiding the contents of the screen.
  50. setScreenState(Display.STATE_OFF);   //如果Color Fade level为0.0f, 设置屏幕状态为OFF
  51. mPendingScreenOff = false;
  52. mPowerState.dismissColorFadeResources();
  53. } else if (performScreenOffTransition  //performScreenOffTransition为true, 有灭屏过渡动画
  54. && mPowerState.prepareColorFade(mContext,
  55. mColorFadeFadesConfig ?
  56. ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
  57. && mPowerState.getScreenState() != Display.STATE_OFF) {
  58. // Perform the screen off animation.
  59. mColorFadeOffAnimator.start();    //灭屏动画,Color fade leve慢慢将1.0变为0.0f
  60. } else {
  61. // Skip the screen off animation and add a black surface to hide the
  62. // contents of the screen.
  63. mColorFadeOffAnimator.end();     //跳过灭屏动画
  64. }
  65. }
  66. }

在上面函数中主要就是调用setScreenState设置屏幕状态, 只有设置好状态并且setScreenState返回true,之后才会判断是否有亮度渐变动画将Color Fade Level设置为1.0f. 否则一直会阻塞在setScreenState函数上.

[java] view plain copy
  1. private boolean setScreenState(int state) {
  2. if (mPowerState.getScreenState() != state) {
  3. final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
  4. mPowerState.setScreenState(state);   //调用DisplayPowerState设置屏幕状态
  5. // Tell battery stats about the transition.
  6. try {
  7. mBatteryStats.noteScreenState(state);
  8. } catch (RemoteException ex) {
  9. // same process
  10. }
  11. }
  12. // Tell the window manager policy when the screen is turned off or on unless it's due
  13. // to the proximity sensor.  We temporarily block turning the screen on until the
  14. // window manager is ready by leaving a black surface covering the screen.
  15. // This surface is essentially the final state of the color fade animation and
  16. // it is only removed once the window manager tells us that the activity has
  17. // finished drawing underneath.
  18. final boolean isOff = (state == Display.STATE_OFF);   //是否是灭屏状态
  19. if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
  20. && !mScreenOffBecauseOfProximity) {
  21. mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
  22. unblockScreenOn();
  23. mWindowManagerPolicy.screenTurnedOff();
  24. PMSFactory.getInstance().createExtraDisplayPowerState(mContext).setButtonOn(false);
  25. } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
  26. mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
  27. if (mPowerState.getColorFadeLevel() == 0.0f) {    //亮屏处理, 此时Colorfade level为0.0f 为true
  28. blockScreenOn();        //block亮屏, 创建一个mPendingScreenOnUnblocker对象
  29. } else {
  30. unblockScreenOn(); //将创建的mPendingScreenOnUnblocker对象销毁,设置NULL
  31. }
  32. mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);    //调用PhoneWindowManager进行处理
  33. if (PMSFactory.getInstance().createExtraDisplayPowerController(mContext).getButtonTimeout() != -2){
  34. PMSFactory.getInstance().createExtraDisplayPowerState(mContext).setButtonOn(true);
  35. }
  36. }
  37. // Return true if the screen isn't blocked.
  38. return mPendingScreenOnUnblocker == null;   //blockScreenOn时创建一个mPendingScreenOnUnblocker对象,所以返回false, block亮屏
  39. }
[java] view plain copy
  1. private void blockScreenOn() {
  2. if (mPendingScreenOnUnblocker == null) {
  3. Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
  4. mPendingScreenOnUnblocker = new ScreenOnUnblocker();
  5. mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();   //开始blocked亮屏的时间
  6. Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
  7. }
  8. }
  9. private void unblockScreenOn() {
  10. if (mPendingScreenOnUnblocker != null) {
  11. mPendingScreenOnUnblocker = null;
  12. long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
  13. Slog.i(TAG, "Unblocked screen on after " + delay + " ms");   //输出log,一共block亮屏多长时间
  14. Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
  15. }
  16. }

在setScreenState函数中主要做了两件事情:
1.调用DisplayPowerState对屏幕状态进行设置
2.通知PhoneWindowManager对keyguard和windows进行绘制.
设置屏幕状态

当设置屏幕状态时,如果新状态与之前的状态不同时就会将新的状态值记录在成员变量mScreenState中,这样可以让其它类来获取当前的屏幕状态。之后在一个Runnable对象的run函数中根据屏幕状态与ColorFade level来进行获取屏幕亮度,此时是亮屏操作但是windows尚未绘制完成level仍然是0.0,此时获取的亮度值为0,由此可知,只要windows绘制不完成亮度值会一直为0,即屏幕不会亮。

[java] view plain copy
  1. private final Runnable mScreenUpdateRunnable = new Runnable() {
  2. @Override
  3. public void run() {
  4. mScreenUpdatePending = false;
  5. int brightness = mScreenState != Display.STATE_OFF
  6. && mColorFadeLevel > 0f ? mScreenBrightness : 0;   //根据屏幕状态设置亮度值, 亮屏时如果color Fade Level为0.0f, brightness一直为0,不会亮屏
  7. if (mPhotonicModulator.setState(mScreenState, brightness)) {
  8. if (DEBUG) {
  9. Slog.d(TAG, "Screen ready");
  10. }
  11. mScreenReady = true;
  12. invokeCleanListenerIfNeeded();
  13. } else {
  14. if (DEBUG) {
  15. Slog.d(TAG, "Screen not ready");
  16. }
  17. }
  18. }
  19. };

通过调用线程PhotonicModulator的setState函数来记录所请求的状态,如果线程此时处于wait状态,就调用NotifyAll函数将其唤醒。在线程PhotonicModulator的run函数中为一个死循环,不停的进行判断屏幕亮度与屏幕状态是否发生了改变,如果两者都没有发生变化,为了减轻cpu负载线程就会wait。由于此时屏幕状态发生变化,新的状态为STATE_ON,所以suspending为false。之后进行请求设备状态。

[java] view plain copy
  1. public void run() {
  2. for (;;) {
  3. // Get pending change.
  4. final int state;
  5. final boolean stateChanged;
  6. final int backlight;
  7. final boolean backlightChanged;
  8. synchronized (mLock) {
  9. state = mPendingState;
  10. stateChanged = (state != mActualState);
  11. backlight = mPendingBacklight;
  12. backlightChanged = (backlight != mActualBacklight);
  13. if (!stateChanged) {   //判断状态是否变化
  14. // State changed applied, notify outer class.
  15. postScreenUpdateThreadSafe();
  16. mStateChangeInProgress = false;
  17. }
  18. if (!backlightChanged) {
  19. mBacklightChangeInProgress = false;
  20. }
  21. if (!stateChanged && !backlightChanged) {   //如果亮度,状态都没有改变线程将wait
  22. try {
  23. mLock.wait();
  24. } catch (InterruptedException ex) { }
  25. continue;
  26. }
  27. mActualState = state;     //获取确实的状态.亮度
  28. mActualBacklight = backlight;
  29. }
  30. // Apply pending change.
  31. if (DEBUG) {
  32. Slog.d(TAG, "Updating screen state: state="
  33. + Display.stateToString(state) + ", backlight=" + backlight);
  34. }
  35. mBlanker.requestDisplayState(state, backlight);    //mBlanker为DisplayManagerService中创建的对象,前面有提到.
  36. }
  37. }

在DisplayManagerSerice中的LocalService初始化函数initPowerManagement中创建的mBlanker, 所以就调用他的requestDisplayState函数

[java] view plain copy
  1. DisplayBlanker blanker = new DisplayBlanker() {
  2. @Override
  3. public void requestDisplayState(int state, int brightness) {
  4. // The order of operations is important for legacy reasons.
  5. if (state == Display.STATE_OFF) {
  6. requestGlobalDisplayStateInternal(state, brightness);   //灭屏先调用该函数
  7. }
  8. callbacks.onDisplayStateChange(state);    //callbacks为PowerManagerService中对象
  9. if (state != Display.STATE_OFF) {
  10. requestGlobalDisplayStateInternal(state, brightness);   //亮屏调用该处函数
  11. }
  12. }
  13. };

在此处先讲解回调PowerManagerService的onDisplayStateChange函数做了那些事情,耗时点在什么地方. 在该函数中会首先获取一个mLock的锁,这把锁是不是很熟悉,我们在前面讲绘制windows流程的时候window与power交互时需要获取mLock,如果该锁被别的线程持有,window绘制流程就会阻塞。而根据上面流程可以看出,请求设备状态是在绘制window之前发生的,所以调用函数onDisplayStateChange没有结束的话,该锁就一直被持有,导致window绘制流程不能及时返回。

[java] view plain copy
  1. public void onDisplayStateChange(int state) {
  2. // This method is only needed to support legacy display blanking behavior
  3. // where the display's power state is coupled to suspend or to the power HAL.
  4. // The order of operations matters here.
  5. synchronized (mLock) {     //获取mLock锁
  6. if (mDisplayState != state) {
  7. mDisplayState = state;
  8. if (state == Display.STATE_OFF) {  //灭屏
  9. if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
  10. setHalInteractiveModeLocked(false);
  11. }
  12. if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
  13. setHalAutoSuspendModeLocked(true);
  14. }
  15. } else {      //亮屏
  16. if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
  17. setHalAutoSuspendModeLocked(false);    //设置自动suspend模式
  18. }
  19. if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
  20. setHalInteractiveModeLocked(true);   //设置hal交互模式
  21. }
  22. }
  23. }
  24. }
  25. }
  26. private void setHalAutoSuspendModeLocked(boolean enable) {
  27. if (enable != mHalAutoSuspendModeEnabled) {
  28. if (DEBUG) {
  29. Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
  30. }
  31. mHalAutoSuspendModeEnabled = enable;
  32. Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalAutoSuspend(" + enable + ")");
  33. try {
  34. nativeSetAutoSuspend(enable);   //调用JNI设置
  35. } finally {
  36. Trace.traceEnd(Trace.TRACE_TAG_POWER);
  37. }
  38. }
  39. }

之后就会通过函数setHalAutoSuspendModeLocked调用到底层进行处理。而在底层进行处理时可以通过log信息看出,耗时的长短。

[java] view plain copy
  1. static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
  2. if (enable) {
  3. ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");  //灭屏执行超过100ms,会输出log
  4. autosuspend_enable();
  5. } else {
  6. ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on"); //亮屏执行该函数超过100ms, 会输出该行log
  7. autosuspend_disable();
  8. }
  9. }

而在亮屏时调用autosuspend_disable()是往/sys/power/state写 on(亮屏)的函数。在往节点写入状态后,调用late_resume将LCD resume,关于late_resume 阶段 “sprdfb_dispc_resume”函数执行时间可能由于手机硬件信息的不同,导致执行时间相差较大。
上面执行完之后,现在重新回到DMS中继续向下进行执行。

在DMS中通过变量mGlobalDisplayState进行记录当前的设备状态,如果设备状态发生改变时就会重新记录,之后更新设备状态将device对应的Runnable放入队列。然后就会将Runnable从队列中取出执行run函数。根据dumpsys信息可以知道,设备信息中只有一个设备“内置屏幕”,并且对应的Adapter为LocalDisplayAdapter,所以就会调用LocalDisplayAdapter中的run函数。在run函数中会调用SurfaceControl中的setDisplayPowerMode函数处理。最终到JNI中,此处也有可能发生超时,也可从输出log中看出。

[cpp] view plain copy
  1. static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
  2. sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
  3. if (token == NULL) return;
  4. ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()");
  5. SurfaceComposerClient::setDisplayPowerMode(token, mode);
  6. }

之后就调用frameworks/native/libs/gui/SurfaceComposerClient.cpp的setDisplayPowerMode函数中, 属于GUI模块.

[cpp] view plain copy
  1. void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
  2. int mode) {
  3. ComposerService::getComposerService()->setPowerMode(token, mode);
  4. }

当该流程结束后,设置设备状态就结束了。

绘制keyguard与windows

在DisplayPowerController中调用screenTurningOn函数到PhoneWindowManager中.将mPendingScreenOnUnblocker对象传过来方便完成绘制后回调回来.

[java] view plain copy
  1. // Called on the DisplayManager's DisplayPowerController thread.
  2. @Override
  3. public void screenTurningOn(final ScreenOnListener screenOnListener) {
  4. if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
  5. updateScreenOffSleepToken(false);
  6. synchronized (mLock) {
  7. mScreenOnEarly = true;
  8. mScreenOnFully = false;
  9. mKeyguardDrawComplete = false;
  10. mWindowManagerDrawComplete = false;
  11. mScreenOnListener = screenOnListener;
  12. if (mKeyguardDelegate != null) {
  13. mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
  14. mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);  //发送超时消息, 1000ms keyguard还没有绘制完,就继续向下执行
  15. mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);  //调用keyguard中函数, 绘制完成后回调mKeyguardDrawnCallback
  16. } else {
  17. if (DEBUG_WAKEUP) Slog.d(TAG,
  18. "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
  19. finishKeyguardDrawn();   //如果没有keyguard就直接结束绘制
  20. }
  21. }
  22. }

当绘制完keyguard或者keyguard绘制超时都会调用finishKeyguardDrawn结束绘制.

[java] view plain copy
  1. final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {
  2. @Override
  3. public void onDrawn() {   //绘制完成调用onDrawn函数
  4. if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");
  5. mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);  //发送MSG_KEYGUARD_DRAWN_COMPLETE消息
  6. }
  7. };
  8. private class PolicyHandler extends Handler {
  9. @Override
  10. public void handleMessage(Message msg) {
  11. switch (msg.what) {
  12. case MSG_KEYGUARD_DRAWN_COMPLETE:
  13. if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
  14. finishKeyguardDrawn();   //keyguard绘制完成, 结束
  15. break;
  16. case MSG_KEYGUARD_DRAWN_TIMEOUT:
  17. Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
  18. finishKeyguardDrawn();   //keyguard绘制超时, 结束
  19. break;
  20. }
  21. }
  22. }

keyguard绘制结束后调用WindowManagerService对Windows进行绘制, 绘制windows超时时间也为1000ms

[java] view plain copy
  1. /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
  2. static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;      //windows绘制超时时间1000ms
  3. private void finishKeyguardDrawn() {
  4. synchronized (mLock) {
  5. if (!mScreenOnEarly || mKeyguardDrawComplete) {
  6. return; // We are not awake yet or we have already informed of this event.
  7. }
  8. mKeyguardDrawComplete = true;
  9. if (mKeyguardDelegate != null) {
  10. mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);  //移除keyguard超时的message
  11. }
  12. mWindowManagerDrawComplete = false;
  13. }
  14. // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
  15. // as well as enabling the orientation change logic/sensor.
  16. mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
  17. WAITING_FOR_DRAWN_TIMEOUT);    //windows绘制完成后回调mWindowManagerDrawCallback
  18. }

在WindowManagerService中获取需要绘制的windows将其加入mWaitingForDrawn中等待绘制,通过检查mWaitingForDrawn是否为空来判断,window是否绘制完成。此时screenTurningOn函数就执行完了,剩下的就是等待windows绘制完成.

[java] view plain copy
  1. @Override
  2. public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
  3. boolean allWindowsDrawn = false;
  4. synchronized (mWindowMap) {
  5. mWaitingForDrawnCallback = callback;
  6. final WindowList windows = getDefaultWindowListLocked();  //获取windows列表
  7. for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
  8. final WindowState win = windows.get(winNdx);
  9. final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
  10. if (win.isVisibleLw()
  11. && (win.mAppToken != null || isForceHiding)) {
  12. win.mWinAnimator.mDrawState = DRAW_PENDING;
  13. // Force add to mResizingWindows.
  14. win.mLastContentInsets.set(-1, -1, -1, -1);
  15. mWaitingForDrawn.add(win);   //将所要绘制的windows加入mWaitingForDrawn中
  16. // No need to wait for the windows below Keyguard.
  17. if (isForceHiding) {
  18. break;
  19. }
  20. }
  21. }
  22. mWindowPlacerLocked.requestTraversal();
  23. mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);   //先将绘制windows超时的message移除, 以便重新计时
  24. if (mWaitingForDrawn.isEmpty()) {
  25. allWindowsDrawn = true;
  26. } else {
  27. mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);  //发送绘制超时的延迟消息
  28. checkDrawnWindowsLocked();   //检查windows是否绘制完成
  29. }
  30. }
  31. if (allWindowsDrawn) {
  32. callback.run();   //如果所有windows都绘制完成了就调用回调接口, 回到PhoneWindowManager中
  33. }
  34. }
  35. void checkDrawnWindowsLocked() {
  36. if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
  37. return;   //如果没有要绘制的windows或者没有回调接口就直接返回了
  38. }
  39. for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {  //遍历要绘制的windows
  40. WindowState win = mWaitingForDrawn.get(j);
  41. if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +
  42. ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
  43. " mHasSurface=" + win.mHasSurface +
  44. " drawState=" + win.mWinAnimator.mDrawState);
  45. if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {
  46. // Window has been removed or hidden; no draw will now happen, so stop waiting.
  47. if (DEBUG_SCREEN_ON) Slog.w(TAG_WM, "Aborted waiting for drawn: " + win);
  48. mWaitingForDrawn.remove(win);   //如果window已经被移除或者隐藏 就不需要绘制了, 直接从等待列表中移除
  49. } else if (win.hasDrawnLw()) {
  50. // Window is now drawn (and shown).
  51. if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "Window drawn win=" + win);
  52. mWaitingForDrawn.remove(win);    //如果window已经绘制完成,也从等待列表中移除
  53. }
  54. }
  55. if (mWaitingForDrawn.isEmpty()) { //如果等待列表为空
  56. if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");
  57. mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);  //移除超时消息
  58. mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);  //发送ALL_WINDOWS_DRAWN消息
  59. }
  60. }

这时只用等待所有的windows绘制了.

Windows的绘制在ViewRootImpl的draw函数中,其中ViewRoot的draw是通过vsync进行同步绘制。在绘制完成之后就会调用到WMS中DO_TRAVERSAL流程进行调用函数checkDrawnWindowsLocked判断每个window是否绘制完成。绘制完成后会发起ALL_WINDOWS_DRAWN的Message,回调回PhoneWindowManager。由于在调用函数performLayoutAndPlaceSurfacesLockedInner过程中需要与Power中的一些函数进行交互,而在Power中函数执行需要获得mLock锁,如果该锁被别的线程所持有就会发生阻塞,就不会及时返回发出window绘制完成的信号,在该流程中具体mLock还会被那些线程获取, 在讲解设置设置状态时讲解过可能被power中线程获取.
当window绘制完成后通过接口回调到PhoneWindowManager中,发送Window准备好的Message进行结束window绘制,将变量mWindowManagerDrawComplete置为true。最后回到DPC中。

[java] view plain copy
  1. case ALL_WINDOWS_DRAWN: {   //绘制windows完成
  2. Runnable callback;
  3. synchronized (mWindowMap) {
  4. callback = mWaitingForDrawnCallback;
  5. mWaitingForDrawnCallback = null;
  6. }
  7. if (callback != null) {
  8. callback.run();  //回调回PhoneWindowManager
  9. }
  10. }
  11. case WAITING_FOR_DRAWN_TIMEOUT: {   //绘制Windows超时
  12. Runnable callback = null;
  13. synchronized (mWindowMap) {
  14. Slog.w(TAG_WM, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);  //输出超时log信息
  15. mWaitingForDrawn.clear();   //将等待绘制列表清空
  16. callback = mWaitingForDrawnCallback;
  17. mWaitingForDrawnCallback = null;
  18. }
  19. if (callback != null) {
  20. callback.run(); //回调回PhoneWindowManager
  21. }
  22. break;
  23. }

回调会PhoneWindowManager后发送所有windows绘制完成的message

[java] view plain copy
  1. final Runnable mWindowManagerDrawCallback = new Runnable() {
  2. @Override
  3. public void run() {
  4. if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
  5. mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE); //发送Handler消息
  6. }
  7. };
  8. private class PolicyHandler extends Handler {
  9. @Override
  10. public void handleMessage(Message msg) {
  11. switch (msg.what) {
  12. //........
  13. case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
  14. if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
  15. finishWindowsDrawn();    //结束windows绘制
  16. break;
  17. //.......
  18. }
  19. }
  20. }
  21. private void finishWindowsDrawn() {
  22. synchronized (mLock) {
  23. if (!mScreenOnEarly || mWindowManagerDrawComplete) {
  24. return; // Screen is not turned on or we did already handle this case earlier.
  25. }
  26. mWindowManagerDrawComplete = true;   //设置windows绘制完成为true
  27. }
  28. finishScreenTurningOn();   //调用screenTurningOn就要结束了
  29. }
  30. private void finishScreenTurningOn() {
  31. synchronized (mLock) {
  32. // We have just finished drawing screen content. Since the orientation listener
  33. // gets only installed when all windows are drawn, we try to install it again.
  34. updateOrientationListenerLp();  //更新转向监听器
  35. }
  36. final ScreenOnListener listener;
  37. final boolean enableScreen;
  38. synchronized (mLock) {
  39. if (DEBUG_WAKEUP) Slog.d(TAG,
  40. "finishScreenTurningOn: mAwake=" + mAwake
  41. + ", mScreenOnEarly=" + mScreenOnEarly
  42. + ", mScreenOnFully=" + mScreenOnFully
  43. + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
  44. + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
  45. if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
  46. || (mAwake && !mKeyguardDrawComplete)) {
  47. return; // spurious or not ready yet
  48. }
  49. if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
  50. listener = mScreenOnListener;
  51. mScreenOnListener = null;
  52. mScreenOnFully = true;
  53. // Remember the first time we draw the keyguard so we know when we're done with
  54. // the main part of booting and can enable the screen and hide boot messages.
  55. if (!mKeyguardDrawnOnce && mAwake) {
  56. mKeyguardDrawnOnce = true;
  57. enableScreen = true;
  58. if (mBootMessageNeedsHiding) {
  59. mBootMessageNeedsHiding = false;
  60. hideBootMessages();
  61. }
  62. } else {
  63. enableScreen = false;
  64. }
  65. }
  66. if (listener != null) {
  67. listener.onScreenOn();    //回调回DisplayPowerController的onScreenOn函数
  68. }
  69. if (enableScreen) {
  70. try {
  71. mWindowManager.enableScreenIfNeeded();
  72. } catch (RemoteException unhandled) {
  73. }
  74. }
  75. }


Windows绘制完成回调回来之后,此时就不用block screen了,将mPendingScreenOnUnblocker置为空,并计算screen一共block了多少毫秒。之后进行更新power state,由于之前调用DisplayPS设置过状态为ON,现在状态没有发生改变,故不用进行设置直接返回,由于window已经绘制完成mPendingScreenOnUnblocker为空,故返回true。如果没有亮屏动画直接将ColorFade level设置为1.0,如果有亮屏动画的话会有ColorFade level会从0.0逐渐变为1.0。

[java] view plain copy
  1. private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
  2. @Override
  3. public void onScreenOn() {
  4. Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
  5. msg.setAsynchronous(true);
  6. mHandler.sendMessage(msg);   //发送unblock的消息
  7. }
  8. }
  9. private final class DisplayControllerHandler extends Handler {
  10. public DisplayControllerHandler(Looper looper) {
  11. super(looper, null, true /*async*/);
  12. }
  13. @Override
  14. public void handleMessage(Message msg) {
  15. switch (msg.what) {
  16. case MSG_UPDATE_POWER_STATE:
  17. updatePowerState();
  18. break;
  19. case MSG_PROXIMITY_SENSOR_DEBOUNCED:
  20. debounceProximitySensor();
  21. break;
  22. case MSG_SCREEN_ON_UNBLOCKED: //Handler收到unblock的消息后
  23. if (mPendingScreenOnUnblocker == msg.obj) {
  24. unblockScreenOn();    //将mPendingScreenOnUnblocker赋值NULL,并且输出unblock的时间, 之前有讲解
  25. updatePowerState();   //重新更新power 状态. setPowerState返回true, 继续设置Color Fade Level为1.0f
  26. }
  27. break;
  28. }
  29. }
  30. }

之后就是通过animateScreenBrightness函数设置屏幕亮度.

Android 系统(41)---Android7.0 PowerManagerService亮灭屏分析(二)相关推荐

  1. Android7.0 PowerManagerService亮灭屏分析(二)

    在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerRequest中传入DisplayPowerController中进一步处理.在亮屏过程中Disp ...

  2. Android 系统(42)---Android7.0 PowerManagerService亮灭屏分析(三)

    Android7.0 PowerManagerService亮灭屏分析(三) 在前面两部分已经对绘制windows与设置设备状态进行了详细讲解. 之后接着就该对亮度值进行设置, 实现亮屏动作了. 在D ...

  3. Android 系统(40)--Android7.0 PowerManagerService亮灭屏分析(一)

    Android7.0 PowerManagerService亮灭屏分析(一) 可以导致手机亮灭屏的因素有多种,而在本文中主要讲解按power键亮灭屏过程以及来电亮屏.在亮灭屏过程power中主要的实现 ...

  4. Android7.0 PowerManagerService亮灭屏分析(三)

    在前面两部分已经对绘制windows与设置设备状态进行了详细讲解. 之后接着就该对亮度值进行设置, 实现亮屏动作了. 在DisplayPowerController中的animateScreenBri ...

  5. Android7.0 PowerManagerService亮灭屏分析(一)

    绪论 可以导致手机亮灭屏的因素有多种,而在本文中主要讲解按power键亮灭屏过程以及来电亮屏.在亮灭屏过程power中主要的实现类与功能如下所述: PowerManagerService.java:以 ...

  6. Android 知识点 109 —— Android7.0 PowerManagerService 之亮灭屏

    原文地址: https://www.cnblogs.com/dyufei/p/8017604.html 写的太好了,粘过来! 本篇从按下power按键后,按键事件从InputManagerServic ...

  7. Android7.0 PowerManagerService 之亮灭屏(二) PMS 电源状态管理updatePowerStateLocked()...

    本篇注意接着上篇[Android7.0 PowerManagerService 之亮灭屏(一)]继续分析量灭屏的流程,这篇主要分析PMS的状态计算和更新流程,也是PMS中最为重要和复杂的一部分电源状态 ...

  8. Android 8.0 手机亮灭屏

    本文主要跟踪分析通过按松power键来唤醒,熄灭屏幕的逻辑.下面是一些相关类的介绍 PowerManagerService.java:简称PMS,负责Andorid系统中电源管理方面的工作.作为系统核 ...

  9. Android 系统(211)---Power键不亮屏分析方法

    Power键不亮屏分析方法 亮屏流程 (1)  以下是列出的整个按键唤醒的log关键点,每条都有粗体字说明其含义以及该注意的关键字: (2)  一条一条依次检查,直到如果发现某条log找不到,那问题就 ...

最新文章

  1. 如何高效地爬取链家的房源信息(四)
  2. JQuery 模糊匹配
  3. 爬取小说 spider
  4. c++计算机等级考试笔记(1)
  5. pip指定包的安装路径
  6. 分享到系统面板_win7电脑没有nvidia控制面板怎么办【解决方法】
  7. Spring的常见问题及答案
  8. PHP特级课视频教程_第三十四集 Mongodb性能优化_李强强
  9. 图书馆管理系统的c语言,图书馆管理系统 c语言.doc
  10. 怎样保护计算机桌面不被更改,电脑保护屏幕怎么设置
  11. 【渝粤教育】国家开放大学2018年秋季 0062-21T港台文学专题讲座 参考试题
  12. G_分包具体详情及处理
  13. [二分查找] [luoguP3500] [POI2010] TES-Intelligence Test
  14. 每天一个俯卧撑的健身法 - 微习惯实践
  15. 信息学奥赛一本通2063
  16. 织梦dedecms 幻灯片 自定义设置
  17. 使用计算机制作数字文本格式,计算机中数字、文字、图像、声音和视频的表示与编码...
  18. 建模添加原子时出现以下错误
  19. 返利是怎么返的_天猫超市抢券攻略
  20. Python遥感可视化 — folium模块展示热力图

热门文章

  1. data structure最短路径问题
  2. 【JAVA SE】第九章 接口
  3. 阿里巴巴Druid数据源及使用
  4. apache 设置缓存
  5. linux 权限管理命令
  6. HttpClient调用http接口(POST)
  7. tomcat启动正常,但是访问项目时,404. Eclipse没有正确部署工程项目
  8. ubuntu如何配置lxr
  9. ios--小结系列六
  10. [ruby on rails] 跟我学之(7)创建数据