and5.1PowerManagerService深入分析(三)updatePowerStateLocked函数

来源:互联网 发布:跳舞直播软件 编辑:程序博客网 时间:2024/05/18 13:41

PMS更新各个状态,最终都会调用updatePowerStateLocked函数,下面我们来分析下

[java] view plain copy
  1. private void updatePowerStateLocked() {  
  2.     if (!mSystemReady || mDirty == 0) {//mDirty=0代表没有变化,或者系统没有准备好,直接退出  
  3.         return;  
  4.     }  
  5.     if (!Thread.holdsLock(mLock)) {  
  6.         Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");  
  7.     }  
  8.   
  9.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");  
  10.     try {  
  11.         // Phase 0: Basic state updates.  
  12.         updateIsPoweredLocked(mDirty);//更新电源状态  
  13.         updateStayOnLocked(mDirty);  
  14.         updateScreenBrightnessBoostLocked(mDirty);  

updateIsPoweredLocked函数,先是要dirty有DIRTY_BATTERY_STATE标志位。我们在下面分析下,什么时候会有这个标志位

[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);//这些都是从BatteryService获取  
  7.         mPlugType = mBatteryManagerInternal.getPlugType();  
  8.         mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();  
  9.         mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();  
  10.   
  11.         if (DEBUG_SPEW) {  
  12.             Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered  
  13.                     + ", mIsPowered=" + mIsPowered  
  14.                     + ", oldPlugType=" + oldPlugType  
  15.                     + ", mPlugType=" + mPlugType  
  16.                     + ", mBatteryLevel=" + mBatteryLevel);  
  17.         }  
  18.   
  19.         if (wasPowered != mIsPowered || oldPlugType != mPlugType) {//是否充电或者充电类型改变了  
  20.             mDirty |= DIRTY_IS_POWERED;//mDirty置位  
  21.   
  22.             // Update wireless dock detection state.  
  23.             final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(//无线充电相关  
  24.                     mIsPowered, mPlugType, mBatteryLevel);  
  25.   
  26.             // Treat plugging and unplugging the devices as a user activity.  
  27.             // Users find it disconcerting when they plug or unplug the device  
  28.             // and it shuts off right away.  
  29.             // Some devices also wake the device when plugged or unplugged because  
  30.             // they don't have a charging LED.  
  31.             final long now = SystemClock.uptimeMillis();  
  32.             if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,  
  33.                     dockedOnWirelessCharger)) {//是否需要唤醒设备  
  34.                 wakeUpNoUpdateLocked(now, Process.SYSTEM_UID);  
  35.             }  
  36.             userActivityNoUpdateLocked(//触发userActivity  
  37.                     now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);  
  38.   
  39.             // Tell the notifier whether wireless charging has started so that  
  40.             // it can provide feedback to the user.  
  41.             if (dockedOnWirelessCharger) {//无线充电相关  
  42.                 mNotifier.onWirelessChargingStarted();  
  43.             }  
  44.         }  
  45.   
  46.         if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {  
  47.             if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {  
  48.                 if (DEBUG_SPEW) {  
  49.                     Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");  
  50.                 }  
  51.                 mAutoLowPowerModeSnoozing = false;  
  52.             }  
  53.             updateLowPowerModeLocked();//更新低功耗模式  
  54.         }  
  55.     }  
  56. }  

首先systemReady函数最终会把mDirty置位为DIRTY_BATTERY_STATE,还有收BatterySevice发出来的广播,最总也会置这个标志位。

[java] view plain copy
  1. private final class BatteryReceiver extends BroadcastReceiver {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         synchronized (mLock) {  
  5.             handleBatteryStateChangedLocked();  
  6.         }  
  7.     }  
  8. }  

[java] view plain copy
  1. private void handleBatteryStateChangedLocked() {  
  2.     mDirty |= DIRTY_BATTERY_STATE;  
  3.     updatePowerStateLocked();  
  4. }  

再来看看电池状态发生什么变化要唤醒设备:

[java] view plain copy
  1. private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(  
  2.         boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {  
  3.     // Don't wake when powered unless configured to do so.  
  4.     if (!mWakeUpWhenPluggedOrUnpluggedConfig) {//如果资源中没有配置这项,直接退出不唤醒设备  
  5.         return false;  
  6.     }  
  7.   
  8.     // Don't wake when undocked from wireless charger.  
  9.     // See WirelessChargerDetector for justification.  
  10.     if (wasPowered && !mIsPowered  
  11.             && oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {//这是一个 拔出的工作,然后之前的无线充电  
  12.         return false;  
  13.     }  
  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.   
  23.     // If already dreaming and becoming powered, then don't wake.  
  24.     if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {//正在充电,但是mWakefulness 是做梦状态  
  25.         return false;  
  26.     }  
  27.   
  28.     // Don't wake while theater mode is enabled.  
  29.     if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {  
  30.         return false;  
  31.     }  
  32.   
  33.     // Otherwise wake up!  
  34.     return true;//其他就唤醒设备  
  35. }  


继续分析updatePowerStateLocked函数,分析updateStayOnLocked函数。一般这个函数mStatyon为fasle,除非在资源中设置哪种充电状态下可以长亮。

[java] view plain copy
  1. private void updateStayOnLocked(int dirty) {  
  2.     if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {//当dirty是电池状态和设置的状态改变时  
  3.         final boolean wasStayOn = mStayOn;  
  4.         if (mStayOnWhilePluggedInSetting != 0//这个值从资源中读取,一般设置的话代表哪种充电时可以常亮  
  5.                 && !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {//看有没有设mMaximumScreenOffTimeoutFromDeviceAdmin屏幕最大亮屏时间,没设默认最大。那么这个函数返回是false  
  6.             mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);  
  7.         } else {  
  8.             mStayOn = false;  
  9.         }  
  10.   
  11.         if (mStayOn != wasStayOn) {  
  12.             mDirty |= DIRTY_STAY_ON;  
  13.         }  
  14.     }  
  15. }  


继续分析updatePowerStateLocked函数的updateScreenBrightnessBoostLocked函数,这个函数是更新屏幕是否保持最亮状态

[java] view plain copy
  1. private void updateScreenBrightnessBoostLocked(int dirty) {  
  2.     if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {//这个状态实在boostScreenBrightnessInternal函数中设置最亮时置位,当然下面发送消息MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT也会将这个标志位置位  
  3.         if (mScreenBrightnessBoostInProgress) {//当前正在最亮屏幕这个状态  
  4.             final long now = SystemClock.uptimeMillis();  
  5.             mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);  
  6.             if (mLastScreenBrightnessBoostTime > mLastSleepTime) {  
  7.                 final long boostTimeout = mLastScreenBrightnessBoostTime +  
  8.                         SCREEN_BRIGHTNESS_BOOST_TIMEOUT;  
  9.                 if (boostTimeout > now) {//看当前时间是否小于最亮屏幕结束的时间  
  10.                     Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);  
  11.                     msg.setAsynchronous(true);  
  12.                     mHandler.sendMessageAtTime(msg, boostTimeout);//发送一个延迟的消息,到最亮屏幕结束的时候接受到消息,将标志位置为DIRTY_SCREEN_BRIGHTNESS_BOOST后,重新再回到这个函数  
  13.                     return;  
  14.                 }  
  15.             }  
  16.             mScreenBrightnessBoostInProgress = false;//回到这个函数时,直接将这个屏幕最亮状态的标志位改成false  
  17.             userActivityNoUpdateLocked(now,//触发一个userActivity  
  18.                     PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);  
  19.         }  
  20.     }  
  21. }  

下面看看MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT消息的处理函数。

[java] view plain copy
  1. case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:  
  2.     handleScreenBrightnessBoostTimeout();  
  3.     break;  
[java] view plain copy
  1. private void handleScreenBrightnessBoostTimeout() { // runs on handler thread  
  2.     synchronized (mLock) {  
  3.         if (DEBUG_SPEW) {  
  4.             Slog.d(TAG, "handleScreenBrightnessBoostTimeout");  
  5.         }  
  6.   
  7.         mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;  
  8.         updatePowerStateLocked();  
  9.     }  
  10. }  


接下来看updatePowerStateLocked函数的另一个阶段:

[java] view plain copy
  1. // Phase 1: Update wakefulness.  
  2. // Loop because the wake lock and user activity computations are influenced  
  3. // by changes in wakefulness.  
  4. final long now = SystemClock.uptimeMillis();  
  5. int dirtyPhase2 = 0;  
  6. for (;;) {  
  7.     int dirtyPhase1 = mDirty;//这个循环中每次新的mDirty全部给dirtyPhase1,并且在这个循环中使用这个dirty  
  8.     dirtyPhase2 |= dirtyPhase1;//dirtyPhase2 会把之前所有的mDirty状态全部或上,然后用这个状态继续下面的函数  
  9.     mDirty = 0;//mDirty会在这里清零  
  10.   
  11.     updateWakeLockSummaryLocked(dirtyPhase1);  
  12.     updateUserActivitySummaryLocked(now, dirtyPhase1);  
  13.     if (!updateWakefulnessLocked(dirtyPhase1)) {  
  14.         break;  
  15.     }  
  16. }  

先看下updateWakeLockSummaryLocked函数,更新wakelock的函数

[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();  
  6.         for (int i = 0; i < numWakeLocks; i++) {  
  7.             final WakeLock wakeLock = mWakeLocks.get(i);  
  8.             switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {//先根据wakelock的flag,mWakeLockSummary或上各种状态  
  9.                 case PowerManager.PARTIAL_WAKE_LOCK:  
  10.                     mWakeLockSummary |= WAKE_LOCK_CPU;  
  11.                     break;  
  12.                 case PowerManager.FULL_WAKE_LOCK:  
  13.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;  
  14.                     break;  
  15.                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  
  16.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;  
  17.                     break;  
  18.                 case PowerManager.SCREEN_DIM_WAKE_LOCK:  
  19.                     mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;  
  20.                     break;  
  21.                 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK://距离传感器相关  
  22.                     mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  23.                     break;  
  24.                 case PowerManager.DOZE_WAKE_LOCK:  
  25.                     mWakeLockSummary |= WAKE_LOCK_DOZE;  
  26.                     break;  
  27.             }  
  28.         }  
  29.   
  30.         // Cancel wake locks that make no sense based on the current state.  
  31.         if (mWakefulness != WAKEFULNESS_DOZING) {//下面根据各种状态,将上面或上的mWakeLockSummary,有的减去  
  32.             mWakeLockSummary &= ~WAKE_LOCK_DOZE;  
  33.         }  
  34.         if (mWakefulness == WAKEFULNESS_ASLEEP  
  35.                 || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {  
  36.             mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM  
  37.                     | WAKE_LOCK_BUTTON_BRIGHT);  
  38.             if (mWakefulness == WAKEFULNESS_ASLEEP) {  
  39.                 mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;  
  40.             }  
  41.         }  
  42.   
  43.         // Infer implied wake locks where necessary based on the current state.  
  44.         if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {//只要有屏幕锁,cpu锁必须持有  
  45.             if (mWakefulness == WAKEFULNESS_AWAKE) {  
  46.                 mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;  
  47.             } else if (mWakefulness == WAKEFULNESS_DREAMING) {  
  48.                 mWakeLockSummary |= WAKE_LOCK_CPU;  
  49.             }  
  50.         }  
  51.   
  52.         if (DEBUG_SPEW) {  
  53.             Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="  
  54.                     + PowerManagerInternal.wakefulnessToString(mWakefulness)  
  55.                     + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));  
  56.         }  
  57.     }  
  58. }  

下面分析下updateUserActivitySummaryLocked函数

[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);  
  6.   
  7.            long nextTimeout = 0;  
  8.            if (mWakefulness == WAKEFULNESS_AWAKE//状态为awake,dreaming,dozing,否则mUserActivitySummary为0  
  9.                    || mWakefulness == WAKEFULNESS_DREAMING  
  10.                    || mWakefulness == WAKEFULNESS_DOZING) {  
  11.                final int sleepTimeout = getSleepTimeoutLocked();//睡眠timeout  
  12.                final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);//灭屏的timeout  
  13.                final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);//屏幕由亮变暗的timeout  
  14.   
  15.                mUserActivitySummary = 0;  
  16.                if (mLastUserActivityTime >= mLastWakeTime) {//userActivity的time大于上次唤醒时间  
  17.                    nextTimeout = mLastUserActivityTime//这个时间代表是比较亮的一个时间的结束点  
  18.                            + screenOffTimeout - screenDimDuration;  
  19.                    if (now < nextTimeout) {  
  20.                        mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;//mUserActivitySummary赋值  
  21.                    } else {  
  22.                        nextTimeout = mLastUserActivityTime + screenOffTimeout;//这个时间代表屏幕暗的一个时间结束点  
  23.                        if (now < nextTimeout) {  
  24.                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;  
  25.                        }  
  26.                    }  
  27.                }  
  28.                if (mUserActivitySummary == 0  
  29.                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {//这个time是userActivity一个特殊的flag才会设置  
  30.                    nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;  
  31.                    if (now < nextTimeout) {  
  32.                        if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {  
  33.                            mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;  
  34.                        } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {  
  35.                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;  
  36.                        }  
  37.                    }  
  38.                }  
  39.                if (mUserActivitySummary == 0) {  
  40.                    if (sleepTimeout >= 0) {  
  41.                        final long anyUserActivity = Math.max(mLastUserActivityTime,  
  42.                                mLastUserActivityTimeNoChangeLights);  
  43.                        if (anyUserActivity >= mLastWakeTime) {  
  44.                            nextTimeout = anyUserActivity + sleepTimeout;  
  45.                            if (now < nextTimeout) {  
  46.                                mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;  
  47.                            }  
  48.                        }  
  49.                    } else {  
  50.                        mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;  
  51.                        nextTimeout = -1;//该值为-1,下面就不会发送消息了  
  52.                    }  
  53.                }  
  54.                if (mUserActivitySummary != 0 && nextTimeout >= 0) {  
  55.                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);  
  56.                    msg.setAsynchronous(true);  
  57.                    mHandler.sendMessageAtTime(msg, nextTimeout);//到下个时间timeout结束的时候发送消息,重新进入这个函数  
  58.                }  
  59.            } else {  
  60.                mUserActivitySummary = 0;  
  61.            }  

MSG_USER_ACTIVITY_TIMEOUT的消息处理

[java] view plain copy
  1. @Override  
  2. public void handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case MSG_USER_ACTIVITY_TIMEOUT:  
  5.             handleUserActivityTimeout();  
  6.             break;  
[java] view plain copy
  1. private void handleUserActivityTimeout() { // runs on handler thread  
  2.     synchronized (mLock) {  
  3.         if (DEBUG_SPEW) {  
  4.             Slog.d(TAG, "handleUserActivityTimeout");  
  5.         }  
  6.   
  7.         mDirty |= DIRTY_USER_ACTIVITY;  
  8.         updatePowerStateLocked();  
  9.     }  
  10. }  


继续分析函数updateWakefulnessLocked

[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的时候,直接返回false,也就是上面的循环退出  
  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. }  

再来看看isItBedTimeYetLocked函数

[java] view plain copy
  1. private boolean isItBedTimeYetLocked() {  
  2.     return mBootCompleted && !isBeingKeptAwakeLocked();  
  3. }  

isBeingKeptAwakeLocked函数,如果isBeingKeptAwakeLocked返回true代表处于亮屏状态,isItBedTimeYetLocked返回false,上面的for死循环退出

[java] view plain copy
  1. private boolean isBeingKeptAwakeLocked() {  
  2.     return mStayOn  
  3.             || mProximityPositive//距离传感器有关  
  4.             || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0  
  5.             || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT  
  6.                     | USER_ACTIVITY_SCREEN_DIM)) != 0  
  7.             || mScreenBrightnessBoostInProgress;//屏幕处于最亮状态  
  8. }  

如果isBeingKeptAwakeLocked返回false,并且mBootCompleted 为true开机完成了。那么updateWakefulnessLocked函数进入判断条件
那再来看看shouldNapAtBedTimeLocked函数,就是看有没有做梦这个设置,如果没有直接到goToSleepNoUpdateLocked函数,到了goToSleepNoUpdateLocked函数后将mWakefulness 设为WAKEFULNESS_DOZING显示返回true还要继续循环,下次到updateWakefulnessLocked这个函数,不是awake类型的,也返回false,直接退出死循环了。到napNoUpdateLocked函数也是一样的先是将mWakefulness置为WAKEFULNESS_DREAMING,返回true,继续循环,下次不是awake类型就返回false,退出循环了。

[java] view plain copy
  1. private boolean shouldNapAtBedTimeLocked() {  
  2.     return mDreamsActivateOnSleepSetting  
  3.             || (mDreamsActivateOnDockSetting  
  4.                     && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);  
  5. }  

下面分析就是updateDisplayPowerStateLocked函数要和Display交互。放在下一篇博客分析。

阅读全文
0 0
原创粉丝点击