概述
DisplayPowerController(以下简称DPC)用于控制显示电源状态,用来处理亮灭屏、背光的调节,包括接近传感器(P-Senser)、光线传感器(L-senser)和亮灭屏动画。它独立于PMS的其余部分,并且不共享任何状态,而是通过DisplayPowerCallbacks接口异步回调进行通信,通知PMS有关Display的改变。当PMS中请求屏幕状态时,会等待它返回一个结果,这个结果表示显示是否准备完成(mDisplayReady)。如果显示未准备就绪,则mDisplayReady为false。
可以将DPC看做是PMS和DMS的之间的一个“中介”,此外由于DPC的功能就是独立于PMS之外,PMS将Display交给它处理,因此在分析DPC时,以Display为切入点进行分析,因此在下面我们从亮屏、灭屏、亮度调节开始进行分析。
在PMS相关文档中已经分析过了PMS部分的亮屏、灭屏了,然而,仅仅是分析了PMS中相关的逻辑,并没有分析之后在DisplayPowerController中的逻辑,分析到updatePowerStateLocked()
时就停止了。在PMS的updatePowerStateLocked()方法中,会调用updateDisplayPowerStateLocked()
更新显示,而这个方法中更新显示时,是通过DPC完成,接下来我们将以之前的分析过的接口为入口点,开始分析DisplayPowerController中的逻辑。
1.requestPowerState()
这个方法是亮屏、亮度调节的入口方法,PMS中调用该方法从而进入DisplayPowerController并和DisplayManagerService交互。
该方法工作原理是这样的:当亮屏或者亮度调节时,最终都会走PMS中的updatePowerStateLocked()
方法,在这个方法中,通过DMS的LocalService传入封装了Display信息的DisplayPowerState
对象去请求DMS,之后进入DisplayPowerController中的requsetPowerState()
方法中,在这个方法中,首先会判断这次请求的DisplayPowerState是否改变,如果改变,则表示这是一次新的请求,此时在Handler中异步去执行更新操作,同时,返回给PMS的返回值mDisplayReadyLock置为false,表示Display没有更新完成。当异步操作完成后,将mDisplayReadyLock置为true,同时回调DisplayPowerCallback.onStateChanged()
方法,PMS重写了这个方法,在这个方法中又调用updatePowerState()方法,因此再此会请求一遍DMS,在这次请求中,由于DisplayPowerState,没有改变,因此直接返回mDisplayReadyLock了。
首先来看PMS中的请求显示的逻辑:
private boolean updateDisplayPowerStateLocked(int dirty) {
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
return mDisplayReady && !oldDisplayReady;
}
接下来开始详细分析这个方法,其代码如下:
/**
* @param request PMS中传入的DisplayPowerState对象,封装了Display信息
* @param waitForNegativeProximity 如果带有PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记,则该值为true,表示在由PSensor灭屏后,当释放PROXIMITY WakeLock时,不会立即亮屏,而是直到等待PSensor收到远离事件后才亮屏
* @return 如果display改变完成则返回true
*/
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mLock) {
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
//开机后第一次进入
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request);
changed = true;
//如果该次请求和上次请求不同,说明有状态改变,需要更新Display
} else if (!mPendingRequestLocked.equals(request)) {
mPendingRequestLocked.copyFrom(request);
changed = true;
}
/**
* changed为true,说明有改变发生,这个改变交给Handler异步去处理,此时说
* 明显示没有准备好,mDisplayReadyLocked=false
* 直到改变处理成功,mDisplayReadyLocked将被置为true,
*/
if (changed) {
mDisplayReadyLocked = false;
}
//mPendingRequestChangedLocked:用于标识电源请求状态或者PSensor标签是
//否改变
if (changed && !mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
return mDisplayReadyLocked;
}
}
Changed表示是否需要改变Display。这个方法中就好比一扇门,只有符合条件才能进入到下一个阶段。条件是什么呢?
- 1.先会对第二个形参进行判断,
waitForNegativeProximity
如果为true,则表示在释放PSensor相关的WakeLock时,如果PSensor还是靠近事件,则必须等待PSensor远离后才会亮屏,这个值释放wakelock时传入的flag有关,如果在释放wakelock时使用release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY)
的形式释放PSensor的WakeLock,则该值为true,大多数场景下为false; - 2.如果开机第一次进入该函数,则实例化代表将要请求的DisplayPowerRequest对象。
- 3.如果本次请求和上次请求不相同,则说明需要更新Display。mPendingRequestChangedLocked用于标识电源请求状态是否要改变,如果changed变为true,则该值会由false变为true,之后又会置为false。
如果满足以上条件,则changed变为true,表示Display需要改变,因此,调用sendUpdatePowerStateLocked()
方法获取Handler,并使用Handler进行Display的更新,同时返回值为false,表示Display还没有更新准备完成。
再来看看第二个参数waitForNegativeProximity
,这个值来自于PMS中:
private void releaseWakeLockInternal(IBinder lock, int flags) {
if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {
mRequestWaitForNegativeProximity = true;
}
}
因此,在释放WakeLock锁时,如果带有PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY
标记,该值就是true,并且在每一次请求完Display之后又会重新置为false,在updateDisplayPowerStateLocked()
方法中可以看到。通话过程中,如果由PSensor灭屏并一直保持,然后按Power键,此时系统将执行goToSleep流程,当再次按power键,此时系统将执行Wakeup流程,但是,如果waitForNegativeProximity
为true,则系统不会亮屏,直到PSensor接收到远离数据而亮屏。具体的逻辑在updatePowerState()
方法中,下面会提到。
再继续分析其异步做了哪些处理,我们接着上一步骤的分析,看看sendUpdatePowerStateLocked()
方法:
private void sendUpdatePowerStateLocked() {
if (!mPendingUpdatePowerStateLocked) {
//要打算更新电源状态了
mPendingUpdatePowerStateLocked = true;
//异步更新
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
这个方法中获取了Handler,并通过异步的方式调用了updatePowerState()方法执行下步处理:
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;
2.updatePowerState()
updatePowerState()方法是一个非常庞大的方法,也是DisplayPowerController中的核心方法,其中处理亮灭屏、调节亮度,都会在这里进行决策处理。该方法的完整代码如下:
private void updatePowerState() {
// Update the power state request.
//当DisplayPowerController中更新屏幕状态成功后是否必须通知PMS
final boolean mustNotify;
//是否要进行初始化
boolean mustInitialize = false;
//是否自动调节亮度调节值改变
boolean autoBrightnessAdjustmentChanged = false;
synchronized (mLock) {
//该值表示"是否将要更新电源状态",重置该值为false,从而可以被下一次
//sendUpdatePowerStateLocked()处理该方法
mPendingUpdatePowerStateLocked = false;
//表示"将要请求的DisplayPowerRequest对象",当PMS中发起请求后,
//在requestDisplayPowerState()中会将请求携带的DPS对象赋给该值,
//或者在系统启动时,通过请求携带的DPS对象实例化该值
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
//mPowerRequest表示"当前的电源请求状态",初始值为null,
//由mPengdingReqestLocked对象拷贝或实例化
//因此只有系统开机后第一次会进入if中,之后不会进入
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity =
mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
//标记值,如果请求状态和当前状态不同,则true
} else if (mPendingRequestChangedLocked) {
//自动调节亮度值是否改变,由"当前电源的请求状态"和"将要请求的电源请求状态"比较
autoBrightnessAdjustmentChanged =
(mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
//复制mPendingRequestLocked给mPowerRequset,
//即将"将要请求的电源请求状态"赋给"当前电源的请求状态"
mPowerRequest.copyFrom(mPendingRequestLocked);
//mWaitingForNegativeProximity表示在亮屏之前是否要等待PSensor接收到远事件值
//该值由PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记在释放锁时决定
mWaitingForNegativeProximity |=
mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
//重置该值为false
mPendingRequestChangedLocked = false;
//表示未准备就绪
mDisplayReadyLocked = false;
}
//是否进行通知
mustNotify = !mDisplayReadyLocked;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
//初始化亮灭屏动画、mPowerState等
initialize();
}
int state;
int brightness = PowerManager.BRIGHTNESS_DEFAULT;
boolean performScreenOffTransition = false;
//根据PMS中的请求参数决定屏幕状态和屏幕亮度值
switch (mPowerRequest.policy) {
//灭屏
case DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
//Doze模式
case DisplayPowerRequest.POLICY_DOZE:
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
//是否允许在自动调节亮度下配置doze亮度值
if (!mAllowAutoBrightnessWhileDozingConfig) {
brightness = mPowerRequest.dozeScreenBrightness;
}
break;
//VR模式
case DisplayPowerRequest.POLICY_VR:
state = Display.STATE_VR;
break;
//DIM和亮屏
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
assert(state != Display.STATE_UNKNOWN);
// Apply the proximity sensor.
//PSensor相关
/*-------------PSensor设置 beg--------------*/
if (mProximitySensor != null) {
//如果mPowerRequest.useProximitySensor=true&&Display状态不等于灭屏
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
//设置Psensor可用
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
//该值表示由PSensor灭屏
mScreenOffBecauseOfProximity = true;
//通过DisplayPowerCallback回调PMS
sendOnProximityPositiveWithWakelock();
}
} else if (mWaitingForNegativeProximity //如果该值为true
&& mScreenOffBecauseOfProximity //且由PSensor灭屏
&& mProximity == PROXIMITY_POSITIVE //且当前PSensor靠近
&& state != Display.STATE_OFF) {
//且Display状态不为灭屏状态
setProximitySensorEnabled(true);
} else {
//不满足以上条件,设置PSensor不可用
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
//如果满足说明此时PSensor处理远离事件,重置mScreenOffBecauseOfProximity为false
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
}
//由PSensor灭屏为true,则将state置位DISPLAY.STATE_OFF
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
}
/*-------------PSensor设置 end--------------*/
//获取屏幕状态,此时还未设置新的屏幕状态,因此是”旧”的
final int oldState = mPowerState.getScreenState();
//在这个方法中会进行屏幕状态、亮度的设置和处理亮灭屏动画
animateScreenStateChange(state, performScreenOffTransition);
//获取屏幕状态,此时已经设置新的屏幕状态
state = mPowerState.getScreenState();
// Use zero brightness when screen is off.
//如果屏幕状态为灭屏,设置亮度为0
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
}
// Configure auto-brightness.
//自动调节亮度是否可用
boolean autoBrightnessEnabled = false;
if (mAutomaticBrightnessController != null) {
//Doze模式下自动调节亮度是否可用
final boolean autoBrightnessEnabledInDoze =
mAllowAutoBrightnessWhileDozingConfig
&& (state == Display.STATE_DOZE || state ==
Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightness < 0;
final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
&& mPowerRequest.brightnessSetByUser;
//配置AutomaticBrightnessController
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state !=
Display.STATE_ON, userInitiatedChange);
}
/*----------------------亮度调节值计算 BEG-------------------------------------*/
//brightnessboost相关
if (mPowerRequest.boostScreenBrightness
&& brightness != PowerManager.BRIGHTNESS_OFF) {
brightness = PowerManager.BRIGHTNESS_ON;
}
// Apply auto-brightness.
boolean slowChange = false;
//如果brightness=PowerManager.BRIGHTNESS_DEFAULT=-1,说明请求屏幕状态非Off
if (brightness < 0) {
//default = -1
//如果自动调节亮度可用
if (autoBrightnessEnabled) {
//从AutomaticBrightnessController中获取自动调节亮度值
brightness =
mAutomaticBrightnessController.getAutomaticScreenBrightness();
}
if (brightness >= 0) {
//说明使用了自动亮度
// Use current auto-brightness value and slowly adjust to changes.
//调整brightness保持在最小值和最大值之间
//即mScreenBrightnessRangeMinimum <= brightness <= mScreenBrightnessRangeMaximum
brightness = clampScreenBrightness(brightness);
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
slowChange = true; // slowly adapt to auto-brightness
}
mAppliedAutoBrightness = true;//表示使用自动亮度
} else {
mAppliedAutoBrightness = false;
}
} else {
mAppliedAutoBrightness = false;
}
//如果PMS中请求的屏幕状态为Doze,则将亮度设置为Doze状态的亮度
if (brightness < 0 && (state == Display.STATE_DOZE
|| state == Display.STATE_DOZE_SUSPEND)) {
brightness = mScreenBrightnessDozeConfig;
}
//如果此时brightness还为-1,说明没有使用自动调节亮度和doze状态亮度,则使用手动设置亮度
if (brightness < 0) {
//获取screenBrightness并在取值区间进行判断
brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
}
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
//如果PMS中请求屏幕状态为Dim状态,则使用dim状态时的亮度,基于手动调节值
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightness > mScreenBrightnessRangeMinimum) {
brightness = Math.max(Math.min(brightness -
SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig),
mScreenBrightnessRangeMinimum);
}
if