欢迎大家关注我的掘金帐号
我会在那里定期更新最新版本的Android Framework源码模块分析~~
在Android 8.1 PowerManagerService分析(一)中对PMS的启动流程进行了分析,本篇对PMS中的一些核心方法进行分析。
1.2.updatePowerStateLocked方法详解
接着上文分析,在systemReady()
方法的最后,调用了updatePowerStateLocked()
方法:
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
........
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
updatePowerStateLocked()
方法是整个PMS中的核心方法,也是整个PSM中最重要的一个方法,它用来更新整个电源状态的改变,并进行重新计算。PMS中使用一个int值mDirty作为标志位判断电源状态是否发生变化,当电源状态发生改变时,如亮灭屏、电池状态改变、暗屏…都会调用该方法,在该方法中调用了其他同级方法进行更新,下面逐个进行分析,先看其代码:
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
try {
// Phase 0: Basic state updates.
//更新电池信息
updateIsPoweredLocked(mDirty);
//更新屏幕保持唤醒标识值mStayOn
updateStayOnLocked(mDirty);
//亮度增强相关
updateScreenBrightnessBoostLocked(mDirty);
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
//更新统计wakelock的标记值mWakeLockSummary
updateWakeLockSummaryLocked(dirtyPhase1);
//更新统计userActivity的标记值mUserActivitySummary和休眠到达时间
updateUserActivitySummaryLocked(now, dirtyPhase1);
//用来更新屏幕唤醒状态,状态改变返回true
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Update display power state.
//和Display交互,请求Display状态
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 3: Update dream state (depends on display ready signal).
//更新屏保
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 4: Send notifications, if needed.
//如果wakefulness改变,做最后的收尾工作
finishWakefulnessChangeIfNeededLocked();
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make
//surewe finished everything else first!
//更新Suspend锁
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
如果没有进行特定场景的分析,这块可能很难理解,在后续的分析中会对特定场景进行分析,这样更能理解方法的使用,如果这里还不太理解,不用太担心。
在整个方法中,当系统没有准备就绪或者mDirty没有进行置位时,不会执行后续步骤,直接return;接下来对该方法中的内容进行分析,由于此方法非常重要,因此这里将所有的方法都贴出来。
1.2.1.updateIsPoweredLocker()
这个方法主要功能有两个:
- 1.USB插播亮屏入口点;
- 2.更新低电量模式;
该方法如下:
/**
* 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;//是否处于低电量
/*---------------------BatteryService交互Begin-----------------------------*/
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.
BATTERY_PLUGGED_ANY);
mPlugType = mBatteryManagerInternal.getPlugType();
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
/*---------------------BatteryService交互 End-----------------------------*/
//充电状态改变
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED;
//是否连接无线充电
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(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0,
Process.SYSTEM_UID);
if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted();
}
}
//上次是否充电和当前是否充电不同||上次电量是否处于低电量和当前是否处于
//低电量不同
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
//上次处于低电量&&当前不处于低电量
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
//当电池处于低电量模式触发值时,用户是否关闭了低电量模式
mAutoLowPowerModeSnoozing = false;
}
//更新低电量模式
updateLowPowerModeLocked();
}
}
}
从代码中看出,只有满足mDirty&DIRTY_BATTERY_STATE!=0
时才会执行这个方法,满足此条件的有两处:
- 第一处:在调用systemServer()方法中:
public void systemReady(IAppOpsService appOps) {
.................
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
.................
}
- 第二处:在监听电量状态改变的广播中:
//监听ACTION_BATTERY_CHANGED
private final class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
//设置mDirty |= DIRTY_BATTERY_STAT
handleBatteryStateChangedLocked();
}
}
}
因此可以看到,这个方法跟电池有关,只要电池状态发生变化,就能够调用执行到这个方法进行操作。
在这个方法中,通过BatteryService的本地服务BatteryManagerInternal,和BatteryService进行交互,刷新电池信息,并记录上次的电池数据;然后判断是插拔USB是否需要唤醒屏幕。我们在插拔USB时,可以唤醒屏幕就是从这里为入口进行唤醒的。然后更新用户活动事件;之后会处理低电量时的操作,