这一节主要了解电源更新,源码中一般是通过xxxLocked来实现。函数updatePowerStateLocked 的功能是更新电源状态的锁定,通过把影响到 PowerManagement 发生变化的放在一起进行更新,函数updatePowerStateLocked的具体实现代码如下所示:
/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
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 = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 4: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 6: 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);
}
}
通过上述实现代码可知,函数updatePowerStateLocked按照如下阶段对Power State(电源状态)进行更新
第1阶段:基本状态的更新。
首先执行函数 updateIsPoweredLocked, 功能是判断设备是否处于充电状态,如果 DIRTY_BATTERY_STATE发生了变化,说明设备的电池状态有改变。函数updateIsPoweredLocked的具体实现代码如下所示:
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
*/
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 (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
}
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED;
// Update wireless dock detection state.
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
mIsPowered, mPlugType);
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
final long now = mClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
wakeUpNoUpdateLocked(now, PowerManager.WAKE_REASON_PLUGGED_IN,
"android.server.power:PLUGGED:" + mIsPowered, Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
}
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
// only play charging sounds if boot is completed so charging sounds don't play
// with potential notification sounds
if (mBootCompleted) {
if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
&& BatteryManager.isPlugWired(mPlugType)) {
mNotifier.onWiredChargingStarted(mUserId);
} else if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted(mBatteryLevel, mUserId);
}
}
}
mBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);
}
}
然后通过对比判断(通过电池状态前后的变化和充电状态的变化来判断)确定是否处于充电状态,会在mDirty中标记出充电方式的改变, 并同时根据充电状态的变化进行一些相应的处理,同时在处理是否在充电或者充电方式的改变时,都会认为是发生了一次用户事件或者称为用户活动的发生。
接着执行函数updateStayOnLocked,功能是更新device是否处于开启状态。此函数也是通过mStayOn 发生的前后变化作为判断依据,如果device 的属性 Settings.Global.STAY _ON_WHILEPLUGGED_IN为置位,并且没有达到电池充电时持续开屏时间的最大值(也就是说,在插入电源后的一段时间内保持开屏状态),那么 mStayOn 为真。函数 updateStayOnLocked 的具体实现代码如下所示:
/**
* Updates the value of mStayOn.
* Sets DIRTY_STAY_ON if a change occurred.
*/
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;
}
}
}
可以看到这一阶段的更新过程中主要是进行了充电状态的判断工作,然后根据充电的状态,更新了一些必要属性的变化,同时更新了mDirty.
第2阶段:显示内容的更新
mWakefuless表示device处于醒着、睡眠,或两者之间的一种状态,这种状态会影响到wakelock和 user activity的计算,所以要进行更新。在第2阶段先通过一个死循环进行处理,只有当update WakefulnessLocked 返回为false 时才能跳出这个循环。在刚进入这个循环时,对mDirty进行了重置,这能够说明在这次updatePowerState 后会执行前面所有发生的 power state,而不会让其影响到下一次的变化。同时也在为下一次的power state 从头开始更新做好准备。其中函数updateWakeLockSummaryLocked的实现代码如下所示:
/**
* Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
* Note that most wake-locks are ignored when the system