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

上一篇博客我们主要分析了在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 (;;) {
                // 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, "setDisplayBrightnessbrightness1=" + brightness);
                            setDisplayBrightness(brightness);
                            Slog.d(TAG, "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;
        }

 

 

 

 

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) {
                // 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");
                }
            }
        }
    };

 

 

 

 

 

 

 

 

 


 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值