?Power状态更新
主要在PowerManagerService.java,根据系统状态更新下次update的时间,遍历wakelock状态更新显示状态等
一、函数updatePowerStateLocked
根据MDRTY中记录的脏位更新全局电源状态。这是执行电源状态转换的主要功能。我们将它们集中在这里,这样每当重要的事情发生变化时,我们就可以完全重新计算权力状态,并确保每次都以同样的方式进行。重点是在这里收集所有的转换逻辑。
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = mClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Lock profiles that became inactive/not kept awake.
updateProfilesLocked(now);
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 4: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
// Phase 6: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
(1)基本状态更新
a、函数updateIsPoweredLocked
有需要时更新电池状态 DIRTY_BATTERY_STATE
b、函数updateStayOnLocked
DIRTY_STAY_ON
c、函数updateScreenBrightnessBoostLocked
DIRTY_SCREEN_BRIGHTNESS_BOOST
(2)更新清醒状态
a、函数updateWakeLockSummaryLocked
更新mWakeLockSummary的值,以汇总所有活动唤醒锁的状态。请注意,当系统处于睡眠状态时,大多数唤醒锁都会被忽略。DIRTY_WAKE_LOCKS
b、函数updateUserActivitySummaryLocked
更新mUserActivitySummary的值,以总结用户请求的系统状态,例如屏幕是亮还是暗。 请注意,当系统处于睡眠状态时,用户活动将被忽略 DIRTY_USER_ACTIVITY
c、函数updateAttentiveStateLocked
d、函数updateWakefulnessLocked
该功能根据当前唤醒锁和用户活动状态决定设备是否应该开始做梦。如果清醒状态发生变化,它可能会修改MDRTY。如果唤醒状态发生变化,需要重新启动电源状态计算,则返回true
(3)锁定处于非活动状态/未保持清醒状态的配置文件。
函数updateProfilesLocked
检查配置文件超时并通知应锁定的配置文件
(4)更新显示电源状态。
函数updateDisplayPowerStateLocked
异步更新显示电源状态。更新完成后,mDisplayReady将设置为true。显示控制器会发布一条消息,告诉我们实际的显示电源状态何时已更新,所以我们回到这里再次检查并完成。此函数每次都会重新计算显示电源状态。 return True,如果显示就绪。
(5)更新梦想状态(取决于显示就绪信号)。
函数updateDreamLocked
确定是否向sandman发布消息以更新梦境状态。
(6)如果需要,发送通知。
函数finishWakefulnessChangeIfNeededLocked
(7)更新暂停阻止程序。
因为我们可能会在这里释放最后一个暂停阻止程序,所以我们需要确保先完成其他所有操作!
函数updateSuspendBlockerLocked
背光亮度调整
主要在DisplayPowerController.java中更新设备状态,在LightsService.java中为实际的操作
一、DisplayPowerController.java函数updatePowerState
获取从PowerManagerService传来的DisplayPowerRequest状态,实时更新背光状态,显示屏状态。
(1)使用策略计算基本显示状态。
主要包括使用POLICY决定显示状态和拨打电话时距离传感器影响显示状态
int state;
float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
boolean performScreenOffTransition = false;
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) {
brightnessState = mPowerRequest.dozeScreenBrightness;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
}
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.
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.
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;
sendOnProximityPositiveWithWakelock();
}
} 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;
}
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 (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();
if (state == Display.STATE_OFF) {
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);
}
(2)使用策略计算基本背光状态。
主要包括正常情况下的亮度、光传感器自动调节时的亮度、DIM下的亮度、低电量下的亮度等等
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 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.
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(autoBrightnessEnabled,
mBrightnessConfiguration,
mLastUserSetScreenBrightness,
userSetBrightnessChanged, autoBrightnessAdjustment,
autoBrightnessAdjustmentChanged, mPowerRequest.policy);
}
if (mBrightnessTracker != null) {
mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
}
// Apply auto-brightness.
boolean slowChange = false;
if (Float.isNaN(brightnessState)) {
float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
if (autoBrightnessEnabled) {
brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness();
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
}
// Tell the rest of the system about the new brightness. 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.
putScreenBrightnessSetting(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 {
mAppliedAutoBrightness = false;
brightnessAdjustmentFlags = 0;
}
// Use default brightness when dozing unless overridden.
if ((Float.isNaN(brightnessState))
&& Display.isDozeState(state)) {
brightnessState = mScreenBrightnessDozeConfig;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
// Apply manual brightness.
if (Float.isNaN(brightnessState)) {
brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
brightnessState = Math.max(Math.min(brightnessState
- SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
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 > mScreenBrightnessRangeMinimum) {
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
brightnessState = Math.max(lowPowerBrightnessFloat,
mScreenBrightnessRangeMinimum);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
slowChange = false;
}
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
(3)当屏幕打开或打瞌睡时,设置屏幕亮度的动画。
// 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 = 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.
float animateValue = brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT
? PowerManager.BRIGHTNESS_MIN : brightnessState;
if (isValidBrightnessValue(animateValue)) {
if (initialRampSkip || hasBrightnessBuckets
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(animateValue, SCREEN_ANIMATION_RATE_MINIMUM);
} else {
animateScreenBrightness(animateValue,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
}
}
if (!brightnessIsTemporary) {
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;
}
notifyBrightnessChanged(
BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessState),
userInitiatedChange, hadUserBrightnessPoint);
}
}
// 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);
}
二、操作背光亮度
(1)LightsService.java函数setBrightness
setBrightness会决定走一下那个流程:
方式1:system_server->SF->HWC HAL->设备节点->背光驱动 方式2:system_server->Light HAL->设备节点->背光驱动
@Override
public void setBrightness(float brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER);
}
@Override
public void setBrightness(float brightness, int brightnessMode) {
if (Float.isNaN(brightness)) {
Slog.w(TAG, "Brightness is not valid: " + brightness);
return;
}
synchronized (this) {
// LOW_PERSISTENCE cannot be manually set
if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mHwLight.id
+ ": brightness=" + brightness);
return;
}
// Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
// right now we just fall back to the old path through Lights brightessMode is
// anything but USER or the device shouldBeInLowPersistenceMode().
if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
&& mSurfaceControlMaximumBrightness == 255) {
// New system
// TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
// reason we enforce 255 right now is to stay consistent with the old path. In
// the future, the framework should be refactored so that brightness is a float
// between 0.0f and 1.0f, and the actual number of supported brightness levels
// is determined in the device-specific implementation.
if (DEBUG) {
Slog.d(TAG, "Using new setBrightness path!");
}
SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
} else {
// Old system
int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(
getContext(), brightness);
int color = brightnessInt & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color;
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
}
(2)SurfaceControl.setDisplayBrightness
此方法的流程为:system_server->SF->HWC HAL->设备节点->背光驱动
(3)函数setLightLocked
通过 android.hardware.light.ILights/default获取Light HAL,走流程:
方式2:system_server->Light HAL->设备节点->背光驱动
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (shouldBeInLowPersistenceMode()) {
brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
} else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
brightnessMode = mLastBrightnessMode;
}
if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
offMS != mOffMS || mBrightnessMode != brightnessMode) {
if (DEBUG) {
Slog.v(TAG, "setLight #" + mHwLight.id + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
}
mInitialized = true;
mLastColor = mColor;
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
mBrightnessMode = brightnessMode;
setLightUnchecked(color, mode, onMS, offMS, brightnessMode);
}
}
private void setLightUnchecked(int color, int mode, int onMS, int offMS,
int brightnessMode) {
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLightState(" + mHwLight.id + ", 0x"
+ Integer.toHexString(color) + ")");
try {
if (mVintfLights != null) {
HwLightState lightState = new HwLightState();
lightState.color = color;
lightState.flashMode = (byte) mode;
lightState.flashOnMs = onMS;
lightState.flashOffMs = offMS;
lightState.brightnessMode = (byte) brightnessMode;
mVintfLights.get().setLightState(mHwLight.id, lightState);
} else {
setLight_native(mHwLight.id, color, mode, onMS, offMS, brightnessMode);
}
} catch (RemoteException | UnsupportedOperationException ex) {
Slog.e(TAG, "Failed issuing setLightState", ex);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
|