上一篇博客我们主要分析了在setScreenState中调用PhoneWindowManager的一些流程,在setScreenState中先是调用了DisplayPowerState的setScreenState函数。上篇博客我们没有分析,这篇博客我们先从这个函数开始分析,主要分析下亮度的设置流程。
public void setScreenState(int state) { if (mScreenState != state) { if (DEBUG) { Slog.d(TAG, "setScreenState: state=" + state); } mScreenState = state; mScreenReady = false; scheduleScreenUpdate(); } }
scheduleScreenUpdate主要通过消息方式,最后调用到下面函数。当我们屏幕刚要点亮,这个时候mScreenBrightness为0,所以这个时候调用mPhotonicModulator.setState设置state是点亮,但是brightness是0的。
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)) { if (DEBUG) { Slog.d(TAG, "Screen ready"); } mScreenReady = true; invokeCleanListenerIfNeeded(); } else { if (DEBUG) { Slog.d(TAG, "Screen not ready"); } } } };
mPhotonicModulator.setState应该要PhotonicModulator的run函数结合一起看。
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; boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress; mStateChangeInProgress = stateChanged; mBacklightChangeInProgress = backlightChanged; if (!changeInProgress) { Slog.d(TAG,"notify set backlight thread run"); mLock.notifyAll(); } } return !mStateChangeInProgress; } }
两者结合看先setState设置了状态,只有状态改变时,我们才能重新设置状态(设置到mpendingState和mPendingBacklight)。而在run函数中,当设置的状态mPendingState、mPendingBacklight和mActualState、mActualBacklight(真正设置到背光的状态、亮度)不一样时,才会调用mBlanker.requestDisplayState设置亮度。否则状态没有改变,就会把mStateChangeInProgress 和mBacklightChangeInProgress 设置为false,然后线程就wait住。
而此时setState重新设置下来的话,这个时候把亮度和状态设置到mPendingState 和mPendingBacklight 。然后这时mStateChangeInProgress 和 mBacklightChangeInProgress都是false。这样就可以调用mLock的notifyAll函数重新唤醒线程,这样就把把前面setState设置下来的mPendingState和mPendingBacklight再通过mBlanker.requestDisplayState设置到背光设备中去。
@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) { try { mLock.wait(); } catch (InterruptedException ex) { } continue; } mActualState = state; mActualBacklight = backlight; } // Apply pending change. if (true) { Slog.d(TAG, "Updating screen state: state=" + Display.stateToString(state) + ", backlight=" + backlight); } mBlanker.requestDisplayState(state, backlight); Slog.d(TAG, "kangchen Updating screen state: state="); } }
DisplayBlanker的requestDisplayState如下,主要调用requestGlobalDisplayStateInternal函数。
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); } } };
requestGlobalDisplayStateInternal函数先是对state和brightness的处理,然后把这个两个变量放在mGlobalDisplayState 和mGlobalDisplayBrightness成员变量中。紧接着调用applyGlobalDisplayStateLocked函数mTempDisplayStateWorkQueue作为参数。最后再调用mTempDisplayStateWorkQueue各个成员的run函数(这里返回的是Runnable接口,这里就会设置状态和亮度到设备中去)。
private void requestGlobalDisplayStateInternal(int state, int brightness) { if (state == Display.STATE_UNKNOWN) { state = Display.STATE_ON; } if (state == Display.STATE_OFF) { brightness = PowerManager.BRIGHTNESS_OFF; } else if (brightness < 0) { brightness = PowerManager.BRIGHTNESS_DEFAULT; } else if (brightness > PowerManager.BRIGHTNESS_ON) { brightness = PowerManager.BRIGHTNESS_ON; } synchronized (mTempDisplayStateWorkQueue) { try { synchronized (mSyncRoot) { if (mGlobalDisplayState == state && mGlobalDisplayBrightness == brightness) { return; // no change } mGlobalDisplayState = state; mGlobalDisplayBrightness = brightness; applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); } // Setting the display power state can take hundreds of milliseconds // to complete so we defer the most expensive part of the work until // after we have exited the critical section to avoid blocking other // threads for a long time. for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) { mTempDisplayStateWorkQueue.get(i).run();//设置亮度、状态到设备 } } finally { mTempDisplayStateWorkQueue.clear(); } } }
applyGlobalDisplayStateLocked函数会遍历各个显示设备(多显示),然后调用updateDisplayStateLocked函数返回一个Runnable,最后把这个Runnable放入之前传入的mTempDisplayStateWorkQueue队列中。
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) { final int count = mDisplayDevices.size(); for (int i = 0; i < count; i++) { DisplayDevice device = mDisplayDevices.get(i); Runnable runnable = updateDisplayStateLocked(device); if (runnable != null) { workQueue.add(runnable); } } }
那下面我们看下updateDisplayStateLocked函数,主要是调用了DisplayDevice的requestDisplayStateLocked函数,当然mGlobalDisplayState和mGlobalDisplayBrightness作为参数。
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) { return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); } return null; }
这里的DisplayDevice的requestDisplayStateLocked函数,是在LocalDisplayAdapter中实现的,这里吧state和brightness保存在mState和mBrightness中,然后返回Runnable接口,最后在Runnable接口中设置亮度和状态。
public Runnable requestDisplayStateLocked(final int state, final int brightness) { // Assume that the brightness is off if the display is being turned off. assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF; final boolean stateChanged = (mState != state); final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null; if (stateChanged || brightnessChanged) { final int displayId = mBuiltInDisplayId; final IBinder token = getDisplayTokenLocked(); final int oldState = mState; if (stateChanged) { mState = state;//保存state updateDeviceInfoLocked(); } if (brightnessChanged) { mBrightness = brightness;//保存brightness } // 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() {//返回Runnable @Override public void run() { // Exit a suspended state before making any changes. int currentState = oldState; if (Display.isSuspendedState(oldState) || oldState == Display.STATE_UNKNOWN) { if (!Display.isSuspendedState(state)) { setDisplayState(state); currentState = state; } else if (state == Display.STATE_DOZE_SUSPEND || oldState == Display.STATE_DOZE_SUSPEND) { setDisplayState(Display.STATE_DOZE); currentState = Display.STATE_DOZE; } else { return; // old state and new state is off } } // Apply brightness changes given that we are in a non-suspended state. if (brightnessChanged) { Slog.d(TAG, "kangchen setDisplayBrightnessbrightness1=" + brightness); setDisplayBrightness(brightness); Slog.d(TAG, "kangchen setDisplayBrightnessbrightness2=" + brightness); } // Enter the final desired state, possibly suspended. if (state != currentState) { setDisplayState(state); } } private void setDisplayState(int state) { if (DEBUG) { Slog.d(TAG, "setDisplayState(" + "id=" + displayId + ", state=" + Display.stateToString(state) + ")"); } try { final int mode = getPowerModeForState(state); SurfaceControl.setDisplayPowerMode(token, mode);//到SurfaceControl设置状态 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } private void setDisplayBrightness(int brightness) { try { mBacklight.setBrightness(brightness);//设置亮度 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } }; } return null; }
上面在DisplayPowerState中仅仅是设置状态,比如刚点亮屏幕这个时候其实设置的brightness为0,我们继续分析DisplayPowerState的updatePowerState函数。在updatePowerState函数中,当设置亮度时会调用如下代码:
if (!mPendingScreenOff) { if (state == Display.STATE_ON || state == Display.STATE_DOZE) { animateScreenBrightness(brightness, slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); } else { animateScreenBrightness(brightness, 0); } }
我们注意到这里有一个BRIGHTNESS_RAMP_RATE_SLOW 和BRIGHTNESS_RAMP_RATE_FAST(这里涉及到亮度显示原理我们后面分析),先看animateScreenBrightness函数。这里函数主要调用了mScreenBrightnessRampAnimator.animateTo函数。
private void animateScreenBrightness(int target, int rate) { if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { try { mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { // same process } } }
我们再来看mScreenBrightnessRampAnimator 对象的创建
mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
我们注意一个参数是DisplayPowerState对象mPowerState,另一个参数是DisplayPowerState.SCREEN_BRIGHTNESS
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(); } };
RampAnimator的构造函数。
public RampAnimator(T object, IntProperty<T> property) { mObject = object; mProperty = property; mChoreographer = Choreographer.getInstance(); }
我们结合RampAnimator的构造函数,再来分析RampAnimator的animateTo函数。
1. 当rate<=0时,这个时候,我们直接调用mProperty.setValue。就是调用DisplayPowerState的setScreenBrightness函数。这个setScreenBrightness函数我们后面分析。
2. 当rate>0时,这个时候会调用postAnimationCallback函数(这个函数根据VSync信号过来,把亮度慢慢上升的一个过程),而且mAnimating置为true。
public boolean animateTo(int target, int rate) { // Immediately jump to the target the first time. if (mFirstTime || rate <= 0) { if (mFirstTime || target != mCurrentValue) { mFirstTime = false; mRate = 0; mTargetValue = target; mCurrentValue = target; mProperty.setValue(mObject, target);//设置值 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) { mAnimating = true; mAnimatedValue = mCurrentValue; mLastFrameTimeNanos = System.nanoTime(); postAnimationCallback(); } return changed; }
下面我们先分析postAnimationCallback函数,这个和之前分析WMS的VSync信号类似,当VSync信号过来时,会调用mAnimationCallback函数。(可以看之前博客http://blog.csdn.net/kc58236582/article/details/53835998)
private void postAnimationCallback() { mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null); }
那我们继续看mAnimationCallback 的run函数,这个函数当当前值和上一次值不一样,我们就调用DisplayPowerState的setScreenBrightness来设置亮度。而且当前值不是目标值,我们就继续调用postAnimationCallback函数,来设置VSync回调。最后当亮度变成目标值后,将mAnimating 置为false,代表亮度变化的动画结束了。
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; 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);//设置到DisplayPowerState的setScreenBrightness函数中 } if (mTargetValue != mCurrentValue) {//当前值还不是目标值,继续设置VSync回调 postAnimationCallback(); } else { mAnimating = false;//否则动画标志置为false if (mListener != null) { mListener.onAnimationEnd(); } } } }
最后我们再看下DisplayPowerState的SetScreenBrightness函数,将亮度设置到mScreenBrightness 中,当屏幕状态不为off时,调用scheduleScreenUpdate函数(所以肯定先要调用setScreenState来设置屏幕状态为on,这样才能设置屏幕亮度)。
public void setScreenBrightness(int brightness) { if (mScreenBrightness != brightness) { mScreenBrightness = brightness; if (mScreenState != Display.STATE_OFF) { mScreenReady = false; scheduleScreenUpdate(); } } }scheduleScreenUpdate最后通过发消息会调用如下代码,这里状态已经是ON了,就会把刚刚设置的mScreenBrightness作为参数设置到mPhotonicModulator.setState中。流程和设置state一样了,只是一开始亮屏时,设置state时,亮度为0而已。
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)) { if (DEBUG) { Slog.d(TAG, "Screen ready"); } mScreenReady = true; invokeCleanListenerIfNeeded(); } else { if (DEBUG) { Slog.d(TAG, "Screen not ready"); } } } };
Android6.0 亮屏灭屏流程(DisplayPowerControler、WMS)(二)亮度设置
原文:http://blog.csdn.net/kc58236582/article/details/54616756