下拉状态栏有个亮度的进度条,如果开启了亮度自动调节开关,会随着周围光线变化,这个进度条也会随着变化,接下来就是看看这个功能是如何实现的。

源码版本

基于 Android 9.0 分析。

BrightnessDialog,位于:frameworks/base/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java

ToggleSliderView,位于:frameworks/base/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java

DisplayPowerController,位于:frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

AutomaticBrightnessController,位于:frameworks/base/services/core/java/com/android/server/display/AutomaticBrightnessController.java

BrightnessMappingStrategy,

概述

状态栏里亮度页面是 BrightnessDialog,其中进度条设置是 ToggleSliderView,亮度自动调节主要是 DisplayPowerController 和 AutomaticBrightnessController 两个类,当亮度发生变化时,如果关联到 ToggleSliderView,用的是 ContentObserver,Uri 为 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ。

源码梳理

1、BrightnessDialog#onCreate:

@Override

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

//省略部分代码

mBrightnessController = newBrightnessController( this, icon, slider);

}

2、这里进行了 BrightnessController 初始化,来看下:

publicBrightnessController(Context context, ImageView icon, ToggleSlider control){

//省略部分代码

mBrightnessObserver = newBrightnessObserver(mHandler);

//省略部分代码

}

又进行了 BrightnessObserver 初始化:

/** ContentObserver to watch brightness **/

privateclassBrightnessObserverextendsContentObserver{

//省略部分代码

privatefinalUri BRIGHTNESS_FOR_VR_URI =

Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);

//Add By WuXiaolong for AutomaticBrightness

privatefinalUri BRIGHTNESS_ADJ_URI =

Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);

publicBrightnessObserver(Handler handler){

super(handler);

}

@Override

publicvoidonChange(booleanselfChange){

onChange(selfChange, null);

}

@Override

publicvoidonChange(booleanselfChange, Uri uri){

if(selfChange) return;

if(BRIGHTNESS_MODE_URI.equals(uri)) {

mBackgroundHandler.post(mUpdateModeRunnable);

mBackgroundHandler.post(mUpdateSliderRunnable);

}

//省略部分代码

//Add By WuXiaolong for AutomaticBrightness

elseif(BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {

mBackgroundHandler.post(mUpdateSliderRunnable);

} else{

mBackgroundHandler.post(mUpdateModeRunnable);

mBackgroundHandler.post(mUpdateSliderRunnable);

}

for(BrightnessStateChangeCallback cb : mChangeCallbacks) {

cb.onBrightnessLevelChanged();

}

}

publicvoidstartObserving(){

finalContentResolver cr = mContext.getContentResolver();

cr.unregisterContentObserver( this);

//省略部分代码

cr.registerContentObserver(

BRIGHTNESS_FOR_VR_URI,

false, this, UserHandle.USER_ALL);

//Add By WuXiaolong for AutomaticBrightness

cr.registerContentObserver(

BRIGHTNESS_ADJ_URI,

false, this, UserHandle.USER_ALL);

}

publicvoidstopObserving(){

finalContentResolver cr = mContext.getContentResolver();

cr.unregisterContentObserver( this);

}

}

其实我目前下载的源码,这块功能是不全的,我已经加上了,哪里进行 BrightnessObserver 的 ContentObserver 注册呢?

3、回到 BrightnessDialog#onStart:

@Override

protectedvoidonStart(){

super.onStart();

mBrightnessController.registerCallbacks();

MetricsLogger.visible( this, MetricsEvent.BRIGHTNESS_DIALOG);

}

4、调用mBrightnessController.registerCallbacks();最终走到 mStartListeningRunnable:

privatefinalRunnable mStartListeningRunnable = newRunnable() {

@Override

publicvoidrun(){

//BrightnessObserver 注册

mBrightnessObserver.startObserving();

mUserTracker.startTracking();

// Update the slider and mode before attaching the listener so we don't

// receive the onChanged notifications for the initial values.

mUpdateModeRunnable.run();

mUpdateSliderRunnable.run();

mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);

}

};

当亮度有变化时,会走 BrightnessObserver#onChange,最终走到:

privatefinalHandler mHandler = newHandler() {

@Override

publicvoidhandleMessage(Message msg){

mExternalChange = true;

try{

switch(msg.what) {

//省略部分代码

caseMSG_UPDATE_SLIDER:

updateSlider(msg.arg1, msg.arg2 != 0);

break;

//省略部分代码

default:

super.handleMessage(msg);

}

} finally{

mExternalChange = false;

}

}

};

走 updateSlider方法,到 :

privatevoidanimateSliderTo(inttarget){

if(!mControlValueInitialized) {

// Don't animate the first value since it's default state isn't mea

mControl.setValue(target);

mControlValueInitialized = true;

}

//省略部分代码

}

5、跳到 ToggleSliderView#setValue:

@Override

publicvoidsetValue(intvalue){

//这里正是修改进度条

mSlider.setProgress(value);

if(mMirror != null) {

mMirror.setValue(value);

}

}

接下来就是看看亮度自动调节主要的两个类 DisplayPowerController 和 AutomaticBrightnessController。DisplayPowerController 属于 Display 模块,其控制设备屏幕亮灭、背光、与Power关系密切,这里主要看下屏幕亮度的控制这方面的逻辑。

6、首先,在 DisplayManagerService 中初始化 DisplayPowerController,如下:

privatefinalclassLocalServiceextendsDisplayManagerInternal{

@Override

publicvoidinitPowerManagement(finalDisplayPowerCallbacks callbacks, Handler handler,

SensorManager sensorManager){

synchronized(mSyncRoot) {

//省略部分代码

mDisplayPowerController = newDisplayPowerController(

mContext, callbacks, handler, sensorManager, blanker);

}

mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);

}

7、接着看下 DisplayPowerController 构造方法,如下:

publicDisplayPowerController(Context context,

DisplayPowerCallbacks callbacks, Handler handler,

SensorManager sensorManager, DisplayBlanker blanker){

//省略部分代码

mUseSoftwareAutoBrightnessConfig = resources.getBoolean(

com.android.internal.R.bool.config_automatic_brightness_available);

//省略部分代码

if(mUseSoftwareAutoBrightnessConfig) {

//省略部分代码

mBrightnessMapper = BrightnessMappingStrategy.create(resources);

if(mBrightnessMapper != null) {

mAutomaticBrightnessController = newAutomaticBrightnessController( this,

handler.getLooper(), sensorManager, mBrightnessMapper,

lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,

mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,

initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,

autoBrightnessResetAmbientLuxAfterWarmUp, hysteresisLevels);

} else{

mUseSoftwareAutoBrightnessConfig = false;

}

}

//省略部分代码

mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();

mTemporaryAutoBrightnessAdjustment = Float.NaN;

//省略部分代码

}

由于亮屏之后屏幕自动亮度才会生效,所以在亮屏的时候,流程会走到 DisplayPowerController 中的核心函数 updatePowerState():

privatevoidupdatePowerState(){

// Update the power state request.

//省略部分代码

finalbooleanautoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();

if(autoBrightnessAdjustmentChanged) {

mTemporaryAutoBrightnessAdjustment = Float.NaN;

}

// Use the autobrightness adjustment override if set.

finalfloatautoBrightnessAdjustment;

if(!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {

autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;

mAppliedTemporaryAutoBrightnessAdjustment = true;

} else{

autoBrightnessAdjustment = mAutoBrightnessAdjustment;

mAppliedTemporaryAutoBrightnessAdjustment = false;

}

booleanhadUserBrightnessPoint = false;

// Configure auto-brightness.

if(mAutomaticBrightnessController != null) {

hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();

mAutomaticBrightnessController.configure(autoBrightnessEnabled,

mBrightnessConfiguration,

mLastUserSetScreenBrightness / ( float) PowerManager.BRIGHTNESS_ON,

userSetBrightnessChanged, autoBrightnessAdjustment,

autoBrightnessAdjustmentChanged, mPowerRequest.policy);

}

// Apply auto-brightness.

booleanslowChange = false;

if(brightness < 0) {

floatnewAutoBrightnessAdjustment = autoBrightnessAdjustment;

if(autoBrightnessEnabled) {

brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();

newAutoBrightnessAdjustment =

mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();

}

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

}

// Tell the rest of the system about the new brightness. Note that we do this

// before applying the low power or dim transformations so that the slider

// accurately represents the full possible range, even if they range changes what

// it means in absolute terms.

putScreenBrightnessSetting(brightness);

mAppliedAutoBrightness = true;

} else{

mAppliedAutoBrightness = false;

}

if(autoBrightnessAdjustment != newAutoBrightnessAdjustment) {

// If the autobrightness controller has decided to change the adjustment value

// used, make sure that's reflected in settings.

putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);

}

} else{

mAppliedAutoBrightness = false;

}

//省略部分代码

}

接下来分别看看 autoBrightnessAdjustment 和 newAutoBrightnessAdjustment 怎么来的?

autoBrightnessAdjustment 是来自 mTemporaryAutoBrightnessAdjustment 或 mAutoBrightnessAdjustment 赋值,mAutoBrightnessAdjustment 在第 7 步mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();有初始化,看下 getAutoBrightnessAdjustmentSetting():

privatefloatgetAutoBrightnessAdjustmentSetting(){

finalfloatadj = Settings.System.getFloatForUser(mContext.getContentResolver(),

Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);

returnFloat.isNaN(adj) ? 0.0f: clampAutoBrightnessAdjustment(adj);

}

继续看下 clampAutoBrightnessAdjustment:

privatestaticfloatclampAutoBrightnessAdjustment(floatvalue){

returnMathUtils.constrain( value, -1.0f, 1.0f);

}

这里注意下 MathUtils.constrain() 表示百分比缩放函数,比如 MathUtils.constrain(0.5, 0, 255) 表示 (255-0)*0.5。

这样了解了 autoBrightnessAdjustment,接下来看 newAutoBrightnessAdjustment。

8、回到 DisplayPowerController#updatePowerState(),看到 newAutoBrightnessAdjustment 调用了 AutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment(),最终是到了 BrightnessMapper#getAutoBrightnessAdjustment() 其中 mAutoBrightnessAdjustment 变量,赋值是在 BrightnessMapper#setAutoBrightnessAdjustment:

@Override

publicbooleansetAutoBrightnessAdjustment(floatadjustment){

adjustment = MathUtils.constrain(adjustment, - 1, 1);

if(adjustment == mAutoBrightnessAdjustment) {

returnfalse;

}

if(DEBUG) {

Slog.d(TAG, "setAutoBrightnessAdjustment: "+ mAutoBrightnessAdjustment + " => "+

adjustment);

PLOG.start( "auto-brightness adjustment");

}

mAutoBrightnessAdjustment = adjustment;

computeSpline();

returntrue;

}

9、BrightnessMapper#setAutoBrightnessAdjustment 这个方法调用又回到了 AutomaticBrightnessController#setAutoBrightnessAdjustment:

privatebooleansetAutoBrightnessAdjustment(floatadjustment){

returnmBrightnessMapper.setAutoBrightnessAdjustment(adjustment);

}

AutomaticBrightnessController#setAutoBrightnessAdjustment调用是来到 AutomaticBrightnessController#configure()方法:

publicvoidconfigure(booleanenable, @Nullable BrightnessConfiguration configuration,

floatbrightness, booleanuserChangedBrightness, floatadjustment,

booleanuserChangedAutoBrightnessAdjustment, intdisplayPolicy){

// While dozing, the application processor may be suspended which will prevent us from

// receiving new information from the light sensor. On some devices, we may be able to

// switch to a wake-up light sensor instead but for now we will simply disable the sensor

// and hold onto the last computed screen auto brightness. We save the dozing flag for

// debugging purposes.

booleandozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);

booleanchanged = setBrightnessConfiguration(configuration);

changed |= setDisplayPolicy(displayPolicy);

if(userChangedAutoBrightnessAdjustment) {

changed |= setAutoBrightnessAdjustment(adjustment);

}

if(userChangedBrightness && enable) {

// Update the brightness curve with the new user control point. It's critical this

// happens after we update the autobrightness adjustment since it may reset it.

changed |= setScreenBrightnessByUser(brightness);

}

finalbooleanuserInitiatedChange =

userChangedBrightness || userChangedAutoBrightnessAdjustment;

if(userInitiatedChange && enable && !dozing) {

prepareBrightnessAdjustmentSample();

}

changed |= setLightSensorEnabled(enable && !dozing);

if(changed) {

updateAutoBrightness( false/*sendUpdate*/);

}

}

AutomaticBrightnessController#configure()调用来到了 DisplayPowerController #updatePowerState()。

这样也知道了 newAutoBrightnessAdjustment,继续 putAutoBrightnessAdjustmentSetting:

privatevoidputAutoBrightnessAdjustmentSetting(floatadjustment){

mAutoBrightnessAdjustment = adjustment;

Settings.System.putFloatForUser(mContext.getContentResolver(),

Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, UserHandle.USER_CURRENT);

}

就调到第 4 步 BrightnessObserver#onChange,进度条随之变化,Over!

android自动亮度流程,Android 亮度自动调节是如何实现的?相关推荐

  1. android 屏幕旋转流程,android自动屏幕旋转流程分析.doc

    android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...

  2. android屏幕适配流程,Android屏幕适配姿势

    GitHub地址 为什么要屏幕适配? device_framentation.png 统计 碎片化 品牌机型碎片化 屏幕尺寸碎片化 操作系统碎片化 为了保证用户获得一致的用户体验效果,使得某一元素在A ...

  3. android p 权限流程,Android native 权限控制流程

    关联文章: 前言: 在 Android Runtime Permission 详解 中详细的说明了permission 在Android 6.0 前后的区别,对于M 以后应用可以通过checkPerm ...

  4. android 自动 键盘,关于Android中的软键盘

    InputMethodService为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示.当我们点击输入框时,系 ...

  5. android自动更新demo,Android程序自动更新功能模块的实现方法【附完整demo源码下载】...

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更 ...

  6. android自动创建快捷方式,Android开发之生成桌面快捷方式细则(原创)

    本文已独家授权 郭霖 ( guolin_blog) 公众号发布! 申明,标题里的快捷方式不是指开发人员使用频率极高的Ctrl+C和Ctrl+V:也不是IDE里Ctrl+D.Ctrl+F等常用快捷键.这 ...

  7. android自动夜间模式,Android实现日夜间模式的深入理解

    在本篇文章中给出了三种实现日间/夜间模式切换的方案,三种方案综合起来可能导致文章的篇幅过长,请耐心阅读. 1.使用 setTheme的方法让 Activity重新设置主题: 2.设置 Android ...

  8. android自动切换图片,Android应用中图片浏览时实现自动切换功能的方法详解

    先给最终效果图: 当我们在最下边的gallery中切换图片时,上面的大图片会自动切换,切换时有动画效果哦,很简单的一个程序,有待完善更多的功能! activity代码: package cn.com. ...

  9. android wifi wps 流程,android中WiFi wps连接方式

    Android 个人热点 wps方式连接流程 android手机开启个人热点时,可以选择WPS连接方式 个人热点端 连接端 当个人热点端选择按钮时,连接端只需要点击WPS按钮即可连接:当个人热点端选择 ...

  10. Android 自动搜索频道,Android自定义收音机搜台控件RadioRulerView

    前言:像这类的自定义控件有非常多的开源项目,但还是没有找到我项目想要的,所以简单实现了一个,下面简单讲讲实现原理. 效果图: 实现思路: 首先画固定背景尺子,而实现这个则要计算刻度线的宽度.刻度线间的 ...

最新文章

  1. Linux Kernel TCP/IP Stack — L4 Layer
  2. 《棋牌游戏服务器》玩法服务器架构
  3. jquery总结06-动画事件02-上卷下拉动画
  4. 【新功能,新插件】-全新来袭,CSDN浏览器助手这一款无广告干净界面插件你值得拥有!
  5. mysql恢复root用户_恢复MYSQL的root用户
  6. 页面中切换echarts主题
  7. 用webBrowser取源文件取不到的点击数--选秀榜selectop.com网站内容管理系统之六
  8. [Android] Android统计Apk , jar包方法数
  9. 《Maintainable JavaScript》读书笔记
  10. 一些关于网页标题的动态js特效
  11. vivo手机刷鸿蒙教程,vivo手机怎么刷机_vivo手机刷机全教程
  12. Word文档输入网址自动换行的解决办法
  13. 影视后期调色必要性以及操作理论
  14. 计算机防火墙知识点,防火墙及防火墙的基本概念-信息安全工程师知识点
  15. 什么是云原生架构?云原生和应用上云不是一码事!
  16. 金陵科技学院c语言校内题库,金陵科技学院校内二级复习题
  17. 这可能是史上最好用的PickerView库了
  18. 时空大数据可视化专栏
  19. 【计算机网络】DV算法
  20. 纯手写F3飞控的直升机固件(2.直升机倾斜盘混控了解)

热门文章

  1. aidlearning开发python使用教程_极致安卓之—Aid Learning基于Jupyter开发Java和Python
  2. kaka-manager和kafka-offset-monitor的安装和使用
  3. 计算机图像处理顶级教授,【科研新成果】我院两项成果被图像处理领域顶级期刊录用...
  4. ARP缓存表过期问题
  5. 王强 河南大学计算机学院,王强-河南大学生命科学学院
  6. 绝对最大额定值(ABSOLUTE MAXIMUM RATINGS: ABS)是否可以超过
  7. 团队作业8----第二次项目冲刺(Beta阶段) 第二天
  8. 深度学习研究生常用网站||图像处理||医学影像||使用评价||汇总
  9. 【xubuntu】 在xubuntu系统上开启自动登陆,并自动启动一个应用程序。
  10. 妙味课堂:JavaScript初级--第11课:字符串、查找高亮显示