创作不易,请尊重原创,转载须注明出处:https://blog.csdn.net/An_Times/article/details/120027015
一、前言
环境:本文基于MTK 6765 Android 11
PowerManagerService(下文简称PMS)是Android系统的核心服务之一,控制着系统的亮灭屏,电源管理,等等重要的功能,本文将先从Power键亮灭屏流程分析入手去了解PMS。
二、PhoneWindowManager中Power键按键响应流程
代码路径:
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java.`
Power键按键处理是在PhoneWindowManager中,分为按下事件和松开事件。interceptKeyBeforeDispatching方法中也是根据是按下事件还是松开事件分别对应处理。final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
按下power键事件对应处理方法是interceptPowerKeyDown(event, interactive);
松开power键事件对应处理方法是interceptPowerKeyUp(event, interactive, canceled);
// TODO(b/117479243): handle it in InputPolicy
/** {@inheritDoc} */
@Override
public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,
int policyFlags) {
...省略部分代码
case KeyEvent.KEYCODE_POWER: {
EventLogTags.writeInterceptPower(
KeyEvent.actionToString(event.getAction()),
mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter);
// Any activity on the power button stops the accessibility shortcut
cancelPendingAccessibilityShortcutAction();
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
...省略部分代码
// Let the application handle the key.
return 0;
}
Power键按下事件处理方法 interceptPowerKeyDown
主要做以下几件事:
wakeUpFromPowerKey
方法唤醒。 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
//获得一个PARTIAL_WAKE_LOCK 保持CPU运行,WAKE_LOCK这里不介绍,后面文章在介绍。
if (!mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.acquire();
}
// Cancel multi-press detection timeout.
if (mPowerKeyPressCounter != 0) {
mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
}
mWindowManagerFuncs.onPowerKeyDown(interactive);
//2、判断是否是组合键截图事件,并做对应的处理。
// Latch power key state to detect screenshot chord.
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered = true;
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
interceptRingerToggleChord();
}
//3、判断是否开启了对应的功能,power键可以直接挂断电话或者关闭来电响铃。
// Stop ringing or end call if configured to do so when power is pressed.
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telecomManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telecomManager.isInCall() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telecomManager.endCall();
}
}
//4、判断是否是手势事件对应处理。
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
if (gestureService != null) {
gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
mTmpBoolean);
if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
mCameraGestureTriggeredDuringGoingToSleep = true;
}
}
// Inform the StatusBar; but do not allow it to consume the event.
sendSystemKeyToStatusBarAsync(event.getKeyCode());
schedulePossibleVeryLongPressReboot();
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
|| mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
// Wait for a long press or for the button to be released to decide what to do.
//interactive为true,当前是Awake状态即亮屏状态,处理亮屏下的Power键长按事件
if (hasLongPressOnPowerBehavior()) {
if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
powerLongPress();
} else {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
if (hasVeryLongPressOnPowerBehavior()) {
Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
longMsg.setAsynchronous(true);
mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
}
}
}
} else {
//interactive为false说明不是唤醒状态即灭屏状态,则调用 wakeUpFromPowerKey 方法唤醒系统。
wakeUpFromPowerKey(event.getDownTime());
if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
powerLongPress();
} else {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
if (hasVeryLongPressOnPowerBehavior()) {
Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
longMsg.setAsynchronous(true);
mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
}
}
mBeganFromNonInteractive = true;
} else {
final int maxCount = getMaxMultiPressPowerCount();
if (maxCount <= 1) {
mPowerKeyHandled = true;
} else {
mBeganFromNonInteractive = true;
}
}
}
}
}
三、PowerManagerService 继续处理wakeup事件
3.1、power键按下时PowerManagerService 的wakeup到updatePowerStateLocked 调用过程
代码路径:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java.`
1、上文中 PhoneWindowManager的 wakeUpFromPowerKey
方法调用的是PowerManagerService
的WakeUp方法,再通过Binder 跨进程调用服务端PowerManagerService
的wakeUp
,最后除非是当前已经是唤醒等情况,否则都会调用到updatePowerStateLocked
方法。
2、wakeUpNoUpdateLocked 只有在如下几种情况下为false,正常情况都是true。
a)、当前事件时间比上次asleep 时间还早(这不可能,除非穿越了);
b)、当前已经是WAKEFULNESS_AWAKE 唤醒状态;
c)、mForceSuspendActive 为true,即有强制挂起激活标志;
d)、刚开机系统没有Ready 好;
3、wakeUpNoUpdateLocked
主要是设置当前Wakefulness 为WAKEFULNESS_AWAKE
,然后通知wakeup,和调用userActivityNoUpdateLocked
更新用户活动时间,这个和超时休眠有关。
...此处省略部分代码
@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
String opPackageName) {
if (eventTime > mClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
wakeUpInternal(eventTime, reason, details, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
...此处省略部分代码
private void wakeUpInternal(long eventTime, @WakeReason int reason, String details, int uid,
String opPackageName, int opUid) {
synchronized (mLock) {
/**wakeUpNoUpdateLocked 只有在如下几种情况下为false,正常情况都是true
*1、当前事件时间比上次asleep 时间还早(这不可能,除非穿越了);
*2、当前已经是WAKEFULNESS_AWAKE 唤醒状态;
*3、mForceSuspendActive 为true,即有强制挂起激活标志;
*4、刚开机系统没有Ready 好;
*/
if (wakeUpNoUpdateLocked(eventTime, reason, details, uid, opPackageName, opUid)) {
updatePowerStateLocked();
}
}
}
...此处省略部分代码
四、PowerManagerService 的核心方法 updatePowerStateLocked
代码路径:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java.`
PMS中updatePowerStateLocked 方法调用的非常频繁并且非常的重要,里面的case 情况非常多,如果能搞清楚这个方法,基本上对PMS的逻辑流程就很熟悉了。
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
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);
//更新屏幕保持唤醒标识值mStayOn
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);
}
}
4.1 APP等进程向PowerManager申请的WakeLock在PowerManagerService中的名称变化
PowerManager.PARTIAL_WAKE_LOCK
,使用距离传感器控制屏幕亮灭申请的是PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK
等等,这些是应用向PowerManager 申请的WakeLock,而且不同的应用申请各种WakeLock,因此在PMS 里面呢它用的是mWakeLockSummary与之对应,可以理解是持有wakeLock 的汇总概要,他的对应关系如下。 /** Get wake lock summary flags that correspond to the given wake lock. */
private int getWakeLockSummaryFlags(WakeLock wakeLock) {
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.
return WAKE_LOCK_CPU;
}
break;
case PowerManager.FULL_WAKE_LOCK:
return WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
return WAKE_LOCK_SCREEN_BRIGHT;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
return WAKE_LOCK_SCREEN_DIM;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
return WAKE_LOCK_PROXIMITY_SCREEN_OFF;
case PowerManager.DOZE_WAKE_LOCK:
return WAKE_LOCK_DOZE;
case PowerManager.DRAW_WAKE_LOCK:
return WAKE_LOCK_DRAW;
}
return 0;
}
4.2、updatePowerStateLocked 之 updateWakeLockSummaryLocked 整合PMS持有的wakelock 的状态
1、PMS整合所持有的Wakelock 过程都是一些按位运算,刚开始看的时候直接搞懵逼了。后来多看几遍发现清楚多了。
2、首选PMS获取从PowerManager里面申请的所有Wakelock的集合,然后将所有的Wakelock转化整合成 mWakeLockSummary。
3、通过getWakefulnessLocked()获取当前设置的Wakefulness,这里power键按下事件在前面设置过是WAKEFULNESS_AWAKE
状态。然后根据当前的Wakefulness 和整合后的mWakeLockSummary,去对mWakeLockSummary重新赋值。
/**
* Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
* Note that most wake-locks are ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
@SuppressWarnings("deprecation")
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 0;
final int numProfiles = mProfilePowerState.size();
for (int i = 0; i < numProfiles; i++) {
mProfilePowerState.valueAt(i).mWakeLockSummary = 0;
}
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
final int wakeLockFlags = getWakeLockSummaryFlags(wakeLock);
mWakeLockSummary |= wakeLockFlags;
for (int j = 0; j < numProfiles; j++) {
final ProfilePowerState profile = mProfilePowerState.valueAt(j);
if (wakeLockAffectsUser(wakeLock, profile.mUserId)) {
profile.mWakeLockSummary |= wakeLockFlags;
}
}
}
mWakeLockSummary = adjustWakeLockSummaryLocked(mWakeLockSummary);
for (int i = 0; i < numProfiles; i++) {
final ProfilePowerState profile = mProfilePowerState.valueAt(i);
profile.mWakeLockSummary = adjustWakeLockSummaryLocked(profile.mWakeLockSummary);
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
}
}
}
private int adjustWakeLockSummaryLocked(int wakeLockSummary) {
// Cancel wake locks that make no sense based on the current state.
//如果当前wakefulness 不是打盹儿Dozing 状态就忽略WAKE_LOCK_DOZE 和WAKE_LOCK_DRAW
if (getWakefulnessLocked() != WAKEFULNESS_DOZING) {
wakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
//如果整合之后wakefulness 是 WAKEFULNESS_ASLEEP或者包含了WAKE_LOCK_DOZE状态就忽略WAKE_LOCK_SCREEN_BRIGHT 和WAKE_LOCK_SCREEN_DIM、WAKE_LOCK_BUTTON_BRIGHT这里还亮屏的状态。
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| (wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
wakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
wakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state.
/*这里开始应用整合之后的wakeLockSummary状态:
*1、如果整合之后wakefulness 包含亮屏的WAKE_LOCK_SCREEN_BRIGHT 或者 WAKE_LOCK_SCREEN_DIM,如果获取当前wakeLockSummary是WAKEFULNESS_AWAKE就把 wakeLockSummary 改为WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE.
*2、如果获取当前wakeLockSummary是WAKEFULNESS_DREAMING就把 wakeLockSummary 改为WAKE_LOCK_CPU.
*/
if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
wakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
} else if (getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
wakeLockSummary |= WAKE_LOCK_CPU;
}
}
if ((wakeLockSummary & WAKE_LOCK_DRAW) != 0) {
wakeLockSummary |= WAKE_LOCK_CPU;
}
return wakeLockSummary;
}
4.3、updatePowerStateLocked 之updateUserActivitySummaryLocked更新用户活动状态
updateUserActivitySummaryLocked
主要用于更新用户活动时间以及重新计算下次超时灭屏时间。screenOffTimeout
一般情况下是设置里面设置的超时灭屏时间,它从数据库里读取。screenDimDuration
是 Dim 屏幕变暗状态下的持续时间,这里他是设置的超时灭屏时间乘以mMaximumScreenDimRatioConfig
系数计算的。由dumpsys power可以打印出来,当前我设置超时灭屏时间是15s,灭屏前Dim状态的变暗的那段时长是 15*0.2 = 3s 。 /**
* Updates the value of mUserActivitySummary to summarize the user requested
* state of the system such as whether the screen should be bright or dim.
* Note that user activity is ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
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 (getWakefulnessLocked() == WAKEFULNESS_AWAKE
|| getWakefulnessLocked() == WAKEFULNESS_DREAMING
|| getWakefulnessLocked() == WAKEFULNESS_DOZING) {
//1、默认为-1 禁用,可以从dumpsys power中看到值
final long attentiveTimeout = getAttentiveTimeoutLocked();
final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
//2、设置中的超时灭屏时长
final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
attentiveTimeout);
//3、DIM 屏幕变暗持续的时间。
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
mUserActivitySummary = 0;
//4、根据最后一次用户活动时间和设置的超时灭屏时间判断下一次超时灭屏的时间。
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
|| mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
//5、屏保时间相关
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 != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
if ((mUserActivitySummary &
(USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
// Device is being kept awake by recent user activity
if (nextTimeout >= now && mOverriddenTimeout == -1) {
// Save when the next timeout would have occurred
mOverriddenTimeout = nextTimeout;
}
}
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
if ((mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
&& (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) {
nextTimeout = mAttentionDetector.updateUserActivity(nextTimeout,
screenDimDuration);
}
if (nextProfileTimeout > 0) {
nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
}
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
scheduleUserInactivityTimeout(nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
}
}
4.4、updatePowerStateLocked 之updateWakefulnessLocked更新Wakefulness状态
在updateWakefulnessLocked 执行之前还有 updateAttentiveStateLocked方法,这个没啥好说的,就是更新系统即将进入休眠。
我们可以看到 updatePowerStateLocked 方法中有一个for死循环,而updateWakefulnessLocked方法返回为false是退出死循环的唯一办法。
系统的WAKEFULNESS 有如下四种状态, updateWakefulnessLocked 方法中如果当前设备处于唤醒状态(awake),并且将要退出唤醒状态,也就是进入睡眠状态(sleep)或者屏保状态(dreaming),如果设备开启了屏保,进入屏保状态,否则直接进入睡眠状态。这种情况下,wakefulness发生改变,因此返回值为true,需要通过下一次循环重新统计wakelockSummary和userActivitySummary。如果不是以上情况,则不会进入if语句,说明不需要改变wakefulness值,返回false,则循环体只执行一次便退出。因此,该循环只有在一段时间不活动到达用户超时时间后进入屏保或者进入睡眠时,会执行两次,其他情况下只执行一次便退出,比如按power键灭屏等只会执行一次,因为当power键灭屏时,wakefulness值已经由唤醒状态变为SLEEP状态,因此不满足执行条件。
当刚开始灭屏,power键按下的时候系统状态是WAKEFULNESS_AWAKE
,但是isItBedTimeYetLocked为false,因此不会进入这个判断直接返回false 跳出for循环。
WAKEFULNESS_ASLEEP;
WAKEFULNESS_AWAKE;
WAKEFULNESS_DOZING;
WAKEFULNESS_DREAMING;
/**
* Updates the wakefulness of the device.
*
* This is the function that decides whether the device should start dreaming
* based on the current wake locks and user activity state. It may modify mDirty
* if the wakefulness changes.
*
* Returns true if the wakefulness changed and we need to restart power state calculation.
*/
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 | DIRTY_ATTENTIVE | DIRTY_SETTINGS
| DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
//当前屏幕保持唤醒&&设备将要退出唤醒状态(睡眠or屏保).
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = mClock.uptimeMillis();
//mAttentiveTimeoutSetting=-1,这里没有启用
if (isAttentiveTimeoutExpired(time)) {
changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
//是否在休眠时启用屏保
} else if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
} else {
changed = goToSleepNoUpdateLocked(time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
}
}
}
return changed;
}
4.5、updatePowerStateLocked 之updateDisplayPowerStateLocked更新屏幕状态
/**
* Updates the display power state asynchronously.
* When the update is finished, mDisplayReady will be set to true. The display
* controller posts a message to tell us when the actual display power state
* has been updated so we come back here to double-check and finish up.
*
* This function recalculates the display power state each time.
*
* @return True if the display became ready.
*/
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 | DIRTY_VR_MODE_CHANGED |
DIRTY_QUIESCENT)) != 0) {
if ((dirty & DIRTY_QUIESCENT) != 0) {
sQuiescent = false;
}
//1、获取将要设置的屏幕状态告诉DisplayPowerController(DPC).
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
final boolean autoBrightness;
//2、设置亮度
final float screenBrightnessOverride;
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
screenBrightnessOverride = mScreenBrightnessSettingDefault;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
autoBrightness = false;
screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
} else {
autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
// Update display power request.
mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
//3、设置是否使用了距离传感器,这跟PROXIMITY_SCREEN_OFF_WAKE_LOCK 有关
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
&& !mDrawWakeLockOverrideFromSidekick) {
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;
}
}
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManagerFloat;
} else {
mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
mDisplayPowerRequest.dozeScreenBrightness =
PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
//4、发送请求给DPC
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + getWakefulnessLocked()
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ ", screenBrightnessOverride=" + screenBrightnessOverride
+ ", useAutoBrightness=" + autoBrightness
+ ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+ ", mIsVrModeEnabled= " + mIsVrModeEnabled
+ ", sQuiescent=" + sQuiescent);
}
}
return mDisplayReady && !oldDisplayReady;
}
五、DisplayPowerController (下文简称DPC) 处理PMS的 改变屏幕状态request
5.1、PMS与DPC的关联过程
上面4.5小结我们知道 发送请求是 mDisplayManagerInternal.requestPowerState
,这个DisplayManagerInternal
是抽象类,DispalyManagerService的内部类 LocalService extends DisplayManagerInternal
, DispalyManagerService 实际上就是调用mDisplayPowerController处理的。这个过程非常简单是同步的没有跨进程调用。
代码路径:
frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java.`
@Override
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
}
5.2、DPC处理PMS发过来的改变屏幕状态request 请求
代码路径:
frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java.`
如果看过log就知道PMS的 updatePowerStateLocked 被调用的非常频繁,其他进程每次申请、释放Wake Lock,AMS回调过来的进程状态发送了改变、用户活动改变更新timeout 计时等等都会调用到,而且每次调用最终都会走到updateDisplayPowerStateLocked像DPC发送屏幕请求的,如果DPC每个都响应,那不得忙的要死,所以这里肯定是有过滤的。
如下注释中第三步说明的,后续只有判断PMS的 request 与之前的不一样才会继续处理,这样保证DPC处理的都是有效的请求。
mPendingRequestLocked 是上一次PMS发送过来的请求。
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
...此处省略部分代码
if (mPendingRequestLocked == null) {
//1、只有系统第一次起来会走这里
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) {
//2、后面PMS发送过来请求都会走这里,只有request发生了改变才会将changed置为true
mPendingRequestLocked.copyFrom(request);
changed = true;
}
...
if (changed && !mPendingRequestChangedLocked) {
//3.changed为true,mPendingRequestChangedLocked通常处理过就立即为false,所以走的是这里继续处理请求
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
...此处省略部分代码
5.3、DPC根据PMSrequest 请求在updatePowerState 中设置屏幕状态和亮度
代码路径:
frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java.`
updatePowerState 方法很长,除了PMS发过来的request 不一样会执行该方法以外,P-Sensor事件也会执行该方法。同时P-Sensor事件只设置屏幕状态,并没有将系统从Asleep状态中唤醒。
updatePowerState 主要做的事情如下:
private void updatePowerState() {
...此处省略部分代码
//设置屏幕的亮灭
animateScreenStateChange(state, performScreenOffTransition);
...此处省略部分代码
六、结语
本文作为PMS系列的第一篇博客,以Power键灭屏现象为切入点去了解代码流程,排版和编排顺序可能有点乱,其实PowerManagerService还有很多内容,比如WakeLock机制,P-Sensor亮灭屏原理,电池管理等等。等本博主写完之后会做一个整理,这样读起来可能会由浅入深了解的更加深刻。如果博客中有什么错误的地方欢迎评论指正!