亮度调节
亮度调节分两种,一种自动亮度调节,一种手动亮度调节,调用的入口在Settings和SystemUI当中,
SytemUI手动调节亮度方式如下
//非自动背光下的调节
else if (!mAutomatic) {
final int val = value + mMinimumBacklight;
if (stopTracking) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
}
//利用aidl调用PowManangerService的内部类BinderService处理背光调节的请求(val的值在0-255之间)
setBrightness(val);
if (!tracking) {
AsyncTask.execute(new Runnable() {
public void run() {
//把调节的亮度更新到数据库,存取的值为(0-255)
Settings.System.putIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, val,
UserHandle.USER_CURRENT);
}
});
}
} else {
//自动背光开关打开的情况下调节进度条
final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
//利用aidl调用PowManangerService的内部类BinderService处理背光调节的请求(adj的值在 -1,1之间)
setBrightnessAdj(adj);
if (!tracking) {
AsyncTask.execute(new Runnable() {
public void run() {
//把调节的亮度更新到数据库,存取的值为(-1 - 1)
Settings.System.putFloatForUser(mContext.getContentResolver(),
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj,
UserHandle.USER_CURRENT);
}
});
}
}
1.先通过Binder进程间通信与PowManangerService的内部类BinderService进行交互,然后更新Settings数据库
把亮度值存到Settings数据库当中
2.自动背光关闭情况下,手动可调节的范围0-255,自动开关打开情况下,手动可调节范围 -1 - 1;
- setBrightness(val) 方法的实现
private void setBrightness(int brightness) {
try {
//通过IPC进程间通信调用内部类BinderService的接口函数
mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException ex) {
}
}
- setBrightnessAdj(adj);
private void setBrightnessAdj(float adj) {
try {
//通过IPC进程间通信调用内部类BinderService的接口函数
mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);
} catch (RemoteException ex) {
}
}
继续分析PowerManagerService中的setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法
@Override // Binder call
public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideChj(int dispalyId,float adj) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj(dispalyId,adj);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
接着调用setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法,方法实现如下:
private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj(int displayId,float adj) {
synchronized (mLock) {
// Note: This condition handles NaN because NaN is not equal to any other
// value, including itself.
if (displayId == DEFAULT_DISPLAY){
if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverride != adj) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = adj;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
} else if (displayId == SECOND_DISPLAY){
if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay != adj) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay = adj;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
}
- 1.经过一系列的调用最终都会调到PowerManagerService的setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法当中
- 2.针对不同屏幕设置不同的亮度(mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay),displayId代表屏幕Id值(0代表中控,1代表副屏幕,2代表仪表,3代表空调)
- 3.最终都会调用到updatePowerStateLocked方法当中
播放视频下的亮度调节设置
在播放视频时,可以通过上下滑动来调整屏幕的亮度,但是,退出播放视频以后,又恢复到原来的亮度,其调用接口在PowerManagerService的setScreenBrightnessOverrideFromWindowManagerChj方法
@Override
public void setScreenBrightnessOverrideFromWindowManagerChj(int screenBrightness,int displayId){
if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
|| screenBrightness > PowerManager.BRIGHTNESS_ON) {
screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness,displayId);
}
private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness,int displayId) {
synchronized (mLock) {
if (displayId == DEFAULT_DISPLAY){
if (mScreenBrightnessOverrideFromWindowManager != brightness) {
mScreenBrightnessOverrideFromWindowManager = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}else if (displayId == SECOND_DISPLAY){
if (mScreenBrightnessOverrideSecondFromWindowManager != brightness) {
mScreenBrightnessOverrideSecondFromWindowManager = brightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
}
1.针对不同的屏幕适配不同的亮度,这里只针对中屏幕和副屏幕亮度做调节,因为只有中控和副屏才可以播放视频。
2.最终也会调用到updatePowerStateLocked方法当中
在updatePowerStateLocked会调用updateDisplayPowerStateLocked方法处理屏幕的亮灭以及亮度调节的逻辑
所以我们直接看updateDisplayStateLocked方法解析
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) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
//用来决定中控屏幕使用自动亮度还是手动设置亮度
boolean brightnessSetByUser = true;
boolean brightnessSetByUserSecondDisplay = true;
// 需要设置的亮度值(中控),默认为config.xml中config_screenBrightnessSettingDefault的值
int screenBrightness = mScreenBrightnessSettingDefault;
// 需要设置的亮度值(副屏),默认为config.xml中config_screenBrightnessSettingDefault的值
int screenBrightnessSecondDisplay = mScreenBrightnessSettingDefault;
//需要设置的亮度值(仪表),默认为config.xml中config_screenBrightnessSettingDefault的值
int screenBrightnessIpc = mScreenBrightnessSettingDefault;
//需要设置的亮度值(空调),默认为config.xml中config_screenBrightnessSettingDefault的值
int screenBrightnessCcp = mScreenBrightnessSettingDefault;
//自动背光调节的比例值(中控)
float screenAutoBrightnessAdjustment = 0.0f;
//自动背光调节的比例值(副屏)
float screenAutoBrightnessAdjustmentSecondDisplay = 0.0f;
//是否打开自动背光开关,在Settings设置打开,该值为true,否则为false
boolean autoBrightness = (mScreenBrightnessModeSetting ==
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
boolean autoBrightnessSecondDisplay = autoBrightness;
//系统服务未启动完成情况下,设置以下各项都为false
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
brightnessSetByUser = false;
autoBrightnessSecondDisplay = false;
brightnessSetByUserSecondDisplay = false;
//VR模式下的设置
} else if (mIsVrModeEnabled) {
screenBrightness = mScreenBrightnessForVrSetting;
autoBrightness = false;
//当主屏或者副屏正在播放视频
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)
|| isValidBrightness(mScreenBrightnessOverrideSecondFromWindowManager)) {
if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)){
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
brightnessSetByUser = false;
}else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)){
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;
screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;
} else if ((isValidBrightness(mScreenBrightnessSetting))){
screenBrightness = mScreenBrightnessSetting;
screenBrightnessIpc = mScreenBrightnessSetting;
screenBrightnessCcp = mScreenBrightnessSetting;
}
if (isValidBrightness(mScreenBrightnessOverrideSecondFromWindowManager)){
screenBrightnessSecondDisplay = mScreenBrightnessOverrideSecondFromWindowManager;
autoBrightnessSecondDisplay = false;
brightnessSetByUserSecondDisplay = false;
}else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverrideSecondDisplay)
|| isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
screenBrightnessSecondDisplay = mTemporaryScreenBrightnessSettingOverrideSecondDisplay;
if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)){
screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;
screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;
}
}else if (isValidBrightness(mScreenBrightnessSettingSecondDisplay)
|| isValidBrightness(mScreenBrightnessSetting)) {
if (isValidBrightness(mScreenBrightnessSetting)){
screenBrightnessIpc = mScreenBrightnessSetting;
screenBrightnessCcp = mScreenBrightnessSetting;
}
screenBrightnessSecondDisplay = mScreenBrightnessSettingSecondDisplay;
}
//SystemUI中的调节
} else if ((isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) ||
(isValidBrightness(mTemporaryScreenBrightnessSettingOverrideSecondDisplay))) {
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
screenBrightnessSecondDisplay = mTemporaryScreenBrightnessSettingOverrideSecondDisplay;
screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;
screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;
//Settings中的调节 //Settings.System.SCREEN_BRIGHTNESS的值,即保存在数据库中的亮度值,亮度值设置完成后,都会进行保存
} else if ((isValidBrightness(mScreenBrightnessSetting)) ||
(isValidBrightness(mScreenBrightnessSettingSecondDisplay))) {
screenBrightness = mScreenBrightnessSetting;
screenBrightnessSecondDisplay = mScreenBrightnessSettingSecondDisplay;
screenBrightnessIpc = mScreenBrightnessSetting;
screenBrightnessCcp = mScreenBrightnessSetting;
}
//自动背光开关打开(主控),手动调节亮度,设置亮度调节的比例值
if (autoBrightness) {
screenBrightness = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
screenAutoBrightnessAdjustment =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSetting)) {
screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
}
}
//自动背光打开(副屏),调节亮度,设置亮度调节的比例值
if (autoBrightnessSecondDisplay) {
screenBrightnessSecondDisplay = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay)) {
screenAutoBrightnessAdjustmentSecondDisplay =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSettingSecondDisplay)) {
screenAutoBrightnessAdjustmentSecondDisplay = mScreenAutoBrightnessAdjustmentSettingSecondDisplay;
}
}
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
screenBrightnessSecondDisplay = Math.max(Math.min(screenBrightnessSecondDisplay,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustmentSecondDisplay = Math.max(Math.min(
screenAutoBrightnessAdjustmentSecondDisplay, 1.0f), -1.0f);
screenBrightnessIpc = Math.max(Math.min(screenBrightnessIpc,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenBrightnessCcp =Math.max(Math.min(screenBrightnessCcp,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
// Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenBrightnessSecondDisplay = screenBrightnessSecondDisplay;
mDisplayPowerRequest.screenBrightnessCcp = screenBrightnessCcp;
mDisplayPowerRequest.screenBrightnessIpc = screenBrightnessIpc;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.screenAutoBrightnessAdjustment = screenAutoBrightnessAdjustment;
mDisplayPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay =
screenAutoBrightnessAdjustmentSecondDisplay;
mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
mDisplayPowerRequest.brightnessSetByUserSecondDisplay = brightnessSetByUserSecondDisplay;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useAutoBrightnessSecondDisplay = autoBrightnessSecondDisplay;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
&& (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
}
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
} else {
mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if ((dirty & DIRTY_QUIESCENT) != 0) {
sQuiescent = false;
}
return mDisplayReady && !oldDisplayReady;
}
四屏幕调节的逻辑,
- 1.手动调节的时候,无论自动背光开关打开或关闭,都会跟随中控的亮度变化而变换,(即,手动调节中控的亮度条,4个屏幕设置亮度一致)
- 2.自动背光自动调节亮度上三屏幕一致,使用仪表中的光感Sensor数据(中控,副屏,仪表亮度保持一致),空调屏幕自动背光自动调节单独由空调屏幕的光感Sensor控制
- 3.把请求的数据封装到mDisplayPowerRequest对象里,交给DisplayManagerService中requestPowerState去处理,最终会调用到DispalyPowerController.java
中的updatePowerState方法中 - 4.以上亮度设置值,优先级为:自动调节亮度 > 视频播放时设置亮度 > Settings、SystemUI中设置亮度(因为autoBrightness时将screenBrightness重置了)。
DispalyPowerController : updatePowerState()
private void updatePowerState() {
// Update the power state request.
final boolean mustNotify;
boolean mustInitialize = false;
boolean autoBrightnessAdjustmentChanged = false;//自动背光打开,有没有手动调节亮度,初始值设置为false(中控)
boolean autoBrightnessAdjustmentSecondChanged = false;//自动背光打开,有没有手动调节亮度,初始值设置为false(副屏)
//自动背光中控控制器
AutomaticBrightnessController automaticBrightnessController = getAutomaticBrightnessController(DEFAULT_DISPLAY);
//自动背光副屏控制器
AutomaticBrightnessController automaticBrightnessControllerSecondDisplay = getAutomaticBrightnessController(SECOND_DISPLAY);
//自动背光空调控制器
AutomaticBrightnessController automaticCCPBrightnessController = getAutomaticBrightnessController(CCP_DISPLAY);
//自动背光仪表控制器
AutomaticBrightnessController automaticIPCBrightnessController = getAutomaticBrightnessController(IPC_DISPLAY);
if (DEBUG) {
Slog.d(TAG, "updatePowerState: original no displayId");
}
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
//开机第一次重启会走这边的逻辑.重新创建DisplayPowerRequest对象
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
//从PowerManagerService中获取DisplayPowerRequest对象
} else if (mPendingRequestChangedLocked) {
autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
autoBrightnessAdjustmentSecondChanged = (mPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay
!= mPendingRequestLocked.screenAutoBrightnessAdjustmentSecondDisplay );
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
mustNotify = !mDisplayReadyLocked;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
initialize();
}
// Compute the basic display state using the policy.
// We might override this below based on other factors.
int state;
//初始化亮度值
int brightness = PowerManager.BRIGHTNESS_DEFAULT;
int brightnessSecondDisplay = PowerManager.BRIGHTNESS_DEFAULT;
int brightnessIpc = PowerManager.BRIGHTNESS_DEFAULT;
int brightnessCcp = PowerManager.BRIGHTNESS_DEFAULT;
// Configure auto-brightness.
//检测是是否开启自动亮度调节
boolean autoCCPIPCBrightnessEnabled = mZMQ.checkBrightnessAutomodeEnabled(CCP_DISPLAY);
boolean performScreenOffTransition = false;
//根据请求的Policy设置屏幕的状态
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
case DisplayPowerRequest.POLICY_DOZE:
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
if (!mAllowAutoBrightnessWhileDozingConfig) {
brightness = mPowerRequest.dozeScreenBrightness;
brightnessSecondDisplay = mPowerRequest.dozeScreenBrightness;
}
break;
case DisplayPowerRequest.POLICY_VR:
state = Display.STATE_VR;
break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
state = Display.STATE_ON;
break;
}
assert(state != Display.STATE_UNKNOWN);
// Apply the proximity sensor.
//proximity sensor距离传感器,与打电话有关,后续分析.
if (mProximitySensor != null) {
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = true;
sendOnProximityPositiveWithWakelock();
}
} else if (mWaitingForNegativeProximity
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
setProximitySensorEnabled(true);
} else {
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
if (mScreenOffBecauseOfProximity
&& mProximity != PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
}
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
}
// Animate the screen state change unless already animating.
// The transition may be deferred, so after this point we will use the
// actual state instead of the desired one.
//获取屏幕状态,此时还未设置新的屏幕状态,因此是”旧”的
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;
brightnessSecondDisplay = PowerManager.BRIGHTNESS_OFF;
}
// Configure auto-brightness.
//配置自动亮度调节
boolean autoBrightnessEnabled = false;
boolean autoBrightnessEnabledSecondDisplay = false;
if (automaticBrightnessController != null) {
final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightness < 0;
/*if (mZMQ != null) {
autoBrightnessEnabled |= mZMQ.checkBrightnessAutomodeEnabled(DEFAULT_DISPLAY);
}*/
//是否手动调节了亮度,自动开关打开情况下
final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
&& mPowerRequest.brightnessSetByUser;
//配置自动亮度调节功能,后续分析
automaticBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
userInitiatedChange);
}
//副屏幕的自动背光配置
if (automaticBrightnessControllerSecondDisplay != null) {
final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabledSecondDisplay = mPowerRequest.useAutoBrightnessSecondDisplay
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightnessSecondDisplay < 0;
/*if (mZMQ != null) {
autoBrightnessEnabled |= mZMQ.checkBrightnessAutomodeEnabled(DEFAULT_DISPLAY);
}*/
final boolean userInitiatedChangeSecondDisplay = autoBrightnessAdjustmentSecondChanged
&& mPowerRequest.brightnessSetByUserSecondDisplay;
automaticBrightnessControllerSecondDisplay.configure(autoBrightnessEnabledSecondDisplay,
mPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay, state != Display.STATE_ON,
userInitiatedChangeSecondDisplay);
}
//仪表屏幕的自动背光配置
if (automaticIPCBrightnessController != null) {
final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig
&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);
autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze);
final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
&& mPowerRequest.brightnessSetByUser;
automaticIPCBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
userInitiatedChange);
}
// Apply brightness boost.
// We do this here after configuring auto-brightness so that we don't
// disable the light sensor during this temporary state. That way when
// boost ends we will be able to resume normal auto-brightness behavior
// without any delay.
//亮度增强相关(中控),设置亮度增强,
if (mPowerRequest.boostScreenBrightness
&& brightness != PowerManager.BRIGHTNESS_OFF) {
brightness = PowerManager.BRIGHTNESS_ON;
}
//亮度增强相关(副屏),设置亮度增强,
if (mPowerRequest.boostScreenBrightness
&& brightnessSecondDisplay != PowerManager.BRIGHTNESS_OFF) {
brightnessSecondDisplay = PowerManager.BRIGHTNESS_ON;
}
// Apply auto-brightness.
//自动调节,如果是自动亮度设置缓慢亮度变化
boolean slowChange = false;
//设置自动亮度(因为上三屏亮度要保持一致,所以自动背光的亮度发生变化,这都会用仪表的亮度,规定用仪表的亮度曲线)
if (brightnessIpc < 0) {
if (autoCCPIPCBrightnessEnabled && !autoBrightnessAdjustmentChanged ) {
brightnessIpc = automaticIPCBrightnessController.getAutomaticScreenBrightness();
}
if (brightnessIpc >= 0) {
// Use current auto-brightness value and slowly adjust to changes.
brightnessIpc = clampScreenBrightness(brightnessIpc);
if (autoBrightnessEnabled && !autoBrightnessAdjustmentChanged){
brightness = brightnessIpc;
putScreenBrightnessSetting(brightness);
}
if (autoBrightnessEnabledSecondDisplay && !autoBrightnessAdjustmentSecondChanged){
brightnessSecondDisplay = brightnessIpc;
putSecondScreenBrightnessSetting(brightnessSecondDisplay);
}
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
slowChange = true; // slowly adapt to auto-brightness
}
mAppliedAutoBrightness = true;
mAppliedAutoBrightnessSecondDisplay = true;
mIPCAppliedAutoBrightness = true;
} else {
mAppliedAutoBrightness = false;
mAppliedAutoBrightnessSecondDisplay = false;
mIPCAppliedAutoBrightness = false;
}
} else {
mAppliedAutoBrightness = false;
mAppliedAutoBrightnessSecondDisplay = false;
mIPCAppliedAutoBrightness = false;
}
//空调屏幕的亮度调节变化
if (brightnessCcp < 0) {
if (autoCCPIPCBrightnessEnabled) {
//当环境光变化,获取自动调节的亮度(后续讲自动亮度调节的逻辑)
brightnessCcp = automaticCCPBrightnessController.getAutomaticScreenBrightness();
}
if (brightnessCcp >= 0) {
// Use current auto-brightness value and slowly adjust to changes.
brightnessCcp = clampScreenBrightness(brightnessCcp);
if (mCCPAppliedAutoBrightness) {
slowChange = true; // slowly adapt to auto-brightness
}
mCCPAppliedAutoBrightness = true;
} else {
mCCPAppliedAutoBrightness = false;
}
} else {
mCCPAppliedAutoBrightness = false;
}
// Use default brightness when dozing unless overridden.
//Doze状态下配置Doze状态的亮度(中控)
if (brightness < 0 && (state == Display.STATE_DOZE
|| state == Display.STATE_DOZE_SUSPEND)) {
brightness = mScreenBrightnessDozeConfig;
}
//Doze状态下配置Doze状态的亮度(副屏幕)
if (brightnessSecondDisplay < 0 && (state == Display.STATE_DOZE
|| state == Display.STATE_DOZE_SUSPEND)) {
brightnessSecondDisplay = mScreenBrightnessDozeConfig;
}
// Apply manual brightness.
// Use the current brightness setting from the request, which is expected
// provide a nominal default value for the case where auto-brightness
// is not ready yet.
//自动背光关闭情况下,手动调节亮度值设置(中控)
if (brightness < 0) {
brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
}
//自动背光关闭情况下,手动调节亮度值设置(副屏)
if (brightnessSecondDisplay < 0) {
brightnessSecondDisplay = clampScreenBrightness(mPowerRequest.screenBrightnessSecondDisplay);
}
//自动背光关闭情况下,手动调节亮度值设置(仪表)
if (brightnessIpc < 0){
brightnessIpc = clampAbsoluteBrightness(mPowerRequest.screenBrightnessIpc);
}
//自动背光关闭情况下,手动调节亮度值设置(空调)
if (brightnessCcp < 0){
brightnessCcp = clampAbsoluteBrightness(mPowerRequest.screenBrightnessCcp);
}
Slog.d(TAG," brightness: "+brightness+" brightnessSecondDisplay: "+brightnessSecondDisplay+" brightnessIpc: "+brightnessIpc+" brightnessCcp: "+brightnessCcp);
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
//设置暗屏的亮度
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightness > mScreenBrightnessRangeMinimum) {
brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
}
if (brightnessSecondDisplay > mScreenBrightnessRangeMinimum) {
brightnessSecondDisplay = Math.max(Math.min(brightnessSecondDisplay - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
}
if (!mAppliedDimming) {
slowChange = false;
}
mAppliedDimming = true;
} else if (mAppliedDimming) {
slowChange = false;
mAppliedDimming = false;
}
//如果当前是低电量模式,设置低电量模式的亮度
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
if (brightness > mScreenBrightnessRangeMinimum) {
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final int lowPowerBrightness = (int) (brightness * brightnessFactor);
brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
}
if (brightnessSecondDisplay > mScreenBrightnessRangeMinimum) {
final float brightnessFactorSecondDisplay =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final int lowPowerBrightness = (int) (brightnessSecondDisplay * brightnessFactorSecondDisplay);
brightnessSecondDisplay = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
}
if (!mAppliedLowPower) {
slowChange = false;
}
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
//背光调节时候,设置调节的动画,看起来比较丝滑
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended or transition to/from VR.
if (!mPendingScreenOff) {
if (mSkipScreenOnBrightnessRamp) {
if (state == Display.STATE_ON) {
if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
mInitialAutoBrightness = brightness;
mInitialAutoBrightnessSecondDisplay = brightnessSecondDisplay;
mSkipRampState = RAMP_STATE_SKIP_INITIAL;
} else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
&& mUseSoftwareAutoBrightnessConfig
&& (brightness != mInitialAutoBrightness
|| brightnessSecondDisplay != mInitialAutoBrightnessSecondDisplay)) {
mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
} else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
} else {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
}
boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
int brightnessIPCCCP = (((brightnessCcp&0xff)<<8)|(brightnessIpc&0xff));
int chjbrightness = (((brightnessSecondDisplay&0xff)<<8)|(brightness&0xff));
if ((state == Display.STATE_ON
&& mSkipRampState == RAMP_STATE_SKIP_NONE
|| state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)
&& !wasOrWillBeInVr) {
// 更新仪表和空调的亮度
updateIPCCCPBrightnessState(brightnessIPCCCP,slowChange);
//进入动画调节,更新中控和副屏的亮度
animateScreenBrightness(chjbrightness, slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
} else {
animateScreenBrightness(chjbrightness, 0);
}
}
//后续逻辑和亮灭屏相关以后分析
// Determine whether the display is ready for use in the newly requested state.
// Note that we do not wait for the brightness ramp animation to complete before
// reporting the display is ready because we only need to ensure the screen is in the
// right power state even as it continues to converge on the desired brightness.
final boolean ready = mPendingScreenOnUnblocker == null &&
(!mColorFadeEnabled ||
(!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
&& mPowerState.waitUntilClean(mCleanListener);
final boolean finished = ready
&& !mScreenBrightnessRampAnimator.isAnimating();
// Notify policy about screen turned on.
if (ready && state != Display.STATE_OFF
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
mWindowManagerPolicy.screenTurnedOn();
}
// Grab a wake lock if we have unfinished business.
if (!finished && !mUnfinishedBusiness) {
if (DEBUG) {
Slog.d(TAG, "Unfinished business...");
}
mCallbacks.acquireSuspendBlocker();
mUnfinishedBusiness = true;
}
// Notify the power manager when ready.
if (ready && mustNotify) {
// Send state change.
synchronized (mLock) {
if (!mPendingRequestChangedLocked) {
mDisplayReadyLocked = true;
if (DEBUG) {
Slog.d(TAG, "Display ready!");
}
}
}
sendOnStateChangedWithWakelock();
}
// Release the wake lock when we have no unfinished business.
if (finished && mUnfinishedBusiness) {
if (DEBUG) {
Slog.d(TAG, "Finished business...");
}
mUnfinishedBusiness = false;
mCallbacks.releaseSuspendBlocker();
}
// Record if dozing for future comparison.
mDozing = state != Display.STATE_ON;
}
这里简单做一个小结
- 1.当要请求进入Doze状态时,如果配置了Doze下LightSensor不可用,则将亮度设置为dozeScreenBrightness,(针对中控和副屏)
- 2.当要灭屏时候,设置灭屏亮度背光为0(针对中控和副屏)
- 3.当设置亮度增强的功能时候,设置亮度值255(针对中控和副屏)
- 4.以上3个条件都不满足,且开启了自动亮度调节功能,则获取自动调节的亮度(中控,副屏,仪表使用同一自动亮度,空调单独使用亮度)
- 5.以上4个条件都不满足,且当前为Doze状态,则将亮度值设置为mScreenBrightnessDozeConfig;(针对中控和副屏)
- 6.如果不满足以上5步,则使用手动调节的亮度,这些亮度值从PowerManagerService中获取(四屏幕使用同一亮度值)
- 7.如果要请求进入DIM状态时,则需要将当前得到的亮度值-10,并和mScreenBrightnessDimConfig比较取最小,和mScreenBrightnessRangeMinimum比较取最大。(针对中控和副屏)
- 8.如果当前处于低电量模式,则需要将当前得到的亮度值* 低电量模式下亮度缩放比例,然后和mScreenBrightnessRangeMinimum取最大(一般缩放值为0.5,即减半);(针对中控和副屏)
针对中控和副屏幕的亮度调节
animateScreenBrightness()
private void animateScreenBrightness(int target, int rate) {
if (DEBUG) {
Slog.d(TAG, "Animating brightness: target=" + target + ", rate=" + rate);
}
//target代表最终亮度,rate代表调节动画时调节的速率
if (mScreenBrightnessRampAnimator.chjanimateTo(target, rate)) {
/*if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {*/
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
try {
mBatteryStats.noteScreenBrightness(target);
} catch (RemoteException ex) {
// same process
}
}
}
在这个方法中,第一个参数是updatePowerState()中获得的最终亮度值,第二个参数则和亮度设置时的动画效果有关系,
如果设置为大于0的数,那么会在chjanimateTo()方法中根据这个数逐渐地设置亮度,如果设置为小于等于0,那么则不会有动画效果,直接将亮度值一次性设置。接下来
,说说亮度值设置时的动画相关的逻辑。
RampAnimator.chjanimateTo()
继续跟着上一段分析,mScreenBrightnessRampAnimator是一个RampAnimator对象,RampAnimator类是一个自定义动画类,
专门用于更新亮度,其原理是该类中有一个IntProperty对象作为该类的一个属性:
public boolean chjanimateTo(int target, int rate) {
// Immediately jump to the target the first time.
//如果rate<=0,则直接通过mProperty.setValue(mObject, target)设置为目标亮度
if (mFirstTime || rate <= 0) {
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
//rate<=0时直接设置
mProperty.setValue(mObject, target);
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
return true;
}
return false;
}
if (!mAnimating
|| rate > mRate
|| (target <= mCurrentValue && mCurrentValue <= mTargetValue)
|| (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
mRate = rate;
}
final boolean changed = (mTargetValue != target);
mTargetValue = target;
// Start animating.
if (!mAnimating && target != mCurrentValue) {
mAnimating = true;
mAnimatedValue = mCurrentValue;
mAnimatedValueDefaultDisplay = (mCurrentValue&0xff);
mAnimatedValueSecondDisplay = ((mCurrentValue>>8)&0xff);
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
}
1.如果rate<=0,那么直接调用mProperty.setValue(object,target)设置最终的亮度;如果rate>0,
那么会进入postAnimationCallback()方法,在这个方法中通过rate计算出每次设置的亮度值进行设置,直到设置到最终亮度为止。
2.mProperty.setValue(mObject, target);设置亮度值 ,那这个setValue调用的哪个类的方法呢?
我们先看mScreenBrightnessRampAnimator对象的创建
mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
因此当执行mProperty.setValue(object,target)时,执行的是DisplayPowerState.SCREEN_BRIGHTNESS的setValue()方法,
进入DisplayPowerState中查看该对象:
public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
new IntProperty<DisplayPowerState>("screenBrightness") {
@Override
public void setValue(DisplayPowerState object, int value) {
//设置亮度
object.setScreenBrightness(value);
}
@Override
public Integer get(DisplayPowerState object) {
return object.getScreenBrightness();
}
};
在这里可以看出,当调用setValue()方法后,将调用object.setScreenBrightness(),
从实例化流程可知,object对象还是DisplayPowerState对象。继续setScreenBrightness()方法:
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
mScreenBrightness = brightness;
//对于屏幕状态为State_OFF,根据上面内容的分析,在设置屏幕状态之间就会设置将背光设置为0,此处不进行处理
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate();
}
}
}
在这个方法中,如果当前屏幕状态不为STATE_OFF,即当前不是处于灭屏状态,则开始调用scheduleScreenUpdate()更新背光
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
postScreenUpdateThreadSafe方法
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
通过mHandler异步调用mScreenUpdateRunnable,mScreenUpdateRunnable是一个Runnable实现
具体方法如下
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
//表示是否打算更新屏幕状态,该值在scheduleScreenUpdate()方法中设置为了true
mScreenUpdatePending = false;
//获取背光亮度值,如果屏幕状态为State_Off的话就是0,其他屏幕状态下都是设置的背光值
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0;
//如果该方法返回false,表示屏幕更新完成,否则表示还没有更新完成
if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;//标记屏幕状态是否更新完成
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
- 1.先获取背光的亮度值
- 2.调用mPhotonicModulator的setState去更新亮度值和屏幕状态
- 3.根据setState方法的返回值来决定是否是屏幕状态更新完成
PhotonicModulator是一个Thread的子类,专门用于更新屏幕和背光亮度值的状态,因此,在DisplayPowerState中,更新屏幕和背光状态是在独立的线程中异步进行的。
现在,先来看看这个线程的setState()方法:
public boolean setState(int state, int backlight) {
synchronized (mLock) {
//屏幕状态是否改变,和之前的值做比较
boolean stateChanged = state != mPendingState;
//背光是否改变
boolean backlightChanged = backlight != mPendingBacklight;
//如果有其中之一改变,进入if中
if (stateChanged || backlightChanged) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
//设置state值
mPendingState = state;
//设置将要更新的亮度值
mPendingBacklight = backlight;
//mStateChangeInProgress和mBacklightChangeInProgress分别表示当前屏幕状态和背光值
//正在更新的过程中,changeInProgress表示其中之一是否正在更新的过程中
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
//如果为false,则唤醒mPhotonicModulator线程,执行它的run()方法
if (!changeInProgress) {
mLock.notifyAll();//很关键的一个方法
}
}
//如果该值为true,说明此时正在进行屏幕状态的改变,没有准备好。因此返回false
return !mStateChangeInProgress;
}
}
其中对mLock.notifyAll()这个逻辑再进行下分析,为何当changeInProgress为false的时候需要mLock.notifyAll()呢?
这是因为该线程启动后就是一个死循环,可以无线执行,但在死循环中进行了mLock.wait()操作,这里看看它的run()方法,如下:
@Override
public void run() {
for (;;) {
// Get pending change.
final int state;
final boolean stateChanged;
final int backlight;
final boolean backlightChanged;
synchronized (mLock) {
//通过全局变量给局部变量赋值
state = mPendingState;
//mActualState表示目前实际的状态值
stateChanged = (state != mActualState);
backlight = mPendingBacklight;
//mActualBacklight表示目前实际的亮度值
backlightChanged = (backlight != mActualBacklight);
//stateChange为false表示此时屏幕状态已应用为需要设置的值了(已应用),则再次执行一遍
//postScreenUpdateThreadSafe()方法,这次执行时,PhotonicMudulator.setScreen()将返回
//true,表示屏幕更新完成
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;//表示更新屏幕已完成
}
//说明背光值也已经应用
if (!backlightChanged) {
//置为false,表示更新背光已完成,没有正在进行的改变操作
mBacklightChangeInProgress = false;
}
//如果屏幕状态和背光值都应用完成,则让该线程进入等待状态
if (!stateChanged && !backlightChanged) {
try {
mLock.wait();
} catch (InterruptedException ex) { }
continue;
}
//设置实际状态值和背光值
mActualState = state;
mActualBacklight = backlight;
}
// Apply pending change.
if (DEBUG) {
Slog.d(TAG, "Updating screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
//调用DisplayBlanker中去请求Display
mBlanker.requestDisplayState(state, backlight);
}
}
DisplayBlanker.requestPowerState()
DisplayBlanker是一个接口,它专门用来更新实际的屏幕显示状态以及亮度.在DisplayPowerController中,
DisplayBlanker由DisplayManagerService在实例化DisplayPowerController时作为参数传入,
DisplayPowerController中在实例化DisplayPowerState时又通过构造函数传给了DisplayPowerState,
因此,DisplayBlanker的实现还是在DMS中,我们进入DMS中看DisplayBlanker对象:
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = new DisplayBlanker() {
@Override
public void requestDisplayState(int state, int brightness) {
// The order of operations is important for legacy reasons.
//对于灭屏和非灭屏状态,调用callback的顺序不同
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
//PMS中调用native层方法
callbacks.onDisplayStateChange(state);
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);更新状态和亮度值
}
}
};
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker);
}
}
1.从代码中可以得知当状态亮屏时候,调用requestGlobalDisplayStateInternal更新亮度值
2.从以上逻辑来看先更新状态,后更新亮度(亮屏设置时)
private void requestGlobalDisplayStateInternal(int state, int brightness) {
int brightnessdefaultdisplay = (brightness&0xff); //中控亮度值
int brightnessseconddisplay = ((brightness>>8)&0xff); //副屏亮度值
if (state == Display.STATE_UNKNOWN) {
state = Display.STATE_ON;
}
根据状态设置亮度值,亮度调节时,state为Display.STATE_ON
if (state == Display.STATE_OFF) {
brightnessdefaultdisplay = PowerManager.BRIGHTNESS_OFF;
} else if (brightnessdefaultdisplay < 0) {
brightnessdefaultdisplay = PowerManager.BRIGHTNESS_DEFAULT;
} else if (brightnessdefaultdisplay > PowerManager.BRIGHTNESS_ON) {
brightnessdefaultdisplay = PowerManager.BRIGHTNESS_ON;
}
if (state == Display.STATE_OFF) {
brightnessseconddisplay = PowerManager.BRIGHTNESS_OFF;
} else if (brightnessseconddisplay < 0) {
brightnessseconddisplay = PowerManager.BRIGHTNESS_DEFAULT;
} else if (brightnessseconddisplay > PowerManager.BRIGHTNESS_ON) {
brightnessseconddisplay = PowerManager.BRIGHTNESS_ON;
}
synchronized (mTempDisplayStateWorkQueue) {
try {
// Update the display state within the lock.
// Note that we do not need to schedule traversals here although it
// may happen as a side-effect of displays changing state.
synchronized (mSyncRoot) {
if (mGlobalDisplayState == state
&& mGlobalDisplayBrightness == brightnessdefaultdisplay
&& mGlobalDisplayBrightnessSecondDisplay == brightnessseconddisplay) {
return; // no change
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
+ Display.stateToString(state)
+ ", brightness=" + brightness + ")");
Slog.d(TAG, "requestGlobalDisplayStateInternal mGlobalDisplayState = " + mGlobalDisplayState + " mGlobalDisplayBrightness" + mGlobalDisplayBrightness + " mGlobalDisplayBrightnessSecondDisplay" + mGlobalDisplayBrightnessSecondDisplay);
//更新全局亮度值
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightnessdefaultdisplay;
mGlobalDisplayBrightnessSecondDisplay = brightnessseconddisplay;
//调节亮度
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
}
// Setting the display power state can take hundreds of milliseconds
// to complete so we defer the most expensive part of the work until
// after we have exited the critical section to avoid blocking other
// threads for a long time.
for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
mTempDisplayStateWorkQueue.get(i).run();
}
Trace.traceEnd(Trace.TRACE_TAG_POWER);
} finally {
mTempDisplayStateWorkQueue.clear();
}
}
}
在这个方法中,设置了mGlobalDisplayState和mGlobalDisplayBrightness,这两个全局变量表示整体的显示状态和亮度,然后将这两值传给了下一个方法applyGlobalDisplayStateLocked(),继续分析该方法:
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
Slog.i(TAG, "applyGlobalDisplayStateLocked UniqueId = " + device.getUniqueId());
Runnable runnable = updateDisplayStateLocked(device);
if (runnable != null) {
workQueue.add(runnable);
}
}
}
在这个方法中,首先会遍历mDisplayDevices,它是表示当前所有显示设备的集合,然后更新每一个显示设备.什么是显示设备呢?目前有5种DisplayDevice:
- 1.LocalDisplayDevice:中控屏幕就是一个显示设备;
- 2.WifiDisplayDevice:无线投射,通过wifi将屏幕投射到其他物理屏幕上如TV上.
- 3.VirtualDisplayDevice:虚拟设备
- 4.LocalDisplayDevice:副屏幕也是一个显示设备
- 5.空调和仪表也是显示设备,不过空调和仪表的逻辑不在这里(后续会分享)
调用updateDisplayStateLocked会对中控和副屏幕做不同的处理
DisplayManagerService.updateDisplayStateLocked
private Runnable updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
if (device.getUniqueId().equals("local:1")) {
Slog.i(TAG, "updateDisplayStateLocked UniqueId = " + device.getUniqueId() + " mGlobalDisplayStateSecondDisplay = " + mGlobalDisplayState);
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightnessSecondDisplay);
}
if (((device.getUniqueId().equals("local:0"))) || (device.getUniqueId().equals("local:3"))) {
Slog.i(TAG, "updateDisplayStateLocked UniqueId = " + device.getUniqueId() + " mGlobalDisplayState = " + mGlobalDisplayState);
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
}
}
return null;
}
首先根据DisplayDevice对象的getDisplayDeviceInfoLocked()方法获取了DisplayDeviceInfo对象,
然后根据DisplayDeviceInfo的flag进行决策,调用下一个方法并返回。DisplayDeviceInfo用于描述显示的物理设备特征,如尺寸、分别率等。
local:1
代表副屏,local:0
代表中控
DisplayDevice是一个抽象类,其方法的实现在LocalDisplayDevice类中,因此我们看requestDisplayStateLocked方法实现直接去LocalDisplayDevice类查找
具体方法实现如下
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
if (stateChanged || brightnessChanged) {
final int displayId = mBuiltInDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
if (stateChanged) {
mState = state;
updateDeviceInfoLocked();
}
if (brightnessChanged) {
mBrightness = brightness;
}
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
//返回该Runnable对象
return new Runnable() {
@Override
public void run() {
// Exit a suspended state before making any changes.
int currentState = oldState;
if (Display.isSuspendedState(oldState)
|| oldState == Display.STATE_UNKNOWN) {
if (!Display.isSuspendedState(state)) {
setDisplayState(state);
currentState = state;
} else if (state == Display.STATE_DOZE_SUSPEND
|| oldState == Display.STATE_DOZE_SUSPEND) {
setDisplayState(Display.STATE_DOZE);
currentState = Display.STATE_DOZE;
} else {
return; // old state and new state is off
}
}
// If the state change was from or to VR, then we need to tell the light
// so that it can apply appropriate VR brightness settings. Also, update the
// brightness so the state is propogated to light.
boolean vrModeChange = false;
if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
currentState != state) {
setVrMode(state == Display.STATE_VR);
vrModeChange = true;
}
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged || vrModeChange) {
setDisplayBrightness(brightness);
}
// Enter the final desired state, possibly suspended.
if (state != currentState) {
setDisplayState(state);
}
}
private void setDisplayState(int state) {
try {
final int mode = getPowerModeForState(state);
SurfaceControl.setDisplayPowerMode(token, mode);
Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
private void setDisplayBrightness(int brightness) {
try {
//设置中控屏幕的亮度
if (mBuiltInDisplayId == DEFAULT_DISPLAY)
mBacklight.setBrightness(brightness, true);
//设置副屏的亮度
if (mBuiltInDisplayId == SECOND_DISPLAY)
mBacklight.setBrightness(brightness, false);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness", brightness);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
};
}
return null;
}
最终交给LightService去处理亮度的调节。后面我就不做分析了。下面整理亮度调节的时序图