Android 6.0 PowerManagerService状态分析

本文详细分析了Android系统中PowerManagerService的四个关键函数:goToSleep、wakeUp、userActivity和nap。通过这些函数的深入解读,揭示了设备进入不同状态的内部逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

一、PowerManagerService的goToSleep函数

我们先来看下goToSleep函数:

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

我们再来看看goToSleepNoUpdateLocked函数

  1. private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {  
  2.     if (eventTime < mLastWakeTime  
  3.             || mWakefulness == WAKEFULNESS_ASLEEP  
  4.             || mWakefulness == WAKEFULNESS_DOZING  
  5.             || !mBootCompleted || !mSystemReady) {  
  6.         return false;  
  7.     }  
  8.   
  9.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");  
  10.     try {  
  11.         switch (reason) {//打印原因  
  12.             case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:  
  13.                 Slog.i(TAG, "Going to sleep due to device administration policy "  
  14.                         + "(uid " + uid +")...");  
  15.                 break;  
  16.             case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:  
  17.                 Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");  
  18.                 break;  
  19.             case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:  
  20.                 Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");  
  21.                 break;  
  22.             case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:  
  23.                 Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");  
  24.                 break;  
  25.             case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:  
  26.                 Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");  
  27.                 break;  
  28.             case PowerManager.GO_TO_SLEEP_REASON_HDMI:  
  29.                 Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");  
  30.                 break;  
  31.             default:  
  32.                 Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");  
  33.                 reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;  
  34.                 break;  
  35.         }  
  36.   
  37.         mLastSleepTime = eventTime;  
  38.         mSandmanSummoned = true;  
  39.         setWakefulnessLocked(WAKEFULNESS_DOZING, reason);//置状态  
  40.   
  41.         // Report the number of wake locks that will be cleared by going to sleep.  
  42.         int numWakeLocksCleared = 0;  
  43.         final int numWakeLocks = mWakeLocks.size();  
  44.         for (int i = 0; i < numWakeLocks; i++) {//统计将会被清除的WakeLock  
  45.             final WakeLock wakeLock = mWakeLocks.get(i);  
  46.             switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {  
  47.                 case PowerManager.FULL_WAKE_LOCK:  
  48.                 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:  
  49.                 case PowerManager.SCREEN_DIM_WAKE_LOCK:  
  50.                     numWakeLocksCleared += 1;  
  51.                     break;  
  52.             }  
  53.         }  
  54.         EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);  
  55.   
  56.         // Skip dozing if requested.  
  57.         if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {  
  58.             reallyGoToSleepNoUpdateLocked(eventTime, uid);//有这个flag直接进入sleep。而不用先进入WAKEFULNESS_DOZING状态  
  59.         }  
  60.     } finally {  
  61.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  62.     }  
  63.     return true;  
  64. }  

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

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

  1. public void onWakefulnessChangeStarted(final int wakefulness, int reason) {  
  2.     final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);  
  3.   
  4.     // Tell the activity manager about changes in wakefulness, not just interactivity.  
  5.     // It needs more granularity than other components.  
  6.     mHandler.post(new Runnable() {  
  7.         @Override  
  8.         public void run() {  
  9.             mActivityManagerInternal.onWakefulnessChanged(wakefulness);//调用AMS的onWakefulnessChanged函数  
  10.         }  
  11.     });  
  12.   
  13.     // Handle any early interactive state changes.  
  14.     // Finish pending incomplete ones from a previous cycle.  
  15.     if (mInteractive != interactive) {  
  16.         // Finish up late behaviors if needed.  
  17.         if (mInteractiveChanging) {  
  18.             handleLateInteractiveChange();  
  19.         }  
  20.   
  21.         // Start input as soon as we start waking up or going to sleep.  
  22.         mInputManagerInternal.setInteractive(interactive);//Input设置状态,在PhoneWindowManager那篇博客有分析  
  23.         mInputMethodManagerInternal.setInteractive(interactive);  
  24.   
  25.         // Notify battery stats.  
  26.         try {  
  27.             mBatteryStats.noteInteractive(interactive);  
  28.         } catch (RemoteException ex) { }  
  29.   
  30.         // Handle early behaviors.  
  31.         mInteractive = interactive;  
  32.         mInteractiveChangeReason = reason;  
  33.         mInteractiveChanging = true;  
  34.         handleEarlyInteractiveChange();  
  35.     }  
  36. }  

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


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

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


二、PowerManagerService的updatePowerStateLocked函数

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

  1. private void updatePowerStateLocked() {  
  2.     if (!mSystemReady || 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);  
  15.   
  16.         // Phase 1: Update wakefulness.  
  17.         // Loop because the wake lock and user activity computations are influenced  
  18.         // by changes in wakefulness.  
  19.         final long now = SystemClock.uptimeMillis();  
  20.         int dirtyPhase2 = 0;  
  21.         for (;;) {  
  22.             int dirtyPhase1 = mDirty;  
  23.             dirtyPhase2 |= dirtyPhase1;  
  24.             mDirty = 0;  
  25.   
  26.             updateWakeLockSummaryLocked(dirtyPhase1);  
  27.             updateUserActivitySummaryLocked(now, dirtyPhase1);  
  28.             if (!updateWakefulnessLocked(dirtyPhase1)) {  
  29.                 break;  
  30.             }  
  31.         }  
  32.   
  33.         // Phase 2: Update display power state.  
  34.         boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);  
  35.   
  36.         // Phase 3: Update dream state (depends on display ready signal).  
  37.         updateDreamLocked(dirtyPhase2, displayBecameReady);  
  38.   
  39.         // Phase 4: Send notifications, if needed.  
  40.         finishWakefulnessChangeIfNeededLocked();  
  41.   
  42.         // Phase 5: Update suspend blocker.  
  43.         // Because we might release the last suspend blocker here, we need to make sure  
  44.         // we finished everything else first!  
  45.         updateSuspendBlockerLocked();  
  46.     } finally {  
  47.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  48.     }  
  49. }  


2.1 updateIsPoweredLocked函数

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

  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;  
  13.   
  14.             // Update wireless dock detection state.  
  15.             final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(  
  16.                     mIsPowered, mPlugType, mBatteryLevel);  
  17.   
  18.             final long now = SystemClock.uptimeMillis();  
  19.             if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,//充电方式改变是否需要点亮屏幕  
  20.                     dockedOnWirelessCharger)) {  
  21.                 wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,  
  22.                         mContext.getOpPackageName(), Process.SYSTEM_UID);  
  23.             }  
  24.             userActivityNoUpdateLocked(//触发userActivity事件  
  25.                     now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);  
  26.   
  27.             // Tell the notifier whether wireless charging has started so that  
  28.             // it can provide feedback to the user.  
  29.             if (dockedOnWirelessCharger) {  
  30.                 mNotifier.onWirelessChargingStarted();  
  31.             }  
  32.         }  
  33.   
  34.         if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {//更新低功耗相关配置  
  35.             if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {  
  36.                 if (DEBUG_SPEW) {  
  37.                     Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");  
  38.                 }  
  39.                 mAutoLowPowerModeSnoozing = false;  
  40.             }  
  41.             updateLowPowerModeLocked();  
  42.         }  
  43.     }  
  44. }  

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


2.2 updateStayOnLocked函数 

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


2.3 updateScreenBrightnessBoostLocked函数

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

再来看updateScreenBrightnessBoostLocked函数

  1. private void updateScreenBrightnessBoostLocked(int dirty) {  
  2.     if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {  
  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);  
  13.                     return;//发送消息退出  
  14.                 }  
  15.             }  
  16.             mScreenBrightnessBoostInProgress = false;//状态改变  
  17.             mNotifier.onScreenBrightnessBoostChanged();  
  18.             userActivityNoUpdateLocked(now,//触发userActivity事件  
  19.                     PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);  
  20.         }  
  21.     }  
  22. }  

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

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

2.4 updateWakeLockSummaryLocked函数

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

  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) {  
  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:  
  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) {  
  38.              mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);  
  39.          }  
  40.          if (mWakefulness == WAKEFULNESS_ASLEEP  
  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;  
  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.  }  


2.5 updateUserActivitySummaryLocked函数


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

  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  
  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);  
  14.   
  15.               mUserActivitySummary = 0;  
  16.               if (mLastUserActivityTime >= mLastWakeTime) {  
  17.                   nextTimeout = mLastUserActivityTime  
  18.                           + screenOffTimeout - screenDimDuration;  
  19.                   if (now < nextTimeout) {  
  20.                       mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;//亮屏  
  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) {  
  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;  
  52.                   }  
  53.               }  
  54.               if (mUserActivitySummary != 0 && nextTimeout >= 0) {//不为0,发送消息继续执行这个函数,为0说明要灭屏了不用发消息。  
  55.                   Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);  
  56.                   msg.setAsynchronous(true);  
  57.                   mHandler.sendMessageAtTime(msg, nextTimeout);  
  58.               }  
  59.           } else {  
  60.               mUserActivitySummary = 0;  
  61.           }  
  62.       }  
  63.   }  


2.6 updateWakefulnessLocked函数

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

我们来看下这个函数:

先来看isItBedTimeYetLocked函数

isBeingKeptAwakeLocked需要返回false

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

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

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


2.7 updateDisplayPowerStateLocked函数


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


2.8 updateDreamLocked函数

我们再来看updateDreamLocked函数

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

最后在handleSandman函数中处理

  1. private void handleSandman() { // runs on handler thread  
  2.     // Handle preconditions.  
  3.     final boolean startDreaming;  
  4.     final int wakefulness;  
  5.     synchronized (mLock) {  
  6.         mSandmanScheduled = false;  
  7.         wakefulness = mWakefulness;  
  8.         if (mSandmanSummoned && mDisplayReady) {// 在goToSleep和nap中将mSandmanSummoned置为true  
  9.             startDreaming = canDreamLocked() || canDozeLocked();//是否能做梦  
  10.             mSandmanSummoned = false;  
  11.         } else {  
  12.             startDreaming = false;  
  13.         }  
  14.     }  
  15.   
  16.     // Start dreaming if needed.  
  17.     // We only control the dream on the handler thread, so we don't need to worry about  
  18.     // concurrent attempts to start or stop the dream.  
  19.     final boolean isDreaming;  
  20.     if (mDreamManager != null) {  
  21.         // Restart the dream whenever the sandman is summoned.  
  22.         if (startDreaming) {  
  23.             mDreamManager.stopDream(false /*immediate*/);  
  24.             mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);//开始做梦  
  25.         }  
  26.         isDreaming = mDreamManager.isDreaming();  
  27.     } else {  
  28.         isDreaming = false;  
  29.     }  
  30.   
  31.     // Update dream state.  
  32.     synchronized (mLock) {  
  33.         // Remember the initial battery level when the dream started.  
  34.         if (startDreaming && isDreaming) {//正在做梦  
  35.             mBatteryLevelWhenDreamStarted = mBatteryLevel;  
  36.             if (wakefulness == WAKEFULNESS_DOZING) {  
  37.                 Slog.i(TAG, "Dozing...");  
  38.             } else {  
  39.                 Slog.i(TAG, "Dreaming...");  
  40.             }  
  41.         }  
  42.   
  43.         // If preconditions changed, wait for the next iteration to determine  
  44.         // whether the dream should continue (or be restarted).  
  45.         if (mSandmanSummoned || mWakefulness != wakefulness) {  
  46.             return// wait for next cycle  
  47.         }  
  48.   
  49.         // Determine whether the dream should continue.  
  50.         if (wakefulness == WAKEFULNESS_DREAMING) {  
  51.             if (isDreaming && canDreamLocked()) {  
  52.                 if (mDreamsBatteryLevelDrainCutoffConfig >= 0  
  53.                         && mBatteryLevel < mBatteryLevelWhenDreamStarted  
  54.                                 - mDreamsBatteryLevelDrainCutoffConfig  
  55.                         && !isBeingKeptAwakeLocked()) {  
  56.                     // If the user activity timeout expired and the battery appears  
  57.                     // to be draining faster than it is charging then stop dreaming  
  58.                     // and go to sleep.  
  59.                     Slog.i(TAG, "Stopping dream because the battery appears to "  
  60.                             + "be draining faster than it is charging.  "  
  61.                             + "Battery level when dream started: "  
  62.                             + mBatteryLevelWhenDreamStarted + "%.  "  
  63.                             + "Battery level now: " + mBatteryLevel + "%.");  
  64.                 } else {  
  65.                     return// continue dreaming  
  66.                 }  
  67.             }  
  68.   
  69.             // Dream has ended or will be stopped.  Update the power state.  
  70.             if (isItBedTimeYetLocked()) {  
  71.                 goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),  
  72.                         PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);  
  73.                 updatePowerStateLocked();  
  74.             } else {  
  75.                 wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM",  
  76.                         Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID);  
  77.                 updatePowerStateLocked();  
  78.             }  
  79.         } else if (wakefulness == WAKEFULNESS_DOZING) {  
  80.             if (isDreaming) {//还在做梦退出  
  81.                 return// continue dozing  
  82.             }  
  83.   
  84.             // Doze has ended or will be stopped.  Update the power state.  
  85.             reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);// 设置成睡眠状态  
  86.             updatePowerStateLocked();  
  87.         }  
  88.     }  
  89.   
  90.     // Stop dream.  
  91.     if (isDreaming) {  
  92.         mDreamManager.stopDream(false /*immediate*/);//停止做梦  
  93.     }  
  94. }  

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

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


2.8.1 睡眠状态和Dozing状态区别

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


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


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

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

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

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


三、wakeUp函数


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

  1. private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,  
  2.         String opPackageName, int opUid) {  
  3.     if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE  
  4.             || !mBootCompleted || !mSystemReady) {  
  5.         return false;  
  6.     }  
  7.   
  8.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");  
  9.     try {  
  10.         switch (mWakefulness) {  
  11.             case WAKEFULNESS_ASLEEP:  
  12.                 Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");  
  13.                 break;  
  14.             case WAKEFULNESS_DREAMING:  
  15.                 Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");  
  16.                 break;  
  17.             case WAKEFULNESS_DOZING:  
  18.                 Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");  
  19.                 break;  
  20.         }  
  21.   
  22.         mLastWakeTime = eventTime;  
  23.         setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);//设置状态  
  24.   
  25.         mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);//通知  
  26.         userActivityNoUpdateLocked(//触发userActivity事件  
  27.                 eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);  
  28.     } finally {  
  29.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  30.     }  
  31.     return true;  
  32. }  



四、userActivity函数

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

  1. private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {  
  2.     if (eventTime < mLastSleepTime || eventTime < mLastWakeTime  
  3.             || !mBootCompleted || !mSystemReady) {  
  4.         return false;  
  5.     }  
  6.   
  7.     Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");  
  8.     try {  
  9.         if (eventTime > mLastInteractivePowerHintTime) {  
  10.             powerHintInternal(POWER_HINT_INTERACTION, 0);  
  11.             mLastInteractivePowerHintTime = eventTime;  
  12.         }  
  13.   
  14.         mNotifier.onUserActivity(event, uid);//通知  
  15.   
  16.         if (mWakefulness == WAKEFULNESS_ASLEEP  
  17.                 || mWakefulness == WAKEFULNESS_DOZING  
  18.                 || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {  
  19.             return false;  
  20.         }  
  21.   
  22.         if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {//记录userActivity时间  
  23.             if (eventTime > mLastUserActivityTimeNoChangeLights  
  24.                     && eventTime > mLastUserActivityTime) {  
  25.                 mLastUserActivityTimeNoChangeLights = eventTime;  
  26.                 mDirty |= DIRTY_USER_ACTIVITY;  
  27.                 return true;  
  28.             }  
  29.         } else {//记录userActivity发生时间  
  30.             if (eventTime > mLastUserActivityTime) {  
  31.                 mLastUserActivityTime = eventTime;  
  32.                 mDirty |= DIRTY_USER_ACTIVITY;  
  33.                 return true;  
  34.             }  
  35.         }  
  36.     } finally {  
  37.         Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  38.     }  
  39.     return false;  
  40. }  


五、nap函数

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



六、总结

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


原文地址:http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/kc58236582/article/details/51595390
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值