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

来源:互联网 发布:ubuntu 17.10 安装后 编辑:程序博客网 时间:2024/05/01 21:19

绪论

可以导致手机亮灭屏的因素有多种,而在本文中主要讲解按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.   
  7.     final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;   //是否能与用户交互, 如果亮屏为true  
  8.     final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; //按键down事件  
  9.     final boolean canceled = event.isCanceled();     //事件被取消  
  10.     final int keyCode = event.getKeyCode();       //按键事件的code  
  11.   
  12.     final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;    
  13.     // Basic policy based on interactive state.  
  14.     int result;      
  15.     boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0  
  16.             || 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  
  17.   
  18.     // If the key would be handled globally, just return the result, don't worry about special  
  19.     // key processing.  
  20.     if (isValidGlobalKey(keyCode)     
  21.             && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {  
  22.         if (isWakeKey) {  //如果按键时间有效, 并且在com.android.internal.R.xml.global_keys文件中配置了keycode. 如果是唤醒键就调用wakeUp唤醒屏幕  
  23.             wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");  
  24.         }  
  25.         return result;  
  26.     }  
  27.   
  28.     // Handle special keys.   //处理特殊的按键事件 ,这里主要讲解power键事件  
  29.     switch (keyCode) {  
  30.         case KeyEvent.KEYCODE_BACK:    //back键  
  31.         case KeyEvent.KEYCODE_VOLUME_DOWN: //音量下键  
  32.         case KeyEvent.KEYCODE_VOLUME_UP:  //音量上键  
  33.         case KeyEvent.KEYCODE_VOLUME_MUTE:   //静音键  
  34.         case KeyEvent.KEYCODE_ENDCALL:     //挂断电话键  
  35.         case KeyEvent.KEYCODE_POWER: {      //电源键  
  36.             result &= ~ACTION_PASS_TO_USER;  
  37.             isWakeKey = false// wake-up will be handled separately  
  38.             if (down) {     //power按下事件  
  39.                 interceptPowerKeyDown(event, interactive);   //处理power下键  
  40.             } else {      //power键松开  
  41.                 interceptPowerKeyUp(event, interactive, canceled); //处理power上键  
  42.             }  
  43.             break;  
  44.         }  
  45.         case KeyEvent.KEYCODE_SLEEP:    
  46.         case KeyEvent.KEYCODE_SOFT_SLEEP:  
  47.         case KeyEvent.KEYCODE_WAKEUP:  
  48.         case KeyEvent.KEYCODE_MEDIA_PLAY:  
  49.         case KeyEvent.KEYCODE_MEDIA_PAUSE:  
  50.         case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:  
  51.         case KeyEvent.KEYCODE_HEADSETHOOK:  
  52.         case KeyEvent.KEYCODE_MUTE:  
  53.         case KeyEvent.KEYCODE_MEDIA_STOP:  
  54.         case KeyEvent.KEYCODE_MEDIA_NEXT:  
  55.         case KeyEvent.KEYCODE_MEDIA_PREVIOUS:  
  56.         case KeyEvent.KEYCODE_MEDIA_REWIND:  
  57.         case KeyEvent.KEYCODE_MEDIA_RECORD:  
  58.         case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:  
  59.         case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:  
  60.         case KeyEvent.KEYCODE_CALL:  
  61.         case KeyEvent.KEYCODE_VOICE_ASSIST:  
  62.         case KeyEvent.KEYCODE_WINDOW:  
  63.         }  
  64.     }  
  65.     if (isWakeKey) {   //如果除了power键, 别的按键也需要亮屏,就调用WakeUp亮屏  
  66.         wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");  
  67.     }  
  68.   
  69.     return result;  
  70. }  
处理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.   
  7.     // Latch power key state to detect screenshot chord.  
  8.     if (interactive && !mScreenshotChordPowerKeyTriggered  
  9.             && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {  
  10.         mScreenshotChordPowerKeyTriggered = true;  
  11.         mScreenshotChordPowerKeyTime = event.getDownTime();  
  12.         interceptScreenshotChord();      //屏幕截屏  
  13.     }  
  14.   
  15.     // Stop ringing or end call if configured to do so when power is pressed.  
  16.     TelecomManager telecomManager = getTelecommService();   //获取telecom  
  17.     boolean hungUp = false;  
  18.     if (telecomManager != null) {  
  19.         if (telecomManager.isRinging()) {   //如果来电过程中,按power键手机将静音,停止响铃  
  20.             // Pressing Power while there's a ringing incoming  
  21.             // call should silence the ringer.  
  22.             telecomManager.silenceRinger();  
  23.         } else if ((mIncallPowerBehavior  
  24.                 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0  
  25.                 && telecomManager.isInCall() && interactive) {  
  26.             // Otherwise, if "Power button ends call" is enabled,  
  27.             // the Power button will hang up any current active call.  
  28.             hungUp = telecomManager.endCall();  //如果在Setting数据库中配置了,按power键挂断电话, 就将电话挂断  
  29.         }  
  30.     }  
  31.     //................  
  32.     // If the power key has still not yet been handled, then detect short  
  33.     // press, long press, or multi press and decide what to do.     //如果power键还没有被处理,就判断是短按, 长按,还是多按来决定如何处理  
  34.     mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered  
  35.             || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;  
  36.     if (!mPowerKeyHandled) {  
  37.         if (interactive) {  
  38.             // When interactive, we're already awake.  
  39.             // Wait for a long press or for the button to be released to decide what to do.  
  40.             if (hasLongPressOnPowerBehavior()) {    //如果屏幕是亮这的,长按power键 ,就处理长按事件  
  41.                 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  42.                 msg.setAsynchronous(true);  
  43.                 mHandler.sendMessageDelayed(msg,  
  44.                         ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  45.             }  
  46.         } else {  
  47.             wakeUpFromPowerKey(event.getDownTime());   //如果屏幕是休眠状态,就唤醒屏幕  
  48.   
  49.             if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
  50.                 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  51.                 msg.setAsynchronous(true);  
  52.                 mHandler.sendMessageDelayed(msg,    //如果还是长按power键, 就再处理长按事件  
  53.                         ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  54.                 mBeganFromNonInteractive = true;  
  55.             } else {  
  56.                 final int maxCount = getMaxMultiPressPowerCount();  
  57.   
  58.                 if (maxCount <= 1) {  
  59.                     mPowerKeyHandled = true;  
  60.                 } else {  
  61.                     mBeganFromNonInteractive = true;  
  62.                 }  
  63.             }  
  64.         }  
  65.     }   
  66. }  
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.   
  7.     if (!handled) {    //power键还没被处理  
  8.         // Figure out how to handle the key now that it has been released.  
  9.         mPowerKeyPressCounter += 1;  
  10.   
  11.         final int maxCount = getMaxMultiPressPowerCount();  //多按的次数  
  12.         final long eventTime = event.getDownTime();    //按键发生的时间点  
  13.         if (mPowerKeyPressCounter < maxCount) {  
  14.             // This could be a multi-press.  Wait a little bit longer to confirm.  
  15.             // Continue holding the wake lock.    //等待一会调用powerPress处理  
  16.             Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
  17.                     interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
  18.             msg.setAsynchronous(true);  
  19.             mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
  20.             return;  
  21.         }  
  22.   
  23.         // No other actions.  Handle it immediately.  
  24.         powerPress(eventTime, interactive, mPowerKeyPressCounter);  //没有的的处理, 立即处理power down事件  
  25.     }  
  26.   
  27.     // Done.  Reset our state.  
  28.     finishPowerKeyPress();    //power键处理结束  
  29. }  
  30.   
  31. private void finishPowerKeyPress() {  
  32.     mBeganFromNonInteractive = false;  
  33.     mPowerKeyPressCounter = 0;  
  34.     if (mPowerKeyWakeLock.isHeld()) {  
  35.         mPowerKeyWakeLock.release();   //释放wakLock  
  36.     }  
  37. }  
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.   
  8.     if (count == 2) {  
  9.         powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);  //处理按两次power键事件  
  10.     } else if (count == 3) {  
  11.         powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); //处理按三次power键事件  
  12.     } else if (interactive && !mBeganFromNonInteractive) {  
  13.         switch (mShortPressOnPowerBehavior) {  
  14.             case SHORT_PRESS_POWER_NOTHING:  
  15.                 break;  
  16.             case SHORT_PRESS_POWER_GO_TO_SLEEP:    //灭屏  
  17.                 mPowerManager.goToSleep(eventTime,  
  18.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);  
  19.                 break;  
  20.             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:  //灭屏,不经历doze流程  
  21.                 mPowerManager.goToSleep(eventTime,  
  22.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  23.                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  24.                 break;  
  25.             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:  
  26.                 mPowerManager.goToSleep(eventTime,    //灭屏,不经历doze流程, 并返回home界面  
  27.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  28.                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  29.                 launchHomeFromHotKey();     
  30.                 break;  
  31.             case SHORT_PRESS_POWER_GO_HOME:  //返回home界面  
  32.                 launchHomeFromHotKey(true /* awakenFromDreams */false /*respectKeyguard*/);  
  33.                 break;  
  34.         }  
  35.     }  
  36. }  
根据前面分析可以知道在power键down事件时就会调用wakeUpFromPowerKey函数来唤醒屏幕.

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

当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.   
  7.     if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE  
  8.             || !mBootCompleted || !mSystemReady) {  
  9.         return false;        //判断是否要去亮屏  
  10.     }  
  11.   
  12.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");  
  13.     try {  
  14.         switch (mWakefulness) {  
  15.             case WAKEFULNESS_ASLEEP:  
  16.                 Slog.i(TAG, "Waking up from sleep due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
  17.                 break;  
  18.             case WAKEFULNESS_DREAMING:  
  19.                 Slog.i(TAG, "Waking up from dream due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
  20.                 break;  
  21.             case WAKEFULNESS_DOZING:  
  22.                 Slog.i(TAG, "Waking up from dozing due to"+opPackageName+" "+reason+" (uid " + reasonUid +")...");  
  23.                 break;  
  24.         }  
  25.   
  26.         mLastWakeTime = eventTime;   //设置最后一次唤醒的时间  
  27.         setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);   //Notifier调用onWakefulnessChangeStarted发送亮屏广播  
  28.   
  29.         mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);  //调用Notifier通知battery处理  
  30.         userActivityNoUpdateLocked(     //更新最后一次用户事件的时间  
  31.                 eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);  
  32.     } finally {  
  33.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  34.     }  
  35.     return true;  
  36. }  
在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.   
  8.     // Tell the activity manager about changes in wakefulness, not just interactivity.  
  9.     // It needs more granularity than other components.  
  10.     mHandler.post(new Runnable() {  
  11.         @Override  
  12.         public void run() {  
  13.             mActivityManagerInternal.onWakefulnessChanged(wakefulness);   //与AMS交互处理  
  14.         }  
  15.     });  
  16.   
  17.     // Handle any early interactive state changes.  
  18.     // Finish pending incomplete ones from a previous cycle.  
  19.     if (mInteractive != interactive) {  
  20.         // Finish up late behaviors if needed.  
  21.         if (mInteractiveChanging) {  
  22.             handleLateInteractiveChange();  
  23.         }  
  24.   
  25.         // Start input as soon as we start waking up or going to sleep.  
  26.         mInputManagerInternal.setInteractive(interactive);    //在input中记录现在的屏幕状态  
  27.         mInputMethodManagerInternal.setInteractive(interactive);  
  28.   
  29.         // Notify battery stats.  
  30.         try {  
  31.             mBatteryStats.noteInteractive(interactive);   //唤醒battery状态  
  32.         } catch (RemoteException ex) { }  
  33.   
  34.         // Handle early behaviors.  
  35.         mInteractive = interactive;  
  36.         mInteractiveChangeReason = reason;  
  37.         mInteractiveChanging = true;  
  38.         handleEarlyInteractiveChange();   //初期处理交互模式改变  
  39.     }  
  40. }  
[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, 1000);  
  9.                     mPolicy.startedWakingUp();   //通过PhoneWindowManager系统开始亮屏, 更新转向监听器,手势监听器等  
  10.                 }  
  11.             });  
  12.   
  13.             // Send interactive broadcast.  
  14.             mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;  
  15.             mPendingWakeUpBroadcast = true;  
  16.             updatePendingBroadcastLocked();   //更新亮屏广播  
  17.         } else {  
  18.             // Going to sleep...   //灭屏  
  19.             // Tell the policy that we started going to sleep.  
  20.             final int why = translateOffReason(mInteractiveChangeReason);  
  21.             mHandler.post(new Runnable() {  
  22.                 @Override  
  23.                 public void run() {  
  24.                     mPolicy.startedGoingToSleep(why);  
  25.                 }  
  26.             });  
  27.         }  
  28.     }  
  29. }  
通过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.   
  30.         mBroadcastStartTime = SystemClock.uptimeMillis();  
  31.         powerState = mBroadcastedInteractiveState;  
  32.     }  
  33.   
  34.     EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);  
  35.   
  36.     if (powerState == INTERACTIVE_STATE_AWAKE) {  
  37.         sendWakeUpBroadcast();   //发送亮屏广播  
  38.     } else {  
  39.         sendGoToSleepBroadcast();  
  40.     }  
  41. }  
[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.   
  9.     if (ActivityManagerNative.isSystemReady()) {    
  10.         mContext.sendOrderedBroadcastAsUser(mScreenOnIntent, UserHandle.ALL, null,  
  11.                 mWakeUpBroadcastDone, mHandler, 0nullnull);  //发送亮屏广播,并且其它模块全部处理完后, 自身接收亮屏广播  
  12.     } else {  
  13.         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 21);  
  14.         sendNextBroadcast();  
  15.     }  
  16. }  
  17.   
  18. private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {  
  19.     @Override  
  20.     public void onReceive(Context context, Intent intent) {  
  21.         EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,  
  22.                 SystemClock.uptimeMillis() - mBroadcastStartTime, 1);  
  23.         sendNextBroadcast();   //自身接收到亮屏广播后, 之后会调用finishPendingBroadcastLocked,释放wakeLock  
  24.     }  
  25. };  
    当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.   
  11.         if (wasPowered != mIsPowered || oldPlugType != mPlugType) {  
  12.             mDirty |= DIRTY_IS_POWERED;  //如果充电中设置mDirty  
  13.   
  14.             // Update wireless dock detection state.  
  15.             final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(  
  16.                     mIsPowered, mPlugType, mBatteryLevel);   //无线充电  
  17.   
  18.             // Treat plugging and unplugging the devices as a user activity.  
  19.             // Users find it disconcerting when they plug or unplug the device  
  20.             // and it shuts off right away.  
  21.             // Some devices also wake the device when plugged or unplugged because  
  22.             // they don't have a charging LED.  
  23.             final long now = SystemClock.uptimeMillis();  
  24.             if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,  
  25.                     dockedOnWirelessCharger)) {    //插拔USB是否要点亮屏幕  
  26.                 wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,  
  27.                         mContext.getOpPackageName(), Process.SYSTEM_UID);  
  28.             }  
  29.             userActivityNoUpdateLocked(   //插拔USB算一次用户事件,重新设置最后一次用户事件的时间点  
  30.                     now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);  
  31.   
  32.             // Tell the notifier whether wireless charging has started so that  
  33.             // it can provide feedback to the user.  
  34.             if (dockedOnWirelessCharger) {  
  35.                 mNotifier.onWirelessChargingStarted();  
  36.             }  
  37.         }  
  38.   
  39.         if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {   //低电模式  
  40.             if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {  
  41.                 if (DEBUG_SPEW) {  
  42.                     Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");  
  43.                 }  
  44.                 mAutoLowPowerModeSnoozing = false;  
  45.             }  
  46.             updateLowPowerModeLocked();  //更新低电模式  
  47.         }  
  48.     }  
  49. }  
[java] view plain copy
  1.     mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(  
  2.             com.android.internal.R.bool.config_unplugTurnsOnScreen);   //从xml文件中读取配置信息  
  3.   
  4. private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(  
  5.         boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {  
  6.     // Don't wake when powered unless configured to do so.  
  7.     if (!mWakeUpWhenPluggedOrUnpluggedConfig) {   //如果配置为true, 可能会亮屏  
  8.         return false;  
  9.     }  
  10.   
  11.     // Don't wake when undocked from wireless charger.  
  12.     // See WirelessChargerDetector for justification.  
  13.     if (wasPowered && !mIsPowered  
  14.             && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {  
  15.         return false;  
  16.     }  
  17.   
  18.     // Don't wake when docked on wireless charger unless we are certain of it.  
  19.     // See WirelessChargerDetector for justification.  
  20.     if (!wasPowered && mIsPowered  
  21.             && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS  
  22.             && !dockedOnWirelessCharger) {  
  23.         return false;  
  24.     }  
  25.   
  26.     // If already dreaming and becoming powered, then don't wake.  
  27.     if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {  
  28.         return false;  
  29.     }  
  30.   
  31.     // Don't wake while theater mode is enabled.  
  32.     if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {  
  33.         return false;  
  34.     }  
  35.   
  36.     // Otherwise wake up!  
  37.     return true;  
  38. }  

二:更新wakefulness

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



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.   
  5.         final int numWakeLocks = mWakeLocks.size();    //获取所有的wakeLocks  
  6.         for (int i = 0; i < numWakeLocks; i++) { //遍历所有的wakeLocks, 将wakeLocks记录在mWakeLockSummary中  
  7.             final WakeLock wakeLock = mWakeLocks.get(i);  
  8.             switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {  
  9.                 case PowerManager.PARTIAL_WAKE_LOCK:  
  10.                     if (!wakeLock.mDisabled) {  
  11.                         // We only respect this if the wake lock is not disabled.  
  12.                         mWakeLockSummary |= WAKE_LOCK_CPU;  
  13.                     }  
  14.                     break;  
  15.                 case PowerManager.FULL_WAKE_LOCK:  //屏幕键盘全部点亮  
  16.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;  
  17.                     break;  
  18.                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  //点亮屏幕  
  19.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;  
  20.                     break;  
  21.                 case PowerManager.SCREEN_DIM_WAKE_LOCK:   //dim锁  
  22.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;  
  23.                     break;  
  24.                 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:  //距离灭屏  
  25.                     mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  26.                     break;  
  27.                 case PowerManager.DOZE_WAKE_LOCK:  
  28.                     mWakeLockSummary |= WAKE_LOCK_DOZE;  
  29.                     break;  
  30.                 case PowerManager.DRAW_WAKE_LOCK:  
  31.                     mWakeLockSummary |= WAKE_LOCK_DRAW;  
  32.                     break;  
  33.             }  
  34.         }  
  35.   
  36.         // Cancel wake locks that make no sense based on the current state.  
  37.         if (mWakefulness != WAKEFULNESS_DOZING) {  //根据当前的屏幕状态, 取消不必要的wakeLocks  
  38.             mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);  
  39.         }  
  40.         if (mWakefulness == WAKEFULNESS_ASLEEP   //如果屏幕为休眠,就将屏幕高亮,dim锁取消  
  41.                 || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {  
  42.             mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM  
  43.                     | WAKE_LOCK_BUTTON_BRIGHT);  
  44.             if (mWakefulness == WAKEFULNESS_ASLEEP) {  
  45.                 mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  46.             }  
  47.         }  
  48.   
  49.         // Infer implied wake locks where necessary based on the current state.  
  50.         if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {  
  51.             if (mWakefulness == WAKEFULNESS_AWAKE) {  
  52.                 mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;  //当WakeLock为亮屏锁或dim锁时,需要保持AWAKE状态。  
  53.             } else if (mWakefulness == WAKEFULNESS_DREAMING) {  
  54.                 mWakeLockSummary |= WAKE_LOCK_CPU;     
  55.             }  
  56.         }  
  57.         if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {  
  58.             mWakeLockSummary |= WAKE_LOCK_CPU;  
  59.         }  
  60.   
  61.         if (DEBUG_SPEW) {  
  62.             Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="  
  63.                     + PowerManagerInternal.wakefulnessToString(mWakefulness)  
  64.                     + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));  
  65.         }  
  66.     }  
  67. }  
之后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.   
  7.         long nextTimeout = 0;  
  8.         if (mWakefulness == WAKEFULNESS_AWAKE  
  9.                 || mWakefulness == WAKEFULNESS_DREAMING  
  10.                 || mWakefulness == WAKEFULNESS_DOZING) {  
  11.             final int sleepTimeout = getSleepTimeoutLocked();   //获取睡眠超时时间  
  12.             final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);  //获取屏幕超时时间  
  13.             final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);  //获取dim持续时长  
  14.             final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;  
  15.   
  16.             mUserActivitySummary = 0;  
  17.             if (mLastUserActivityTime >= mLastWakeTime) {   //最后一次的用户时间大于最后一次屏幕醒来的时间  
  18.                 nextTimeout = mLastUserActivityTime   //计算下一次屏幕要变为dim的时间  
  19.                         + screenOffTimeout - screenDimDuration;  
  20.                 if (now < nextTimeout) {    
  21.                     mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;  //现在还早于屏幕超时, 设置现在用户活动为屏幕高亮  
  22.                 } else {  
  23.                     nextTimeout = mLastUserActivityTime + screenOffTimeout;  //重新设置屏幕超时时间,进入dim阶段  
  24.                     if (now < nextTimeout) {    //进入dim阶段了  
  25.                         mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;  
  26.                     }  
  27.                 }  
  28.             }  
  29.             if (mUserActivitySummary == 0  
  30.                     && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {  
  31.                 nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;  
  32.                 if (now < nextTimeout) {  //根据请求的policy来判断屏幕是高亮,还是dim状态  
  33.                     if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {  
  34.                         mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;   
  35.                     } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {  
  36.                         mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;  
  37.                     }  
  38.                 }  
  39.             }  
  40.   
  41.             if (mUserActivitySummary == 0) {   //如果mUserActivitySummary还没赋值  
  42.                 if (sleepTimeout >= 0) {  
  43.                     final long anyUserActivity = Math.max(mLastUserActivityTime,  
  44.                             mLastUserActivityTimeNoChangeLights);  
  45.                     if (anyUserActivity >= mLastWakeTime) {  
  46.                         nextTimeout = anyUserActivity + sleepTimeout;  
  47.                         if (now < nextTimeout) {  
  48.                             mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;   //设置dream状态  
  49.                         }  
  50.                     }  
  51.                 } else {  
  52.                     mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;  
  53.                     nextTimeout = -1;  
  54.                 }  
  55.             }  
  56.   
  57.             if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {  
  58.                 if ((mUserActivitySummary &  
  59.                         (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {  
  60.                     // Device is being kept awake by recent user activity  
  61.                     if (nextTimeout >= now && mOverriddenTimeout == -1) {  
  62.                         // Save when the next timeout would have occurred  
  63.                         mOverriddenTimeout = nextTimeout;  
  64.                     }  
  65.                 }  
  66.                 mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;  
  67.                 nextTimeout = -1;  
  68.             }  
  69.   
  70.             if (mUserActivitySummary != 0 && nextTimeout >= 0) {  //mUserActivitySummary有值, 并且nextTimeout大于等于0, 发超时消息  
  71.                 Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);  
  72.                 msg.setAsynchronous(true);  
  73.                 mHandler.sendMessageAtTime(msg, nextTimeout);   //发送屏幕超时的Message  
  74.             }  
  75.         } else {  
  76.             mUserActivitySummary = 0;  
  77.         }  
  78.   
  79.         if (DEBUG_SPEW) {  
  80.             Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="  
  81.                     + PowerManagerInternal.wakefulnessToString(mWakefulness)  
  82.                     + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)  
  83.                     + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));  
  84.         }  
  85.     }  
  86. }  

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, nulltrue /*async*/);  
  7.     }  
  8.   
  9.     @Override  
  10.     public void handleMessage(Message msg) {  
  11.         switch (msg.what) {  
  12.             case MSG_USER_ACTIVITY_TIMEOUT:  
  13.                 handleUserActivityTimeout();    //处理用户超时事件  
  14.                 break;  
  15.             case MSG_SANDMAN:  
  16.                 handleSandman();  
  17.                 break;  
  18.             case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:  
  19.                 handleScreenBrightnessBoostTimeout();  
  20.                 break;  
  21.         }  
  22.     }  
  23. }  
  24.   
  25. private void handleUserActivityTimeout() { // runs on handler thread  
  26.     synchronized (mLock) {  
  27.         if (DEBUG_SPEW) {  
  28.             Slog.d(TAG, "handleUserActivityTimeout");  
  29.         }  
  30.   
  31.         mDirty |= DIRTY_USER_ACTIVITY;  //设置有用户活动的mDirty值  
  32.         updatePowerStateLocked();   //更新电源状态, 最后去判断是否要睡眠  
  33.     }  
  34. }  
    根据前面流程图可以看出更新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.   
  10.  private boolean shouldNapAtBedTimeLocked() {  //当返回true, 设备自动nap  
  11.     return mDreamsActivateOnSleepSetting  
  12.             || (mDreamsActivateOnDockSetting  
  13.                     && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);  
  14. }  

[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.   
  6.     if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE  
  7.             || !mBootCompleted || !mSystemReady) {  
  8.         return false;  
  9.     }  
  10.   
  11.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");  
  12.     try {  
  13.         Slog.i(TAG, "Nap time (uid " + uid +")...");  
  14.   
  15.         mSandmanSummoned = true;  
  16.         setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);  //设置WAKEFULNESS_DREAMING  
  17.     } finally {  
  18.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  19.     }  
  20.     return true;  
  21. }  

调用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.   
  7.     if (eventTime < mLastWakeTime  
  8.             || mWakefulness == WAKEFULNESS_ASLEEP  
  9.             || mWakefulness == WAKEFULNESS_DOZING  
  10.             || !mBootCompleted || !mSystemReady) {  
  11.         return false;   //判断设备是否应该睡眠  
  12.     }  
  13.   
  14.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");  
  15.     try {  
  16.         switch (reason) {   //输出灭屏的原因  
  17.             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:  
  18.                 Slog.i(TAG, "Going to sleep due to device administration policy "  
  19.                         + "(uid " + uid +")...");  
  20.                 break;  
  21.             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:  
  22.                 Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");  
  23.                 break;  
  24.             case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:  
  25.                 Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");  
  26.                 break;  
  27.             case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:  
  28.                 Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");  
  29.                 break;  
  30.             case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:  
  31.                 Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");  
  32.                 break;  
  33.             case PowerManager.GO_TO_SLEEP_REASON_HDMI:  
  34.                 Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");  
  35.                 break;  
  36.             default:  
  37.                 Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");  
  38.                 reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;  
  39.                 break;  
  40.         }  
  41.   
  42.         mLastSleepTime = eventTime;  
  43.         mSandmanSummoned = true;  
  44.         setWakefulnessLocked(WAKEFULNESS_DOZING, reason);  
  45.   
  46.         // Report the number of wake locks that will be cleared by going to sleep.  
  47.         int numWakeLocksCleared = 0;  
  48.         final int numWakeLocks = mWakeLocks.size();    
  49.         for (int i = 0; i < numWakeLocks; i++) {  //遍历所有的wakeLocks, 将FULL, BRIGHT, DIM Locks,计入numWakeLocksCleared中  
  50.             final WakeLock wakeLock = mWakeLocks.get(i);  
  51.             switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {  
  52.                 case PowerManager.FULL_WAKE_LOCK:  
  53.                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  
  54.                 case PowerManager.SCREEN_DIM_WAKE_LOCK:  
  55.                     numWakeLocksCleared += 1;  
  56.                     break;  
  57.             }  
  58.         }  
  59.         EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);  
  60.   
  61.         // Skip dozing if requested.  
  62.         if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {  
  63.             reallyGoToSleepNoUpdateLocked(eventTime, uid); //如果没有doze流程,直接设置WAKEFULNESS_ASLEEP  
  64.         }  
  65.     } finally {  
  66.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  67.     }  
  68.     return true;   //返回true  
  69. }  
当第一个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.   
  8.         // Determine appropriate screen brightness and auto-brightness adjustments.  
  9.         boolean brightnessSetByUser = true;  
  10.         int screenBrightness = mScreenBrightnessSettingDefault;  
  11.         float screenAutoBrightnessAdjustment = 0.0f;   //自动亮度调节  
  12.         boolean autoBrightness = (mScreenBrightnessModeSetting ==  
  13.                 Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);   //是否开启自动亮度  
  14.         if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {  
  15.             screenBrightness = mScreenBrightnessOverrideFromWindowManager;  
  16.             autoBrightness = false;  
  17.             brightnessSetByUser = false;  
  18.         } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {  
  19.             screenBrightness = mTemporaryScreenBrightnessSettingOverride;  
  20.         } else if (isValidBrightness(mScreenBrightnessSetting)) {  
  21.             screenBrightness = mScreenBrightnessSetting;  
  22.         }  
  23.         if (autoBrightness) {  
  24.             screenBrightness = mScreenBrightnessSettingDefault;  //自动亮度调节  
  25.             if (isValidAutoBrightnessAdjustment(  
  26.                     mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {  
  27.                 screenAutoBrightnessAdjustment =  
  28.                         mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;  
  29.             } else if (isValidAutoBrightnessAdjustment(  
  30.                     mScreenAutoBrightnessAdjustmentSetting)) {  
  31.                 screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;  
  32.             }  
  33.         }  
  34.         screenBrightness = Math.max(Math.min(screenBrightness,  //获得请求亮度  
  35.                 mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);  
  36.         screenAutoBrightnessAdjustment = Math.max(Math.min(  
  37.                 screenAutoBrightnessAdjustment, 1.0f), -1.0f);  
  38.   
  39.         // Update display power request.  //将数据记录在mDisplayPowerRequest中  
  40.         mDisplayPowerRequest.screenBrightness = screenBrightness;  
  41.         mDisplayPowerRequest.screenAutoBrightnessAdjustment =  
  42.                 screenAutoBrightnessAdjustment;  
  43.         mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;  
  44.         mDisplayPowerRequest.useAutoBrightness = autoBrightness;  
  45.         mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();  
  46.         mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;  
  47.         mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;  
  48.         mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;  
  49.   
  50.         if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {  
  51.             mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;  
  52.             if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND  
  53.                     && (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {  
  54.                 mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;  
  55.             }  
  56.             mDisplayPowerRequest.dozeScreenBrightness =  
  57.                     mDozeScreenBrightnessOverrideFromDreamManager;  
  58.         } else {  
  59.             mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;  
  60.             mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;  
  61.         }  
  62.   
  63.         mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,  
  64.                 mRequestWaitForNegativeProximity);     //调用requestPowerState请求电源状态  
  65.         mRequestWaitForNegativeProximity = false;  
  66.   
  67.         if (DEBUG_SPEW) {  
  68.             Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady  
  69.                     + ", policy=" + mDisplayPowerRequest.policy  
  70.                     + ", mWakefulness=" + mWakefulness  
  71.                     + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)  
  72.                     + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)  
  73.                     + ", mBootCompleted=" + mBootCompleted  
  74.                     + ", mScreenBrightnessBoostInProgress="  
  75.                             + mScreenBrightnessBoostInProgress);  
  76.         }  
  77.     }  
  78.     return mDisplayReady && !oldDisplayReady;  
  79. }  

阅读全文
0 1