上一篇博客我们主要分析了在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");
- }
- }
- }
- };
DisplayPowerState的设置亮度状态逻辑分析
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 (;;) {
-
- 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) {
-
- postScreenUpdateThreadSafe();
- mStateChangeInProgress = false;
- }
- if (!backlightChanged) {
- mBacklightChangeInProgress = false;
- }
- if (!stateChanged && !backlightChanged) {
- try {
- mLock.wait();
- } catch (InterruptedException ex) { }
- continue;
- }
- mActualState = state;
- mActualBacklight = backlight;
- }
-
-
- 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) {
-
- 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;
- }
-
- mGlobalDisplayState = state;
- mGlobalDisplayBrightness = brightness;
- applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
- }
-
-
-
-
-
- for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
- mTempDisplayStateWorkQueue.get(i).run();
- }
- } finally {
- mTempDisplayStateWorkQueue.clear();
- }
- }
- }
applyGlobalDisplayStateLocked函数会遍历各个显示设备(多显示),然后调用updateDisplayStateLocked函数返回一个Runnable,最后把这个Runnable放入之前传入的mTempDisplayStateWorkQueue队列中。
- private void applyGlobalDisplayStateLocked(List 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) {
-
-
- 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) {
-
- 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;
- updateDeviceInfoLocked();
- }
-
- if (brightnessChanged) {
- mBrightness = brightness;
- }
-
-
-
-
- return new Runnable() {
- @Override
- public void run() {
-
- 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;
- }
- }
-
-
- if (brightnessChanged) {
- Slog.d(TAG, "setDisplayBrightnessbrightness1=" + brightness);
- setDisplayBrightness(brightness);
- Slog.d(TAG, "setDisplayBrightnessbrightness2=" + brightness);
- }
-
-
- 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);
- } 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;
- }
DisplayPowerControl设置亮度逻辑(根据VSync信号将亮度慢慢变亮)
上面在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) {
-
- }
- }
- }
我们再来看mScreenBrightnessRampAnimator 对象的创建
- mScreenBrightnessRampAnimator = new RampAnimator(
- mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
我们注意一个参数是DisplayPowerState对象mPowerState,另一个参数是DisplayPowerState.SCREEN_BRIGHTNESS
- public static final IntProperty SCREEN_BRIGHTNESS =
- new IntProperty("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 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) {
-
- 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;
- }
-
-
-
-
-
-
-
-
- if (!mAnimating
- || rate > mRate
- || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
- || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
- mRate = rate;
- }
-
- final boolean changed = (mTargetValue != target);
- mTargetValue = target;
-
-
- 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
- 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) {
-
- 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);
- }
-
- if (mTargetValue != mCurrentValue) {
- postAnimationCallback();
- } else {
- mAnimating = 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");
- }
- }
- }
- };