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

可以导致手机亮灭屏的因素有多种,而在本文中主要讲解按power键亮灭屏过程以及来电亮屏。在亮灭屏过程power中主要的实现类与功能如下所述:
PowerManagerService.java:以下简称PMS或者PowerMS,主要处理系统中与power相关的计算,然后决策系统该如何反应。同时协调power如何与系统其他模块的交互,比如没有用户活动时屏幕变暗等。
DisplayPowerController.java:以下简称DPC或者DisplayPC,管理display设备状态,在DisplayManagerService.java(简称DMS)中实例化一个对象,以DMS为桥梁与PMS进行交互。主要处理距离传感器,亮灭屏动画,以及计算屏幕目标亮度值。通过异步回调机制来通知PMS那些事情发生了改变。同时也与WMS进行交互。
DisplayPowerState.java:以下简称DPS,power通过其与系统进行交互,如调用其它模块设置屏幕状态与亮度。仅在DPC中实例化一个对象,它算是DPC的一部分只不过将其独立出来了。
Notifier.java:将power状态的重要变化,通过广播发送出去,并且参与了与AMS,WMS,IMP的交互。
ColorFade.java:负责屏幕由关到开,由开到关的一些GL动画,由DPC进行控制。
AutomaticBrightnessController.java:主要处理光传感器,将底层上传的参数进行处理计算,将计算的新的亮度值传给DPC。
RampAnimator.java:处理屏幕亮度渐变动画。

亮屏总览

在点击power键亮屏过程中,主要流程就是input对按键事件的传输,传送到上层处理。之后就是在power中进行对亮屏状态的处理,计算一系列的数值,并且与AMS,WMS等模块进行交互,最后调用底层LCD进行最终的设备状态与亮度的设置。在下面将会对各流程详细讲解。

Input传输Power键

当触发power键,kernel会将该事件中断,然后InputReader通过EventHub获取事件,并且对输入事件进行处理,之后交由InputDispatcher进行分发。如果该事件为key事件会先调用interceptKeyBeforeQueueing,提前对需要系统处理的事件进行处理。最终调到PhoneWindowManager类中的interceptKeyBeforeQueueing函数对该事件优先处理,对power键以及屏幕状态进行判断,来决定亮屏还是灭屏等操作。当需要亮屏时,会调用PowerMangerService中的wakeup函数进行处理。
从底层到上层的具体代码调用流程 InputReader.cpp->InputDispatcher.cpp->com_android_server_input_InputManagerService.cpp->InputManagerService.java->InputMonitor.java->WindowManagerPolicy.java->PhoneWindowManager.java最终来到java层处理按键事件.

[java] view plain copy
  1. public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
  2. if (!mSystemBooted) {      //系统还没有启动完成,不处理任何按键事件
  3. // If we have not yet booted, don't let key events do anything.
  4. return 0;
  5. }
  6. final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;   //是否能与用户交互, 如果亮屏为true
  7. final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; //按键down事件
  8. final boolean canceled = event.isCanceled();     //事件被取消
  9. final int keyCode = event.getKeyCode();       //按键事件的code
  10. final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
  11. // Basic policy based on interactive state.
  12. int result;
  13. boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
  14. || event.isWakeKey();   //flags有wake标记,或者按键为KEYCODE_BACK, KEYCODE_MENU, KEYCODE_WAKEUP, KEYCODE_PAIRING, KEYCODE_STEM_1, KEYCODE_STEM_2, KEYCODE_STEM_3设置isWakeKey为true.  power ,home键属于systemKey
  15. // If the key would be handled globally, just return the result, don't worry about special
  16. // key processing.
  17. if (isValidGlobalKey(keyCode)
  18. && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
  19. if (isWakeKey) {  //如果按键时间有效, 并且在com.android.internal.R.xml.global_keys文件中配置了keycode. 如果是唤醒键就调用wakeUp唤醒屏幕
  20. wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
  21. }
  22. return result;
  23. }
  24. // Handle special keys.   //处理特殊的按键事件 ,这里主要讲解power键事件
  25. switch (keyCode) {
  26. case KeyEvent.KEYCODE_BACK:    //back键
  27. case KeyEvent.KEYCODE_VOLUME_DOWN: //音量下键
  28. case KeyEvent.KEYCODE_VOLUME_UP:  //音量上键
  29. case KeyEvent.KEYCODE_VOLUME_MUTE:   //静音键
  30. case KeyEvent.KEYCODE_ENDCALL:     //挂断电话键
  31. case KeyEvent.KEYCODE_POWER: {      //电源键
  32. result &= ~ACTION_PASS_TO_USER;
  33. isWakeKey = false; // wake-up will be handled separately
  34. if (down) {     //power按下事件
  35. interceptPowerKeyDown(event, interactive);   //处理power下键
  36. } else {      //power键松开
  37. interceptPowerKeyUp(event, interactive, canceled); //处理power上键
  38. }
  39. break;
  40. }
  41. case KeyEvent.KEYCODE_SLEEP:
  42. case KeyEvent.KEYCODE_SOFT_SLEEP:
  43. case KeyEvent.KEYCODE_WAKEUP:
  44. case KeyEvent.KEYCODE_MEDIA_PLAY:
  45. case KeyEvent.KEYCODE_MEDIA_PAUSE:
  46. case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
  47. case KeyEvent.KEYCODE_HEADSETHOOK:
  48. case KeyEvent.KEYCODE_MUTE:
  49. case KeyEvent.KEYCODE_MEDIA_STOP:
  50. case KeyEvent.KEYCODE_MEDIA_NEXT:
  51. case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
  52. case KeyEvent.KEYCODE_MEDIA_REWIND:
  53. case KeyEvent.KEYCODE_MEDIA_RECORD:
  54. case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
  55. case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
  56. case KeyEvent.KEYCODE_CALL:
  57. case KeyEvent.KEYCODE_VOICE_ASSIST:
  58. case KeyEvent.KEYCODE_WINDOW:
  59. }
  60. }
  61. if (isWakeKey) {   //如果除了power键, 别的按键也需要亮屏,就调用WakeUp亮屏
  62. wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
  63. }
  64. return result;
  65. }

处理power键down事件

[java] view plain copy
  1. private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
  2. // Hold a wake lock until the power key is released.
  3. if (!mPowerKeyWakeLock.isHeld()) {
  4. mPowerKeyWakeLock.acquire();   //获取wakeLock,保持cpu唤醒状态
  5. }
  6. // Latch power key state to detect screenshot chord.
  7. if (interactive && !mScreenshotChordPowerKeyTriggered
  8. && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
  9. mScreenshotChordPowerKeyTriggered = true;
  10. mScreenshotChordPowerKeyTime = event.getDownTime();
  11. interceptScreenshotChord();      //屏幕截屏
  12. }
  13. // Stop ringing or end call if configured to do so when power is pressed.
  14. TelecomManager telecomManager = getTelecommService();   //获取telecom
  15. boolean hungUp = false;
  16. if (telecomManager != null) {
  17. if (telecomManager.isRinging()) {   //如果来电过程中,按power键手机将静音,停止响铃
  18. // Pressing Power while there's a ringing incoming
  19. // call should silence the ringer.
  20. telecomManager.silenceRinger();
  21. } else if ((mIncallPowerBehavior
  22. & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
  23. && telecomManager.isInCall() && interactive) {
  24. // Otherwise, if "Power button ends call" is enabled,
  25. // the Power button will hang up any current active call.
  26. hungUp = telecomManager.endCall();  //如果在Setting数据库中配置了,按power键挂断电话, 就将电话挂断
  27. }
  28. }
  29. //................
  30. // If the power key has still not yet been handled, then detect short
  31. // press, long press, or multi press and decide what to do.     //如果power键还没有被处理,就判断是短按, 长按,还是多按来决定如何处理
  32. mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
  33. || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
  34. if (!mPowerKeyHandled) {
  35. if (interactive) {
  36. // When interactive, we're already awake.
  37. // Wait for a long press or for the button to be released to decide what to do.
  38. if (hasLongPressOnPowerBehavior()) {    //如果屏幕是亮这的,长按power键 ,就处理长按事件
  39. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  40. msg.setAsynchronous(true);
  41. mHandler.sendMessageDelayed(msg,
  42. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  43. }
  44. } else {
  45. wakeUpFromPowerKey(event.getDownTime());   //如果屏幕是休眠状态,就唤醒屏幕
  46. if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
  47. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  48. msg.setAsynchronous(true);
  49. mHandler.sendMessageDelayed(msg,    //如果还是长按power键, 就再处理长按事件
  50. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  51. mBeganFromNonInteractive = true;
  52. } else {
  53. final int maxCount = getMaxMultiPressPowerCount();
  54. if (maxCount <= 1) {
  55. mPowerKeyHandled = true;
  56. } else {
  57. mBeganFromNonInteractive = true;
  58. }
  59. }
  60. }
  61. }
  62. }

Power键up事件

[java] view plain copy
  1. private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
  2. final boolean handled = canceled || mPowerKeyHandled;
  3. mScreenshotChordPowerKeyTriggered = false;
  4. cancelPendingScreenshotChordAction();
  5. cancelPendingPowerKeyAction();
  6. if (!handled) {    //power键还没被处理
  7. // Figure out how to handle the key now that it has been released.
  8. mPowerKeyPressCounter += 1;
  9. final int maxCount = getMaxMultiPressPowerCount();  //多按的次数
  10. final long eventTime = event.getDownTime();    //按键发生的时间点
  11. if (mPowerKeyPressCounter < maxCount) {
  12. // This could be a multi-press.  Wait a little bit longer to confirm.
  13. // Continue holding the wake lock.    //等待一会调用powerPress处理
  14. Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
  15. interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
  16. msg.setAsynchronous(true);
  17. mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
  18. return;
  19. }
  20. // No other actions.  Handle it immediately.
  21. powerPress(eventTime, interactive, mPowerKeyPressCounter);  //没有的的处理, 立即处理power down事件
  22. }
  23. // Done.  Reset our state.
  24. finishPowerKeyPress();    //power键处理结束
  25. }
  26. private void finishPowerKeyPress() {
  27. mBeganFromNonInteractive = false;
  28. mPowerKeyPressCounter = 0;
  29. if (mPowerKeyWakeLock.isHeld()) {
  30. mPowerKeyWakeLock.release();   //释放wakLock
  31. }
  32. }

powerPress函数主要通过按power键的次数以及不同的behavior对power键做不同的处理.

[java] view plain copy
  1. private void powerPress(long eventTime, boolean interactive, int count) {
  2. if (mScreenOnEarly && !mScreenOnFully) {
  3. Slog.i(TAG, "Suppressed redundant power key press while "
  4. + "already in the process of turning the screen on.");
  5. return;
  6. }
  7. if (count == 2) {
  8. powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);  //处理按两次power键事件
  9. } else if (count == 3) {
  10. powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); //处理按三次power键事件
  11. } else if (interactive && !mBeganFromNonInteractive) {
  12. switch (mShortPressOnPowerBehavior) {
  13. case SHORT_PRESS_POWER_NOTHING:
  14. break;
  15. case SHORT_PRESS_POWER_GO_TO_SLEEP:    //灭屏
  16. mPowerManager.goToSleep(eventTime,
  17. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
  18. break;
  19. case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:  //灭屏,不经历doze流程
  20. mPowerManager.goToSleep(eventTime,
  21. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
  22. PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
  23. break;
  24. case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
  25. mPowerManager.goToSleep(eventTime,    //灭屏,不经历doze流程, 并返回home界面
  26. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
  27. PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
  28. launchHomeFromHotKey();
  29. break;
  30. case SHORT_PRESS_POWER_GO_HOME:  //返回home界面
  31. launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
  32. break;
  33. }
  34. }
  35. }

根据前面分析可以知道在power键down事件时就会调用wakeUpFromPowerKey函数来唤醒屏幕.

[java] view plain copy
  1. private void wakeUpFromPowerKey(long eventTime) {
  2. wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
  3. }
  4. private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
  5. final boolean theaterModeEnabled = isTheaterModeEnabled();
  6. if (!wakeInTheaterMode && theaterModeEnabled) {
  7. return false;
  8. }
  9. if (theaterModeEnabled) {
  10. Settings.Global.putInt(mContext.getContentResolver(),
  11. Settings.Global.THEATER_MODE_ON, 0);
  12. }
  13. mPowerManager.wakeUp(wakeTime, reason);      //调用PowerManagerService唤醒屏幕
  14. return true;
  15. }

发送亮屏广播

当power接收到亮灭屏调用后,会先进行设置手机wakefullness状态. 之后发送亮灭屏广播通知其他应用手机处于亮屏还是灭屏状态。

[java] view plain copy
  1. private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
  2. String opPackageName, int opUid) {
  3. if (DEBUG_SPEW) {
  4. Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
  5. }
  6. if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
  7. || !mBootCompleted || !mSystemReady) {
  8. return false;        //判断是否要去亮屏
  9. }
  10. Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
  11. try {
  12. switch (mWakefulness) {
  13. case WAKEFULNESS_ASLEEP:
  14. Slog.i(TAG, "Waking up from sleep due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");
  15. break;
  16. case WAKEFULNESS_DREAMING:
  17. Slog.i(TAG, "Waking up from dream due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");
  18. break;
  19. case WAKEFULNESS_DOZING:
  20. Slog.i(TAG, "Waking up from dozing due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");
  21. break;
  22. }
  23. mLastWakeTime = eventTime;   //设置最后一次唤醒的时间
  24. setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);   //Notifier调用onWakefulnessChangeStarted发送亮屏广播
  25. mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);  //调用Notifier通知battery处理
  26. userActivityNoUpdateLocked(     //更新最后一次用户事件的时间
  27. eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
  28. } finally {
  29. Trace.traceEnd(Trace.TRACE_TAG_POWER);
  30. }
  31. return true;
  32. }

在Notifier.java中与AMS,window,input进行交互,通知各模块手机状态发生了改变,根据屏幕状态各自进行处理, 最后发送亮灭屏广播, 通知关心的模块.

[java] view plain copy
  1. public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
  2. final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); //获取交互模式,亮屏为true, 灭屏为false
  3. if (DEBUG) {
  4. Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
  5. + ", reason=" + reason + ", interactive=" + interactive);
  6. }
  7. // Tell the activity manager about changes in wakefulness, not just interactivity.
  8. // It needs more granularity than other components.
  9. mHandler.post(new Runnable() {
  10. @Override
  11. public void run() {
  12. mActivityManagerInternal.onWakefulnessChanged(wakefulness);   //与AMS交互处理
  13. }
  14. });
  15. // Handle any early interactive state changes.
  16. // Finish pending incomplete ones from a previous cycle.
  17. if (mInteractive != interactive) {
  18. // Finish up late behaviors if needed.
  19. if (mInteractiveChanging) {
  20. handleLateInteractiveChange();
  21. }
  22. // Start input as soon as we start waking up or going to sleep.
  23. mInputManagerInternal.setInteractive(interactive);    //在input中记录现在的屏幕状态
  24. mInputMethodManagerInternal.setInteractive(interactive);
  25. // Notify battery stats.
  26. try {
  27. mBatteryStats.noteInteractive(interactive);   //唤醒battery状态
  28. } catch (RemoteException ex) { }
  29. // Handle early behaviors.
  30. mInteractive = interactive;
  31. mInteractiveChangeReason = reason;
  32. mInteractiveChanging = true;
  33. handleEarlyInteractiveChange();   //初期处理交互模式改变
  34. }
  35. }
[java] view plain copy
  1. private void handleEarlyInteractiveChange() {
  2. synchronized (mLock) {
  3. if (mInteractive) {
  4. // Waking up...    //亮屏
  5. mHandler.post(new Runnable() {
  6. @Override
  7. public void run() {
  8. EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
  9. mPolicy.startedWakingUp();   //通过PhoneWindowManager系统开始亮屏, 更新转向监听器,手势监听器等
  10. }
  11. });
  12. // Send interactive broadcast.
  13. mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
  14. mPendingWakeUpBroadcast = true;
  15. updatePendingBroadcastLocked();   //更新亮屏广播
  16. } else {
  17. // Going to sleep...   //灭屏
  18. // Tell the policy that we started going to sleep.
  19. final int why = translateOffReason(mInteractiveChangeReason);
  20. mHandler.post(new Runnable() {
  21. @Override
  22. public void run() {
  23. mPolicy.startedGoingToSleep(why);
  24. }
  25. });
  26. }
  27. }
  28. }

通过Handler发送MSG_BROADCAST消息来发送下一个广播sendNextBroadcast()

[java] view plain copy
  1. private void sendNextBroadcast() {
  2. final int powerState;
  3. synchronized (mLock) {
  4. if (mBroadcastedInteractiveState == INTERACTIVE_STATE_UNKNOWN) {
  5. // Broadcasted power state is unknown.  Send wake up.
  6. mPendingWakeUpBroadcast = false;
  7. mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;   //亮屏状态
  8. } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
  9. // Broadcasted power state is awake.  Send asleep if needed.
  10. if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
  11. || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
  12. mPendingGoToSleepBroadcast = false;
  13. mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP; //灭屏状态
  14. } else {
  15. finishPendingBroadcastLocked();    //结束发送广播
  16. return;
  17. }
  18. } else {
  19. // Broadcasted power state is asleep.  Send awake if needed.
  20. if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
  21. || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
  22. mPendingWakeUpBroadcast = false;
  23. mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
  24. } else {
  25. finishPendingBroadcastLocked();
  26. return;
  27. }
  28. }
  29. mBroadcastStartTime = SystemClock.uptimeMillis();
  30. powerState = mBroadcastedInteractiveState;
  31. }
  32. EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
  33. if (powerState == INTERACTIVE_STATE_AWAKE) {
  34. sendWakeUpBroadcast();   //发送亮屏广播
  35. } else {
  36. sendGoToSleepBroadcast();
  37. }
  38. }
[java] view plain copy
  1. mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);   //亮屏广播intent
  2. mScreenOnIntent.addFlags(   //前台广播
  3. Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
  4. private void sendWakeUpBroadcast() {
  5. if (DEBUG) {
  6. Slog.d(TAG, "Sending wake up broadcast.");
  7. }
  8. if (ActivityManagerNative.isSystemReady()) {
  9. mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,
  10. mWakeUpBroadcastDone, mHandler, 0, null, null);  //发送亮屏广播,并且其它模块全部处理完后, 自身接收亮屏广播
  11. } else {
  12. EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
  13. sendNextBroadcast();
  14. }
  15. }
  16. private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
  17. @Override
  18. public void onReceive(Context context, Intent intent) {
  19. EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
  20. SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
  21. sendNextBroadcast();   //自身接收到亮屏广播后, 之后会调用finishPendingBroadcastLocked,释放wakeLock
  22. }
  23. };

当power接收到亮灭屏调用后,会先进行设置手机wakefullness状态,之后发送亮灭屏广播通知其他应用手机处于亮屏还是灭屏状态。并且在发送广播过程中power也与AMS,window,input进行交互,通知各模块手机状态发生了改变,根据屏幕状态各自进行处理。其中发送亮灭屏广播的主要实现在Notifier.java中。
当wakefulness状态发生改变,AMS收到通知。如果亮屏操作,AMS就会通过函数comeOutOfSleepIfNeedLocked调用到ActivityStackSupervisor中,将sleep超时消息移除,如果抓的有partial锁,就将其释放,最后将在栈顶的activity显示出来。
power是通过WindowManagerPolicy与PhoneWindowManager进行交互,当屏幕在wakingup时需要通知window进行更新手势监听,更新方向监听,更新锁屏超时时间。最后通知keyguard屏幕点亮了,进行刷新锁屏界面时间,之后通过回调接口,回调回PhoneWindowManager的onShown函数,通知window keyguard准备完成。
当亮屏时通过InputManagerService将当前屏幕状态传入JNI中进行记录,当再次发生power键事件可以方便确认该事件是需要亮屏还是灭屏。

更新Power全局状态

当广播处理完毕后就会调用PMS的内部函数updatePowerStateLocked来更新全局电源状态。其实在PMS中很多函数都只是对一些必须的属性进行赋值,大部分最终都会调用到updatePowerStateLocked函数中进行功能执行,其中更新电源状态主要依据就是变量mDirty。mDirty就是用来记录power state的变化的标记位,这样的状态变化在系统中一共定义了12个,每一个状态对应一个固定的数字,都是2的倍数。这样,若有多个状态一块变化,进行按位取或这样结果既是唯一的,又能准确标记出各个状态的变化。在updatePowerStateLocked中主要做了如下事情:
一.首先判断手机是否处于充电状态,如果标记位DIRTY_BATTERY_STATE发生改变时就证明电池状态发生了改变,然后通过对比判断(通过电池前后变化与充电状态的变化),确认手机是否处于充电状态。如果手机处于充电状态会将表示充电的标记位记入mDirty中。当有USB插拔时我们也可以通过配置信息来决定是否需要点亮屏幕。并且是否在充电或者充电方式发生改变,系统都会认为发生了一次用户事件进行更新最后用户操作时间,以此来重新计算屏幕超时时间。

[java] view plain copy
  1. private void updateIsPoweredLocked(int dirty) {
  2. if ((dirty & DIRTY_BATTERY_STATE) != 0) {
  3. final boolean wasPowered = mIsPowered;  //是否在充电
  4. final int oldPlugType = mPlugType;     //充电类型
  5. final boolean oldLevelLow = mBatteryLevelLow;  //低电模式
  6. mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
  7. mPlugType = mBatteryManagerInternal.getPlugType();
  8. mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
  9. mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
  10. if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
  11. mDirty |= DIRTY_IS_POWERED;  //如果充电中设置mDirty
  12. // Update wireless dock detection state.
  13. final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
  14. mIsPowered, mPlugType, mBatteryLevel);   //无线充电
  15. // Treat plugging and unplugging the devices as a user activity.
  16. // Users find it disconcerting when they plug or unplug the device
  17. // and it shuts off right away.
  18. // Some devices also wake the device when plugged or unplugged because
  19. // they don't have a charging LED.
  20. final long now = SystemClock.uptimeMillis();
  21. if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
  22. dockedOnWirelessCharger)) {    //插拔USB是否要点亮屏幕
  23. wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
  24. mContext.getOpPackageName(), Process.SYSTEM_UID);
  25. }
  26. userActivityNoUpdateLocked(   //插拔USB算一次用户事件,重新设置最后一次用户事件的时间点
  27. now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
  28. // Tell the notifier whether wireless charging has started so that
  29. // it can provide feedback to the user.
  30. if (dockedOnWirelessCharger) {
  31. mNotifier.onWirelessChargingStarted();
  32. }
  33. }
  34. if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {   //低电模式
  35. if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
  36. if (DEBUG_SPEW) {
  37. Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
  38. }
  39. mAutoLowPowerModeSnoozing = false;
  40. }
  41. updateLowPowerModeLocked();  //更新低电模式
  42. }
  43. }
  44. }
[java] view plain copy
  1. mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
  2. com.android.internal.R.bool.config_unplugTurnsOnScreen);   //从xml文件中读取配置信息
  3. private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
  4. boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
  5. // Don't wake when powered unless configured to do so.
  6. if (!mWakeUpWhenPluggedOrUnpluggedConfig) {   //如果配置为true, 可能会亮屏
  7. return false;
  8. }
  9. // Don't wake when undocked from wireless charger.
  10. // See WirelessChargerDetector for justification.
  11. if (wasPowered && !mIsPowered
  12. && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
  13. return false;
  14. }
  15. // Don't wake when docked on wireless charger unless we are certain of it.
  16. // See WirelessChargerDetector for justification.
  17. if (!wasPowered && mIsPowered
  18. && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
  19. && !dockedOnWirelessCharger) {
  20. return false;
  21. }
  22. // If already dreaming and becoming powered, then don't wake.
  23. if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {
  24. return false;
  25. }
  26. // Don't wake while theater mode is enabled.
  27. if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {
  28. return false;
  29. }
  30. // Otherwise wake up!
  31. return true;
  32. }

二:更新wakefulness

[java] view plain copy
  1. for (;;) {
  2. int dirtyPhase1 = mDirty;
  3. dirtyPhase2 |= dirtyPhase1;
  4. mDirty = 0;    //将mDirty清零,不影响下个循环
  5. updateWakeLockSummaryLocked(dirtyPhase1);
  6. updateUserActivitySummaryLocked(now, dirtyPhase1);
  7. if (!updateWakefulnessLocked(dirtyPhase1)) {   //当updateWakefulnessLocked返回false跳出循环
  8. break;
  9. }
  10. }


updateWakeLockSummaryLocked函数将wakeLock的类型用mWakeLockSummary进行记录,最后与Wakefulness状态结合重新算出新的mWakeLockSummary值,在下面判断是否需要睡眠时会使用。

[java] view plain copy
  1. private void updateWakeLockSummaryLocked(int dirty) {
  2. if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
  3. mWakeLockSummary = 0;
  4. final int numWakeLocks = mWakeLocks.size();    //获取所有的wakeLocks
  5. for (int i = 0; i < numWakeLocks; i++) { //遍历所有的wakeLocks, 将wakeLocks记录在mWakeLockSummary中
  6. final WakeLock wakeLock = mWakeLocks.get(i);
  7. switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
  8. case PowerManager.PARTIAL_WAKE_LOCK:
  9. if (!wakeLock.mDisabled) {
  10. // We only respect this if the wake lock is not disabled.
  11. mWakeLockSummary |= WAKE_LOCK_CPU;
  12. }
  13. break;
  14. case PowerManager.FULL_WAKE_LOCK:  //屏幕键盘全部点亮
  15. mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
  16. break;
  17. case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  //点亮屏幕
  18. mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
  19. break;
  20. case PowerManager.SCREEN_DIM_WAKE_LOCK:   //dim锁
  21. mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
  22. break;
  23. case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:  //距离灭屏
  24. mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
  25. break;
  26. case PowerManager.DOZE_WAKE_LOCK:
  27. mWakeLockSummary |= WAKE_LOCK_DOZE;
  28. break;
  29. case PowerManager.DRAW_WAKE_LOCK:
  30. mWakeLockSummary |= WAKE_LOCK_DRAW;
  31. break;
  32. }
  33. }
  34. // Cancel wake locks that make no sense based on the current state.
  35. if (mWakefulness != WAKEFULNESS_DOZING) {  //根据当前的屏幕状态, 取消不必要的wakeLocks
  36. mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
  37. }
  38. if (mWakefulness == WAKEFULNESS_ASLEEP   //如果屏幕为休眠,就将屏幕高亮,dim锁取消
  39. || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
  40. mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
  41. | WAKE_LOCK_BUTTON_BRIGHT);
  42. if (mWakefulness == WAKEFULNESS_ASLEEP) {
  43. mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
  44. }
  45. }
  46. // Infer implied wake locks where necessary based on the current state.
  47. if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
  48. if (mWakefulness == WAKEFULNESS_AWAKE) {
  49. mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;  //当WakeLock为亮屏锁或dim锁时,需要保持AWAKE状态。
  50. } else if (mWakefulness == WAKEFULNESS_DREAMING) {
  51. mWakeLockSummary |= WAKE_LOCK_CPU;
  52. }
  53. }
  54. if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
  55. mWakeLockSummary |= WAKE_LOCK_CPU;
  56. }
  57. if (DEBUG_SPEW) {
  58. Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
  59. + PowerManagerInternal.wakefulnessToString(mWakefulness)
  60. + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
  61. }
  62. }
  63. }

之后updateUserActivitySummaryLocked就会更新屏幕超时时间,根据最后一次的用户事件与屏幕超时时间与dim持续时间来计算屏幕超时的时间,然后与现在的时间进行对比,来决定屏幕要继续高亮,还是要变为dim状态。

[java] view plain copy
  1. private void updateUserActivitySummaryLocked(long now, int dirty) {
  2. // Update the status of the user activity timeout timer.
  3. if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
  4. | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
  5. mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);  //移除屏幕超时的Message
  6. long nextTimeout = 0;
  7. if (mWakefulness == WAKEFULNESS_AWAKE
  8. || mWakefulness == WAKEFULNESS_DREAMING
  9. || mWakefulness == WAKEFULNESS_DOZING) {
  10. final int sleepTimeout = getSleepTimeoutLocked();   //获取睡眠超时时间
  11. final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);  //获取屏幕超时时间
  12. final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);  //获取dim持续时长
  13. final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
  14. mUserActivitySummary = 0;
  15. if (mLastUserActivityTime >= mLastWakeTime) {   //最后一次的用户时间大于最后一次屏幕醒来的时间
  16. nextTimeout = mLastUserActivityTime   //计算下一次屏幕要变为dim的时间
  17. + screenOffTimeout - screenDimDuration;
  18. if (now < nextTimeout) {
  19. mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;  //现在还早于屏幕超时, 设置现在用户活动为屏幕高亮
  20. } else {
  21. nextTimeout = mLastUserActivityTime + screenOffTimeout;  //重新设置屏幕超时时间,进入dim阶段
  22. if (now < nextTimeout) {    //进入dim阶段了
  23. mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
  24. }
  25. }
  26. }
  27. if (mUserActivitySummary == 0
  28. && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
  29. nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
  30. if (now < nextTimeout) {  //根据请求的policy来判断屏幕是高亮,还是dim状态
  31. if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {
  32. mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
  33. } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
  34. mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
  35. }
  36. }
  37. }
  38. if (mUserActivitySummary == 0) {   //如果mUserActivitySummary还没赋值
  39. if (sleepTimeout >= 0) {
  40. final long anyUserActivity = Math.max(mLastUserActivityTime,
  41. mLastUserActivityTimeNoChangeLights);
  42. if (anyUserActivity >= mLastWakeTime) {
  43. nextTimeout = anyUserActivity + sleepTimeout;
  44. if (now < nextTimeout) {
  45. mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;   //设置dream状态
  46. }
  47. }
  48. } else {
  49. mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
  50. nextTimeout = -1;
  51. }
  52. }
  53. if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
  54. if ((mUserActivitySummary &
  55. (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
  56. // Device is being kept awake by recent user activity
  57. if (nextTimeout >= now && mOverriddenTimeout == -1) {
  58. // Save when the next timeout would have occurred
  59. mOverriddenTimeout = nextTimeout;
  60. }
  61. }
  62. mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
  63. nextTimeout = -1;
  64. }
  65. if (mUserActivitySummary != 0 && nextTimeout >= 0) {  //mUserActivitySummary有值, 并且nextTimeout大于等于0, 发超时消息
  66. Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
  67. msg.setAsynchronous(true);
  68. mHandler.sendMessageAtTime(msg, nextTimeout);   //发送屏幕超时的Message
  69. }
  70. } else {
  71. mUserActivitySummary = 0;
  72. }
  73. if (DEBUG_SPEW) {
  74. Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
  75. + PowerManagerInternal.wakefulnessToString(mWakefulness)
  76. + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
  77. + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
  78. }
  79. }
  80. }

PowerManagerHandler接收屏幕超时的消息, 并且调用handleUserActivityTimeout进行处理, 该函数之后就在Handler线程中运行.

[java] view plain copy
  1. /**
  2. * Handler for asynchronous operations performed by the power manager.
  3. */
  4. private final class PowerManagerHandler extends Handler {
  5. public PowerManagerHandler(Looper looper) {
  6. super(looper, null, true /*async*/);
  7. }
  8. @Override
  9. public void handleMessage(Message msg) {
  10. switch (msg.what) {
  11. case MSG_USER_ACTIVITY_TIMEOUT:
  12. handleUserActivityTimeout();    //处理用户超时事件
  13. break;
  14. case MSG_SANDMAN:
  15. handleSandman();
  16. break;
  17. case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
  18. handleScreenBrightnessBoostTimeout();
  19. break;
  20. }
  21. }
  22. }
  23. private void handleUserActivityTimeout() { // runs on handler thread
  24. synchronized (mLock) {
  25. if (DEBUG_SPEW) {
  26. Slog.d(TAG, "handleUserActivityTimeout");
  27. }
  28. mDirty |= DIRTY_USER_ACTIVITY;  //设置有用户活动的mDirty值
  29. updatePowerStateLocked();   //更新电源状态, 最后去判断是否要睡眠
  30. }
  31. }

根据前面流程图可以看出更新wakefulness过程是通过一个死循环来执行的,只有调用函数updateWakefulnessLocked返回false时才会跳出循环。在循环中对wakeLockSummary进行更新,并且更新自动灭屏时间后,进行判断系统是否该睡眠了,是否可以跳出循环,具体流程图如下:

在updateWakefulnessLocked中主要根据是否存在wakeLock,用户活动进行判断设备是否需要进入睡眠状态。从函数isBeingKeptAwakeLocked可以看出当device拿着一个wake lock,有用户事件,有距离传感器等都不会灭屏进行睡眠状态。如果需要睡眠就会往下面调用,最后跳出循环。

[java] view plain copy
  1. private boolean updateWakefulnessLocked(int dirty) {
  2. boolean changed = false;
  3. if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
  4. | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
  5. | DIRTY_DOCK_STATE)) != 0) {
  6. if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {   //mWakefulness为AWAKE, 并且到了睡觉时间, 就去睡觉
  7. if (DEBUG_SPEW) {
  8. Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
  9. }
  10. final long time = SystemClock.uptimeMillis();
  11. if (shouldNapAtBedTimeLocked()) {
  12. changed = napNoUpdateLocked(time, Process.SYSTEM_UID);  //睡觉前先小憩一会
  13. } else {
  14. changed = goToSleepNoUpdateLocked(time,
  15. PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);  //直接睡觉
  16. }
  17. }
  18. }
  19. return changed;
  20. }
[java] view plain copy
  1. private boolean isItBedTimeYetLocked() {// 对所有该唤醒的情况取反, 就是该休眠了
  2. return mBootCompleted && !isBeingKeptAwakeLocked();
  3. }
  4. private boolean isBeingKeptAwakeLocked() {
  5. return mStayOn  //设置了stay on
  6. || mProximityPositive  //距离传感器返回一个positive结果,保持唤醒
  7. || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0  //当有wake lock时保持唤醒
  8. || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
  9. | USER_ACTIVITY_SCREEN_DIM)) != 0   //有user activity时保持唤醒
  10. || mScreenBrightnessBoostInProgress;
  11. }
[java] view plain copy
  1. mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
  2. Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
  3. mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
  4. UserHandle.USER_CURRENT) != 0);     //从settings数据库获取对应值
  5. mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
  6. Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
  7. mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
  8. UserHandle.USER_CURRENT) != 0);
  9. private boolean shouldNapAtBedTimeLocked() {  //当返回true, 设备自动nap
  10. return mDreamsActivateOnSleepSetting
  11. || (mDreamsActivateOnDockSetting
  12. && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
  13. }
[java] view plain copy
  1. private boolean napNoUpdateLocked(long eventTime, int uid) {
  2. if (DEBUG_SPEW) {
  3. Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
  4. }
  5. if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
  6. || !mBootCompleted || !mSystemReady) {
  7. return false;
  8. }
  9. Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
  10. try {
  11. Slog.i(TAG, "Nap time (uid " + uid +")...");
  12. mSandmanSummoned = true;
  13. setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);  //设置WAKEFULNESS_DREAMING
  14. } finally {
  15. Trace.traceEnd(Trace.TRACE_TAG_POWER);
  16. }
  17. return true;
  18. }

调用goToSleepNoUpdateLocked进行睡眠, 当按power键灭屏是也会调用该函数.

[java] view plain copy
  1. private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
  2. if (DEBUG_SPEW) {
  3. Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
  4. + ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
  5. }
  6. if (eventTime < mLastWakeTime
  7. || mWakefulness == WAKEFULNESS_ASLEEP
  8. || mWakefulness == WAKEFULNESS_DOZING
  9. || !mBootCompleted || !mSystemReady) {
  10. return false;   //判断设备是否应该睡眠
  11. }
  12. Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
  13. try {
  14. switch (reason) {   //输出灭屏的原因
  15. case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
  16. Slog.i(TAG, "Going to sleep due to device administration policy "
  17. + "(uid " + uid +")...");
  18. break;
  19. case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
  20. Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
  21. break;
  22. case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
  23. Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
  24. break;
  25. case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
  26. Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
  27. break;
  28. case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
  29. Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
  30. break;
  31. case PowerManager.GO_TO_SLEEP_REASON_HDMI:
  32. Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
  33. break;
  34. default:
  35. Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
  36. reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
  37. break;
  38. }
  39. mLastSleepTime = eventTime;
  40. mSandmanSummoned = true;
  41. setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
  42. // Report the number of wake locks that will be cleared by going to sleep.
  43. int numWakeLocksCleared = 0;
  44. final int numWakeLocks = mWakeLocks.size();
  45. for (int i = 0; i < numWakeLocks; i++) {  //遍历所有的wakeLocks, 将FULL, BRIGHT, DIM Locks,计入numWakeLocksCleared中
  46. final WakeLock wakeLock = mWakeLocks.get(i);
  47. switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
  48. case PowerManager.FULL_WAKE_LOCK:
  49. case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
  50. case PowerManager.SCREEN_DIM_WAKE_LOCK:
  51. numWakeLocksCleared += 1;
  52. break;
  53. }
  54. }
  55. EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
  56. // Skip dozing if requested.
  57. if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
  58. reallyGoToSleepNoUpdateLocked(eventTime, uid); //如果没有doze流程,直接设置WAKEFULNESS_ASLEEP
  59. }
  60. } finally {
  61. Trace.traceEnd(Trace.TRACE_TAG_POWER);
  62. }
  63. return true;   //返回true
  64. }

当第一个for循环中将所有的状态都设置好了, 并且此时也没有重要的mDirty发生变化, 在下一次循环中mDirty的值为0, updateWakefulnessLocked返回false,就会跳出循环.

当跳出循环之后在函数updateDisplayPowerStateLocked中进行获取需要请求的设备电源状态是亮还是灭或者dim,判断是否开启了自动调节亮度开关,是否使用了距离传感器,并经过一系列的计算获取亮度值等,最终都记录到DisplayPowerRequest中,经过DMS传入DPC中,进行处理。

[java] view plain copy
  1. private boolean updateDisplayPowerStateLocked(int dirty) {
  2. final boolean oldDisplayReady = mDisplayReady;
  3. if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
  4. | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
  5. | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
  6. mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(); //根据mWakefulness与mWakeLockSummary获得,设备新状态是DIM, BRIGHT, OFF还是DOZE
  7. // Determine appropriate screen brightness and auto-brightness adjustments.
  8. boolean brightnessSetByUser = true;
  9. int screenBrightness = mScreenBrightnessSettingDefault;
  10. float screenAutoBrightnessAdjustment = 0.0f;   //自动亮度调节
  11. boolean autoBrightness = (mScreenBrightnessModeSetting ==
  12. Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);   //是否开启自动亮度
  13. if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
  14. screenBrightness = mScreenBrightnessOverrideFromWindowManager;
  15. autoBrightness = false;
  16. brightnessSetByUser = false;
  17. } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
  18. screenBrightness = mTemporaryScreenBrightnessSettingOverride;
  19. } else if (isValidBrightness(mScreenBrightnessSetting)) {
  20. screenBrightness = mScreenBrightnessSetting;
  21. }
  22. if (autoBrightness) {
  23. screenBrightness = mScreenBrightnessSettingDefault;  //自动亮度调节
  24. if (isValidAutoBrightnessAdjustment(
  25. mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
  26. screenAutoBrightnessAdjustment =
  27. mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
  28. } else if (isValidAutoBrightnessAdjustment(
  29. mScreenAutoBrightnessAdjustmentSetting)) {
  30. screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
  31. }
  32. }
  33. screenBrightness = Math.max(Math.min(screenBrightness,  //获得请求亮度
  34. mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
  35. screenAutoBrightnessAdjustment = Math.max(Math.min(
  36. screenAutoBrightnessAdjustment, 1.0f), -1.0f);
  37. // Update display power request.  //将数据记录在mDisplayPowerRequest中
  38. mDisplayPowerRequest.screenBrightness = screenBrightness;
  39. mDisplayPowerRequest.screenAutoBrightnessAdjustment =
  40. screenAutoBrightnessAdjustment;
  41. mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
  42. mDisplayPowerRequest.useAutoBrightness = autoBrightness;
  43. mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
  44. mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
  45. mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
  46. mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
  47. if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
  48. mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
  49. if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
  50. && (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
  51. mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
  52. }
  53. mDisplayPowerRequest.dozeScreenBrightness =
  54. mDozeScreenBrightnessOverrideFromDreamManager;
  55. } else {
  56. mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
  57. mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
  58. }
  59. mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
  60. mRequestWaitForNegativeProximity);     //调用requestPowerState请求电源状态
  61. mRequestWaitForNegativeProximity = false;
  62. if (DEBUG_SPEW) {
  63. Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
  64. + ", policy=" + mDisplayPowerRequest.policy
  65. + ", mWakefulness=" + mWakefulness
  66. + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
  67. + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
  68. + ", mBootCompleted=" + mBootCompleted
  69. + ", mScreenBrightnessBoostInProgress="
  70. + mScreenBrightnessBoostInProgress);
  71. }
  72. }
  73. return mDisplayReady && !oldDisplayReady;
  74. }

版权声明:

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

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

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

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

    Android7.0 PowerManagerService亮灭屏分析(二) 3029 在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerReque ...

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

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

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

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

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

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

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

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

  7. Android 8.0 手机亮灭屏

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

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

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

  9. Android7.1 Kyguard界面灭屏时间分析

    概述 在Android系统中,当用户没有操作手机一段时间后,系统会自动灭屏进入休眠状态,从而降低手机功耗.一般情况下系统灭屏的时间由用户在手机设置中自己进行定义是10s,30s还是1min等等.但是如 ...

最新文章

  1. 给女友讲讲设计模式——适配器模式(JAVA实例)5
  2. 如何使用 jMeter CSV Data Set config
  3. python学习-综合练习二(整数和浮点数判断奇偶、质数判断)
  4. 前端学习(688):断点调试
  5. Qt文档阅读笔记-官方Form Extractor Example实例解析
  6. hive动态分区shell_hive-shell批量操作分区文件
  7. wangeditor 请求头_跨域上传 · wangEditor2使用手册 · 看云
  8. oracle表连接——处理连接过程中另外一张表没有相关数据不显示问题
  9. IDEA——使用JSONObject时报错怎么办?
  10. img 转esxi vmdk_KVM qcow2、raw、vmdk等镜像格式和转换
  11. Linux无头浏览器的自动化测试实现
  12. 微信群聊在哪个服务器,微信怎么找附近的群聊?微信群不见了怎么找?
  13. Reflex WMS入门系列七:收货(Receipt)
  14. windows聚焦壁纸不更新_锁屏壁纸windows聚焦不更新?
  15. java knn kd树_KD树实现KNN
  16. jquery衬衣产品内容详情页
  17. surfacepro3运行C语言,【微软 Surface PRO3使用总结】C面|D面|噪音|材质_摘要频道_什么值得买...
  18. windows10正式版官方原版镜像iso下载地址
  19. elasticsearch查询关键字slop
  20. win10下局域网不同电脑间如何实现文件共享?

热门文章

  1. 【STM32】HAL库 STM32CubeMX教程六----定时器中断
  2. 嵌入式Linux系统编程学习之十一Linux进程的创建与控制
  3. bootstrap 垂直居中 布局_网页布局都有哪种?一般都用什么布局?
  4. 【数据库】第一章 数据库的分类、SQL、数据库、表和表记录的常用操作
  5. JSP 九大内置对象详解
  6. POJ 6048 泰国佛塔 【dfs搜索】【暴力大比拼】【北大ACM/ICPC竞赛训练】
  7. webpack代码分割和懒加载
  8. crontab 定时任务
  9. android Camera 录像时旋转角度
  10. topcoder srm 628 div2 250 500