Android6.0 亮屏灭屏流程(DisplayPowerControler、WMS)(二)亮度设置

来源:互联网 发布:曹轩宾可惜不是你知乎 编辑:程序博客网 时间:2024/06/05 17:03

http://blog.csdn.net/kc58236582/article/details/54616756

上一篇博客我们主要分析了在setScreenState中调用PhoneWindowManager的一些流程,在setScreenState中先是调用了DisplayPowerState的setScreenState函数。上篇博客我们没有分析,这篇博客我们先从这个函数开始分析,主要分析下亮度的设置流程。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void setScreenState(int state) {  
  2.     if (mScreenState != state) {  
  3.         if (DEBUG) {  
  4.             Slog.d(TAG, "setScreenState: state=" + state);  
  5.         }  
  6.   
  7.         mScreenState = state;  
  8.         mScreenReady = false;  
  9.         scheduleScreenUpdate();  
  10.     }  
  11. }  



scheduleScreenUpdate主要通过消息方式,最后调用到下面函数。当我们屏幕刚要点亮,这个时候mScreenBrightness为0,所以这个时候调用mPhotonicModulator.setState设置state是点亮,但是brightness是0的。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private final Runnable mScreenUpdateRunnable = new Runnable() {  
  2.     @Override  
  3.     public void run() {  
  4.         mScreenUpdatePending = false;  
  5.   
  6.         int brightness = mScreenState != Display.STATE_OFF  
  7.                 && mColorFadeLevel > 0f ? mScreenBrightness : 0;  
  8.         if (mPhotonicModulator.setState(mScreenState, brightness)) {  
  9.             if (DEBUG) {  
  10.                 Slog.d(TAG, "Screen ready");  
  11.             }  
  12.             mScreenReady = true;  
  13.             invokeCleanListenerIfNeeded();  
  14.         } else {  
  15.             if (DEBUG) {  
  16.                 Slog.d(TAG, "Screen not ready");  
  17.             }  
  18.         }  
  19.     }  
  20. };  


DisplayPowerState的设置亮度状态逻辑分析

mPhotonicModulator.setState应该要PhotonicModulator的run函数结合一起看。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public boolean setState(int state, int backlight) {  
  2.     synchronized (mLock) {  
  3.         boolean stateChanged = state != mPendingState;  
  4.         boolean backlightChanged = backlight != mPendingBacklight;  
  5.         if (stateChanged || backlightChanged) {  
  6.             if (DEBUG) {  
  7.                 Slog.d(TAG, "Requesting new screen state: state="  
  8.                         + Display.stateToString(state) + ", backlight=" + backlight);  
  9.             }  
  10.   
  11.             mPendingState = state;  
  12.             mPendingBacklight = backlight;  
  13.   
  14.             boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;  
  15.             mStateChangeInProgress = stateChanged;  
  16.             mBacklightChangeInProgress = backlightChanged;  
  17.   
  18.             if (!changeInProgress) {  
  19.                 Slog.d(TAG,"notify set backlight thread run");  
  20.                 mLock.notifyAll();  
  21.             }  
  22.         }  
  23.         return !mStateChangeInProgress;  
  24.     }  
  25. }  

两者结合看先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设置到背光设备中去。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2. public void run() {  
  3.     for (;;) {  
  4.         // Get pending change.  
  5.         final int state;  
  6.         final boolean stateChanged;  
  7.         final int backlight;  
  8.         final boolean backlightChanged;  
  9.         synchronized (mLock) {  
  10.             state = mPendingState;  
  11.             stateChanged = (state != mActualState);  
  12.             backlight = mPendingBacklight;  
  13.             backlightChanged = (backlight != mActualBacklight);  
  14.             if (!stateChanged) {  
  15.                 // State changed applied, notify outer class.  
  16.                 postScreenUpdateThreadSafe();  
  17.                 mStateChangeInProgress = false;  
  18.             }  
  19.             if (!backlightChanged) {  
  20.                 mBacklightChangeInProgress = false;  
  21.             }  
  22.             if (!stateChanged && !backlightChanged) {  
  23.                 try {  
  24.                     mLock.wait();  
  25.                 } catch (InterruptedException ex) { }  
  26.                 continue;  
  27.             }  
  28.             mActualState = state;  
  29.             mActualBacklight = backlight;  
  30.         }  
  31.   
  32.         // Apply pending change.  
  33.         if (true) {  
  34.             Slog.d(TAG, "Updating screen state: state="  
  35.                     + Display.stateToString(state) + ", backlight=" + backlight);  
  36.         }  
  37.         mBlanker.requestDisplayState(state, backlight);  
  38.         Slog.d(TAG, "kangchen Updating screen state: state=");  
  39.     }  
  40. }  


设置亮度、状态到背光设备

DisplayBlanker的requestDisplayState如下,主要调用requestGlobalDisplayStateInternal函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. DisplayBlanker blanker = new DisplayBlanker() {  
  2.     @Override  
  3.     public void requestDisplayState(int state, int brightness) {  
  4.         // The order of operations is important for legacy reasons.  
  5.         if (state == Display.STATE_OFF) {  
  6.             requestGlobalDisplayStateInternal(state, brightness);  
  7.         }  
  8.   
  9.         callbacks.onDisplayStateChange(state);  
  10.   
  11.         if (state != Display.STATE_OFF) {  
  12.             requestGlobalDisplayStateInternal(state, brightness);  
  13.         }  
  14.     }  
  15. };  

requestGlobalDisplayStateInternal函数先是对state和brightness的处理,然后把这个两个变量放在mGlobalDisplayState 和mGlobalDisplayBrightness成员变量中。紧接着调用applyGlobalDisplayStateLocked函数mTempDisplayStateWorkQueue作为参数。最后再调用mTempDisplayStateWorkQueue各个成员的run函数(这里返回的是Runnable接口,这里就会设置状态和亮度到设备中去)。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void requestGlobalDisplayStateInternal(int state, int brightness) {  
  2.     if (state == Display.STATE_UNKNOWN) {  
  3.         state = Display.STATE_ON;  
  4.     }  
  5.     if (state == Display.STATE_OFF) {  
  6.         brightness = PowerManager.BRIGHTNESS_OFF;  
  7.     } else if (brightness < 0) {  
  8.         brightness = PowerManager.BRIGHTNESS_DEFAULT;  
  9.     } else if (brightness > PowerManager.BRIGHTNESS_ON) {  
  10.         brightness = PowerManager.BRIGHTNESS_ON;  
  11.     }  
  12.   
  13.     synchronized (mTempDisplayStateWorkQueue) {  
  14.         try {  
  15.             synchronized (mSyncRoot) {  
  16.                 if (mGlobalDisplayState == state  
  17.                         && mGlobalDisplayBrightness == brightness) {  
  18.                     return// no change  
  19.                 }  
  20.   
  21.                 mGlobalDisplayState = state;  
  22.                 mGlobalDisplayBrightness = brightness;  
  23.                 applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);  
  24.             }  
  25.   
  26.             // Setting the display power state can take hundreds of milliseconds  
  27.             // to complete so we defer the most expensive part of the work until  
  28.             // after we have exited the critical section to avoid blocking other  
  29.             // threads for a long time.  
  30.             for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {  
  31.                 mTempDisplayStateWorkQueue.get(i).run();//设置亮度、状态到设备  
  32.             }  
  33.         } finally {  
  34.             mTempDisplayStateWorkQueue.clear();  
  35.         }  
  36.     }  
  37. }  

applyGlobalDisplayStateLocked函数会遍历各个显示设备(多显示),然后调用updateDisplayStateLocked函数返回一个Runnable,最后把这个Runnable放入之前传入的mTempDisplayStateWorkQueue队列中。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {  
  2.     final int count = mDisplayDevices.size();  
  3.     for (int i = 0; i < count; i++) {  
  4.         DisplayDevice device = mDisplayDevices.get(i);  
  5.         Runnable runnable = updateDisplayStateLocked(device);  
  6.         if (runnable != null) {  
  7.             workQueue.add(runnable);  
  8.         }  
  9.     }  
  10. }  

那下面我们看下updateDisplayStateLocked函数,主要是调用了DisplayDevice的requestDisplayStateLocked函数,当然mGlobalDisplayState和mGlobalDisplayBrightness作为参数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private Runnable updateDisplayStateLocked(DisplayDevice device) {  
  2.     // Blank or unblank the display immediately to match the state requested  
  3.     // by the display power controller (if known).  
  4.     DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();  
  5.     if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {  
  6.         return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);  
  7.     }  
  8.     return null;  
  9. }  

这里的DisplayDevice的requestDisplayStateLocked函数,是在LocalDisplayAdapter中实现的,这里吧state和brightness保存在mState和mBrightness中,然后返回Runnable接口,最后在Runnable接口中设置亮度和状态。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public Runnable requestDisplayStateLocked(final int state, final int brightness) {  
  2.     // Assume that the brightness is off if the display is being turned off.  
  3.     assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;  
  4.   
  5.     final boolean stateChanged = (mState != state);  
  6.     final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;  
  7.     if (stateChanged || brightnessChanged) {  
  8.         final int displayId = mBuiltInDisplayId;  
  9.         final IBinder token = getDisplayTokenLocked();  
  10.         final int oldState = mState;  
  11.   
  12.         if (stateChanged) {  
  13.             mState = state;//保存state  
  14.             updateDeviceInfoLocked();  
  15.         }  
  16.   
  17.         if (brightnessChanged) {  
  18.             mBrightness = brightness;//保存brightness  
  19.         }  
  20.   
  21.         // Defer actually setting the display state until after we have exited  
  22.         // the critical section since it can take hundreds of milliseconds  
  23.         // to complete.  
  24.         return new Runnable() {//返回Runnable  
  25.             @Override  
  26.             public void run() {  
  27.                 // Exit a suspended state before making any changes.  
  28.                 int currentState = oldState;  
  29.                 if (Display.isSuspendedState(oldState)  
  30.                         || oldState == Display.STATE_UNKNOWN) {  
  31.                     if (!Display.isSuspendedState(state)) {  
  32.                         setDisplayState(state);  
  33.                         currentState = state;  
  34.                     } else if (state == Display.STATE_DOZE_SUSPEND  
  35.                             || oldState == Display.STATE_DOZE_SUSPEND) {  
  36.                         setDisplayState(Display.STATE_DOZE);  
  37.                         currentState = Display.STATE_DOZE;  
  38.                     } else {  
  39.                         return// old state and new state is off  
  40.                     }  
  41.                 }  
  42.   
  43.                 // Apply brightness changes given that we are in a non-suspended state.  
  44.                 if (brightnessChanged) {  
  45.                     Slog.d(TAG, "setDisplayBrightnessbrightness1=" + brightness);  
  46.                     setDisplayBrightness(brightness);  
  47.                     Slog.d(TAG, "setDisplayBrightnessbrightness2=" + brightness);  
  48.                 }  
  49.   
  50.                 // Enter the final desired state, possibly suspended.  
  51.                 if (state != currentState) {  
  52.                     setDisplayState(state);  
  53.                 }  
  54.             }  
  55.   
  56.             private void setDisplayState(int state) {  
  57.                 if (DEBUG) {  
  58.                     Slog.d(TAG, "setDisplayState("  
  59.                             + "id=" + displayId  
  60.                             + ", state=" + Display.stateToString(state) + ")");  
  61.                 }  
  62.                 try {  
  63.                     final int mode = getPowerModeForState(state);  
  64.                     SurfaceControl.setDisplayPowerMode(token, mode);//到SurfaceControl设置状态  
  65.                 } finally {  
  66.                     Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  67.                 }  
  68.             }  
  69.   
  70.             private void setDisplayBrightness(int brightness) {  
  71.                 try {  
  72.                     mBacklight.setBrightness(brightness);//设置亮度  
  73.                 } finally {  
  74.                     Trace.traceEnd(Trace.TRACE_TAG_POWER);  
  75.                 }  
  76.             }  
  77.         };  
  78.     }  
  79.     return null;  
  80. }  


DisplayPowerControl设置亮度逻辑(根据VSync信号将亮度慢慢变亮)

上面在DisplayPowerState中仅仅是设置状态,比如刚点亮屏幕这个时候其实设置的brightness为0,我们继续分析DisplayPowerState的updatePowerState函数。在updatePowerState函数中,当设置亮度时会调用如下代码:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. if (!mPendingScreenOff) {  
  2.     if (state == Display.STATE_ON || state == Display.STATE_DOZE) {  
  3.         animateScreenBrightness(brightness,  
  4.                 slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);  
  5.     } else {  
  6.         animateScreenBrightness(brightness, 0);  
  7.     }  
  8. }  

我们注意到这里有一个BRIGHTNESS_RAMP_RATE_SLOW 和BRIGHTNESS_RAMP_RATE_FAST(这里涉及到亮度显示原理我们后面分析),先看animateScreenBrightness函数。这里函数主要调用了mScreenBrightnessRampAnimator.animateTo函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void animateScreenBrightness(int target, int rate) {  
  2.     if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {  
  3.         try {  
  4.             mBatteryStats.noteScreenBrightness(target);  
  5.         } catch (RemoteException ex) {  
  6.             // same process  
  7.         }  
  8.     }  
  9. }  

我们再来看mScreenBrightnessRampAnimator 对象的创建

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(  
  2.         mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);  

我们注意一个参数是DisplayPowerState对象mPowerState,另一个参数是DisplayPowerState.SCREEN_BRIGHTNESS

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =  
  2.         new IntProperty<DisplayPowerState>("screenBrightness") {  
  3.     @Override  
  4.     public void setValue(DisplayPowerState object, int value) {  
  5.         object.setScreenBrightness(value);  
  6.     }  
  7.   
  8.     @Override  
  9.     public Integer get(DisplayPowerState object) {  
  10.         return object.getScreenBrightness();  
  11.     }  
  12. };  

RampAnimator的构造函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public RampAnimator(T object, IntProperty<T> property) {  
  2.     mObject = object;  
  3.     mProperty = property;  
  4.     mChoreographer = Choreographer.getInstance();  
  5. }  

我们结合RampAnimator的构造函数,再来分析RampAnimator的animateTo函数。

1. 当rate<=0时,这个时候,我们直接调用mProperty.setValue。就是调用DisplayPowerState的setScreenBrightness函数。这个setScreenBrightness函数我们后面分析。

2. 当rate>0时,这个时候会调用postAnimationCallback函数(这个函数根据VSync信号过来,把亮度慢慢上升的一个过程),而且mAnimating置为true。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public boolean animateTo(int target, int rate) {  
  2.     // Immediately jump to the target the first time.  
  3.     if (mFirstTime || rate <= 0) {  
  4.         if (mFirstTime || target != mCurrentValue) {  
  5.             mFirstTime = false;  
  6.             mRate = 0;  
  7.             mTargetValue = target;  
  8.             mCurrentValue = target;  
  9.             mProperty.setValue(mObject, target);//设置值  
  10.             if (mAnimating) {  
  11.                 mAnimating = false;  
  12.                 cancelAnimationCallback();  
  13.             }  
  14.             if (mListener != null) {  
  15.                 mListener.onAnimationEnd();  
  16.             }  
  17.             return true;  
  18.         }  
  19.         return false;  
  20.     }  
  21.   
  22.     // Adjust the rate based on the closest target.  
  23.     // If a faster rate is specified, then use the new rate so that we converge  
  24.     // more rapidly based on the new request.  
  25.     // If a slower rate is specified, then use the new rate only if the current  
  26.     // value is somewhere in between the new and the old target meaning that  
  27.     // we will be ramping in a different direction to get there.  
  28.     // Otherwise, continue at the previous rate.  
  29.     if (!mAnimating  
  30.             || rate > mRate  
  31.             || (target <= mCurrentValue && mCurrentValue <= mTargetValue)  
  32.             || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {  
  33.         mRate = rate;  
  34.     }  
  35.   
  36.     final boolean changed = (mTargetValue != target);  
  37.     mTargetValue = target;  
  38.   
  39.     // Start animating.  
  40.     if (!mAnimating && target != mCurrentValue) {  
  41.         mAnimating = true;  
  42.         mAnimatedValue = mCurrentValue;  
  43.         mLastFrameTimeNanos = System.nanoTime();  
  44.         postAnimationCallback();  
  45.     }  
  46.   
  47.     return changed;  
  48. }  

下面我们先分析postAnimationCallback函数,这个和之前分析WMS的VSync信号类似,当VSync信号过来时,会调用mAnimationCallback函数。(可以看之前博客http://blog.csdn.net/kc58236582/article/details/53835998)

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void postAnimationCallback() {  
  2.     mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);  
  3. }  

那我们继续看mAnimationCallback 的run函数,这个函数当当前值和上一次值不一样,我们就调用DisplayPowerState的setScreenBrightness来设置亮度。而且当前值不是目标值,我们就继续调用postAnimationCallback函数,来设置VSync回调。最后当亮度变成目标值后,将mAnimating 置为false,代表亮度变化的动画结束了。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private final Runnable mAnimationCallback = new Runnable() {  
  2.     @Override // Choreographer callback  
  3.     public void run() {  
  4.         final long frameTimeNanos = mChoreographer.getFrameTimeNanos();  
  5.         final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)  
  6.                 * 0.000000001f;  
  7.         mLastFrameTimeNanos = frameTimeNanos;  
  8.   
  9.         final float scale = ValueAnimator.getDurationScale();  
  10.         if (scale == 0) {  
  11.             // Animation off.  
  12.             mAnimatedValue = mTargetValue;  
  13.         } else {  
  14.             final float amount = timeDelta * mRate / scale;  
  15.             if (mTargetValue > mCurrentValue) {  
  16.                 mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);  
  17.             } else {  
  18.                 mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);  
  19.             }  
  20.         }  
  21.         final int oldCurrentValue = mCurrentValue;  
  22.         mCurrentValue = Math.round(mAnimatedValue);  
  23.   
  24.         if (oldCurrentValue != mCurrentValue) {  
  25.             mProperty.setValue(mObject, mCurrentValue);//设置到DisplayPowerState的setScreenBrightness函数中  
  26.         }  
  27.   
  28.         if (mTargetValue != mCurrentValue) {//当前值还不是目标值,继续设置VSync回调  
  29.             postAnimationCallback();  
  30.         } else {  
  31.             mAnimating = false;//否则动画标志置为false  
  32.             if (mListener != null) {  
  33.                 mListener.onAnimationEnd();  
  34.             }  
  35.         }  
  36.     }  
  37. }  

最后我们再看下DisplayPowerState的SetScreenBrightness函数,将亮度设置到mScreenBrightness 中,当屏幕状态不为off时,调用scheduleScreenUpdate函数(所以肯定先要调用setScreenState来设置屏幕状态为on,这样才能设置屏幕亮度)。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void setScreenBrightness(int brightness) {  
  2.     if (mScreenBrightness != brightness) {  
  3.         mScreenBrightness = brightness;  
  4.         if (mScreenState != Display.STATE_OFF) {  
  5.             mScreenReady = false;  
  6.             scheduleScreenUpdate();  
  7.         }  
  8.     }  
  9. }  
scheduleScreenUpdate最后通过发消息会调用如下代码,这里状态已经是ON了,就会把刚刚设置的mScreenBrightness作为参数设置到mPhotonicModulator.setState中。流程和设置state一样了,只是一开始亮屏时,设置state时,亮度为0而已。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private final Runnable mScreenUpdateRunnable = new Runnable() {  
  2.     @Override  
  3.     public void run() {  
  4.         mScreenUpdatePending = false;  
  5.   
  6.         int brightness = mScreenState != Display.STATE_OFF  
  7.                 && mColorFadeLevel > 0f ? mScreenBrightness : 0;  
  8.         if (mPhotonicModulator.setState(mScreenState, brightness)) {  
  9.             if (DEBUG) {  
  10.                 Slog.d(TAG, "Screen ready");  
  11.             }  
  12.             mScreenReady = true;  
  13.             invokeCleanListenerIfNeeded();  
  14.         } else {  
  15.             if (DEBUG) {  
  16.                 Slog.d(TAG, "Screen not ready");  
  17.             }  
  18.         }  
  19.     }  
  20. };  






0 0