Android DisplayManagerService--0
本文基于Android 11.0源码分析
1.概述
在分析PMS灭屏流程和亮屏流程时,侧重于PMS部分的流程,DMS中涉及到的流程没有进行分析,只说到请求DMS去设置屏幕亮度和Display状态就略过了。
在DMS模块分析中,会将侧重点放在Display相关的流程上,这篇文章中将会对亮灭屏过程中PMS向DMS发起请求后的流程做详细分析,从而了解设置亮度、Display状态的整个逻辑。
在DMS模块中,和PMS交互的工作由DisplayPowerController进行处理,如控制屏幕亮度、Display状态、PSensor的灭屏。DisplayPowerController属于DMS模块,但它当中的核心逻辑是运行在PMS线程的,保证了和PMS的独立性。它和PMS不共享任何状态,PMS向DMS发起请求,DisplayPowerController接收请求,并在请求处理完毕后,通过回调的方式通知PMS完成改变。
DisplayPowerController对象是在PMS启动过程中进行创建:
// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public void systemReady(IAppOpsService appOps) {
......
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
......
}
DMS中在Local Service中进行创建:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = new DisplayBlanker() {
......
// 创建DisplayPowerController对象
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker,
mDisplayDevices.get(Display.DEFAULT_DISPLAY));
mSensorManager = sensorManager;
}
mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
}
DisplayPowerController在控制状态和亮度的设置时,主要通过另外两个类对象:
-
DisplayPowerState:代表当前Display整体状态,状态和亮度的更新都会交给它,让它做进一步处理;
-
LocalDisplayAdapter:代表默认屏幕的适配器,DisplayPowerState会将Display状态和亮度交给它,由它将状态和亮度设置给连接的物理屏。
下面继续从亮灭屏流程开始。
2.requestPowerState()发起请求
PMS中调用updateDisplayPowerStateLocked()方法请求Display进行更新,这个方法最终调用DisplayPowerController#requesetPowerState()方法:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
/**
* @param request PMS中封装的请求参数
* @param waitForNegativeProximity和Proximity wakelock释放后PSensor锁的动作有关
* @return true表示请求处理完成,false表示请求没有处理完成
*/
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mLock) {
boolean changed = false;
// 是否在PSensor WakeLock锁释放后,延迟解除Psensor监听
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
// 开机后第一次进入
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
} else if (!mPendingRequestLocked.equals(request)) { // 请求发生变化
mPendingRequestLocked.copyFrom(request);
changed = true;
}
// 表示需要处理新请求,先给PMS返回false,表示没有完成
if (changed) {
mDisplayReadyLocked = false;
}
// 开始处理新请求
if (changed && !mPendingRequestChangedLocked) {
// 表示request发生变化,即将更新全局request
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
return mDisplayReadyLocked;
}
}
以上方法中,能否将此次请求作为一个新请求处理,由以下三个条件确定:
-
waitForNegativeProximity是否为true;
-
如果开机第一次进入该函数,则mPendingRequestLocked的值为null,则实例化代表将要请求的DisplayPowerRequest对象;
-
本次请求对象和上次请求对象是否相同。
如果waitForNegativeProximity为true,则表示在释放PROXIMITY_SCREEN_OFF_WAKE_LOCK类型WakeLock时,如果PSenor上报靠近事件而处于灭屏状态,那么必须等待PSensor上报远离事件并亮屏后,才会解除对PSensor的监听。在释放wakelock时使用PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY的标记时,该值为true。
可以尝试下,申请PROXIMITY_SCREEN_OFF_WAKE_LOCK锁后,在遮挡灭屏情况下,分别用release()和release(RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY)释放锁,会看到不一样的效果。
mPendingRequestChangedLocked变量用于表示上次请求已经处理完毕。DisplayPowerRequest对象代表一个请求对象,封装了许多的请求参数:
// frameworks/base/core/java/android/hardware/display/DisplayManagerInternal.java
public static final class DisplayPowerRequest {
public int policy; // 请求的Display状态
public boolean useProximitySensor; // 是否持有PROXIMITY_SCREEN_OFF_WAKE_LOCK锁
public int screenBrightnessOverride; // 是否要覆盖亮度,尤其是来自WindowMananger的亮度
public boolean useAutoBrightness; // 是否使用自动亮度
public boolean lowPowerMode; // 是否进入了低电量模式
public float screenLowPowerBrightnessFactor; // 低电量模式下调整亮度因子
public boolean boostScreenBrightness; // 是否使用了亮度增强
public int dozeScreenBrightness; // 进入Doze状态后的屏幕亮度
public int dozeScreenState; // 进入Doze状态后的Display状态
之后将在sendUpdatePowerStateLocked()方法中,通过Handler进入到PMS线程中开始处理请求:
private void sendUpdatePowerStateLocked() {
if (!mPendingUpdatePowerStateLocked) {
// 表示需要更新power state
mPendingUpdatePowerStateLocked = true;
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
mHandler.sendMessage(msg);
}
}
之后将进入updatePowerState()方法中,这个方法是DisplayPowerController中的核心方法,对请求的解析和处理就是它来完成。
3.updatePowerState()更新状态
updatePowerState()方法非常庞大,处理亮灭屏、调节亮度、Display状态的更新,都会在这里进行处理。该方法的完整代码如下:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void updatePowerState() {
// Update the power state request.
final boolean mustNotify; // 是否要通知PMS完成请求处理
final int previousPolicy;
boolean mustInitialize = false; //是否要进行初始化
int brightnessAdjustmentFlags = 0; // 自动亮度调整因子标记
mBrightnessReasonTemp.set(null); // 记录亮度变化原因
// ####################################################Part 1####################################################
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;// 代表"即将开始更新",这里已经开始了,所以重置为true
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {// 只有系统开机后第一次会进入该if代码块
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
} else if (mPendingRequestChangedLocked) {// 更新全局DisplayPowerRequest
previousPolicy = mPowerRequest.policy;
mPowerRequest.copyFrom(mPendingRequestLocked);// 更新mPowerRequest
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false; // 重置
mDisplayReadyLocked = false;
} else {
previousPolicy = mPowerRequest.policy;
}
mustNotify = !mDisplayReadyLocked;
}
if (mustInitialize) {
initialize(); //初始化亮灭屏动画、DisplayPowerState对象...
}
// ####################################################Part 2####################################################
int state;
float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
boolean performScreenOffTransition = false; // 是否执行灭屏动画
switch (mPowerRequest.policy) { // 将根据policy确定Display要设置的状态
case DisplayPowerRequest.POLICY_OFF:// policy为off,会将Display状态设置为OFF
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
case DisplayPowerRequest.POLICY_DOZE: // policy为doze,则会根据mPowerRequest.dozeScreenState确定Display的状态,默认为DOZE状态
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
if (!mAllowAutoBrightnessWhileDozingConfig) {// 是否支持在Doze状态时使用自动亮度,默认false
brightnessState = mPowerRequest.dozeScreenBrightness;// 将亮度设置为PMS中指定的Doze状态亮度
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);// 记录亮度变化原因——doze状态的亮度
}
break;
case DisplayPowerRequest.POLICY_VR: // policy为VR时,设置Display状态为VR
state = Display.STATE_VR;
break;
case DisplayPowerRequest.POLICY_DIM: // policy为DIM或者BRIGHT时,都表示亮屏,所以将Display状态设置为ON
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
assert(state != Display.STATE_UNKNOWN);
// #################################################### Part 3 ####################################################
if (mProximitySensor != null) {
// 如果持有Proximity WakeLock锁,且请求Display状态不为OFF
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
// 注册PSensor监听
setProximitySensorEnabled(true);
// 上报了靠近事件
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
// 代表“是否由于PSensor收到靠近时间而灭屏”
mScreenOffBecauseOfProximity = true;
// 回调通知PMS PSensor收到靠近事件
sendOnProximityPositiveWithWakelock();
}
// 如果释放Proximity WakeLock锁时带有1标记,发现由于PSensor灭屏且还未收到远离事件,则继续等待,并保持PSensor监听
} else if (mWaitingForNegativeProximity
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
setProximitySensorEnabled(true);
} else {
// 在灭屏时或者释放Proximity WakeLock锁后,解除PSensor监听
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
// 收到远离事件后,重置mScreenOffBecauseOfProximity
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
// 通知PMS PSensor收到远离事件
sendOnProximityNegativeWithWakelock();
}
} else {
// 说明PSensor不可用,那下慢这个值也没用,直接置为false
mWaitingForNegativeProximity = false;
}
// 如果PSensor收到上报靠近时间了,需要灭屏,于是将Display状态设置为OFF
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
}
// #################################################### Part 4 ####################################################
final int oldState = mPowerState.getScreenState();
// 设置Display状态
animateScreenStateChange(state, performScreenOffTransition);
state = mPowerState.getScreenState();
// #################################################### Part 5 ####################################################
// 如果Display状态设置为OFF,说明要灭屏,则将亮度设置为-1.0f
if (state == Display.STATE_OFF) {
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
// 记录亮度变化原因
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
}
// 如果Display状态设置为VR,不常用
if (state == Display.STATE_VR) {
brightnessState = mScreenBrightnessForVr;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
}
// 使用PMS中的亮度覆盖,来自WindowManager如视频界面的亮度
if ((Float.isNaN(brightnessState))
&& isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
brightnessState = mPowerRequest.screenBrightnessOverride;
// 记录亮度变化原因
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
// 表示使用了覆盖亮度
mAppliedScreenBrightnessOverride = true;
} else {
mAppliedScreenBrightnessOverride = false;
}
// 判断是否在Doze状态下使用自动亮度,一般为false
final boolean autoBrightnessEnabledInDoze =
mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
// 判断自动亮度是否可用: 开始了自动亮度&亮屏状态&未使用前几类亮度&配置了自动亮度曲线映射
final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& Float.isNaN(brightnessState)
&& mAutomaticBrightnessController != null;
// 用来更新用户状态栏、设置中手动设置的亮度值的状态,如果用户设置亮度发生变化,返回true
final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
// 该亮度表示用户拖动亮度条调节且未放手时的亮度,所以是一个"临时"亮度,如果存在这个值,则必须使用这个值
if (isValidBrightnessValue(mTemporaryScreenBrightness)) {
brightnessState = mTemporaryScreenBrightness;
// 表示使用了临时用户亮度
mAppliedTemporaryBrightness = true;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
} else {
mAppliedTemporaryBrightness = false;
}
// 更新自动亮度曲线调整值,如果调整值发生变化,返回true
final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
// 由于发生变化已经更新到全局变量上,所以不需要"临时"自动变量调整值,重置
if (autoBrightnessAdjustmentChanged) {
mTemporaryAutoBrightnessAdjustment = Float.NaN;
}
final float autoBrightnessAdjustment;
// 如果临时自动变量调整值存在,则使用它作为全局自动变量调整值,随后它的值将更新到全局自动变量调整值上,并将它重置,如前五行看到的
if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO_TEMP;
// 表示使用了临时自动亮度调整值
mAppliedTemporaryAutoBrightnessAdjustment = true;
// 否则使用全局自动亮度调整值
} else {
autoBrightnessAdjustment = mAutoBrightnessAdjustment;
brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO;
mAppliedTemporaryAutoBrightnessAdjustment = false;
}
// 如果使用了亮度增强,Display状态不处于灭屏,会将亮度设置到最大
if (mPowerRequest.boostScreenBrightness
&& brightness != PowerManager.BRIGHTNESS_OFF) {
brightnessState = PowerManager.BRIGHTNESS_ON;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
// 表示使用了亮度增强
mAppliedBrightnessBoost = true;
} else {
mAppliedBrightnessBoost = false;
}
// 表示是否用户发起了亮度的改变:没有使用以上几类亮度&(自动亮度调整值发生变化||用户设置了亮度)
// 这个值若为true,说明亮度被用户拖动发生改变了
boolean userInitiatedChange = (Float.isNaN(brightnessState))
&& (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
// 是否用户手动调节过自动亮度
boolean hadUserBrightnessPoint = false;
if (mAutomaticBrightnessController != null) {
hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
// 配置自动亮度相关参数
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mBrightnessConfiguration,
mLastUserSetScreenBrightness,
userSetBrightnessChanged, autoBrightnessAdjustment,
autoBrightnessAdjustmentChanged, mPowerRequest.policy); }
// #################################################### Part 6 ####################################################
boolean slowChange = false;
if (brightness < 0) { // 如果前面几类亮度未使用,则使用自动亮度
float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
if (autoBrightnessEnabled) {
// 获取自动亮度
brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness();
// 获取新的自动亮度调整值
newAutoBrightnessAdjustment =
mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
}
// 说明使用了自动亮度
if (isValidBrightnessValue(brightnessState)) {
// 对得到的自动亮度限制范围
brightnessState = clampScreenBrightness(brightness);
// 这俩条件说明是由自动亮度的调节
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
// 用来控制亮度调节速率
slowChange = true;
}
// 将亮度值更新到settings中
putScreenBrightnessSetting(brightnessState);
// 表示使用了自动亮度
mAppliedAutoBrightness = true;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
} else {
mAppliedAutoBrightness = false;
}
// 如果自动亮度调整值发生变化,更新自动亮度调整值到settings中
if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
} else {
// 说明是纯自动亮度,并没有调整
brightnessAdjustmentFlags = 0;
}
} else {
mAppliedAutoBrightness = false;
brightnessAdjustmentFlags = 0;
}
// #################################################### Part 7 ####################################################
// 如果进入Doze状态后,PMS中未指定Doze状态亮度,使用默认的doze亮度
if ((Float.isNaN(brightnessState))
&& Display.isDozeState(state)) {
brightnessState = mScreenBrightnessDozeConfig;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
// #################################################### Part 8 ####################################################
// 如果这里还没有亮度,那么将使用用户设置的亮度
if (Float.isNaN(brightnessState)) {
brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
// #################################################### Part 9 ####################################################
// 设置进入Dim后的亮度
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
brightnessState = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
}
if (!mAppliedDimming) {
slowChange = false; // 表示需要快速设置亮度
}
mAppliedDimming = true; // 表示使用了Dim亮度
} else if (mAppliedDimming) {
slowChange = false;
mAppliedDimming = false;
}
// #################################################### Part 10 ####################################################
// 低电量模式下,需要调低亮度以节约功耗
if (mPowerRequest.lowPowerMode) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
brightnessState = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
slowChange = false;
}
// 表示使用了低电量模式的亮度
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
// #################################################### Part 11 ####################################################
if (!mPendingScreenOff) {
if (mSkipScreenOnBrightnessRamp) { // mSkipScreenOnBrightnessRamp表示亮屏时不使用亮度动画
if (state == Display.STATE_ON) {
if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
mInitialAutoBrightness = brightness;
mSkipRampState = RAMP_STATE_SKIP_INITIAL;
} else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
&& mUseSoftwareAutoBrightnessConfig
&& brightness != mInitialAutoBrightness) {
mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
} else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
} else {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
}
// 是否处于或原本处于VR状态
final boolean wasOrWillBeInVr =
(state == Display.STATE_VR || oldState == Display.STATE_VR);
// 表示是否在亮屏时,使用亮度动画,使用亮度动画,在亮屏时可能会出现缓慢的设置亮度。由mSkipScreenOnBrightnessRamp决定
final boolean initialRampSkip =
state == Display.STATE_ON && mSkipRampState != RAMP_STATE_SKIP_NONE;
// display硬件是否支持全范围亮度值,如果不支持,设置亮度时就不使用亮度动画设置
final boolean hasBrightnessBuckets =
Display.isDozeState(state) && mBrightnessBucketsInDozeConfig; // 表示doze状态时,display硬件是否支持全范围亮度值
// 是否colorfade已经完成对显示内容的覆盖,如果已经覆盖,那么就没必要使用亮度动画了,因为已经看不到显示内容了
final boolean isDisplayContentVisible =
mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
// 是否使用到了临时亮度
final boolean brightnessIsTemporary =
mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
float animateValue = brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT
? PowerManager.BRIGHTNESS_MIN : brightnessState;
if (isValidBrightnessValue(animateValue)) {
// 以下条件,直接设置亮度,没有亮度动画(rate=0)
if (initialRampSkip || hasBrightnessBuckets
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(animateValue, SCREEN_ANIMATION_RATE_MINIMUM);
} else {
animateScreenBrightness(animateValue,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
}
// #################################################### Part 12 ####################################################
// 每次亮度发生变化后,对这次变化进行记录, 依据就是brightnessIsTemporary和userInitiatedChange
// brightnessIsTemporary表示是否使用临时亮度,默认为false,并且在拖动过程中,这个值为ture,拖动亮度条结束后,将重回false
// userInitiatedChange表示用户是否调整过亮度调整过程中为false,调整完成后将变为ture,并在下一次执行到该方法时又重回false
// 因此,只要亮度发生变化,就会进入下面进行统计,userInitiatedChange则表示是否是用户发起的变化,perfect!
// 不过,notifyBrightnessChanged()中则对统计条件进行了限制:只统计使用自动亮度情况下的变化,关闭自动亮度,使用windowOverlay亮度都是不会统计的
if (!brightnessIsTemporary) {
if (userInitiatedChange && (mAutomaticBrightnessController == null
|| !mAutomaticBrightnessController.hasValidAmbientLux())) {
userInitiatedChange = false;
}
notifyBrightnessChanged(brightness, userInitiatedChange, hadUserBrightnessPoint);
}
}
// 每次亮度调整后,log的输出,日常处理问题相当有用
if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
Slog.v(TAG, "Brightness [" + brightnessState + "] reason changing to: '"
+ mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
+ "', previous reason: '" + mBrightnessReason + "'.");
mBrightnessReason.set(mBrightnessReasonTemp);
}
// #################################################### Part 13 ####################################################
if (mDisplayWhiteBalanceController != null) { // 自调节色温
if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
mDisplayWhiteBalanceController.setEnabled(true);
mDisplayWhiteBalanceController.updateDisplayColorTemperature();
} else {
mDisplayWhiteBalanceController.setEnabled(false);
}
}
// #################################################### Part 14 ####################################################
// mPendingScreenOnUnblocker用于亮屏过程,非空表示屏幕目前被阻塞,等待WindowManager模块完成亮屏操作后回调将它置为null
// Colorfade是一个暗层动画,亮灭屏时会淡入淡出
final boolean ready = mPendingScreenOnUnblocker == null &&
(!mColorFadeEnabled ||
(!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted())) // 是否正在有colorfade动画进行
&& mPowerState.waitUntilClean(mCleanListener); // 判断屏幕状态和ColorFade是否设置完成,两个都完成时返回true
// 所以ready表示display状态是否设置完成
// 表示display状态设置完毕,亮度也设置完毕
final boolean finished = ready
&& !mScreenBrightnessRampAnimator.isAnimating(); // 亮度动画是否在进行
// mReportedScreenStateToPolicy表示向PhoneWindowManager报告亮灭屏阶段的值
if (ready && state != Display.STATE_OFF
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON); // 将mReportedScreenStateToPolicy设置为REPORTED_TO_POLICY_SCREEN_ON,表示亮屏完成
mWindowManagerPolicy.screenTurnedOn(); // 报告PhoneWindowManager
}
// 表示更新display的设置或者亮度的设置还没有完成,需要持锁保证它们的完成
if (!finished && !mUnfinishedBusiness) {
mCallbacks.acquireSuspendBlocker();
mUnfinishedBusiness = true;
}
// 回调通知PMS,display状态完成更新,PMS将会再次发起请求
if (ready && mustNotify) {
synchronized (mLock) {
if (!mPendingRequestChangedLocked) {
mDisplayReadyLocked = true; // 表示更新完成了
}
}
sendOnStateChangedWithWakelock(); // 回调PMS
}
// 表示更新display和亮度的设置全部完成,释放锁
if (finished && mUnfinishedBusiness) {
mUnfinishedBusiness = false;
mCallbacks.releaseSuspendBlocker();
}
// 用来记录上次设置Display状态是否为ON
mDozing = state != Display.STATE_ON;
}
根据具体功能将它按功能划分成了几部分来看:
-
Part 1:mPowerRequest的更新,mPowerRequest代表当前PMS中的请求封装对象;
-
Part 2:根据mPowerRequest对象中的policy参数确定要设置的Display状态;
-
Part 3:针对Proximity Sensor的处理;
-
Part 4:根据Part2、Part3确定的state开始设置Display状态;
-
Part 5:确定屏幕亮度;
-
Part 6:应用自动亮度;
-
Part 7:Doze状态时,使用Doze默认亮度;
-
Part 8:应用用户手动调节亮度;
-
Part 9:设置Dim时亮度;
-
Part 10:设置低电量状态时的亮度;
-
Part 11:确定是否使用亮度动画和亮度的设置;
-
Part 12:亮度变化后的log输出和记录;
-
Part 13:更新色温调节状态;
-
Part 14:Display状态和亮度设置完成后的处理。
在这里,对涉及亮灭屏的如下关键流程进行分析:Part1、2、4、11、14,其中Part1、2两部分,是根据PMS中的policy来确定要设置的Display状态,这个好理解,并且都在代码中注释了,所以下面直接从Part4开始。
4.animateScreenStateChange()灭屏动画执行和更新Display状态
当确定好将要设置的Display State后,通过animateScreenStateChange()方法进行设置:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
if (mColorFadeEnabled &&
(mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) { // 如果在已经在进行ColorFade动画,非Display.ON时直接返回
if (target != Display.STATE_ON) {
return;
}
// 代表是否已开始设置灭屏动画(ColorFade淡入,屏幕变黑)
mPendingScreenOff = false;
}
// 在退出Doze状态时,是否需要是先过渡到OFF状态
if (mDisplayBlanksAfterDozeConfig // 默认为fale
&& Display.isDozeState(mPowerState.getScreenState())
&& !Display.isDozeState(target)) {
mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
if (mColorFadeOffAnimator != null) {
mColorFadeOffAnimator.end();
}
// 先过渡到OFF状态
setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
}
// 如果已经开始设置灭屏动画,但又收到非Display OFF请求,则不再等待灭屏动画完成,直接将Display状态设置为OFF
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false; // 重置
mPowerState.dismissColorFadeResources(); // 移除ColorFade
}
// 按照请求状态进行
if (target == Display.STATE_ON) { // Display目标状态为亮屏
// 通过DisplayPowerState去设置Display,并向PhoneWindowManager发出通知,WMS回调后返回true
if (!setScreenState(Display.STATE_ON)) {
return;
}
// 是否使用了亮屏动画,默认false
if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
if (mPowerState.getColorFadeLevel() == 1.0f) {
mPowerState.dismissColorFade();
} else if (mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE :
ColorFade.MODE_WARM_UP)) {
mColorFadeOnAnimator.start(); // 开始亮屏动画的转变
} else {
mColorFadeOnAnimator.end();
}
} else { // 如果没有使用ColorFade动画,则直接将ColorFade级别设置为1(全透明)
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
}
} else if (target == Display.STATE_VR) { // Display目标状态为VR,这个状态略去
// ..........
} else if (target == Display.STATE_DOZE) { // Display目标状态为DOZE
// 如果正在亮屏状态下进行亮度设置过程,先返回
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() == Display.STATE_ON) {
return;
}
// 去设置Doze状态
if (!setScreenState(Display.STATE_DOZE)) {
return;
}
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE_SUSPEND) { // Display目标状态为STATE_DOZE_SUSPEND
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
return;
}
// Display设置成STATE_DOZE_SUSPEND前,状态必须为STATE_DOZE才可以
if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
if (!setScreenState(Display.STATE_DOZE)) {
return;
}
setScreenState(Display.STATE_DOZE_SUSPEND);
}
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_ON_SUSPEND) { // Display目标状态为STATE_ON_SUSPEND
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
return;
}
// Display设置成STATE_ON_SUSPEND前,状态必须为STATE_ON才可以
if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
if (!setScreenState(Display.STATE_ON)) {
return;
}
setScreenState(Display.STATE_ON_SUSPEND);
}
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else { // 只剩下STATE_OFF,说明要灭屏
mPendingScreenOff = true; // 表示开始执行灭屏ColorFade动画
if (!mColorFadeEnabled) { // 如果不支持ColorFade,则直接添加
mPowerState.setColorFadeLevel(0.0f);
}
// 说明ColorFade动画已经执行完毕,于是开始去设置STATE_OFF状态
if (mPowerState.getColorFadeLevel() == 0.0f) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false; // 重置
mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
&& mPowerState.getScreenState() != Display.STATE_OFF) { // 如果以上条件不满足,进入这里,开始执行灭屏动画,第一次都会进入该else-if块
mColorFadeOffAnimator.start(); // 开始执行灭屏动画
} else {
mColorFadeOffAnimator.end(); // 灭屏动画执行完毕
}
}
}
这个方法也很长,但只有两个作用:
-
调用setScreenState()方法来继续设置Display状态;
-
通过ColorFade执行亮灭屏动画。
ColorFade是一个蒙层,它的level设置为1时全透明,0时全黑。在亮屏时,将该层级逐渐设置为1,产生逐渐亮屏的效果。灭屏时,将该层级逐渐设置为0,产生逐渐灭屏的效果。
这个方法可以看出,亮屏时,先设置Display的状态,再设置ColorFadelevel为1;灭屏时,先设置ColorFade level为0,再设置Display状态。这个区别导致了最终亮灭屏过程中设置状态和亮度的先后。
接下来,看下一步setScreenState()方法的执行:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private boolean setScreenState(int state, boolean reportOnly) {
// 是否设置OFF状态
final boolean isOff = (state == Display.STATE_OFF);
// 如果当前状态和目标状态不同
if (mPowerState.getScreenState() != state) {
// 说明非PSensor导致的设置OFF操作,向PhoneWindowManger报告状态
if (isOff && !mScreenOffBecauseOfProximity) {
if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
// 记录状态
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
blockScreenOff();
// 通知PhoneWindowManager灭屏
mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
unblockScreenOff();
} else if (mPendingScreenOffUnblocker != null) {
return false;
}
}
// reportOnly忽略即可,一般都为false
if (!reportOnly) {
// 进入DisplayPowerState中设置Display状态
mPowerState.setScreenState(state);
}
}
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) {
// 记录状态
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
// 解除阻塞
unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff(); // 通知PhoneWindowManager灭屏完毕
} else if (!isOff
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) { //这种情况说明已经灭屏到一半儿了用户又打算亮屏,这时也应该走完灭屏的流程
unblockScreenOff();
mWindowManagerPolicy.screenTurnedOff(); // 通知PhoneWindowManager灭屏完毕
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
}
// 说明由OFF状态切换为其他状态
if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) {
// ColorFade level一直为0,从而导致无法设置亮屏亮度,从而阻塞了亮屏流程,直到WMS中收到回调
blockScreenOn();
} else {
unblockScreenOn(); // 解除阻塞
}
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker); // 通知PhoneWindowManager灭屏完毕
}
// mPendingScreenOnUnblocker会在unblockScreenOn()中置为null,表示解除阻塞
return mPendingScreenOnUnblocker == null;
}
这个方法中,设置Display状态,同时向PhoneWindowManager进行通知。mReportedScreenStateToPolicy变量用来记录当前状态,根据不同状态向PhoneWindowManager进行通知。在Display状态发生变化过程中,每当进行到某一步,会将该值设置成对应的值,共有四个值:
// 设置非OFF状态完成,或者说灭屏状态
private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
// 开始设置非OFF状态
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
// 非OFF状态完成
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
// 开始设置非OFF状态
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
根据这些值通知PhoneWindowManger去执行对应操作。如在开始亮屏时,会调用mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker),WMS模块中收到调用后会做相应处理,这个过程中,由于mPendingScreenOnUnblocker对象非空,因此setScreenState()将返回false,导致阻塞colorFade的设置,从而会无法设置屏幕亮度。
在WMS处理完毕后,又通过mPendingScreenOnUnblocker参数回调DMS,并通过unblockScreenOn()方法,将mPendingScreenOnUnblocker对象置为null:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void unblockScreenOn() {
if (mPendingScreenOnUnblocker != null) {
mPendingScreenOnUnblocker = null;
long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
}
}
再次进入setScreenState()后,由于mPendingScreenOnUnblocker已经为null,因此不会阻塞ColorFade和亮度的设置。接下来,进入DisplayPowerState#setScreenState()来进一步设置Display的状态。
5.DisplayPowerState#setScreenState()设置状态
DisplayPowerState代表了当前Display的整体状态,包括Display的状态、亮度、ColorFade Level值,凡是涉及到Display的值,最后都会进入DisplayPowerState中进行设置,setScreenState()如下:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
public void setScreenState(int state) {
if (mScreenState != state) {
mScreenState = state; // 更新当前Display状态
mScreenReady = false; // 表示更新Display状态、亮度、ColorFade level未完成
scheduleScreenUpdate(); // 执行更新操作
}
}
这里将更新mScreenState变量,更新mScreenReady为false,表示Display状态未更新完成,然后调用scheduleScreenUpdate()方法。scheduleScreenUpdate()方法,在分析完DisplayController中的流程后再进行分析。
6.animateScreenBrightness()更新亮度
回到updatePowerState()中,执行完Part4后,下面来看Part11部分亮度的设置。设置亮度值使用animateScreenBrightness()方法:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void animateScreenBrightness(float target, int rate) {
// mScreenBrightnessRampAnimator中开始设置亮度
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
.......
}
}
第一个参数表示要设置的亮度值,第二个表示设置亮度的速率,关于亮度值和亮度设置速率值的获取、以及亮度动画,会在后面亮度设置部分详细分析,本片文章还是侧重于设置过程。
亮度的设置,不像设置Display状态那样烦琐,mScreenBrightnessRampAnimator是一个RampAnimator对象,该类是一个自定义动画类,专门用于更新亮度。进入该类的animateTo()后,最终会调用到DisplayPowerState的setScreenBrightness()方法,将亮度设置给DisplayPowerState。
7.DisplayPowerState#setScreenBrightness()设置亮度
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
public void setScreenBrightness(float brightness) {
if (mScreenBrightness != brightness) {
// 更新当前亮度值
mScreenBrightness = brightness;
if (mScreenState != Display.STATE_OFF) {
// 表示更新Display状态、亮度、ColorFade level未完成
mScreenReady = false;
// 执行更新操作
scheduleScreenUpdate();
}
}
}
这里更新了mScreenBrightness变量,也调用了scheduleScreenUpdate()开始执行更新操作。现在,Display的状态和亮度都传到了DisplayPowerState中,下面将通过scheduleScreenUpdate()方法开始更新。
8.scheduleScreenUpdate()执行更新
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) { // 表示将开始更新Display整体状态
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
//------------------------------
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
以上两个方法中,先将mScreenUpdatePending设置为true,表示将开始更新Display整体状态,然后通过Handler将在mScreenUpdateRunnable这个runnable中进行处理:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
// 确认最终的亮度,在Display状态为OFF时,或者ColorFade level为0时,将设置为0,其他情况下设置为DPC中传入的亮度值
float brightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
// PhotonicModulator是一个独立的线程,专门用来更新Display状态和亮度
if (mPhotonicModulator.setState(mScreenState, brightnessState)) {
// 更新完成
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
}
}
};
这里会对要更新的亮度值再做一次确认,根据Display状态、ColorFade来确定一个最终亮度值,然后在mPhotonicModulator中开始更新。
9.PhotonicModulator#setState()子线程进行更新
PhotonicModulator是一个继承于Thread的类,专门用于更新Display状态和亮度,因此更新屏幕状态和背光是在独立的线程中异步进行的,setState()方法如下:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
public boolean setState(int state, int backlight) {
synchronized (mLock) {
// Display状态是否发生变化,mPendingState表示即将开始设置的状态,设置完成后也不会清除
boolean stateChanged = state != mPendingState;
// 亮度是否发生变化,mPendingBacklight表示即将开始设置的亮度,设置完成后也不会清除
boolean backlightChanged = backlight != mPendingBacklight;
// Display状态或亮度任意一个发生变化,就开始更新
if (stateChanged || backlightChanged) {
mPendingState = state; // 更新mPendingState值
mPendingBacklight = backlight; // 更新mPendingBacklight值
// 表示是否处于change过程中
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
// 当不处于change过程中时,唤起PhotonicModulator线程
if (!changeInProgress) {
mLock.notifyAll();
}
}
return !mStateChangeInProgress; // 只要State更新完成,就返回true
}
}
当屏幕状态和亮度任意一个发生变化,将通过notifyAll()唤醒PhotonicModulator线程,然后执行该线程的run()方法,这是一个生产-消费者模型,肯定有其他地方对其进行了wait()操作。接下来看下它的run()方法:
// frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
public void run() {
for (;;) {
final int state;
final boolean stateChanged;
final int backlight;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
// mActualState表示实际Display状态
stateChanged = (state != mActualState);
backlight = mPendingBacklight;
// mActualBacklight表示实际亮度
backlightChanged = (backlight != mActualBacklight);
if (!stateChanged) {
// 再一次发起更新流程
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
if (!stateChanged && !backlightChanged) {
try {
// state和亮度都设置完成后,该线程进入wait状态
mLock.wait();
} catch (InterruptedException ex) { }
continue;
}
mActualState = state;
mActualBacklight = backlight;
}
// 调用DisplayBlanker中去请求Display
mBlanker.requestDisplayState(state, backlight);
}
}
在Display状态和亮度都更新完成之后,通过Object.wait()方法,让该线程进入WAITTING状态了。通过这种方式,不断设置过来的Display状态和亮度。
最终,调用mBlanker.requestDisplayState()进行下一步设置,这里又经过DMS,最后会对具体的DisplayDevice对象进行状态和亮度的设置中,这中间的逻辑就略过。
10.LocalDisplayDevice#requestDisplayStateLocked()
requestDisplayStateLocked()为具体的物理屏设置新的Display状态和亮度值:
// frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@Override
public Runnable requestDisplayStateLocked(final int state, final float brightnessState) {
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
mBrightnessState, brightnessState))
&& mBacklight != null;
if (stateChanged || brightnessChanged) {
......
return new Runnable() {
@Override
public void run() {
......
// 设置亮度
if (brightnessChanged || vrModeChange) {
setDisplayBrightness(brightnessState);
}
// 设置状态
if (state != currentState) {
setDisplayState(state);
}
}
private void setDisplayState(int state) {
......
try {
SurfaceControl.setDisplayPowerMode(token, mode);
} finally {}
}
private void setDisplayBrightness(float brightness) {
try {
if (mBacklight != null) {
mBacklight.setBrightness(brightness);
}
} finally {
}
}
};
}
return null;
}
最终,将亮度设置给了LightsService,将状态则是给了SurfaceControl,并由这两模块将分别将亮度和状态SurfaceFlinger中,最终完成整个设置。
回到updatePowerState()中,在Part14部分中,当Display状态和亮度都设置完成后,会将mDisplayReadyLocked值设置为true,表示Display状态更新完成,并在sendOnStateChangedWithWakelock()方法中回调PMS,PMS再次发起请求时,由于mDisplayReadyLocked已经变为true,因此将返回true,PMS将认为DMS对请求处理完成。
11.总结
以上就是display模块中涉及到的亮灭屏流程。结合之前PMS中的两篇亮灭屏流程,Framework层的亮灭屏流程全部分析完成。
(1)亮屏时序图

(2)灭屏时序图
