Android 7.1 亮度调节完整流程分析(二)
上一篇追踪到DisplayPowerController.updatePowerState,即下图中第8步的位置:
本篇就从updatePowerState继续分析。这个函数非常地长,我们主要追踪一下亮度值的传递:
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
if (mPendingRequestLocked == null) {
return; // wait until first actual power request
}
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);//1
mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
!= mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);//2
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
}
mustNotify = !mDisplayReadyLocked;
}
不论是mPowerRequest 为空还是mPendingRequestChangedLocked, 都是将mPendingRequestLocked传递给mPowerRequest。
接下来是一系列针对各种情况对brightness的处理,我们要分析的情况是:
// 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);
}
下面是设置亮度的地方:
// 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) {
boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
} else {
animateScreenBrightness(brightness, 0);
}
}
看一下animateScreenBrightness:
private void animateScreenBrightness(int target, int rate) {
if (DEBUG) {
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
}
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {//1
try {
mBatteryStats.noteScreenBrightness(target);
} catch (RemoteException ex) {
// same process
}
}
}
看一下标记1处的mScreenBrightnessRampAnimator是什么,在DisplayPowerController的initialize中:
private void initialize() {
...以上省略
mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
...以下省略
mScreenBrightnessRampAnimator 是一个RampAnimator类,object是mPowerState,property是DisplayPowerState.SCREEN_BRIGHTNESS,listener是mRampAnimatorListener。接着看一下RampAnimator.animateTo:
public boolean animateTo(int target, int rate) {
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) {//1
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false;
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
mProperty.setValue(mObject, target);//2
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd();
}
return true;
}
return false;
}
// 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) {//3
mAnimating = true;
mAnimatedValue = mCurrentValue;
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
标记1处是第一次设置亮度的情形,直接设置目标亮度,标记2处的mProperty就是上边提到的DisplayPowerState.SCREEN_BRIGHTNESS。标记3处是渐变的情形,看一下postAnimationCallback:
private void postAnimationCallback() {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}
mAnimationCallback定义如下:
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 int oldCurrentValue = mCurrentValue;
mCurrentValue = Math.round(mAnimatedValue);
if (oldCurrentValue != mCurrentValue) {
mProperty.setValue(mObject, mCurrentValue);//1
}
if (mTargetValue != mCurrentValue) {
postAnimationCallback();//2
} else {
mAnimating = false;
if (mListener != null) {
mListener.onAnimationEnd();//3
}
}
}
};
标记1处与animateTo首次设置亮度调用的方法一样,标记2处表明,只要当前亮度还没到达目标亮度,就不断postAnimationCallback,以达到渐变的效果。标记3处是当前亮度已达到目标亮度时,调用mListener的onAnimationEnd。前面在DisplayPowerController的initialize中已经分析过,mListener是mRampAnimatorListener:
private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
@Override
public void onAnimationEnd() {
sendUpdatePowerState();
}
};
onAnimationEnd就是sendUpdatePowerState。我们先不关心这里,重点看mProperty.setValue。
mProperty是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();
}
};
object前面也提到了是mPowerState,即DisplayPowerState,看一下它的setScreenBrightness:
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
mScreenBrightness = brightness;
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate();//1
}
}
}
将目标亮度值赋给了mScreenBrightness ,然后在标记1处调用了scheduleScreenUpdate:
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
postScreenUpdateThreadSafe();
}
}
继续看postScreenUpdateThreadSafe:
private void postScreenUpdateThreadSafe() {
mHandler.removeCallbacks(mScreenUpdateRunnable);
mHandler.post(mScreenUpdateRunnable);
}
private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0;
if (mPhotonicModulator.setState(mScreenState, brightness)) {//1
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
看一下标记1处的mPhotonicModulator是什么,在DisplayPowerState的构造函数中,并且在此处start了该线程:
mPhotonicModulator = new PhotonicModulator();
mPhotonicModulator.start();
PhotonicModulator是DisplayPowerState的私有类,看一下mScreenUpdateRunnable 调用的setState:
private final class PhotonicModulator extends Thread {
private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
private static final int INITIAL_BACKLIGHT = -1; // unknown
private final Object mLock = new Object();
private int mPendingState = INITIAL_SCREEN_STATE;
private int mPendingBacklight = INITIAL_BACKLIGHT;
private int mActualState = INITIAL_SCREEN_STATE;
private int mActualBacklight = INITIAL_BACKLIGHT;
private boolean mStateChangeInProgress;
private boolean mBacklightChangeInProgress;
public PhotonicModulator() {
super("PhotonicModulator");
}
public boolean setState(int state, int backlight) {
synchronized (mLock) {
boolean stateChanged = state != mPendingState;
boolean backlightChanged = backlight != mPendingBacklight;
if (stateChanged || backlightChanged) {
if (DEBUG) {
Slog.d(TAG, "Requesting new screen state: state="
+ Display.stateToString(state) + ", backlight=" + backlight);
}
mPendingState = state;
mPendingBacklight = backlight;//1
boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
mStateChangeInProgress = stateChanged;
mBacklightChangeInProgress = backlightChanged;//2
if (!changeInProgress) {
mLock.notifyAll();//3
}
}
return !mStateChangeInProgress;
}
}
...以下省略
在标记1处将亮度值赋给了mPendingBacklight ,在标记2处更新mBacklightChangeInProgress。在标记3处,唤醒其它线程,本线程执行完毕后释放mLock。可以看到下面的run里也是由mLock控制,并且前面已经说到DisplayPowerState的构造函数里已经启动了PhotonicModulator ,那么看一下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;
stateChanged = (state != mActualState);
backlight = mPendingBacklight;
backlightChanged = (backlight != mActualBacklight);
if (!stateChanged) {
// State changed applied, notify outer class.
postScreenUpdateThreadSafe();
mStateChangeInProgress = false;
}
if (!backlightChanged) {
mBacklightChangeInProgress = false;
}
if (!stateChanged && !backlightChanged) {//1
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);
}
mBlanker.requestDisplayState(state, backlight);//2
}
}
可以看到,这是一个死循环,是一直运行的。标记1处表明当状态和背光亮度都没有发生变化时,就休眠并释放锁,直到被唤醒。上面讲到setState的标记3处会唤醒此线程,并往下执行标记2。mBlanker是在DisplayPowerState的构造函数中被赋值,一路查找就会发现它最初是在DisplayManagerService.LocalService.initPowerManagement中被赋值的,在上一篇也有提到过。看一下这个blanker的requestDisplayState:
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.
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
callbacks.onDisplayStateChange(state);
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);//1
}
}
};
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker);
}
}
标记1处调用了requestGlobalDisplayStateInternal,至于requestGlobalDisplayStateInternal究竟如何,下篇再见,ヾ( ̄▽ ̄)ByeBye