DisplayManagerInternal方法requestPowerState用于控制屏幕的亮灭,由PowerManagerService调用,整体流程如下:
概要的亮屏幕时序:
概要的灭屏时序:
代码如下
//frameworks/base/core/java/android/hardware/display/DisplayManagerInternal.java
public abstract class DisplayManagerInternal {
public abstract boolean requestPowerState(int groupId, DisplayPowerRequest request,
boolean waitForNegativeProximity);
}
DisplayManagerInternal是抽象类,requestPowerState是抽象方法,由DisplayManagerService的内部类LocalService实现:
//frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
final class LocalService extends DisplayManagerInternal {
public boolean requestPowerState(int groupId, DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
groupId);
if (displayGroup == null) {
return true;
}
final int size = displayGroup.getSizeLocked();
boolean ready = true;
for (int i = 0; i < size; i++) {
final int id = displayGroup.getIdLocked(i);
final DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked(
id).getPrimaryDisplayDeviceLocked();
final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(id);
ready &= displayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
}
return ready;
}
}
}
}
调用displayPowerController(DisplayPowerController)的requestPowerState方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
if (DEBUG) {
Slog.d(TAG, "requestPowerState: "
+ request + ", waitForNegativeProximity=" + waitForNegativeProximity);
}
synchronized (mLock) {
if (mStopped) {
return true;
}
boolean changed = false;
if (waitForNegativeProximity
&& !mPendingWaitForNegativeProximityLocked) {
mPendingWaitForNegativeProximityLocked = true;
changed = true;
}
//开机后第一次进入
if (mPendingRequestLocked == null) {
mPendingRequestLocked = new DisplayPowerRequest(request); //创建DisplayPowerRequest对象
changed = true;
} else if (!mPendingRequestLocked.equals(request)) { //如果该次请求和上次请求不同,说明有状态改变,需要更新Display
mPendingRequestLocked.copyFrom(request);
changed = true;
}
/**
* changed为true,说明有改变发生,这个改变交给Handler异步去处理,此时说
* 明显示没有准备好,mDisplayReadyLocked=false
* 直到改变处理成功,mDisplayReadyLocked将被置为true,
*/
if (changed) {
mDisplayReadyLocked = false;
if (!mPendingRequestChangedLocked) {
mPendingRequestChangedLocked = true;
sendUpdatePowerStateLocked();
}
}
return mDisplayReadyLocked;
}
}
}
调用DisplayPowerController的sendUpdatePowerStateLocked方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private void sendUpdatePowerStateLocked() {
if (!mStopped && !mPendingUpdatePowerStateLocked) {
mPendingUpdatePowerStateLocked = true;
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
mHandler.sendMessage(msg);
}
}
}
发送MSG_UPDATE_POWER_STATE消息,消息在中处理:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private final class DisplayControllerHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;
}
}
}
}
DisplayPowerController updatePowerState
调用DisplayPowerController的updatePowerState方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private void updatePowerState() {
// Update the power state request.
final boolean mustNotify; //当DisplayPowerController中更新屏幕状态成功后是否必须通知PMS
final int previousPolicy;
boolean mustInitialize = false;
int brightnessAdjustmentFlags = 0;
mBrightnessReasonTemp.set(null);
mTempBrightnessEvent.reset();
synchronized (mLock) {
if (mStopped) {
return;
}
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mustInitialize = true;
// Assume we're on and bright until told otherwise, since that's the state we turn
// on in.
previousPolicy = DisplayPowerRequest.POLICY_BRIGHT;
} else if (mPendingRequestChangedLocked) {
previousPolicy = mPowerRequest.policy;
//复制mPendingRequestLocked给mPowerRequset, 即将"将要请求的电源请求状态"赋给"当前电源的请求状态"
mPowerRequest.copyFrom(mPendingRequestLocked);
updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
} else {
previousPolicy = mPowerRequest.policy;
}
mustNotify = !mDisplayReadyLocked;
}
// Compute the basic display state using the policy.
// We might override this below based on other factors.
// Initialise brightness as invalid.
int state;
float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
boolean performScreenOffTransition = false;
//根据PMS中的请求参数决定屏幕状态和屏幕亮度值
switch (mPowerRequest.policy) {
case DisplayPowerRequest.POLICY_OFF: //灭屏
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
case DisplayPowerRequest.POLICY_DOZE: //Doze模式
if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
state = mPowerRequest.dozeScreenState;
} else {
state = Display.STATE_DOZE;
}
if (!mAllowAutoBrightnessWhileDozingConfig) {
brightnessState = mPowerRequest.dozeScreenBrightness;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
}
break;
case DisplayPowerRequest.POLICY_VR: //VR模式
state = Display.STATE_VR;
break;
case DisplayPowerRequest.POLICY_DIM: //DIM
case DisplayPowerRequest.POLICY_BRIGHT: //亮屏
default:
state = Display.STATE_ON;
break;
}
assert(state != Display.STATE_UNKNOWN);
// Apply the proximity sensor.
if (mProximitySensor != null) {
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
// At this point the policy says that the screen should be on, but we've been
// asked to listen to the prox sensor to adjust the display state, so lets make
// sure the sensor is on.
//设置Psensor可用
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& !mIgnoreProximityUntilChanged) {
// Prox sensor already reporting "near" so we should turn off the screen.
// Also checked that we aren't currently set to ignore the proximity sensor
// temporarily.
mScreenOffBecauseOfProximity = true; //该值表示由PSensor灭屏
sendOnProximityPositiveWithWakelock(); //通过DisplayPowerCallback回调PMS
}
} else if (mWaitingForNegativeProximity
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
// The policy says that we should have the screen on, but it's off due to the prox
// and we've been asked to wait until the screen is far from the user to turn it
// back on. Let keep the prox sensor on so we can tell when it's far again.
setProximitySensorEnabled(true);
} else {
// We haven't been asked to use the prox sensor and we're not waiting on the screen
// to turn back on...so lets shut down the prox sensor.
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false; //不满足以上条件,设置PSensor不可用
}
if (mScreenOffBecauseOfProximity
&& (mProximity != PROXIMITY_POSITIVE || mIgnoreProximityUntilChanged)) {
// The screen *was* off due to prox being near, but now it's "far" so lets turn
// the screen back on. Also turn it back on if we've been asked to ignore the
// prox sensor temporarily.
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
mIgnoreProximityUntilChanged = false;
}
if (!mLogicalDisplay.isEnabled()
|| mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
|| mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
//初始化亮灭屏动画、mPowerState等
initialize(state);
}
// 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();
if (state == Display.STATE_OFF) {
//如果屏幕状态为灭屏,设置亮度为0
brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
}
// Always use the VR brightness when in the VR state.
if (state == Display.STATE_VR) {
brightnessState = mScreenBrightnessForVr;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
}
if ((Float.isNaN(brightnessState))
&& isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
brightnessState = mPowerRequest.screenBrightnessOverride;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
mAppliedScreenBrightnessOverride = true;
} else {
mAppliedScreenBrightnessOverride = false;
}
final boolean autoBrightnessEnabledInDoze =
mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& Float.isNaN(brightnessState)
&& mAutomaticBrightnessController != null;
final boolean autoBrightnessDisabledDueToDisplayOff = mPowerRequest.useAutoBrightness
&& !(state == Display.STATE_ON || autoBrightnessEnabledInDoze);
final int autoBrightnessState = autoBrightnessEnabled
? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
: autoBrightnessDisabledDueToDisplayOff
? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
: AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;
final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
// Use the temporary screen brightness if there isn't an override, either from
// WindowManager or based on the display state.
if (isValidBrightnessValue(mTemporaryScreenBrightness)) {
brightnessState = mTemporaryScreenBrightness;
mAppliedTemporaryBrightness = true;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
} else {
mAppliedTemporaryBrightness = false;
}
final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
if (autoBrightnessAdjustmentChanged) {
mTemporaryAutoBrightnessAdjustment = Float.NaN;
}
// Use the autobrightness adjustment override if set.
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;
}
// Apply brightness boost.
// We do this here after deciding whether auto-brightness is enabled 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.
// mPowerRequest表示"当前的电源请求状态",初始值为null, 由mPengdingReqestLocked对象拷贝或实例化,因此只有系统开机后第一次会进入if中,之后不会进入
if (mPowerRequest.boostScreenBrightness
&& brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT) {
brightnessState = PowerManager.BRIGHTNESS_MAX;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
mAppliedBrightnessBoost = true;
} else {
mAppliedBrightnessBoost = false;
}
// If the brightness is already set then it's been overridden by something other than the
// user, or is a temporary adjustment.
boolean userInitiatedChange = (Float.isNaN(brightnessState))
&& (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
boolean hadUserBrightnessPoint = false;
// Configure auto-brightness.
if (mAutomaticBrightnessController != null) {
hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
mAutomaticBrightnessController.configure(autoBrightnessState,
mBrightnessConfiguration,
mLastUserSetScreenBrightness,
userSetBrightnessChanged, autoBrightnessAdjustment,
autoBrightnessAdjustmentChanged, mPowerRequest.policy);
}
if (mBrightnessTracker != null) {
mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
}
boolean updateScreenBrightnessSetting = false;
// Apply auto-brightness.
boolean slowChange = false;
if (Float.isNaN(brightnessState)) {
float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
if (autoBrightnessEnabled) { //如果自动调节亮度可用
//从AutomaticBrightnessController中获取自动调节亮度值
brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness(
mTempBrightnessEvent);
newAutoBrightnessAdjustment =
mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
}
if (isValidBrightnessValue(brightnessState)
|| brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
// Use current auto-brightness value and slowly adjust to changes.
brightnessState = clampScreenBrightness(brightnessState);
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
slowChange = true; // slowly adapt to auto-brightness
}
updateScreenBrightnessSetting = mCurrentScreenBrightnessSetting != brightnessState;
mAppliedAutoBrightness = true;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
} else {
mAppliedAutoBrightness = false;
}
if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
// If the autobrightness controller has decided to change the adjustment value
// used, make sure that's reflected in settings.
putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
} else {
// Adjustment values resulted in no change
brightnessAdjustmentFlags = 0;
}
} else {
// Any non-auto-brightness values such as override or temporary should still be subject
// to clamping so that they don't go beyond the current max as specified by HBM
// Controller.
brightnessState = clampScreenBrightness(brightnessState);
mAppliedAutoBrightness = false;
brightnessAdjustmentFlags = 0;
}
// Use default brightness when dozing unless overridden.
if ((Float.isNaN(brightnessState))
&& Display.isDozeState(state)) {
brightnessState = clampScreenBrightness(mScreenBrightnessDozeConfig);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
// Apply manual brightness.
if (Float.isNaN(brightnessState)) {
brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
if (brightnessState != mCurrentScreenBrightnessSetting) {
// The manually chosen screen brightness is outside of the currently allowed
// range (i.e., high-brightness-mode), make sure we tell the rest of the system
// by updating the setting.
updateScreenBrightnessSetting = true;
}
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
// Now that a desired brightness has been calculated, apply brightness throttling. The
// dimming and low power transformations that follow can only dim brightness further.
//
// We didn't do this earlier through brightness clamping because we need to know both
// unthrottled (unclamped/ideal) and throttled brightness levels for subsequent operations.
// Note throttling effectively changes the allowed brightness range, so, similarly to HBM,
// we broadcast this change through setting.
final float unthrottledBrightnessState = brightnessState;
if (mBrightnessThrottler.isThrottled()) {
mTempBrightnessEvent.thermalMax = mBrightnessThrottler.getBrightnessCap();
brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
if (!mAppliedThrottling) {
// Brightness throttling is needed, so do so quickly.
// Later, when throttling is removed, we let other mechanisms decide on speed.
slowChange = false;
}
mAppliedThrottling = true;
} else if (mAppliedThrottling) {
mAppliedThrottling = false;
}
if (updateScreenBrightnessSetting) {
// Tell the rest of the system about the new brightness in case we had to change it
// for things like auto-brightness or high-brightness-mode. Note that we do this
// before applying the low power or dim transformations so that the slider
// accurately represents the full possible range, even if they range changes what
// it means in absolute terms.
updateScreenBrightnessSetting(brightnessState);
}
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
brightnessState = Math.max(
Math.min(brightnessState - mScreenBrightnessMinimumDimAmount,
mScreenBrightnessDimConfig),
PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
}
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 (brightnessState > PowerManager.BRIGHTNESS_MIN) {
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
slowChange = false;
}
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
// The current brightness to use has been calculated at this point, and HbmController should
// be notified so that it can accurately calculate HDR or HBM levels. We specifically do it
// here instead of having HbmController listen to the brightness setting because certain
// brightness sources (such as an app override) are not saved to the setting, but should be
// reflected in HBM calculations.
mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
mBrightnessThrottler.getBrightnessMaxReason());
// 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.
boolean brightnessAdjusted = false;
if (!mPendingScreenOff) {
if (mSkipScreenOnBrightnessRamp) {
if (state == Display.STATE_ON) {
if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
mInitialAutoBrightness = brightnessState;
mSkipRampState = RAMP_STATE_SKIP_INITIAL;
} else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
&& mUseSoftwareAutoBrightnessConfig
&& !BrightnessSynchronizer.floatEquals(brightnessState,
mInitialAutoBrightness)) {
mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
} else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
} else {
mSkipRampState = RAMP_STATE_SKIP_NONE;
}
}
final boolean wasOrWillBeInVr =
(state == Display.STATE_VR || oldState == Display.STATE_VR);
final boolean initialRampSkip =
state == Display.STATE_ON && mSkipRampState != RAMP_STATE_SKIP_NONE;
// While dozing, sometimes the brightness is split into buckets. Rather than animating
// through the buckets, which is unlikely to be smooth in the first place, just jump
// right to the suggested brightness.
final boolean hasBrightnessBuckets =
Display.isDozeState(state) && mBrightnessBucketsInDozeConfig;
// If the color fade is totally covering the screen then we can change the backlight
// level without it being a noticeable jump since any actual content isn't yet visible.
final boolean isDisplayContentVisible =
mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
final boolean brightnessIsTemporary =
mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
// We only want to animate the brightness if it is between 0.0f and 1.0f.
// brightnessState can contain the values -1.0f and NaN, which we do not want to
// animate to. To avoid this, we check the value first.
// If the brightnessState is off (-1.0f) we still want to animate to the minimum
// brightness (0.0f) to accommodate for LED displays, which can appear bright to the
// user even when the display is all black. We also clamp here in case some
// transformations to the brightness have pushed it outside of the currently
// allowed range.
float animateValue = clampScreenBrightness(brightnessState);
// If there are any HDR layers on the screen, we have a special brightness value that we
// use instead. We still preserve the calculated brightness for Standard Dynamic Range
// (SDR) layers, but the main brightness value will be the one for HDR.
float sdrAnimateValue = animateValue;
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
&& ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
|| (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
// We want to scale HDR brightness level with the SDR level
animateValue = mHbmController.getHdrBrightnessValue();
}
final float currentBrightness = mPowerState.getScreenBrightness();
final float currentSdrBrightness = mPowerState.getSdrScreenBrightness();
if (isValidBrightnessValue(animateValue)
&& (animateValue != currentBrightness
|| sdrAnimateValue != currentSdrBrightness)) {
if (initialRampSkip || hasBrightnessBuckets
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
//设置亮度
animateScreenBrightness(animateValue, sdrAnimateValue,
SCREEN_ANIMATION_RATE_MINIMUM);
} else {
boolean isIncreasing = animateValue > currentBrightness;
final float rampSpeed;
if (isIncreasing && slowChange) {
rampSpeed = mBrightnessRampRateSlowIncrease;
} else if (isIncreasing && !slowChange) {
rampSpeed = mBrightnessRampRateFastIncrease;
} else if (!isIncreasing && slowChange) {
rampSpeed = mBrightnessRampRateSlowDecrease;
} else {
rampSpeed = mBrightnessRampRateFastDecrease;
}
//设置亮度
animateScreenBrightness(animateValue, sdrAnimateValue, rampSpeed);
}
}
// Report brightness to brightnesstracker:
// If brightness is not temporary (ie the slider has been released)
// AND if we are not in idle screen brightness mode.
if (!brightnessIsTemporary
&& (mAutomaticBrightnessController != null
&& !mAutomaticBrightnessController.isInIdleMode())) {
if (userInitiatedChange && (mAutomaticBrightnessController == null
|| !mAutomaticBrightnessController.hasValidAmbientLux())) {
// If we don't have a valid lux reading we can't report a valid
// slider event so notify as if the system changed the brightness.
userInitiatedChange = false;
}
notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
hadUserBrightnessPoint);
}
// We save the brightness info *after* the brightness setting has been changed and
// adjustments made so that the brightness info reflects the latest value.
brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
} else {
brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting());
}
if (brightnessAdjusted) {
postBrightnessChangeRunnable();
}
// Log any changes to what is currently driving the brightness setting.
if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
Slog.v(TAG, "Brightness [" + brightnessState + "] reason changing to: '"
+ mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
+ "', previous reason: '" + mBrightnessReason + "'.");
mBrightnessReason.set(mBrightnessReasonTemp);
} else if (mBrightnessReasonTemp.reason == BrightnessReason.REASON_MANUAL
&& userSetBrightnessChanged) {
Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment.");
}
// Log brightness events when a detail of significance has changed. Generally this is the
// brightness itself changing, but also includes data like HBM cap, thermal throttling
// brightness cap, RBC state, etc.
mTempBrightnessEvent.time = System.currentTimeMillis();
mTempBrightnessEvent.brightness = brightnessState;
mTempBrightnessEvent.reason.set(mBrightnessReason);
mTempBrightnessEvent.hbmMax = mHbmController.getCurrentBrightnessMax();
mTempBrightnessEvent.hbmMode = mHbmController.getHighBrightnessMode();
mTempBrightnessEvent.flags |= (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0);
// Temporary is what we use during slider interactions. We avoid logging those so that
// we don't spam logcat when the slider is being used.
boolean tempToTempTransition =
mTempBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY
&& mLastBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY;
if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
|| brightnessAdjustmentFlags != 0) {
mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
// Adjustment flags (and user-set flag) only get added after the equality checks since
// they are transient.
newEvent.adjustmentFlags = brightnessAdjustmentFlags;
newEvent.flags |= (userSetBrightnessChanged ? BrightnessEvent.FLAG_USER_SET : 0);
Slog.i(TAG, newEvent.toString(/* includeTime= */ false));
if (mBrightnessEventRingBuffer != null) {
mBrightnessEventRingBuffer.append(newEvent);
}
}
// Update display white-balance.
if (mDisplayWhiteBalanceController != null) {
if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
mDisplayWhiteBalanceController.setEnabled(true);
mDisplayWhiteBalanceController.updateDisplayColorTemperature();
} else {
mDisplayWhiteBalanceController.setEnabled(false);
}
}
// 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(mDisplayId); //通知WindowManager亮屏完成
}
// Grab a wake lock if we have unfinished business.
if (!finished && !mUnfinishedBusiness) {
if (DEBUG) {
Slog.d(TAG, "Unfinished business...");
}
mCallbacks.acquireSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness);
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!");
}
}
}
//在该方法中回调PMS方法
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(mSuspendBlockerIdUnfinishedBusiness);
}
// Record if dozing for future comparison.
mDozing = state != Display.STATE_ON;
if (previousPolicy != mPowerRequest.policy) {
logDisplayPolicyChanged(mPowerRequest.policy);
}
}
}
从方法源码来看,这个方法可以拆分为六部分:
第一部分:初始化相关变量;
第二部分:根据PMS请求时携带的DisplayPowerState.policy以及PSensor相关确定要请求的屏幕状态state的值;
第三部分:调用animateScreenStateChange()方法设置屏幕状态(灭屏时还会先设置brightness=0);
第四部分:计算亮度值,即调节亮度时的值;
从代码看,在计算亮度值时,影响亮度值的有:自动调节亮度的亮度值、Doze状态下的亮度值(配置文件中读取)、用户手动设置的亮度值、Dim状态下的亮度值、低电量模式下的亮度值,最终会根据当前的场景来选择亮度值。
第五部分:通过animateScreenBrightness()设置亮度值调节动画;
第六部分:当完成屏幕状态更新和亮度更新后、调用WindowManagerPolicy的screenTurnedOn或screenTurnedOff方法。
DisplayPowerController animateScreenStateChange
调用animateScreenStateChange()方法设置屏幕状态,屏幕亮度(仅仅设置灭屏亮度0)、执行灭屏动画,同时调用WindowManager中的接口进行window的绘制等:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
// If there is already an animation in progress, don't interfere with it.
//如果mColorFadeEnabled可用且有动画在执行还未结束,说明正在屏幕转换流程中
if (mColorFadeEnabled &&
(mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
if (target != Display.STATE_ON) {
//如果目标状态不是亮屏状态,直接返回
return;
}
// If display state changed to on, proceed and stop the color fade and turn screen on.
//将该变量值置为false,该变量用来表示是否打算灭屏
mPendingScreenOff = false;
}
if (mDisplayBlanksAfterDozeConfig
&& Display.isDozeState(mPowerState.getScreenState())
&& !Display.isDozeState(target)) {
// Skip the screen off animation and add a black surface to hide the
// contents of the screen.
mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
if (mColorFadeOffAnimator != null) {
mColorFadeOffAnimator.end();
}
// Some display hardware will blank itself on the transition between doze and non-doze
// but still on display states. In this case we want to report to policy that the
// display has turned off so it can prepare the appropriate power on animation, but we
// don't want to actually transition to the fully off state since that takes
// significantly longer to transition from.
setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/); // 设置屏幕状态
}
// If we were in the process of turning off the screen but didn't quite
// finish. Then finish up now to prevent a jarring transition back
// to screen on if we skipped blocking screen on as usual.
//设置显示状态为灭屏状态,mPendingScreenOff表示打算灭屏,在进行灭屏时会设置为true
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF); // 设置屏幕状态
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
}
// 目标状态为亮屏,则调用setScreenState()设置,并根据返回值确定是否继续下面的操作
if (target == Display.STATE_ON) {
// Want screen on. The contents of the screen may not yet
// be visible if the color fade has not been dismissed because
// its last frame of animation is solid black.
// 设置屏幕状态
if (!setScreenState(Display.STATE_ON)) {
return; // screen on blocked
}
// 亮屏动画
if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
// Perform screen on animation.
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 {
// Skip screen on animation.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
}
} else if (target == Display.STATE_VR) {
// Wait for brightness animation to complete beforehand when entering VR
// from screen on to prevent a perceptible jump because brightness may operate
// differently when the display is configured for dozing.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() == Display.STATE_ON) {
return;
}
// Set screen state.
// 设置屏幕状态
if (!setScreenState(Display.STATE_VR)) {
return; // screen on blocked
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE) {
// Want screen dozing.
// Wait for brightness animation to complete beforehand when entering doze
// from screen on to prevent a perceptible jump because brightness may operate
// differently when the display is configured for dozing.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() == Display.STATE_ON) {
return;
}
// Set screen state.
// 设置屏幕状态
if (!setScreenState(Display.STATE_DOZE)) {
return; // screen on blocked
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE_SUSPEND) {
// Want screen dozing and suspended.
// Wait for brightness animation to complete beforehand unless already
// suspended because we may not be able to change it after suspension.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
return;
}
// If not already suspending, temporarily set the state to doze until the
// screen on is unblocked, then suspend.
if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
if (!setScreenState(Display.STATE_DOZE)) { //设置屏幕状态
return; // screen on blocked
}
// 设置屏幕状态
setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else if (target == Display.STATE_ON_SUSPEND) {
// Want screen full-power and suspended.
// Wait for brightness animation to complete beforehand unless already
// suspended because we may not be able to change it after suspension.
if (mScreenBrightnessRampAnimator.isAnimating()
&& mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
return;
}
// If not already suspending, temporarily set the state to on until the
// screen on is unblocked, then suspend.
if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
if (!setScreenState(Display.STATE_ON)) { //设置屏幕状态
return;
}
setScreenState(Display.STATE_ON_SUSPEND); //设置屏幕状态
}
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
} else {
// Want screen off.
// Want screen off.将mPendingScreenOff置为ture
mPendingScreenOff = true;
if (!mColorFadeEnabled) {
//colorfadelevel和图像显示有关,正常显示时为1,灭屏后就为0了
mPowerState.setColorFadeLevel(0.0f);
}
// 如果进入该语句,说明此时灭屏完成
if (mPowerState.getColorFadeLevel() == 0.0f) {
// Turn the screen off.
// A black surface is already hiding the contents of the screen.
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) {
// Perform the screen off animation.
mColorFadeOffAnimator.start(); //开始执行灭屏动画,ObjectAnimator集成ValueAnimator,实际上是开始一个Value动画
} else {
// Skip the screen off animation and add a black surface to hide the
// contents of the screen.
mColorFadeOffAnimator.end(); //停止执行灭屏动画
}
}
}
}
DisplayPowerState setScreenState
根据亮屏和灭屏分别调用setScreenState(Display.STATE_ON)和setScreenState(Display.STATE_OFF)方法,这个方法会调用进入DisplayPoweState中,以及调用Window中的接口,来通知Window进行屏幕状态设置的一些工作,当WindowManager中处理完成后,又会回调DisplayPowerController中的方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private DisplayPowerState mPowerState;
private boolean setScreenState(int state) {
return setScreenState(state, false /*reportOnly*/);
}
private boolean setScreenState(int state, boolean reportOnly) {
final boolean isOff = (state == Display.STATE_OFF);
//如果当前屏幕状态和将要设置的状态不同,则进入
if (mPowerState.getScreenState() != state
|| mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
// If we are trying to turn screen off, give policy a chance to do something before we
// actually turn the screen off.
//灭屏且非PSensor灭屏
if (isOff && !mScreenOffBecauseOfProximity) {
if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON
|| mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
//设置报告的屏幕状态
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
//Window管理策略,在没有灭屏完成时,暂时阻塞屏幕灭屏
blockScreenOff();
//通知WindowManager开始灭屏
mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
//取消灭屏阻塞
unblockScreenOff();
} else if (mPendingScreenOffUnblocker != null) {
// Abort doing the state change until screen off is unblocked.
return false;
}
}
if (!reportOnly && mPowerState.getScreenState() != state) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
//将目标状态设置为屏幕状态,同时进入DisplayPowerState中的逻辑
mPowerState.setScreenState(state);
// Tell battery stats about the transition.
noteScreenState(state);
}
}
// Tell the window manager policy when the screen is turned off or on unless it's due
// to the proximity sensor. We temporarily block turning the screen on until the
// window manager is ready by leaving a black surface covering the screen.
// This surface is essentially the final state of the color fade animation and
// it is only removed once the window manager tells us that the activity has
// finished drawing underneath.
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF); //设置报告屏幕状态的值
unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff(mDisplayId); //通知WindowManager灭屏完成
} else if (!isOff
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
// We told policy already that screen was turning off, but now we changed our minds.
// Complete the full state transition on -> turningOff -> off.
unblockScreenOff();
mWindowManagerPolicy.screenTurnedOff(mDisplayId); //通知WindowManager灭屏完成
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
}
//如果不是灭屏&&屏幕报告值为灭屏(上次是灭屏),则这次为亮屏
if (!isOff
&& (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
|| mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn();
} else {
unblockScreenOn();
}
mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
}
// Return true if the screen isn't blocked.
return mPendingScreenOnUnblocker == null;
}
}
调用mPowerState(DisplayPowerState)的setScreenState方法,设置屏幕状态:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
public void setScreenState(int state) {
if (mScreenState != state) {
if (DEBUG) {
Slog.d(TAG, "setScreenState: state=" + state);
}
mScreenState = state;
mScreenReady = false;
scheduleScreenUpdate();
}
}
}
调用DisplayPowerState的scheduleScreenUpdate方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
}
调用DisplayPowerState的postScreenUpdateThreadSafe方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
}
调用DisplayPowerState的mScreenUpdateRunnable:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
private final PhotonicModulator mPhotonicModulator;
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
float brightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
float sdrBrightnessState = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f
? mSdrScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
if (mPhotonicModulator.setState(mScreenState, brightnessState, sdrBrightnessState)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
}
}
调用mPhotonicModulator(PhotonicModulator)的setState方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
private final class PhotonicModulator extends Thread {
public boolean setState(int state, float brightnessState, float sdrBrightnessState) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
boolean backlightChanged = brightnessState != mPendingBacklight
|| sdrBrightnessState != mPendingSdrBacklight;
if (stateChanged || backlightChanged) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
+ Display.stateToString(state) + ", backlight=" + brightnessState);
}
mPendingState = state;
mPendingBacklight = brightnessState;
mPendingSdrBacklight = sdrBrightnessState;
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged || mStateChangeInProgress;
mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
if (!changeInProgress) {
mLock.notifyAll(); //释放锁
}
}
return !mStateChangeInProgress;
}
}
}
}
调用mLock.notifyAll方法进行锁的释放,之后会运行PhotonicModulator的run方法中mLock.wait();后的代码:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerState.java
final class DisplayPowerState {
private final DisplayBlanker mBlanker;
private final class PhotonicModulator extends Thread {
public void run() {
for (;;) {
// Get pending change.
final int state;
final boolean stateChanged;
final float brightnessState;
final float sdrBrightnessState;
final boolean backlightChanged;
synchronized (mLock) {
state = mPendingState;
stateChanged = (state != mActualState);
brightnessState = mPendingBacklight;
sdrBrightnessState = mPendingSdrBacklight;
backlightChanged = brightnessState != mActualBacklight
|| sdrBrightnessState != mActualSdrBacklight;
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
boolean valid = state != Display.STATE_UNKNOWN && !Float.isNaN(brightnessState);
boolean changed = stateChanged || backlightChanged;
if (!valid || !changed) {
try {
mLock.wait();
} catch (InterruptedException ex) {
if (mStopped) {
return;
}
}
continue;
}
mActualState = state;
mActualBacklight = brightnessState;
mActualSdrBacklight = sdrBrightnessState;
}
// Apply pending change.
if (DEBUG) {
Slog.d(TAG, "Updating screen state: id=" + mDisplayId + ", state="
+ Display.stateToString(state) + ", backlight=" + brightnessState
+ ", sdrBacklight=" + sdrBrightnessState);
}
mBlanker.requestDisplayState(mDisplayId, state, brightnessState,
sdrBrightnessState);
}
}
}
}
调用mBlanker(DisplayBlanker)的requestDisplayState方法,DisplayBlanker是一个接口,再DisplayManagerService中实现:
//frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
// Synchronized to avoid race conditions when updating multiple display states.
@Override
public synchronized void requestDisplayState(int displayId, int state, float brightness,
float sdrBrightness) {
boolean allInactive = true;
boolean allOff = true;
final boolean stateChanged;
synchronized (mSyncRoot) {
final int index = mDisplayStates.indexOfKey(displayId);
if (index > -1) {
final int currentState = mDisplayStates.valueAt(index);
stateChanged = state != currentState;
if (stateChanged) {
final int size = mDisplayStates.size();
for (int i = 0; i < size; i++) {
final int displayState = i == index ? state : mDisplayStates.valueAt(i);
if (displayState != Display.STATE_OFF) {
allOff = false;
}
if (Display.isActiveState(displayState)) {
allInactive = false;
}
if (!allOff && !allInactive) {
break;
}
}
}
} else {
stateChanged = false;
}
}
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
}
if (stateChanged) {
mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff);
}
if (state != Display.STATE_OFF) {
requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
}
}
}
}
调用DisplayManagerService的requestDisplayStateInternal方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
private void requestDisplayStateInternal(int displayId, int state, float brightnessState,
float sdrBrightnessState) {
if (state == Display.STATE_UNKNOWN) {
state = Display.STATE_ON;
}
brightnessState = clampBrightness(state, brightnessState);
sdrBrightnessState = clampBrightness(state, sdrBrightnessState);
// 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.
final Runnable runnable;
final String traceMessage;
synchronized (mSyncRoot) {
final int index = mDisplayStates.indexOfKey(displayId);
final BrightnessPair brightnessPair =
index < 0 ? null : mDisplayBrightnesses.valueAt(index);
if (index < 0 || (mDisplayStates.valueAt(index) == state
&& brightnessPair.brightness == brightnessState
&& brightnessPair.sdrBrightness == sdrBrightnessState)) {
return; // Display no longer exists or no change.
}
traceMessage = "requestDisplayStateInternal("
+ displayId + ", "
+ Display.stateToString(state)
+ ", brightness=" + brightnessState
+ ", sdrBrightness=" + sdrBrightnessState + ")";
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);
mDisplayStates.setValueAt(index, state);
brightnessPair.brightness = brightnessState;
brightnessPair.sdrBrightness = sdrBrightnessState;
runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId)
.getPrimaryDisplayDeviceLocked());
}
// 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.
if (runnable != null) {
runnable.run();
}
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, traceMessage, displayId);
}
}
调用DisplayManagerService的updateDisplayStateLocked方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
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) {
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
if (display == null) {
return null;
}
final int displayId = display.getDisplayIdLocked();
final int state = mDisplayStates.get(displayId);
// Only send a request for display state if display state has already been initialized.
if (state != Display.STATE_UNKNOWN) {
final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
return device.requestDisplayStateLocked(state, brightnessPair.brightness,
brightnessPair.sdrBrightness);
}
}
return null;
}
}
调用device(DisplayDevice)的requestDisplayStateLocked方法,DisplayDevice是一个抽象类,在LocalDisplayAdapter的内部类LocalDisplayDevice实现:
//frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
final class LocalDisplayAdapter extends DisplayAdapter {
private final SurfaceControlProxy mSurfaceControlProxy;
private final class LocalDisplayDevice extends DisplayDevice {
private final BacklightAdapter mBacklightAdapter;
public Runnable requestDisplayStateLocked(final int state, final float brightnessState,
final float sdrBrightnessState) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF
|| brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT;
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = mBrightnessState != brightnessState
|| mSdrBrightnessState != sdrBrightnessState;
if (stateChanged || brightnessChanged) {
final long physicalDisplayId = mPhysicalDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
if (stateChanged) {
mState = state;
updateDeviceInfoLocked();
}
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
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 if (state == Display.STATE_ON_SUSPEND
|| oldState == Display.STATE_ON_SUSPEND) {
setDisplayState(Display.STATE_ON);
currentState = Display.STATE_ON;
// If UNKNOWN, we still want to set the initial display state,
// otherwise, return early.
} else if (oldState != Display.STATE_UNKNOWN) {
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(brightnessState, sdrBrightnessState);
mBrightnessState = brightnessState;
mSdrBrightnessState = sdrBrightnessState;
}
// Enter the final desired state, possibly suspended.
if (state != currentState) {
setDisplayState(state);
}
}
private void setVrMode(boolean isVrEnabled) {
if (DEBUG) {
Slog.d(TAG, "setVrMode("
+ "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
}
mBacklightAdapter.setVrMode(isVrEnabled);
}
private void setDisplayState(int state) {
if (DEBUG) {
Slog.d(TAG, "setDisplayState("
+ "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
}
// We must tell sidekick to stop controlling the display before we
// can change its power mode, so do that first.
if (mSidekickActive) {
Trace.traceBegin(Trace.TRACE_TAG_POWER,
"SidekickInternal#endDisplayControl");
try {
mSidekickInternal.endDisplayControl();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
mSidekickActive = false;
}
final int mode = getPowerModeForState(state);
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayState("
+ "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
try {
mSurfaceControlProxy.setDisplayPowerMode(token, mode);
Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
// If we're entering a suspended (but not OFF) power state and we
// have a sidekick available, tell it now that it can take control.
if (Display.isSuspendedState(state) && state != Display.STATE_OFF
&& mSidekickInternal != null && !mSidekickActive) {
Trace.traceBegin(Trace.TRACE_TAG_POWER,
"SidekickInternal#startDisplayControl");
try {
mSidekickActive = mSidekickInternal.startDisplayControl(state);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
private void setDisplayBrightness(float brightnessState,
float sdrBrightnessState) {
// brightnessState includes invalid, off and full range.
if (Float.isNaN(brightnessState) || Float.isNaN(sdrBrightnessState)) {
return;
}
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + physicalDisplayId
+ ", brightnessState=" + brightnessState
+ ", sdrBrightnessState=" + sdrBrightnessState + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + physicalDisplayId + ", brightnessState="
+ brightnessState + ", sdrBrightnessState=" + sdrBrightnessState
+ ")");
try {
final float backlight = brightnessToBacklight(brightnessState);
final float sdrBacklight = brightnessToBacklight(sdrBrightnessState);
final float nits = backlightToNits(backlight);
final float sdrNits = backlightToNits(sdrBacklight);
mBacklightAdapter.setBacklight(sdrBacklight, sdrNits, backlight, nits);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(brightnessState));
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"SdrScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(
sdrBrightnessState));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
private float brightnessToBacklight(float brightness) {
if (brightness == PowerManager.BRIGHTNESS_OFF_FLOAT) {
return PowerManager.BRIGHTNESS_OFF_FLOAT;
} else {
return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
}
}
private float backlightToNits(float backlight) {
return getDisplayDeviceConfig().getNitsFromBacklight(backlight);
}
};
}
return null;
}
}
}
上面方法主要处理如下:
1、调用setDisplayState方法,在方法中调用mSurfaceControlProxy(SurfaceControlProxy)的setDisplayPowerMode方法。
//frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
final class LocalDisplayAdapter extends DisplayAdapter {
static class SurfaceControlProxy {
public void setDisplayPowerMode(IBinder displayToken, int mode) {
SurfaceControl.setDisplayPowerMode(displayToken, mode);
}
}
}
调用SurfaceControl的setDisplayPowerMode方法:
待更新
2、调用setDisplayBrightness方法,在方法中调用mBacklightAdapter(BacklightAdapter)的setBacklight方法。
//frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
final class LocalDisplayAdapter extends DisplayAdapter {
static class BacklightAdapter {
private final LogicalLight mBacklight;
void setBacklight(float sdrBacklight, float sdrNits, float backlight, float nits) {
if (mUseSurfaceControlBrightness || mForceSurfaceControl) { //如果使用SurfaceControl的Brightness
if (BrightnessSynchronizer.floatEquals(
sdrBacklight, PowerManager.BRIGHTNESS_INVALID_FLOAT)) {
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
} else {
mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, sdrBacklight, sdrNits,
backlight, nits);
}
} else if (mBacklight != null) {
mBacklight.setBrightness(backlight);
}
}
}
}
上面方法判断是否使用SurfaceControl的Brightness,如果使用就调用mSurfaceControlProxy(SurfaceControlProxy)的setBrightness方法:
//frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
final class LocalDisplayAdapter extends DisplayAdapter {
static class SurfaceControlProxy {
public boolean setDisplayBrightness(IBinder displayToken, float brightness) {
return SurfaceControl.setDisplayBrightness(displayToken, brightness);
}
}
}
SurfaceControl setDisplayBrightness
调用SurfaceControl的setDisplayBrightness方法:
待更新
LightsService LightImpl setBrightness
如果不使用SurfaceControl的Brightness,就调用mBacklight(LogicalLight)的setBrightness方法,LogicalLight是一个抽象类,由LightsService的内部类LightImpl实现:
待更新
DisplayPowerController animateScreenBrightness
通过animateScreenBrightness()设置亮度值(背光值):
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private void animateScreenBrightness(float target, float sdrTarget, float rate) {
if (DEBUG) {
Slog.d(TAG, "Animating brightness: target=" + target + ", sdrTarget=" + sdrTarget
+ ", rate=" + rate);
}
if (mScreenBrightnessRampAnimator.animateTo(target, sdrTarget, rate)) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_brightness", String.valueOf(target));
noteScreenBrightness(target);
}
}
}
在这个方法中,只有调用了一个对象的animateTo()方法,并将其参数传给了animateTo(),其他什么也没有做。在这个方法中,第一个参数是updatePowerState()中获得的最终亮度值,第二个参数则和亮度设置时的动画效果有关系,如果设置为大于0的数,那么会在animateTo()方法中根据这个数逐渐地设置亮度,如果设置为小于等于0,那么则不会有动画效果,直接将亮度值一次性设置。
//frameworks/base/services/core/java/com/android/server/display/RampAnimator.java
class RampAnimator<T> {
public boolean animateTo(float targetLinear, float rate) {
// Convert the target from the linear into the HLG space.
final float target = BrightnessUtils.convertLinearToGamma(targetLinear);
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) {
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
setPropertyValue(target);
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
return true;
}
return false;
}
// Adjust the rate so that we do not exceed our maximum animation time.
if (target > mCurrentValue && mAnimationIncreaseMaxTimeSecs > 0.0f
&& ((target - mCurrentValue) / rate) > mAnimationIncreaseMaxTimeSecs) {
rate = (target - mCurrentValue) / mAnimationIncreaseMaxTimeSecs;
} else if (target < mCurrentValue && mAnimationDecreaseMaxTimeSecs > 0.0f
&& ((mCurrentValue - target) / rate) > mAnimationDecreaseMaxTimeSecs) {
rate = (mCurrentValue - target) / mAnimationDecreaseMaxTimeSecs;
}
// Adjust the rate based on the closest target.
// If a faster rate is specified, then use the new rate so that we converge
// more rapidly based on the new request.
// If a slower rate is specified, then use the new rate only if the current
// value is somewhere in between the new and the old target meaning that
// we will be ramping in a different direction to get there.
// Otherwise, continue at the previous rate.
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;
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
}
}
动画结束调用postAnimationCallback方法:
//frameworks/base/services/core/java/com/android/server/display/RampAnimator.java
class RampAnimator<T> {
private Listener mListener;
private void postAnimationCallback() {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}
private final Runnable mAnimationCallback = new Runnable() {
@Override // Choreographer callback
public void run() {
final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
* 0.000000001f;
mLastFrameTimeNanos = frameTimeNanos;
// Advance the animated value towards the target at the specified rate
// and clamp to the target. This gives us the new current value but
// we keep the animated value around to allow for fractional increments
// towards the target.
final float scale = ValueAnimator.getDurationScale();
if (scale == 0) {
// Animation off.
mAnimatedValue = mTargetValue;
} else {
final float amount = timeDelta * mRate / scale;
if (mTargetValue > mCurrentValue) {
mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
} else {
mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
}
}
final float oldCurrentValue = mCurrentValue;
mCurrentValue = mAnimatedValue;
if (oldCurrentValue != mCurrentValue) {
setPropertyValue(mCurrentValue);
}
if (mTargetValue != mCurrentValue) {
postAnimationCallback();
} else {
mAnimating = false;
if (mListener != null) {
mListener.onAnimationEnd();
}
}
}
}
public interface Listener {
void onAnimationEnd();
}
}
DisplayPowerController onAnimationEnd
调用RampAnimator.Listener的onAnimationEnd方法,在DisplayPowerController中实现:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
@Override
public void onAnimationEnd() {
sendUpdatePowerState();
Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
mHandler.sendMessage(msg);
}
};
}
发送MSG_BRIGHTNESS_RAMP_DONE消息,发送的消息在DisplayPowerController的内部类DisplayControllerHandler的handleMessage方法中处理:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BRIGHTNESS_RAMP_DONE:
if (mPowerState != null) {
final float brightness = mPowerState.getScreenBrightness();
reportStats(brightness);
}
break;
}
}
}
}
调用DisplayPowerController的reportStats方法:
//frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
DisplayWhiteBalanceController.Callbacks {
private void reportStats(float brightness) {
if (mLastStatsBrightness == brightness) {
return;
}
float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
synchronized(mCachedBrightnessInfo) {
if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
return;
}
hbmTransitionPoint = mCachedBrightnessInfo.hbmTransitionPoint.value;
}
final boolean aboveTransition = brightness > hbmTransitionPoint;
final boolean oldAboveTransition = mLastStatsBrightness > hbmTransitionPoint;
if (aboveTransition || oldAboveTransition) {
mLastStatsBrightness = brightness;
mHandler.removeMessages(MSG_STATSD_HBM_BRIGHTNESS);
if (aboveTransition != oldAboveTransition) {
// report immediately
logHbmBrightnessStats(brightness, mDisplayStatsId);
} else {
// delay for rate limiting
Message msg = mHandler.obtainMessage();
msg.what = MSG_STATSD_HBM_BRIGHTNESS;
msg.arg1 = Float.floatToIntBits(brightness);
msg.arg2 = mDisplayStatsId;
mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
}
}
}
}
PhoneWindowManager screenTurnedOn
调用WindowManagerPolicy的screenTurnedOn方法,WindowManagerPolicy是一个接口,PhoneWindowManager实现这个接口:
待更新