这篇博客我们主要分析下PowerManagerService的各个状态,主要从goToSleep,wakeUp,userActivity,nap函数作为入口分析。

一、PowerManagerService的goToSleep函数



我们先来看下goToSleep函数:

goToSleep函数主要调用了goToSleepInternal函数:

    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {synchronized (mLock) {if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {updatePowerStateLocked();}}}

我们再来看看goToSleepNoUpdateLocked函数

    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {if (eventTime < mLastWakeTime|| mWakefulness == WAKEFULNESS_ASLEEP|| mWakefulness == WAKEFULNESS_DOZING|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");try {switch (reason) {//打印原因case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:Slog.i(TAG, "Going to sleep due to device administration policy "+ "(uid " + uid +")...");break;case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");break;case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");break;case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");break;case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");break;case PowerManager.GO_TO_SLEEP_REASON_HDMI:Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");break;default:Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;break;}mLastSleepTime = eventTime;mSandmanSummoned = true;setWakefulnessLocked(WAKEFULNESS_DOZING, reason);//置状态// Report the number of wake locks that will be cleared by going to sleep.int numWakeLocksCleared = 0;final int numWakeLocks = mWakeLocks.size();for (int i = 0; i < numWakeLocks; i++) {//统计将会被清除的WakeLockfinal WakeLock wakeLock = mWakeLocks.get(i);switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {case PowerManager.FULL_WAKE_LOCK:case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:case PowerManager.SCREEN_DIM_WAKE_LOCK:numWakeLocksCleared += 1;break;}}EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);// Skip dozing if requested.if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {reallyGoToSleepNoUpdateLocked(eventTime, uid);//有这个flag直接进入sleep。而不用先进入WAKEFULNESS_DOZING状态}} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;}

上面函数会先调用setWakefulnessLocked来设置PowerManagerService的状态,我们来看下这个函数:

    private void setWakefulnessLocked(int wakefulness, int reason) {if (mWakefulness != wakefulness) {mWakefulness = wakefulness;mWakefulnessChanging = true;mDirty |= DIRTY_WAKEFULNESS;mNotifier.onWakefulnessChangeStarted(wakefulness, reason);}}

我们来看这个Notifier的onWakefulnessChangeStarted函数:

    public void onWakefulnessChangeStarted(final int wakefulness, int reason) {final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);// Tell the activity manager about changes in wakefulness, not just interactivity.// It needs more granularity than other components.mHandler.post(new Runnable() {@Overridepublic void run() {mActivityManagerInternal.onWakefulnessChanged(wakefulness);//调用AMS的onWakefulnessChanged函数}});// Handle any early interactive state changes.// Finish pending incomplete ones from a previous cycle.if (mInteractive != interactive) {// Finish up late behaviors if needed.if (mInteractiveChanging) {handleLateInteractiveChange();}// Start input as soon as we start waking up or going to sleep.mInputManagerInternal.setInteractive(interactive);//Input设置状态,在PhoneWindowManager那篇博客有分析mInputMethodManagerInternal.setInteractive(interactive);// Notify battery stats.try {mBatteryStats.noteInteractive(interactive);} catch (RemoteException ex) { }// Handle early behaviors.mInteractive = interactive;mInteractiveChangeReason = reason;mInteractiveChanging = true;handleEarlyInteractiveChange();}}

上面这个函数做了很多重要的事情,通知AMS调用onWakefulnessChanged函数来将之前的Activity resume。也会调用Inpu相关接口,这个我们在之前分析Power按键,到PhoneWindowManager的时候分析过,就是这个时候将power状态设置到Input中,保存在成员变量。然后又按键过来,将这个变量传到了PhoneWindowManager中。
还有在handleEarlyInteractiveChange函数中会发送灭屏和亮屏广播,以及通知PhoneWindowManager做一些事情,这个我会在之前专门写一篇关于Notifier的博客。

我们再回过头分析goToSleepNoUpdateLocked函数,如果睡眠的话,会调用reallyGoToSleepNoUpdateLocked函数,其实也就是将状态设置成睡眠的。

    private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {if (DEBUG_SPEW) {Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime+ ", uid=" + uid);}if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");try {Slog.i(TAG, "Sleeping (uid " + uid +")...");setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);//设置Power状态} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;}

然后我们再来看goToSleepInternal函数,当goToSleepNoUpdateLocked返回true,就会调用updatePowerStateLocked函数。

    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {synchronized (mLock) {if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {updatePowerStateLocked();}}}

二、PowerManagerService的updatePowerStateLocked函数

我们来看下PowerManagerService最核心的函数updatePowerStateLocked:

    private void updatePowerStateLocked() {if (!mSystemReady || mDirty == 0) {return;}if (!Thread.holdsLock(mLock)) {Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");}Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");try {// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);updateStayOnLocked(mDirty);updateScreenBrightnessBoostLocked(mDirty);// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = SystemClock.uptimeMillis();int dirtyPhase2 = 0;for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;mDirty = 0;updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Update display power state.boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);// Phase 3: Update dream state (depends on display ready signal).updateDreamLocked(dirtyPhase2, displayBecameReady);// Phase 4: Send notifications, if needed.finishWakefulnessChangeIfNeededLocked();// Phase 5: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}

2.1 updateIsPoweredLocked函数

我们先来看第一个函数updateIsPoweredLocked函数,主要是电池的一些状态。当收到电池广播时,就是更新电池信息。

    private void updateIsPoweredLocked(int dirty) {if ((dirty & DIRTY_BATTERY_STATE) != 0) {final boolean wasPowered = mIsPowered;final int oldPlugType = mPlugType;final boolean oldLevelLow = mBatteryLevelLow;mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);//是否充电mPlugType = mBatteryManagerInternal.getPlugType();mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();//现在的电量mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();if (wasPowered != mIsPowered || oldPlugType != mPlugType) {mDirty |= DIRTY_IS_POWERED;// Update wireless dock detection state.final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(mIsPowered, mPlugType, mBatteryLevel);final long now = SystemClock.uptimeMillis();if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,//充电方式改变是否需要点亮屏幕dockedOnWirelessCharger)) {wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,mContext.getOpPackageName(), Process.SYSTEM_UID);}userActivityNoUpdateLocked(//触发userActivity事件now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);// Tell the notifier whether wireless charging has started so that// it can provide feedback to the user.if (dockedOnWirelessCharger) {mNotifier.onWirelessChargingStarted();}}if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {//更新低功耗相关配置if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {if (DEBUG_SPEW) {Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");}mAutoLowPowerModeSnoozing = false;}updateLowPowerModeLocked();}}}

上面函数就是保存了一些电池信息,然后充电方式改变后是否唤醒屏幕,一些更新低功耗的配置。

2.2 updateStayOnLocked函数

再来看updateStayOnLocked函数,mStayOnWhilePluggedInSetting这个配置为0,所以mStayOn只能为false

    private void updateStayOnLocked(int dirty) {if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {final boolean wasStayOn = mStayOn;if (mStayOnWhilePluggedInSetting != 0&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);} else {mStayOn = false;}if (mStayOn != wasStayOn) {mDirty |= DIRTY_STAY_ON;}}}

2.3 updateScreenBrightnessBoostLocked函数

再来看updateScreenBrightnessBoostLocked函数,看这个接口之前我们先来看下这个接口:boostScreenBrightnessInternal 将屏幕点最亮

    private void boostScreenBrightnessInternal(long eventTime, int uid) {synchronized (mLock) {if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP|| eventTime < mLastScreenBrightnessBoostTime) {return;}Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");mLastScreenBrightnessBoostTime = eventTime;if (!mScreenBrightnessBoostInProgress) {mScreenBrightnessBoostInProgress = true;//屏幕最亮的状态变量mNotifier.onScreenBrightnessBoostChanged();}mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;userActivityNoUpdateLocked(eventTime,PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);updatePowerStateLocked();}}

再来看updateScreenBrightnessBoostLocked函数

    private void updateScreenBrightnessBoostLocked(int dirty) {if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {if (mScreenBrightnessBoostInProgress) {//将屏幕最亮final long now = SystemClock.uptimeMillis();mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);if (mLastScreenBrightnessBoostTime > mLastSleepTime) {final long boostTimeout = mLastScreenBrightnessBoostTime +SCREEN_BRIGHTNESS_BOOST_TIMEOUT;if (boostTimeout > now) {//还没到时间(最亮屏幕)Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, boostTimeout);return;//发送消息退出}}mScreenBrightnessBoostInProgress = false;//状态改变mNotifier.onScreenBrightnessBoostChanged();userActivityNoUpdateLocked(now,//触发userActivity事件PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);}}}

上面发送消息,最后处理函数:继续点亮屏幕。

    private void handleScreenBrightnessBoostTimeout() { // runs on handler threadsynchronized (mLock) {if (DEBUG_SPEW) {Slog.d(TAG, "handleScreenBrightnessBoostTimeout");}mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;updatePowerStateLocked();}}

最终我们会把mScreenBrightnessBoostInProgress 变量传到DisplayPowerController中去,在那里会把它设置最亮。

2.4 updateWakeLockSummaryLocked函数

updateWakeLockSummaryLocked函数,将各个锁的状态汇总。

   private void updateWakeLockSummaryLocked(int dirty) {if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {mWakeLockSummary = 0;final int numWakeLocks = mWakeLocks.size();for (int i = 0; i < numWakeLocks; i++) {final WakeLock wakeLock = mWakeLocks.get(i);switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {case PowerManager.PARTIAL_WAKE_LOCK:if (!wakeLock.mDisabled) {// We only respect this if the wake lock is not disabled.mWakeLockSummary |= WAKE_LOCK_CPU;}break;case PowerManager.FULL_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;break;case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;break;case PowerManager.SCREEN_DIM_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;break;case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;break;case PowerManager.DOZE_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_DOZE;break;case PowerManager.DRAW_WAKE_LOCK:mWakeLockSummary |= WAKE_LOCK_DRAW;break;}}// Cancel wake locks that make no sense based on the current state.if (mWakefulness != WAKEFULNESS_DOZING) {mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);}if (mWakefulness == WAKEFULNESS_ASLEEP|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM| WAKE_LOCK_BUTTON_BRIGHT);if (mWakefulness == WAKEFULNESS_ASLEEP) {mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;}}// Infer implied wake locks where necessary based on the current state.if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {if (mWakefulness == WAKEFULNESS_AWAKE) {mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;} else if (mWakefulness == WAKEFULNESS_DREAMING) {mWakeLockSummary |= WAKE_LOCK_CPU;}}if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {mWakeLockSummary |= WAKE_LOCK_CPU;}if (DEBUG_SPEW) {Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="+ PowerManagerInternal.wakefulnessToString(mWakefulness)+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));}}}

2.5 updateUserActivitySummaryLocked函数

再来看updateUserActivitySummaryLocked是来改变userActivity事件的时间

  private void updateUserActivitySummaryLocked(long now, int dirty) {// Update the status of the user activity timeout timer.if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);//取消消息long nextTimeout = 0;if (mWakefulness == WAKEFULNESS_AWAKE|| mWakefulness == WAKEFULNESS_DREAMING|| mWakefulness == WAKEFULNESS_DOZING) {final int sleepTimeout = getSleepTimeoutLocked();//各种进入睡眠,屏幕灭屏,亮度调低时间final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);mUserActivitySummary = 0;if (mLastUserActivityTime >= mLastWakeTime) {nextTimeout = mLastUserActivityTime+ screenOffTimeout - screenDimDuration;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;//亮屏} else {nextTimeout = mLastUserActivityTime + screenOffTimeout;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;//暗屏}}}if (mUserActivitySummary == 0&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;if (now < nextTimeout) {if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;}}}if (mUserActivitySummary == 0) {if (sleepTimeout >= 0) {final long anyUserActivity = Math.max(mLastUserActivityTime,mLastUserActivityTimeNoChangeLights);if (anyUserActivity >= mLastWakeTime) {nextTimeout = anyUserActivity + sleepTimeout;if (now < nextTimeout) {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;}}} else {mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;nextTimeout = -1;}}if (mUserActivitySummary != 0 && nextTimeout >= 0) {//不为0,发送消息继续执行这个函数,为0说明要灭屏了不用发消息。Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, nextTimeout);}} else {mUserActivitySummary = 0;}}}

2.6 updateWakefulnessLocked函数

我们再来看updateWakefulnessLocked,这个函数必须返回false,才能跳出循环。

            for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;mDirty = 0;updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}

我们来看下这个函数:

    private boolean updateWakefulnessLocked(int dirty) {boolean changed = false;if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE| DIRTY_DOCK_STATE)) != 0) {if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {//如果状态不是wake的返回falseif (DEBUG_SPEW) {Slog.d(TAG, "updateWakefulnessLocked: Bed time...");}final long time = SystemClock.uptimeMillis();if (shouldNapAtBedTimeLocked()) {changed = napNoUpdateLocked(time, Process.SYSTEM_UID);} else {changed = goToSleepNoUpdateLocked(time,PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);}}}return changed;}

先来看isItBedTimeYetLocked函数

    private boolean isItBedTimeYetLocked() {return mBootCompleted && !isBeingKeptAwakeLocked();}

isBeingKeptAwakeLocked需要返回false

    private boolean isBeingKeptAwakeLocked() {return mStayOn// 常为false|| mProximityPositive//距离传感器|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0//是否有屏幕持锁|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT//userActivity事件| USER_ACTIVITY_SCREEN_DIM)) != 0|| mScreenBrightnessBoostInProgress;//最亮事件}

只有mWakefulness == WAKEFULNESS_AWAKE和isBeingKeptAwakeLocked为true这两个条件才能进入这个判断,只要不满足直接为false,也就能跳出循环了。

那上面时候才会满足这两个条件呢,只要调用wakup唤醒设备时才会满足这个条件。而且需要设备不用保存唤醒状态时。那也即是说之前调用过wakeUp函数,而且又不用保持唤醒才会进入这个条件,因为shouldNapAtBedTimeLocked函数为我们只会返回false。所以只会调用goToSleepNoUpdateLocked,而这个函数会返回true的。这样的情况一般是之前设备被调用wakeUp函数唤醒屏幕了,然后过一段时间没有点击userActivity事件,这个时候其实又不用保持唤醒状态,这样的情况就不会被处理了,但是会调用goToSleepNoUpdateLocked函数重新走睡眠流程。

再来看这个函数,我们两个配置全为false,只能返回false

    private boolean shouldNapAtBedTimeLocked() {return mDreamsActivateOnSleepSetting|| (mDreamsActivateOnDockSetting&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);}

2.7 updateDisplayPowerStateLocked函数

再后面调用updateDisplayPowerStateLocked函数,我们之前分析过了,就是把一些状态传到DisplayPowerControlller来设置背光等。这里就不分析了。

2.8 updateDreamLocked函数

我们再来看updateDreamLocked函数

    private void updateDreamLocked(int dirty, boolean displayBecameReady) {if ((dirty & (DIRTY_WAKEFULNESS| DIRTY_USER_ACTIVITY| DIRTY_WAKE_LOCKS| DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS| DIRTY_IS_POWERED| DIRTY_STAY_ON| DIRTY_PROXIMITY_POSITIVE| DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {if (mDisplayReady) {scheduleSandmanLocked();}}}

scheduleSandmanLocked就是发送一个消息,这是一个异步过程。

    private void scheduleSandmanLocked() {if (!mSandmanScheduled) {mSandmanScheduled = true;Message msg = mHandler.obtainMessage(MSG_SANDMAN);msg.setAsynchronous(true);mHandler.sendMessage(msg);}}

最后在handleSandman函数中处理

    private void handleSandman() { // runs on handler thread// Handle preconditions.final boolean startDreaming;final int wakefulness;synchronized (mLock) {mSandmanScheduled = false;wakefulness = mWakefulness;if (mSandmanSummoned && mDisplayReady) {// 在goToSleep和nap中将mSandmanSummoned置为truestartDreaming = canDreamLocked() || canDozeLocked();//是否能做梦mSandmanSummoned = false;} else {startDreaming = false;}}// Start dreaming if needed.// We only control the dream on the handler thread, so we don't need to worry about// concurrent attempts to start or stop the dream.final boolean isDreaming;if (mDreamManager != null) {// Restart the dream whenever the sandman is summoned.if (startDreaming) {mDreamManager.stopDream(false /*immediate*/);mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);//开始做梦}isDreaming = mDreamManager.isDreaming();} else {isDreaming = false;}// Update dream state.synchronized (mLock) {// Remember the initial battery level when the dream started.if (startDreaming && isDreaming) {//正在做梦mBatteryLevelWhenDreamStarted = mBatteryLevel;if (wakefulness == WAKEFULNESS_DOZING) {Slog.i(TAG, "Dozing...");} else {Slog.i(TAG, "Dreaming...");}}// If preconditions changed, wait for the next iteration to determine// whether the dream should continue (or be restarted).if (mSandmanSummoned || mWakefulness != wakefulness) {return; // wait for next cycle}// Determine whether the dream should continue.if (wakefulness == WAKEFULNESS_DREAMING) {if (isDreaming && canDreamLocked()) {if (mDreamsBatteryLevelDrainCutoffConfig >= 0&& mBatteryLevel < mBatteryLevelWhenDreamStarted- mDreamsBatteryLevelDrainCutoffConfig&& !isBeingKeptAwakeLocked()) {// If the user activity timeout expired and the battery appears// to be draining faster than it is charging then stop dreaming// and go to sleep.Slog.i(TAG, "Stopping dream because the battery appears to "+ "be draining faster than it is charging.  "+ "Battery level when dream started: "+ mBatteryLevelWhenDreamStarted + "%.  "+ "Battery level now: " + mBatteryLevel + "%.");} else {return; // continue dreaming}}// Dream has ended or will be stopped.  Update the power state.if (isItBedTimeYetLocked()) {goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);updatePowerStateLocked();} else {wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);updatePowerStateLocked();}} else if (wakefulness == WAKEFULNESS_DOZING) {if (isDreaming) {//还在做梦退出return; // continue dozing}// Doze has ended or will be stopped.  Update the power state.reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);// 设置成睡眠状态updatePowerStateLocked();}}// Stop dream.if (isDreaming) {mDreamManager.stopDream(false /*immediate*/);//停止做梦}}

上面这个函数是异步执行的,那就是updatePowerState会继续执行,这个函数的作用就是等做梦结束会把power的状态由WAKEFULNESS_DOZING变成睡眠状态

说了这么多那到底把这状态改成睡眠状态后有和之前的Dozing状态什么区别呢?

2.8.1 睡眠状态和Dozing状态区别

1. finishWakefulnessChangeIfNeededLocked函数中,只有在睡眠状态才会调用mNotifier.onWakefulnessChangeFinished

    private void finishWakefulnessChangeIfNeededLocked() {if (mWakefulnessChanging && mDisplayReady) {if (mWakefulness == WAKEFULNESS_DOZING&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {return; // wait until dream has enabled dozing}mWakefulnessChanging = false;mNotifier.onWakefulnessChangeFinished();}}

2. 在updateUserActivitySummaryLocked函数中,如果是睡眠状态mUserActivitySummary 直接为0,而Dozing状态还要走userActivity事件流程。

    private void updateUserActivitySummaryLocked(long now, int dirty) {// Update the status of the user activity timeout timer.if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);long nextTimeout = 0;if (mWakefulness == WAKEFULNESS_AWAKE|| mWakefulness == WAKEFULNESS_DREAMING|| mWakefulness == WAKEFULNESS_DOZING) {......}else {mUserActivitySummary = 0;}}

3. 第三个区别最重要,看下面函数,当是睡眠状态返回POLICY_OFF,而是Dozing状态最终返回的是POLICY_DIM状态。

    private int getDesiredScreenPolicyLocked() {if (mWakefulness == WAKEFULNESS_ASLEEP) {return DisplayPowerRequest.POLICY_OFF;}if (mWakefulness == WAKEFULNESS_DOZING) {if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {return DisplayPowerRequest.POLICY_DOZE;}if (mDozeAfterScreenOffConfig) {return DisplayPowerRequest.POLICY_OFF;}// Fall through and preserve the current screen policy if not configured to// doze after screen off.  This causes the screen off transition to be skipped.}if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0|| !mBootCompleted|| mScreenBrightnessBoostInProgress) {return DisplayPowerRequest.POLICY_BRIGHT;}return DisplayPowerRequest.POLICY_DIM;}

我们再来看updateDisplayPowerStateLocked函数,mDisplayPowerRequest.policy就是从这个函数返回的。然后再传到DisplayPowerController中去。

    private boolean updateDisplayPowerStateLocked(int dirty) {final boolean oldDisplayReady = mDisplayReady;if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();

这样如果power状态是Dozing,DisplayPowerController会把背光设置成暗的状态。
在最后的updateSuspendBlockerLocked函数中,会调用needDisplaySuspendBlockerLocked函数来决定是否要吃Displays锁。

    private void updateSuspendBlockerLocked() {final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();

needDisplaySuspendBlockerLocked函数如果DisplayPowerRequest是暗的时候就会返回 true,导致Displays锁不能释放。也就不会睡眠了

    private boolean needDisplaySuspendBlockerLocked() {if (!mDisplayReady) {return true;}if (mDisplayPowerRequest.isBrightOrDim()) {// If we asked for the screen to be on but it is off due to the proximity// sensor then we may suspend but only if the configuration allows it.// On some hardware it may not be safe to suspend because the proximity// sensor may not be correctly configured as a wake-up source.if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive|| !mSuspendWhenScreenOffDueToProximityConfig) {return true;}}if (mScreenBrightnessBoostInProgress) {return true;}// Let the system suspend if the screen is off or dozing.return false;}

三、wakeUp函数

wakeUp函数最终调用了wakeUpNoUpdateLocked函数之后也调用了updatePowerState函数

    private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,String opPackageName, int opUid) {if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");try {switch (mWakefulness) {case WAKEFULNESS_ASLEEP:Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");break;case WAKEFULNESS_DREAMING:Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");break;case WAKEFULNESS_DOZING:Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");break;}mLastWakeTime = eventTime;setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);//设置状态mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);//通知userActivityNoUpdateLocked(//触发userActivity事件eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;}

四、userActivity函数

这个函数也是调用了userActivityNoUpdateLocked函数之后调用updatePowerState函数

    private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {if (eventTime < mLastSleepTime || eventTime < mLastWakeTime|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");try {if (eventTime > mLastInteractivePowerHintTime) {powerHintInternal(POWER_HINT_INTERACTION, 0);mLastInteractivePowerHintTime = eventTime;}mNotifier.onUserActivity(event, uid);//通知if (mWakefulness == WAKEFULNESS_ASLEEP|| mWakefulness == WAKEFULNESS_DOZING|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {return false;}if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {//记录userActivity时间if (eventTime > mLastUserActivityTimeNoChangeLights&& eventTime > mLastUserActivityTime) {mLastUserActivityTimeNoChangeLights = eventTime;mDirty |= DIRTY_USER_ACTIVITY;return true;}} else {//记录userActivity发生时间if (eventTime > mLastUserActivityTime) {mLastUserActivityTime = eventTime;mDirty |= DIRTY_USER_ACTIVITY;return true;}}} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return false;}

五、nap函数

nap函数最后调用了napNoUpdateLocked,之后也会调用updatePowerState函数

    private boolean napNoUpdateLocked(long eventTime, int uid) {if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE|| !mBootCompleted || !mSystemReady) {return false;}Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");try {Slog.i(TAG, "Nap time (uid " + uid +")...");mSandmanSummoned = true;setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);//设置状态} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}return true;}

六、总结

我们发现当由goToSleep函数引出updatePowerState函数之后,我们详细的分析过updatePowerState函数。后面的nap,wakeUp,userActivity函数的分析都非常容易。

android6.0 PowerManagerService状态分析相关推荐

  1. Android 6.0 PowerManagerService状态分析

    这篇博客我们主要分析下PowerManagerService的各个状态,主要从goToSleep,wakeUp,userActivity,nap函数作为入口分析. 一.PowerManagerServ ...

  2. Android7.0 PowerManagerService(1) 启动过程

    PowerManagerService负责Android系统中电源管理方面的工作,为了简便我们在下文中将其简称为PMS. 我们先大致了解一下PMS在Android中的整体结构:    如上图所示,可以 ...

  3. android6.0源码分析之AMS服务源码分析

    activitymanagerservice服务源码分析 1.ActivityManagerService概述 ActivityManagerService(以下简称AMS)作为Android中最核心 ...

  4. android6.0 framwork修改

    基于android6.0.7.01.20 默认使用Launcher2,修改Launcher2 packages/apps/Launcher3/src/com/android/launcher3/Lau ...

  5. Android6.0 Reset恢复出厂设置流程分析

    点击Settings应用中的恢复出厂设置按钮后流程分析: 先使用grep命令搜索"恢复出厂设置"字符串,找到相应的布局文件: packages/apps/Settings/res/ ...

  6. android 蓝牙找不到电脑,Android6.0 蓝牙搜索不到设备原因

    原因: 为提供更高的数据保护 Android6.0版本上增加了关于Wifi和蓝牙的权限,以下是官方文档说明: 图1 修改方法: 在AndroidManifest 中添加权限 或者 注意 如果targe ...

  7. 编译可在Nexus5上运行的CyanogenMod13.0 ROM(基于Android6.0)

    编译可在Nexus5上运行的CyanogenMod13.0 ROM (基于Android6.0) 作者:寻禹@阿里聚安全 前言 下文中无特殊说明时CM代表CyanogenMod的缩写. 下文中说的&q ...

  8. android6.0麦克风权限,android 6.0权限检测以及6.0以下,麦克风、相机权限判断

    android 6.0以上权限 android 6.0以上权限,我是通过PermissionsDispatcher进行申请,操作的,具体使用方法,见PermissionsDispatcher,Andr ...

  9. nexus5 刷 Android6.0+Xposed

    不得不说现在的刷机工具都做的方便快捷,只需要简单的几天命令就解决了.以前用windows刷的时候还需要装一堆驱动软件啥的. 原文链接: nexus5 刷 Android6.0+Xposed 0x00 ...

最新文章

  1. 计算机上的应用商城,Windows 应用商店帐户将应用安装在多达五台电脑上
  2. mysql floor报错_mysql的floor()报错注入方法详细分析
  3. GitHub上的编程语言:JavaScript领衔Java次之
  4. 反射中 BindingFlags标识
  5. 用php写shell,php与shell实现多线程的简单例子
  6. Lingo优化模型概述
  7. 51nod1675-序列变换【莫比乌斯反演】
  8. iis解析错误的编号_2019年网络工程师考试试题及解析(上午21-44题)
  9. LNK2026 module unsafe for SAFESEH image
  10. Layui第三方扩展LAY_EXCEL导出数据表格的数据
  11. R语言| 中介效应分析,Mediation包和BruceR包,循环Process函数
  12. 工具类App原型制作分享-WizNote
  13. WPS图片精简版 Ver.3.0.5
  14. usb 键盘码表_电脑键盘对应的二进制码表
  15. Win11怎么把桌面文件路径改到D盘
  16. 【HTMLCSS】CSS当中设置背景图片不显示的问题
  17. 如何同时训练左手灵活性和音阶思维
  18. 利用留数定理计算傅立叶变换积分
  19. 小孔成像总结_干货 | 初中物理解题技巧+方法总结,非常实用,初二初三都要看!...
  20. Python爬虫之Selenium

热门文章

  1. python读取批量txt文件
  2. excel怎么合并数据?
  3. 物理环路造成网络风暴,无法访问交换机故障处理过程
  4. 2022年度总结:除旧迎新,继往开来!
  5. Python爬虫 之 异步爬虫
  6. python库吐血整理
  7. 微软沈向洋,百度李彦宏、王海峰,阿里王坚均候选中国工程院院士
  8. python二手交易系统毕业设计开题报告
  9. 小程序开发——页面背景色设置
  10. JavaScript 计算地下城堡2资源何时满仓