Android7.0 PowerManagerService亮灭屏分析(三)

来源:互联网 发布:淘宝商家微淘怎么设置 编辑:程序博客网 时间:2024/05/22 14:15

在前面两部分已经对绘制windows与设置设备状态进行了详细讲解. 之后接着就该对亮度值进行设置, 实现亮屏动作了.

在DisplayPowerController中的animateScreenBrightness函数通过亮度渐变动画来将亮度设置到目标亮度.

    // Brightness animation ramp rate in brightness units per second.    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;     //亮度渐变动画较慢的速率, 每秒变化40个亮度单位         mBrightnessRampRateFast = resources.getInteger(                com.android.internal.R.integer.config_brightness_ramp_rate_fast);   //从配置文件中获取较快的亮度速率        // Animate the screen brightness when the screen is on or dozing.        // Skip the animation when the screen is off or suspended.        if (!mPendingScreenOff) {            if (state == Display.STATE_ON || state == Display.STATE_DOZE) {                animateScreenBrightness(brightness,      //当亮屏或doze状态时有亮度渐变动画                        slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);            } else {                animateScreenBrightness(brightness, 0);   //灭屏时没有亮度渐变动画,直接将亮度设置为0            }        }
在animateScreenBrightness函数中调用动画mScreenBrightnessRampAnimator对亮度值处理, 而mScreenBrightnessRampAnimator是在initialize()函数中进行初始化的, 在构造函数中将DisplayPowerState和DisplayPowerState.SCREEN_BRIGHTNESS传输过去.

  private void initialize() {      //....        mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(  //泛型为DisplayPowerState                mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);        mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);     //...}    private void animateScreenBrightness(int target, int rate) {        if (DEBUG) {            Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);        }        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {    //动画处理亮度值            try {                mBatteryStats.noteScreenBrightness(target);            } catch (RemoteException ex) {                // same process            }        }    }

在RampAnimator的构造函数中将DisplayPowerState赋值给mObject, DisplayPowerState.SCREEN_BRIGHTNESS赋值给mProperty, 并且创建mChoreographer实例.

    public RampAnimator(T object, IntProperty<T> property) {        mObject = object;        mProperty = property;        mChoreographer = Choreographer.getInstance();    }

下面重点讲解animateTo函数.

    public boolean animateTo(int target, int rate) {        // Immediately jump to the target the first time.        if (mFirstTime || rate <= 0) {   //当第一次调用animateTo, 或者rate小于等于0时直接设置目标亮度.            if (mFirstTime || target != mCurrentValue) {                mFirstTime = false;   //之后就不是第一次调用该函数                mRate = 0;              //设置mRate为0                mTargetValue = target;   //设置目标亮度为target                mCurrentValue = target;                mProperty.setValue(mObject, target);   //调用DisplayPowerState.SCREEN_BRIGHTNESS设置亮度值                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;    //重新设置mTargetValue        // Start animating.  开始动画        if (!mAnimating && target != mCurrentValue) {              mAnimating = true;            mAnimatedValue = mCurrentValue;            mLastFrameTimeNanos = System.nanoTime();            postAnimationCallback();        }        return changed;     }
在postAnimationCallback中调用Choreographer的postCallback函数处理, 调用完成后回调回mAnimationCallback的run函数

    private void postAnimationCallback() {        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);    }    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;  //记录最后一次的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;   //让scale为0时, 表示动画停止了, 将mAnimatedValue设置为目标亮度            } else {                final float amount = timeDelta * mRate / scale;  //计算每一次需要变化的亮度值                if (mTargetValue > mCurrentValue) {                    mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);  //亮屏,每次增加亮度amount,不超过目标亮度                } else {                    mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue); //暗屏, 每次减少amount个亮度, 不超过目标亮度                }            }            final int oldCurrentValue = mCurrentValue;            mCurrentValue = Math.round(mAnimatedValue);  //获取当前要达到的亮度值            if (oldCurrentValue != mCurrentValue) {                mProperty.setValue(mObject, mCurrentValue);  //调用DisplayPowerState.SCREEN_BRIGHTNESS设置亮度值            }            if (mTargetValue != mCurrentValue) {                postAnimationCallback();   //如果还没有达到目标亮度,就会继续调用postAnimationCallback循环设置亮度值            } else {                mAnimating = false;                if (mListener != null) {                    mListener.onAnimationEnd();  //否则,亮度动画结束                }            }        }    };
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);  //调用DisplayPowerState的setScreenBrightness函数,设置亮度值        }        @Override        public Integer get(DisplayPowerState object) {            return object.getScreenBrightness();        }    };    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();   //如果不是灭屏状态,更新屏幕状态            }        }    }
scheduleScreenUpdate函数最终通过Handler发送mScreenUpdateRunnable对象来更新亮度值. 从run函数中可以看出只有当mColorFadeLevel > 0f时才能给brightness设置亮度值, 所以说当windows没有绘制完成时就算mScreenBrightness有值不为0, 但是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");                }            }        }    };
之后的流程就与设置设置状态的流程相同了, 调用DisplayManagerService中DisplayBlanker的requestDisplayState函数.

                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);  //亮屏调用设置状态,亮度                        }                    }                };
    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;  //灭屏设置屏幕亮度为0        } else if (brightness < 0) {            brightness = PowerManager.BRIGHTNESS_DEFAULT;  //屏幕亮度小于0,设置为默认亮度        } else if (brightness > PowerManager.BRIGHTNESS_ON) {            brightness = PowerManager.BRIGHTNESS_ON;    //屏幕亮度大于255设置最大亮度值255        }        synchronized (mTempDisplayStateWorkQueue) {            try {                // Update the display state within the lock.                // Note that we do not need to schedule traversals here although it                // may happen as a side-effect of displays changing state.                synchronized (mSyncRoot) {                    if (mGlobalDisplayState == state                            && mGlobalDisplayBrightness == brightness) {                        return; // no change     亮度与状态都没有改变就return                    }                    Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("                            + Display.stateToString(state)                            + ", brightness=" + brightness + ")");                    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();  //运行mTempDisplayStateWorkQueue队列中的runnable                }                Trace.traceEnd(Trace.TRACE_TAG_POWER);            } finally {                mTempDisplayStateWorkQueue.clear();            }        }    }
在applyGlobalDisplayStateLocked函数中获取所有的devices, 调用对应设备的requestDisplayStateLocked函数更新请求状态. 启动devices为LocalDisplayAdapter, 就会调用到该类的requestDisplayStateLocked获得runnable.
    private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {        final int count = mDisplayDevices.size();        for (int i = 0; i < count; i++) {   //遍历devices            DisplayDevice device = mDisplayDevices.get(i);            Runnable runnable = updateDisplayStateLocked(device);  //获得devices中的runnable            if (runnable != null) {                workQueue.add(runnable);  //将runnable加入workQueue队列, 即mTempDisplayStateWorkQueue队列            }        }    }    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();  //获取devices信息        if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {            return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); //调用requestDisplayStateLocked函数        }        return null;    }

在requestDisplayStateLocked中主要的任务就是创建一个runnable返回到DisplayManagerService中,并且等待回调run函数.

        @Override        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;                    updateDeviceInfoLocked();                }                if (brightnessChanged) {                    mBrightness = brightness;  //设置mBrightness                }                // 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() {  //在DisplayManagerService中调用run函数                        // Exit a suspended state before making any changes.                          int currentState = oldState;                        if (Display.isSuspendedState(oldState)    //判断设置是否还是在suspend状态                                || 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) {                            if (isPowerDebug()) {                                Slog.d(TAG, "set display brightness=" + brightness);                            }                            setDisplayBrightness(brightness);    //设置屏幕亮度                        }                        // Enter the final desired state, possibly suspended.                        if (state != currentState) {                            if(isPowerDebug()) {                                Slog.d(TAG, "set display state=" + state);                            }                            setDisplayState(state);                        }                    }
                    private void setDisplayBrightness(int brightness) {                        if (DEBUG) {                            Slog.d(TAG, "setDisplayBrightness("                                    + "id=" + displayId + ", brightness=" + brightness + ")");                        }                        Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("                                + "id=" + displayId + ", brightness=" + brightness + ")");                        try {                            mBacklight.setBrightness(brightness);   //调用LightService设置亮度                        } finally {                            Trace.traceEnd(Trace.TRACE_TAG_POWER);                        }                    }                };            }            return null;        }
        @Override        public void setBrightness(int brightness) {            setBrightness(brightness, BRIGHTNESS_MODE_USER);   //亮度模式默认为BRIGHTNESS_MODE_USER        }        @Override        public void setBrightness(int brightness, int brightnessMode) {            synchronized (this) {                int color = brightness & 0x000000ff;                color = 0xff000000 | (color << 16) | (color << 8) | color;   //设置光颜色                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);            }        }        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {            if (!LightsUtilsFactory.getInstance().isBatteryOpenWhenNotificationCome(mId, color)){                if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||                        mBrightnessMode != brightnessMode)) {                    if (DEBUG || isDebugNotifyLight()) Slog.v(TAG, "setLight #" + mId + ": color=#"                            + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);                    mLastColor = mColor;                    mColor = color;                    mMode = mode;                    mOnMS = onMS;                    mOffMS = offMS;                    mLastBrightnessMode = mBrightnessMode;                    mBrightnessMode = brightnessMode;                    Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"                            + Integer.toHexString(color) + ")");                    try {                        setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);  //调用jni层设置亮度                    } finally {                        Trace.traceEnd(Trace.TRACE_TAG_POWER);                    }                }            }        }
通过JNI调用com_android_server_lights_LightsService.cpp的setLight_native函数
static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode){    Devices* devices = (Devices*)ptr;    light_state_t state;    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {        return ;    }    uint32_t version = devices->lights[light]->common.version;    memset(&state, 0, sizeof(light_state_t));    if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {        if (light != LIGHT_INDEX_BACKLIGHT) {            ALOGE("Cannot set low-persistence mode for non-backlight device.");            return;        }        if (version < LIGHTS_DEVICE_API_VERSION_2_0) {            // HAL impl has not been upgraded to support this.            return;        }    } else {        // Only set non-brightness settings when not in low-persistence mode        state.color = colorARGB;        state.flashMode = flashMode;        state.flashOnMS = onMS;        state.flashOffMS = offMS;    }    state.brightnessMode = brightnessMode;    {        ALOGD_IF_SLOW(50, "Excessive delay setting light");   //当设置亮度耗时大于50ms,就会输出该行log.        devices->lights[light]->set_light(devices->lights[light], &state);    }}
之后调用BSP向亮度节点写入亮度值. 从而点亮屏幕.


灭屏流程分析

灭屏总览


                   

在点击power键灭屏过程中,主要流程就是input对按键事件的传输,传送到上层处理。在PhoneWindowManager中判断是否为灭屏事件, 之后就是在power中进行对亮屏状态的处理,计算一系列的数值,并且与AMS,WMS等模块进行交互,最后调用底层LCD进行最终的设备状态与亮度的设置。灭屏流程与亮屏流程有很多共同流程,在这里只讲解灭屏的独特流程。
                            
当wakefulness状态发生改变,AMS收到通知。如果亮屏操作,AMS就会通过函数comeOutOfSleepIfNeedLocked调用到ActivityStackSupervisor中,将sleep超时消息移除,如果抓的有partial锁,就将其释放,最后将在栈顶的activity显示出来。
当亮屏时通过InputManagerService将当前屏幕状态传入JNI中进行记录,当再次发生power键事件可以方便确认该事件是需要亮屏还是灭屏。
灭屏时首先在Notifier中通过PhoneWindowManager来通知keyguard系统开始灭屏。
灭屏动画
在PowerManagerService中获得屏幕的请求状态为OFF,即设置state为Display.STATE_OFF,在这里将performScreenOffTransition为true。

            case DisplayPowerRequest.POLICY_OFF:                state = Display.STATE_OFF;                performScreenOffTransition = true;                break;
调用animateScreenStateChange进行处理屏幕状态。
        // Animate the screen state change unless already animating.        // The transition may be deferred, so after this point we will use the        // actual state instead of the desired one.        animateScreenStateChange(state, performScreenOffTransition);        state = mPowerState.getScreenState();
如果目标亮度不为STATE_ON,STATE_DOZE,STATE_DOZE_SUSPEND屏幕就要去睡眠了。
            // Want screen off.            mPendingScreenOff = true;            if (mPowerState.getColorFadeLevel() == 0.0f) {                // Turn the screen off.                // A black surface is already hiding the contents of the screen.                setScreenState(Display.STATE_OFF);                mPendingScreenOff = false;                mPowerState.dismissColorFadeResources();            } else if (performScreenOffTransition                    && mPowerState.prepareColorFade(mContext,                            mColorFadeFadesConfig ?                                    ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)                    && mPowerState.getScreenState() != Display.STATE_OFF) {                // Perform the screen off animation.                mColorFadeOffAnimator.start();            } else {                // Skip the screen off animation and add a black surface to hide the                // contents of the screen.                mColorFadeOffAnimator.end();            }
在这里就要判断ColorFadeLevel是不是0.0,由于亮屏时将ColorFadeLevel设置为1.0所以走else语句,如果performScreenOffTransition为true并且将ColorFade准备好了就开始灭屏动画将ColorFadeLevel从1.0渐变为0.0。但是前面知道将performScreenOffTransition设置为了false,所以就没有了灭屏动画,直接将ColorFadeLevel设置为0.0。之后就调用setScreenState设置状态。
发送灭屏广播
                              

power是通过WindowManagerPolicy与PhoneWindowManager进行交互,当屏幕在finishedGoingToSleep时需要通知window进行更新手势监听,更新方向监听,更新锁屏超时时间。之后发送灭屏广播通知关心灭屏事件的模块。

到此为止亮灭屏流程讲解完毕.

0 0
原创粉丝点击