您的位置:首页 > 移动开发 > Android开发

android6.0 PowerManagerService状态分析

2016-06-06 20:04 423 查看
这篇博客我们主要分析下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++) {//统计将会被清除的WakeLock
final 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() {
@Override
public 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 thread
synchronized (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的返回false
if (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置为true
startDreaming = 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函数的分析都非常容易。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  powerManager