失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android 8.1 DisplayPowerController(四) 自动调节亮度(1)——流程

Android 8.1 DisplayPowerController(四) 自动调节亮度(1)——流程

时间:2019-04-09 18:19:56

相关推荐

Android 8.1 DisplayPowerController(四) 自动调节亮度(1)——流程

和手动调节亮度相比,自动调节亮度则稍微复杂些。其中涉及到多个算法。这里先笼统地介绍其流程,对涉及到的算法在下一篇文章中进行学习。

从前面的分析得到,不管是哪种背光调节方式,其最终都会在DisplayPowerController的updatePowerState()方法中进行决策,得到最终的背光值,自动背光的亮度也不例外:

private void updatePowerState() {if (brightness < 0) {if (autoBrightnessEnabled) {//得到自动亮度背光值brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();}}if (brightness >= 0) {// Use current auto-brightness value and slowly adjust to changes.brightness = clampScreenBrightness(brightness);if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {slowChange = true; // slowly adapt to auto-brightness}mAppliedAutoBrightness = true;} else {mAppliedAutoBrightness = false;}} else {mAppliedAutoBrightness = false;}}

从上面逻辑可以看出,自动调节的亮度值是通过mAutomaticBrightnessControllergetAutomaticScreenBrightness()方法得到的,所以,现在开始学习一下mAutomaticBrightnessController是什么,以及mAutomaticBrightnessController中是如何得到自动亮度的。

1.AutoBrightnessController的初始化

AutoBrightnessController是自动调节亮度的控制器,在DisplayManagerService中初始化DisplayPowerController时,就获取了该控制器实例:

/*** Creates the display power controller.*/public DisplayPowerController(Context context,DisplayPowerCallbacks callbacks, Handler handler,SensorManager sensorManager, DisplayBlanker blanker) {mSensorManager = sensorManager;final Resources resources = context.getResources();int screenBrightnessRangeMinimum = Math.min(Math.min(screenBrightnessSettingMinimum, mScreenBrightnessDimConfig),mScreenBrightnessDarkConfig);mUseSoftwareAutoBrightnessConfig = resources.getBoolean(com.android.internal.R.bool.config_automatic_brightness_available);int lightSensorRate = resources.getInteger(com.android.internal.R.integer.config_autoBrightnessLightSensorRate);int initialLightSensorRate = resources.getInteger(com.android.internal.R.integer.config_autoBrightnessInitialLightSensorRate);if (initialLightSensorRate == -1) {initialLightSensorRate = lightSensorRate;} else if (initialLightSensorRate > lightSensorRate) {Slog.w(TAG, "Expected config_autoBrightnessInitialLightSensorRate ("+ initialLightSensorRate + ") to be less than or equal to "+ "config_autoBrightnessLightSensorRate (" + lightSensorRate + ").");}long brighteningLightDebounce = resources.getInteger(com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);long darkeningLightDebounce = resources.getInteger(com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);int ambientLightHorizon = resources.getInteger(com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);float autoBrightnessAdjustmentMaxGamma = resources.getFraction(com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,1, 1);int[] brightLevels = resources.getIntArray(com.android.internal.R.array.config_dynamicHysteresisBrightLevels);int[] darkLevels = resources.getIntArray(com.android.internal.R.array.config_dynamicHysteresisDarkLevels);int[] luxLevels = resources.getIntArray(com.android.internal.R.array.config_dynamicHysteresisLuxLevels);HysteresisLevels dynamicHysteresis = new HysteresisLevels(brightLevels, darkLevels, luxLevels);if (mUseSoftwareAutoBrightnessConfig) {int[] lux = resources.getIntArray(com.android.internal.R.array.config_autoBrightnessLevels);int[] screenBrightness = resources.getIntArray(com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);int lightSensorWarmUpTimeConfig = resources.getInteger(com.android.internal.R.integer.config_lightSensorWarmupTime);final float dozeScaleFactor = resources.getFraction(com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,1, 1);Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);if (screenAutoBrightnessSpline == null) {Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues ... disabled.");mUseSoftwareAutoBrightnessConfig = false;} else {int bottom = clampAbsoluteBrightness(screenBrightness[0]);if (mScreenBrightnessDarkConfig > bottom) {}if (bottom < screenBrightnessRangeMinimum) {screenBrightnessRangeMinimum = bottom;}//实例化AutomaticBrightnessControllermAutomaticBrightnessController = new AutomaticBrightnessController(this,handler.getLooper(), sensorManager, screenAutoBrightnessSpline,lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);}}}

在DisplayPowerController的构造方法中,实例化了AutomaticBrightnessController,从以上逻辑中看出,其构造方法参数多达16个,构造方法以及参数如下:

/*** @param callbacks AutomaticBrightnessController.Callbacks接口对象,DisplayPowerController实现了该接口* @param looper 来自PMS中的Handler的looper;* @param sensorManager SensorManager对象* @param autoBrightnessSpline 样条插值后的Spline对象* @param lightSensorWarmUpTime LightSensor预热时间* @param brightnessMin 可以设置的最小亮度值,Math.min(Math.min(Settings,dim),dark)* @param brightnessMax 可以设置的最大亮度值,255* @param dozeScaleFactor Doze下自动调节亮度的减少比例,100%表示不减少* @param lightSensorRate LightSensor事件速率* @param initialLightSensorRate 初始LightSensor事件速率,用于在进入sleep后,获得第一个光样例时,-1表示禁用该值* @param brighteningLightDebounceConfig 进入明亮环境时的去抖时间* @param darkeningLightDebounceConfig 进入黑暗环境时的去抖时间* @param resetAmbientLuxAfterWarmUpConfig 是否在预热之后将立即重新计算环境光水平估计,并立即调整屏幕亮度* @param ambientLightHorizon 采集光样本的时间范围周期* @param autoBrightnessAdjustmentMaxGamma 伽马最大调整范围* @param dynamicHysteresis 使用给定的等长数组创建的HysteresisLevels对象*/public AutomaticBrightnessController(Callbacks callbacks, Looper looper,SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,int brightnessMin, int brightnessMax, float dozeScaleFactor,int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,HysteresisLevels dynamicHysteresis) {mCallbacks = callbacks;mSensorManager = sensorManager;mScreenAutoBrightnessSpline = autoBrightnessSpline;mScreenBrightnessRangeMinimum = brightnessMin;mScreenBrightnessRangeMaximum = brightnessMax;mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;mDozeScaleFactor = dozeScaleFactor;mNormalLightSensorRate = lightSensorRate;mInitialLightSensorRate = initialLightSensorRate;mCurrentLightSensorRate = -1;mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;mAmbientLightHorizon = ambientLightHorizon;mWeightingIntercept = ambientLightHorizon;mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;mDynamicHysteresis = dynamicHysteresis;//创建AutomaticBrightnessHandler实例,使用来自PMS中的LoopermHandler = new AutomaticBrightnessHandler(looper);//AmbientLightRingBuffer是已存储光照Lux值和对应时间点的环形缓冲区,按时间排序//存储所有的时间戳、Lux值mAmbientLightRingBuffer =new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);//只存储初始采集光强时间范围的时间戳、Lux值(LSensor开启前10s的)mInitialHorizonAmbientLightRingBuffer =new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);//获取LightSensor实例if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);}}

以上就是AutomaticBrightnessController的初始化流程,其中一些参数含义已在代码中进行了注释。

在初始化完成后,接下来我们来看它的配置。

2.AutomaticBrightnessController的配置

自动背光控制器的配置也是在DisplayPowerController中完成的。回到DisplayPowerController中,对AutomaticBrightnessController有如下配置:

private void updatePowerState() {// Configure auto-brightness.boolean autoBrightnessEnabled = false;//如果mAutomaticBrightnessController 不为空if (mAutomaticBrightnessController != null) {//是否在doze下自动调节亮度可用final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);//是否自动调节亮度可用autoBrightnessEnabled = mPowerRequest.useAutoBrightness&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)&& brightness < 0;//是否自动调节亮度调整值发生变化final boolean userInitiatedChange = autoBrightnessAdjustmentChanged&& mPowerRequest.brightnessSetByUser;//配置AutomaticBrightnessControllermAutomaticBrightnessController.configure(autoBrightnessEnabled,mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,userInitiatedChange);}}

在这里可以看出,每当调用updatePowerState()方法,都会通过调用AutomaticBrightnessController的configure()方法进行相关值的配置。其中参数:

1.autoBrightnessEnabled:表示自动调节亮度是否开启,通过PMS中得到,而PMS中则通过字段Settings.System.SCREEN_BRIGHTNESS_MODE获取Settings数据库中的值;2.mPowerRequest.screenAutoBrightnessAdjustment:表示自动调节亮度的调整值,这个值是当Settings中打开自动调节亮度后,如果拖动亮度进度条调节亮度,将会改变该值,具体逻辑在BrightnessController中:

private void setBrightnessAdj(float adj) {try {mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);} catch (RemoteException ex) {}}

在分析手动调节亮度时也说过,如果自动调节亮度是打开的,那么拖动亮度条时,虽然可以改变亮度,其原理就是由于此值发生改变,从而使得AutomaticBrightnessController的得到的亮度值发生了改变。

3.userInitiatedChange:表示自动调节亮度的调整值是否发生过改变,简而言之,表示是否在自动调节亮度打开的情况下拖动亮度条。

现在进入configure()方法中,该方法如下:

/*** @param enable 自动亮度调节是否可用* @param adjustment 自动亮度调节调整值* @param dozing 屏幕是否处于Doze状态下* @param userInitiatedChange 自动亮度调节调整值是否发生变化*/public void configure(boolean enable, float adjustment, boolean dozing,boolean userInitiatedChange) {mDozing = dozing;//注册/解除注册LightSensor,即开启自动调节亮度且非Doze状态下才可用boolean changed = setLightSensorEnabled(enable && !dozing);//如果自动背光调整值发生变化if (enable && !dozing && userInitiatedChange) {prepareBrightnessAdjustmentSample();}//设置调整值changed |= setScreenAutoBrightnessAdjustment(adjustment);//changed为true则说明自动调节亮度状态发生改变或自动亮度调整值发生改变,则更新亮度if (changed) {updateAutoBrightness(false /*sendUpdate*/);}}

利用这个方法,将一步步地撬开AutomaticBrightnessController的大门。在configure()方法中,调用了四个方法,这些方法放在此处分析比较凌乱,因此在下面对configure()方法拆分一一进行分析。

2.1.注册LightSensor

注册LightSensor方法如下:

private boolean setLightSensorEnabled(boolean enable) {if (enable) {if (!mLightSensorEnabled) {//表示LightSensor可用mLightSensorEnabled = true;//LSensor开始时间mLightSensorEnableTime = SystemClock.uptimeMillis();//当前LSensor事件率mCurrentLightSensorRate = mInitialLightSensorRate;mSensorManager.registerListener(mLightSensorListener, mLightSensor,mCurrentLightSensorRate * 1000, mHandler);return true;}} else {if (mLightSensorEnabled) {//表示LightSensor不可用mLightSensorEnabled = false;//是否需要在点亮屏幕后立即调整亮度mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;//环形缓冲区中最近收集的光照样例的数量mRecentLightSamples = 0;//清除环形缓冲区mAmbientLightRingBuffer.clear();mInitialHorizonAmbientLightRingBuffer.clear();//当前LSensor事件速率置为-1mCurrentLightSensorRate = -1;//移除更新Lux值的handlermHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);mSensorManager.unregisterListener(mLightSensorListener);}}return false;}

在上述方法中,根据参数对LightSensor进行了注册和解除注册并返回true或false。

这个方法比较简单,其中有个成员变量需要注意——mAmbientLuxValid,它表示mAmbientLux变量是否持有一个有效参数,在解除L-Sensor时,mAmbientLuxValid的值由mResetAmbientLuxAfterWarmUpConfig值取反得到,后者在构造方法中初始化,如果为true,则表示在屏幕打开后,自动背光控制器将尝试根据当前传感器读数调整亮度;如果为false,控制器将收集更多数据,然后才决定是否更改亮度。默认情况下,mResetAmbientLuxAfterWarmUpConfig为true,因此在解除L-Sensor时,mAmbientLuxValid为false。

mAmbientLux表示当前的光照强度值(Lux值)。

2.2.prepareBrightnessAdjustmentSample()

在这个方法中,对旧值做一个记录,然后设置一个10s的Handler去打印log,这个方法也比较简单:

private void prepareBrightnessAdjustmentSample() {if (!mBrightnessAdjustmentSamplePending) {//一个标记值mBrightnessAdjustmentSamplePending = true;//将当前调节值标记为旧的自动调节值mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment;//将当前Lux值标记为旧的Lux值,其中如果mAmbientLuxValid为false(解除LSensor后),则标记为-1mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1;//计算的自动调节的亮度值mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness;//Gamma值mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma;} else {mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE);}//Handler中仅仅打印Event logmHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE,BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS);}

2.3.setScreenAutoBrightnessAdjustment()

在这个方法中,设置自动调节调节值,并根据调节值是否变化返回结果:

private boolean setScreenAutoBrightnessAdjustment(float adjustment) {if (adjustment != mScreenAutoBrightnessAdjustment) {//设置新的adjustment值mScreenAutoBrightnessAdjustment = adjustment;return true;}return false;}

其中当亮度条滑到最小时,亮度调节值为-1;当亮度条滑到最大时,亮度调节值为1;当亮度条滑到中间时,亮度调节值为0.

2.4.updateAutoBrightness()

configure()方法中,如果当adjust值发生变化,或者开启了L-Sensor,则将会调用updateAutoBrightness()方法,这个方法是更新自动亮度的方法,该方法如下:

private void updateAutoBrightness(boolean sendUpdate) {//只有当mResetAmbientLuxAfterWarmUpConfig配置为true,且解除L-Sensor时,mAmbientLuxValid为falseif (!mAmbientLuxValid) {return;}//根据当前的Lux值得到样条曲线中的valuefloat value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);float gamma = 1.0f;if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT&& mScreenAutoBrightnessAdjustment != 0.0f) {//得到adjGamma值final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma,Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));gamma *= adjGamma;}if (gamma != 1.0f) {//说明使用了adjGammafinal float in = value;//再次计算valuevalue = MathUtils.pow(value, gamma);}//新的亮度值=value * 255int newScreenAutoBrightness =clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));if (mScreenAutoBrightness != newScreenAutoBrightness) {//更新亮度值mScreenAutoBrightness = newScreenAutoBrightness;mLastScreenAutoBrightnessGamma = gamma;if (sendUpdate) {//configure()方法中调用时为false//回调至DisplayPowerController中mCallbacks.updateBrightness();}}}

在这个方法中,将计算出最终的亮度值,并根据传入的参数sendUpdate决定是否通过mCallbacks.updateBrightness()进入DisplayPowerController中设置亮度:

//DisplayPowerController.java@Overridepublic void updateBrightness() {sendUpdatePowerState();}

从这个方法中也可以看出,mScreenAutoBrightnessAdjustmentMaxGammamScreenAutoBrightnessAdjustment对自动调节亮度打开时拖动亮度条调节亮度有很大的影响,前者是一个配置值,后者则在拖动亮度条时设置。

同时,如果想在打开自动调节亮度的情况下使得拖动亮度条无效,则将USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT常亮设置为false即可。

然而需要注意的一点是,当从configure()方法中调用进入updateAutoBrightness()时,传入参数为false,也就是说,不会主动回调至DipplayPowerController的中去更新亮度。那么在自动调节打开的情况下,拖动亮度条,是如何成功设置亮度的呢?如果是此种情况,由于此处已经得到了新的亮度值mScreenAutoBrightness,所以DisplayPowerController中调用了如下方法:

public int getAutomaticScreenBrightness() {if (mDozing) {return (int) (mScreenAutoBrightness * mDozeScaleFactor);}return mScreenAutoBrightness;}

至此,关于自动亮度控制器的初始化和配置相关的流程就分析完毕。接下来来看看LSensor事件的触发以及触发后是如何处理LSensor事件并设置亮度的。

3.LSensor事件触发后的流程

configure()方法中,对L-Sensor进行了注册,因此当外界亮度改变时,将会回调L-Sensor监听事件:

private final SensorEventListener mLightSensorListener = new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent event) {if (mLightSensorEnabled) {final long time = SystemClock.uptimeMillis();//得到当前光照强度值final float lux = event.values[0];//处理LSensor事件handleLightSensorEvent(time, lux);}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// Not used.}};

3.1.handleLightSensorEvent()

当SensorEventListener中收到L-Sensor事件后,获取了当前环境的光强值(lux值),然后在handleLightSensorEvent()中做了下一步的处理:

private void handleLightSensorEvent(long time, float lux) {mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);//如果环形缓冲区中没有数据,说明此时还未收集光照样例if (mAmbientLightRingBuffer.size() == 0) {// switch to using the steady-state sample rate after grabbing the initial light sample// 重新注册L-Sensor,切换到正常速率,因为第一次注册L-Sensor时使用的是mInitialLightSensorRateadjustLightSensorRate(mNormalLightSensorRate);}//将时间和lux值添加到缓冲区applyLightSensorMeasurement(time, lux);//更新lux值updateAmbientLux(time);}

在以上方法中,mAmbientLightRingBuffer是一个记录光照强度值和对应时间的环形缓冲区,其大小为:配置的采集光照强度周期 × 额外比例 / LSensor事件速率。在控制器构造方法中,获取了它的实例:

mAmbientLightRingBuffer =new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);mInitialHorizonAmbientLightRingBuffer =new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);

如果该缓冲区中没有数据,说明还未开始收集,此时调整LSensor事件速率,因为在setLightSensorEnabled()中首次注册LSensor时,使用的速率为mInitialLightSensorRate。此值仅用于获取第一份光照样例,一般情况下,该值等于mNormalLightSensorRate。adjustLightSensorRate()方法如下:

3.2.adjustLightSensorRate()

private void adjustLightSensorRate(int lightSensorRate) {// if the light sensor rate changed, update the sensor listenerif (lightSensorRate != mCurrentLightSensorRate) {mCurrentLightSensorRate = lightSensorRate;mSensorManager.unregisterListener(mLightSensorListener);mSensorManager.registerListener(mLightSensorListener, mLightSensor,lightSensorRate * 1000, mHandler);}}

继续进行分析,接下来调用applyLightSensorMeasurement()方法:

3.3.applyLightSensorMeasurement()

private void applyLightSensorMeasurement(long time, float lux) {//LightSensor 可用(打开、可用)之后收集的光照样例的数量mRecentLightSamples++;//如果当前时间 <= LightSensor开始时间+光照样例采集周期(LSensor开启未超过10s)//也就是说,mInitialHorizonAmbientLightRingBuffer中存储了开启LSensor后10s的数据if (time <= mLightSensorEnableTime + mAmbientLightHorizon) {mInitialHorizonAmbientLightRingBuffer.push(time, lux);}//删除距离当前mAmbientLightHorizon(10s)秒的数据//LSensor500ms上报一次值,因此存储10s内可存储21组数据mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);//添加此次数据mAmbientLightRingBuffer.push(time, lux);// Remember this sample value.mLastObservedLux = lux;mLastObservedLuxTime = time;}

该方法中,对缓冲区中的数据做了处理,移除了指定界限前的数据,同事将新的time和lux值push到了环形缓冲区。

接下来,调用updateAmbientLux(time)方法更新lux值:

3.4.updateAmbientLux()

private void updateAmbientLux(long time) {//mAmbientLuxValid为false,说明mResetAmbientLuxAfterWarmUpConfig为ture,也就是说当LSensor 可用后,立即调整亮度//因此mResetAmbientLuxAfterWarmUpConfig的功能的实现就在这个if语句中if (!mAmbientLuxValid) {final long timeWhenSensorWarmedUp =mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;//如果当前时间小于LSensor预热时间,则LSensor not ready yet,此时通过Handler发送定时消息后重新调用if (time < timeWhenSensorWarmedUp) {mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,timeWhenSensorWarmedUp);return;}//开启LSensor后,根据2s内的LSensor数据,立即设置新的Lux值,AMBIENT_LIGHT_SHORT_HORIZON_MILLIS为2000setAmbientLux(calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS));mAmbientLuxValid = true;//更新亮度updateAutoBrightness(true);}//置于明亮/昏暗环境下时,多久开始调节亮度long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);//分别得到距离当前10s内的Lux值和2s内的Lux值float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS);float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS);//大于Brightening阀值或小于Darkening阀值,且到达调节时间时if (slowAmbientLux >= mBrighteningLuxThreshold &&fastAmbientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time|| slowAmbientLux <= mDarkeningLuxThreshold&& fastAmbientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {//将fastAmbientLux设置为全局Lux值setAmbientLux(fastAmbientLux);//开始更新亮度updateAutoBrightness(true);//重置明亮/昏暗环境下,下次调节亮度时间nextBrightenTransition = nextAmbientLightBrighteningTransition(time);nextDarkenTransition = nextAmbientLightDarkeningTransition(time);}//取最小值获得下次调节时间long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition);nextTransitionTime =nextTransitionTime > time ? nextTransitionTime : time + mNormalLightSensorRate;//发送定时消息,到达时间后继续调用updateAmbientLux()mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);}

在这个方法中,首先它对mAmbientLuxValid变量进行了判断,如果该值为false,则进入if语句中,计算一个新的lux值,并调用updateAutoBrightness(true)去主动更新亮度。而在前面说过,要使得mAmbientLuxValid为false,则mResetAmbientLuxAfterWarmUpConfig为true,该值在congfig.xml中配置:

<bool name="config_autoBrightnessResetAmbientLuxAfterWarmUp">true</bool>

它表示是否当开启LSensor后(打开自动调节亮度且亮屏),LSensor度过预热期后立即调整亮度,所以这个值代表的功能,就在这个if语句中实现的。

当第一次执行updateAmbientLux()后,mAmbientLuxValid将置为true,直到LSensor再次被解除注册。也就是说,这里的if语句只会在LSensor开启后第一次执行,且只执行一次。

这里对涉及到计算lux值的流程暂且略过,只需要知道通过setAmbientLux()将新计算得到的lux值进行了设置,该方法如下:

private void setAmbientLux(float lux) {//将lux赋值给表示当前lux的全局变量mAmbientLuxmAmbientLux = lux;//环境亮度阈值,用于使屏幕变亮或变暗的Lux临界值mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux);mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux);}

继续回到updateAmbientLux()方法中,if(!mAmbientLuxValid)代码块之后,计算了两个时间值nextBrightenTransitionnextDarkenTransition,它们分别表示置于明亮和昏暗环境下时、多久开始调节亮度,该值的计算和防抖动时间有关,相关方法如下:

private long nextAmbientLightBrighteningTransition(long time) {final int N = mAmbientLightRingBuffer.size();long earliestValidTime = time;//遍历缓冲区,当Lux值小于等于明亮Lux阀值时break,得到第一次小于Lux阀值的一次时间for (int i = N - 1; i >= 0; i--) {if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) {break;}earliestValidTime = mAmbientLightRingBuffer.getTime(i);}//最近一次时间+防抖动时间就是下一次调节亮度时间return earliestValidTime + mBrighteningLightDebounceConfig;}private long nextAmbientLightDarkeningTransition(long time) {final int N = mAmbientLightRingBuffer.size();long earliestValidTime = time;for (int i = N - 1; i >= 0; i--) {if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) {break;}earliestValidTime = mAmbientLightRingBuffer.getTime(i);}return earliestValidTime + mDarkeningLightDebounceConfig;}

在以上方法中可以看出,是根据第一次小于Lux阀值的时间+防抖时间得到调节亮度的时间,在方法的最后会利用这个时间值,通过Handler发送一个定时消息。

计算完毕下次调节亮度时间后,接下来计算了两个Lux值:slowAmbientLuxfastAmbientLux,这两个值分别是距离此次2s内和10s内的Lux值,根据注释可知,fastAmbientLux一般代表当前的Lux值,slowAmbientLux只是确保长时间内光照是否有所变化。当满足条件后,将开始调用updateAutoBrightness(true)更新自动亮度,并主动回调DisplayPowerController中开始更新背光。

updateAmbientLux()方法的最后,通过Handler发送一个定时消息,当时间到达后,执行逻辑如下:

private void updateAmbientLux() {long time = SystemClock.uptimeMillis();//从缓冲区中裁剪掉mAmbientLightHorizon(10)秒前的数据mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);//更新Lux值updateAmbientLux(time);}

关于此处的prune()方法,会在下一篇文章中,分析其算法时进行分析。

以上就是整个自动调节亮度的流程,至于算法,在下一篇文章中进行分析。

如果觉得《Android 8.1 DisplayPowerController(四) 自动调节亮度(1)——流程》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。