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

更新时间:2023-12-03 04:24:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

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

亮度设置

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

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 public void setScreenState(int state) { if (mScreenState != state) { if (DEBUG) {

Slog.d(TAG, \ }

mScreenState = state; mScreenReady = false; scheduleScreenUpdate(); } }

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

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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, \ }

mScreenReady = true;

invokeCleanListenerIfNeeded(); } else {

if (DEBUG) {

Slog.d(TAG, \ } } }

};

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

mPhotonicModulator.setState应该要PhotonicModulator的run函数结合一起看。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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, \

+ Display.stateToString(state) + \ }

mPendingState = state;

mPendingBacklight = backlight;

boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;

mStateChangeInProgress = stateChanged;

mBacklightChangeInProgress = backlightChanged;

if (!changeInProgress) {

Slog.d(TAG,\ 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设置到背光设备中去。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 @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, \

+ Display.stateToString(state) + \ }

mBlanker.requestDisplayState(state, backlight);

Slog.d(TAG, \ } }

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

DisplayBlanker的requestDisplayState如下,主要调用requestGlobalDisplayStateInternal函数。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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接口,这里就会设置状态和亮度到设备中去)。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

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队列中。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

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作为参数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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接口中设置亮度和状态。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

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, \ + \

+ \ } 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函数中,当设置亮度时会调用如下代码:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 private void animateScreenBrightness(int target, int rate) {

if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { try {

mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { // same process } } }

我们再来看mScreenBrightnessRampAnimator 对象的创建

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

mScreenBrightnessRampAnimator = new RampAnimator( mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);

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

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

public static final IntProperty SCREEN_BRIGHTNESS = new IntProperty(\ @Override

public void setValue(DisplayPowerState object, int value) { object.setScreenBrightness(value); }

@Override

public Integer get(DisplayPowerState object) { return object.getScreenBrightness(); } };

RampAnimator的构造函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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 nwww.sm136.comew 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函数。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 private void postAnimationCallback() {

mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null); }

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

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 private final Runnable mAnimationCallback = new Runnable() { @Override // Choreographer callback public void ruwww.tt951.comn() {

final long frameTimeNanos = mChoreographer.getFrameTimeNanos(); final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos) * 0.000000001f;

mLastFrameTimeNanos = frameTimeNanos;

final float scale = ValueAnimator.getDurationScale(); if (scale == 0) {

// Animanc630.comtion 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,这样才能设置屏幕亮度)。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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而已。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 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, \ }

mScreenReady = true;

invokeCleanListenerIfNeeded(); } else {

if (DEBUG) {

Slog.d(TAG, \ } } } };

本文来源:https://www.bwwdw.com/article/pr5t.html

Top