Android7.0背光调节

news/2024/9/23 2:16:58/

涉及类:

 

.简述

Android屏幕背光属于Android系统中display模块,display是从Power中分出来的,所以和Power有着密不可分的关系。背光调节中,又可以分为手动调节和自动调节两个功能,Android定义背光值0-255

日常调试过程中,我们可以直接cat/sys/class/leds/lcd-backlight/brightness的值,来获得当前屏幕背光的值。

.流程原理分析

自动背光手动背光中最核心的当属DisplayPowerControlAutomaticBrightnessController,两个类。其初始化流程如下:

2.1. SystemServer.startBootstrapServices

[->SystemServer.java]

acquireWakeLockInternal(IBinder, int,String, String, WorkSource, String, int, ...)

boostScreenBrightnessInternal(long, int)

goToSleepInternal(long, int, int, int)

handleBatteryStateChangedLocked()

handleSandman()

handleScreenBrightnessBoostTimeout()

handleSettingsChangedLocked()

handleUserActivityTimeout()

napInternal(long, int)

onBootPhase(int)

onReceive(Context, Intent)

removeWakeLockLocked(WakeLock, int)

setDozeOverrideFromDreamManagerInternal(int,int)

setMaximumScreenOffTimeoutFromDeviceAdminInternal(int)

setScreenBrightnessOverrideFromWindowManagerInternal(int)

setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float)

setTemporaryScreenBrightnessSettingOverrideInternal(int)

setUserActivityTimeoutOverrideFromWindowManagerInternal(long)

setUserInactiveOverrideFromWindowManagerInternal()

systemReady(IAppOpsService)

updatePowerStateLocked()

updateWakeLockDisabledStatesLocked()

userActivityInternal(long, int, int,int)

wakeUpInternal(long, String, int,String, int)

 

首先DisplayPowerControl的初始化在DisplayManagerService中,

   private final class LocalService extends DisplayManagerInternal {

       @Override

       public void initPowerManagement(final DisplayPowerCallbacks callbacks,Handler handler,

                SensorManager sensorManager) {

            synchronized (mSyncRoot) {

                DisplayBlanker blanker = newDisplayBlanker() {

                    @Override

                    public voidrequestDisplayState(int state, int brightness) {

                        // The order ofoperations is important for legacy reasons.

                        if (state ==Display.STATE_OFF) {

                           requestGlobalDisplayStateInternal(state, brightness);

                        }

 

                       callbacks.onDisplayStateChange(state);

 

                        if (state !=Display.STATE_OFF) {

                           requestGlobalDisplayStateInternal(state, brightness);

                        }

                    }

               };

                mDisplayPowerController = new DisplayPowerController(

                       mContext, callbacks, handler, sensorManager, blanker);

            }

       }

DisplayManagerInternal的本地服务实现,LocalService,当PowerManagerService调用SystemReady的时候,同时也调用了DisplayManagerInternalinitPowerManagementinitPowerManagement该方法比较重要,重点在于提供了一个DisplayBlanker回调,用来与PMS交互设置power相关的状态,还有就是使用LightService设置背光值。

其中还初始化了背光核心类DisplayPowerControl,在DisplayManagerService中,也就requestPowerState方法中使用了DisplayPowerControl,先看看他的构造方法

   public DisplayPowerController(Context context,

            DisplayPowerCallbacks callbacks,Handler handler,

            SensorManager sensorManager,DisplayBlanker blanker) {

DisplayPowerCallbacksPowerManagerService中实现,HandlerPMShandler,在DisplayPowerController的构造方法中,初始化了另一个核心类AutomaticBrightnessController。关于Android自动背光的功能所有的控制都在该类中。

2.2. 自动背光

2.1中介绍了AutomaticBrightnessController,是自动背光的核心,它是在DisplayPowerController的构造方法中,被初始化的。其构造方法如下:

   public AutomaticBrightnessController(Callbacks callbacks, Looper looper,

            SensorManager sensorManager, SplineautoBrightnessSpline, int lightSensorWarmUpTime,

            int brightnessMin, intbrightnessMax, float dozeScaleFactor,

           int lightSensorRate, longbrighteningLightDebounceConfig,

            long darkeningLightDebounceConfig,boolean resetAmbientLuxAfterWarmUpConfig,

            int ambientLightHorizon, floatautoBrightnessAdjustmentMaxGamma )

 

mSensorManager = sensorManager;//用来获取光感传感器

mScreenAutoBrightnessSpline =autoBrightnessSpline;//光照/背光mapping对应值,主要靠config匹配,系统配置文件中有两个数组:

<integer-arrayname="config_autoBrightnessLevels">//标示光照1-10000

<integer-arrayname="config_autoBrightnessLcdBacklightValues">//屏幕背光值1-255,他们之间的对应函数靠mScreenAutoBrightnessSpline实现。

mAmbientLightHorizon =ambientLightHorizon;

mWeightingIntercept =ambientLightHorizon;

mScreenAutoBrightnessAdjustmentMaxGamma= autoBrightnessAdjustmentMaxGamma;//gamma值,这个默认为300%,他是自动背光调节,计算光值大小的一个系数,该值得大小,体现为,gamma大于1,越来越大时,当环境光照变化时,屏幕背光值反映的很明显。当小于1,越来越小时,环境光变化时,屏幕背光值反映越来越缓慢。一般取值在1的左右。

mScreenAutoBrightnessAdjustment//当手机设置为自动背光,此时还需要手动调节背光条调节背光,此时该值就是对应着背光条的值大小该值范围大小-1~1。默认为0,代表背光条在最中间位置,最右边代表1,反之则为-1

2.2.1 自动背光流程

下面就是自动背光详细的代码流程:

SensorEventListener mLightSensorListener.onSensorChanged-> handleLightSensorEvent

 1.->applyLightSensorMeasurement

 2.->updateAmbientLux(time) ->updateAutoBrightness(true) -> Callbacks.updateBrightness()

  -> DisplayPowerController.updateBrightness() -> sendUpdatePowerState()->sendUpdatePowerStateLocked()

  -> MSG_UPDATE_POWER_STATE -> updatePowerState ->animateScreenBrightness ----调节屏幕亮度

  -> DisplayPowerState$PhotonicModulator.run() ->DisplayBlanker.requestDisplayState() -> DisplayManagerService(newDisplayBlanker)

  -> DisplayManagerInternal.DisplayPowerCallbacks.onStateChanged

其中animateScreenBrightness这个方法就是设置屏幕背光的入口,配合animateScreenStateChange,改变DisplayPowerState中的statebacklight值,当DisplayPowerState中这两个值都变化时其中的PhotonicModulator线程就会被唤醒,此时便会开始执行设置背光值的操作,标志性log如下:DisplayPowerState: Updatingscreen state: state=ON, backlight=255

这里便会又走进initPowerManagement中初始化的DisplayBlanker,之前我们说该类的作用就是与PMS交互,1.设置power状态(屏幕状态…)2.Light交互设置背光值。分别对应方法DisplayPowerCallbacks.onDisplayStateChange(state)requestGlobalDisplayStateInternal

 

 

 

 

2.2.2 自动背光原理

2.2.1中简述了当手机开启自动背光功能时,代码走的流程,但是实际运行过程中,为了避免频繁的改变手机背光值,必须采取一些操作。使得用户体验更好。

2.2.1代码走到handleLightSensorEvent时,会分成两部分applyLightSensorMeasurementupdateAmbientLux

   private void applyLightSensorMeasurement(long time, float lux) {

       mRecentLightSamples++;

       // Store all of the light measurements for the intial horizon period.This is to help

       // diagnose dim wake ups and slow responses in b/27951906.

       if (time <= mLightSensorEnableTime + mAmbientLightHorizon) {

           mInitialHorizonAmbientLightRingBuffer.push(time, lux);

       }

       mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);

       mAmbientLightRingBuffer.push(time, lux);

 

       // Remember this sample value.

       mLastObservedLux = lux;

       mLastObservedLuxTime = time;

   }

这里需要说明的时,参数time,指的是从开机到现在的毫秒数(手机睡眠的时间不包括在内),所以说这里的一个判断指的是设置完自动背光功能开启之后采集前十秒之内的光线值,但是这个数组在目前代码中只是启到一个参考作用,真正用到的是mAmbientLightRingBufferprune就是裁剪,对于为什么裁剪一下,我们这里先暂且放放,push就是讲采集到的光线值放入集合内。

因此这里我们理解为每次当光线传感器接收到光线值时,都会讲之前采集到的值,做一个裁剪操作,然后将本次的光线值存入集合。接着就去执行updateAmbientLux操做,

   private void updateAmbientLux(long time) {

       // If the light sensor was just turned on then immediately update ourinitial

       // estimate of the current ambient light level.

       if (!mAmbientLuxValid) {

            //这里就是当我们刚设置手机屏幕背光为自动背光时,我们需要手机立即生效的操作

       }

 

       long nextBrightenTransition =nextAmbientLightBrighteningTransition(time);

       long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);

       float ambientLux = calculateAmbientLux(time);

       if (ambientLux >= mBrighteningLuxThreshold &&nextBrightenTransition <= time

                || ambientLux <=mDarkeningLuxThreshold && nextDarkenTransition <= time) {

            setAmbientLux(ambientLux);

            updateAutoBrightness(true);

            nextBrightenTransition =nextAmbientLightBrighteningTransition(time);

            nextDarkenTransition =nextAmbientLightDarkeningTransition(time);

       }

       long nextTransitionTime = Math.min(nextDarkenTransition,nextBrightenTransition);

       nextTransitionTime =

                nextTransitionTime > time ?nextTransitionTime : time + mLightSensorRate;

       mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,nextTransitionTime);

}

nextBrightenTransition下一次变亮的时间nextDarkenTransition下一次变暗的时间,mBrighteningLuxThreshold使屏幕变亮所需要的环境光照阈值,一般为当前光线值的1.1倍,mDarkeningLuxThreshold使屏幕变暗所需要的环境光照阈值,一般为当前光线值的1.2倍,当环境光照小于该数值的时候,屏幕才可能变暗。这里就是之前所说为了避免频繁改变屏幕背光,采取一些操作。使得用户体验更好。

calculateAmbientLux(time)这里就是获取当前时间之前采取的光线值的一个加权平均,权重为采集时间。然后就会设置mAmbientLux为刚刚计算得到的光值。

updateAutoBrightness(true),就是计算出需要设置到屏幕上的光值大小,在前面也介绍过mScreenAutoBrightnessSpline就是用来对应光值和背光值的,其运用的算法就是数学中的样条插值,目的在于使得光线变化时,屏幕光值设置的更加平滑。在updateAutoBrightness操作中,会设置成员mScreenAutoBrightness为当前计算的到的光值,之后的设置过程中会同过getAutomaticScreenBrightness获取其值大小

2.3. 手动改背光

不管是从SystemUI下拉statubar,从qstile拖动背光条,还是从settings的拖动,他们都会向数据库写入相应的数值。

此时PowerManagerService里的SettingsObserver,一旦检测到数据库有变化,便会直接执行相关更新操作,与自动区别的只是参数是否为auto的不一样。

   private void handleSettingsChangedLocked() {

       updateSettingsLocked();

       updatePowerStateLocked();

   }

 

 

 

.实际运用

2.3. 需求:自动背光和手动背光切换时屏幕亮度要求不变化

diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.javab/services/core/java/com/android/server/display/AutomaticBrightnessController.java

index 7d986d1..6481cb4 100644

---a/services/core/java/com/android/server/display/AutomaticBrightnessController.java

---a/services/core/java/com/android/server/display/DisplayPowerController.java

+++b/services/core/java/com/android/server/display/DisplayPowerController.java

@@ -48,6 +48,13 @@ importandroid.view.WindowManagerPolicy;

 

 import java.io.PrintWriter;

 

+import android.database.ContentObserver;

+import android.content.ContentResolver;

+import android.provider.Settings;

+import android.os.UserHandle;

+

 /**

  *Controls the power state of the display.

  *

@@ -261,6 +268,8 @@ final classDisplayPowerController implements AutomaticBrightnessController.Call

    private static final int BRIGHTNESS_RAMP_RATE_FASTER = 800;

+   private BrightnessModeObserver mBrightnessModeObserver;

    /**

     * Creates the display power controller.

     */

@@ -388,6 +397,35 @@ final classDisplayPowerController implements AutomaticBrightnessController.Call

            }

        }

 

+       mBrightnessModeObserver = new BrightnessModeObserver(null);

+       mBrightnessModeObserver.startObserving();

+

+   }

+

+   private class BrightnessModeObserver extends ContentObserver {

+       public BrightnessModeObserver(Handler handler) {

+           super(handler);

+       }

+

+       @Override

+       public void onChange(boolean selfChange) {

+            boolean autoBrightness =Settings.System.getIntForUser(mContext.getContentResolver(),

+                                               Settings.System.SCREEN_BRIGHTNESS_MODE, 1, UserHandle.USER_CURRENT) ==1;

+           if (!autoBrightness) {

+                int brightness =mPowerState.getScreenBrightness();

+               Settings.System.putIntForUser(mContext.getContentResolver(),

+                                   Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);

+           }

+       }

+

+       public void startObserving() {

+           final ContentResolver cr = mContext.getContentResolver();

+           cr.unregisterContentObserver(this);

+           cr.registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),

+                                        false,this);

+       }

    }

 

    /**

这里就是在DisplayPowerController增加一个观察者,当是否为自动时,直接获取当前背光值并写入数据库,此时切换时,光值不会改变

 

 

 

 

 

 

 


http://www.ppmy.cn/news/871328.html

相关文章

ANDROID 背光调节

Android的屏幕亮度好像在2.1+的时候提供了自动调节的功能,所以,如果当开启自动调节功能的时候, 我们进行调节好像是没有一点作用的,这点让我很是无语,结果只有进行判断,看是否开启了屏幕亮度的自动调节功能。 /** * 判断是否开启了自动亮度调节 * * @par…

LCD 背光

LCD的背光由驱动产生文件/sys/class/leds/lcdbacklight/brightness 对LCD的背光亮度调整&#xff0c; 原理是改变PWM信号的占空比来设置亮度 占空比是在连续的脉冲信号频率或周期不变的前提下定义的&#xff0c;用来衡量开关管导通或截至状况&#xff0c;在这个前提下&#…

Backlight 背光

转自&#xff1a;http://blog.csdn.net/jiajie961/article/details/6030405 1,总论 背光模块属于HAL层开发&#xff0c;HAL层开发&#xff0c;用一句话来概括就是定义一个hardware.h中定义的名称为宏HAL_MODULE_INFO_SYM的hw_module_t结构体&#xff0c; 然后实现结构体的相关…

Android 修改屏幕背光方案

极力推荐Android 开发大总结文章&#xff1a;欢迎收藏Android 开发技术文章大总结 本篇文章主要介绍 Android 开发中的部分知识点&#xff0c;通过阅读本篇文章&#xff0c;您将收获以下内容: 一、获取系统Settings 中的亮度 系统屏幕亮度值在&#xff08;0~255&#xff09;之间…

Android原生调节屏幕背光流程

Android 5.1调节背光流程 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 by-sa 版权协议&#xff0c;转载请附上原文出处链接和本声明。 https://mp.csdn.net/mdeditor/99670972 目录 1、启动相关服务(PMS,LightService,DMS) 2、背光修改Code执行流程 3…

数字脉冲调光(用于手机或平板电脑等设备的背光调节原理)

数字脉冲调光是一种利用脉冲个数的不同来实现背光调节的 调光方法&#xff0c;此种方法占用一个普通的GPIO口&#xff0c;调光时通过向 背光IC的EN端口发送相应个数的脉冲来实现相应阶数的背光调 节&#xff0c;一般有16阶可调&#xff0c;所发脉冲要满足IC相应的要求。 下图为…

android修改自动背光,android 背光控制

echo 23 > /sys/devices/platform/atmel_lcdfb.0/backlight/backlight/brightness android 源代码 http://blog.chinaunix.net/u1/49742/showart_2077813.html android 知识总结 http://www.limodev.cn/ Android 背光的控制&#xff1a; 屏幕背光设置 packages/apps/Setting…

android lcd 背光控制流程

此文章是网上看到的&#xff0c;在MTK平台基础上的背光控制流程的分析。个人觉得写得比较详细&#xff0c;于是截取部分内容转载出来。 不过话说在前头&#xff0c;对于lcd而言&#xff0c;决定显示效果的有几个因素&#xff1a;pwm&#xff0c;gama&#xff08;屏幕灰度&#…