android自动亮度流程,Android 亮度自动调节是如何实现的?
下拉状态栏有个亮度的进度条,如果开启了亮度自动调节开关,会随着周围光线变化,这个进度条也会随着变化,接下来就是看看这个功能是如何实现的。
源码版本
基于 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 亮度自动调节是如何实现的?相关推荐
- android 屏幕旋转流程,android自动屏幕旋转流程分析.doc
android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...
- android屏幕适配流程,Android屏幕适配姿势
GitHub地址 为什么要屏幕适配? device_framentation.png 统计 碎片化 品牌机型碎片化 屏幕尺寸碎片化 操作系统碎片化 为了保证用户获得一致的用户体验效果,使得某一元素在A ...
- android p 权限流程,Android native 权限控制流程
关联文章: 前言: 在 Android Runtime Permission 详解 中详细的说明了permission 在Android 6.0 前后的区别,对于M 以后应用可以通过checkPerm ...
- android 自动 键盘,关于Android中的软键盘
InputMethodService为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示.当我们点击输入框时,系 ...
- android自动更新demo,Android程序自动更新功能模块的实现方法【附完整demo源码下载】...
本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更 ...
- android自动创建快捷方式,Android开发之生成桌面快捷方式细则(原创)
本文已独家授权 郭霖 ( guolin_blog) 公众号发布! 申明,标题里的快捷方式不是指开发人员使用频率极高的Ctrl+C和Ctrl+V:也不是IDE里Ctrl+D.Ctrl+F等常用快捷键.这 ...
- android自动夜间模式,Android实现日夜间模式的深入理解
在本篇文章中给出了三种实现日间/夜间模式切换的方案,三种方案综合起来可能导致文章的篇幅过长,请耐心阅读. 1.使用 setTheme的方法让 Activity重新设置主题: 2.设置 Android ...
- android自动切换图片,Android应用中图片浏览时实现自动切换功能的方法详解
先给最终效果图: 当我们在最下边的gallery中切换图片时,上面的大图片会自动切换,切换时有动画效果哦,很简单的一个程序,有待完善更多的功能! activity代码: package cn.com. ...
- android wifi wps 流程,android中WiFi wps连接方式
Android 个人热点 wps方式连接流程 android手机开启个人热点时,可以选择WPS连接方式 个人热点端 连接端 当个人热点端选择按钮时,连接端只需要点击WPS按钮即可连接:当个人热点端选择 ...
- Android 自动搜索频道,Android自定义收音机搜台控件RadioRulerView
前言:像这类的自定义控件有非常多的开源项目,但还是没有找到我项目想要的,所以简单实现了一个,下面简单讲讲实现原理. 效果图: 实现思路: 首先画固定背景尺子,而实现这个则要计算刻度线的宽度.刻度线间的 ...
最新文章
- Linux Kernel TCP/IP Stack — L4 Layer
- 《棋牌游戏服务器》玩法服务器架构
- jquery总结06-动画事件02-上卷下拉动画
- 【新功能,新插件】-全新来袭,CSDN浏览器助手这一款无广告干净界面插件你值得拥有!
- mysql恢复root用户_恢复MYSQL的root用户
- 页面中切换echarts主题
- 用webBrowser取源文件取不到的点击数--选秀榜selectop.com网站内容管理系统之六
- [Android] Android统计Apk , jar包方法数
- 《Maintainable JavaScript》读书笔记
- 一些关于网页标题的动态js特效
- vivo手机刷鸿蒙教程,vivo手机怎么刷机_vivo手机刷机全教程
- Word文档输入网址自动换行的解决办法
- 影视后期调色必要性以及操作理论
- 计算机防火墙知识点,防火墙及防火墙的基本概念-信息安全工程师知识点
- 什么是云原生架构?云原生和应用上云不是一码事!
- 金陵科技学院c语言校内题库,金陵科技学院校内二级复习题
- 这可能是史上最好用的PickerView库了
- 时空大数据可视化专栏
- 【计算机网络】DV算法
- 纯手写F3飞控的直升机固件(2.直升机倾斜盘混控了解)
热门文章
- aidlearning开发python使用教程_极致安卓之—Aid Learning基于Jupyter开发Java和Python
- kaka-manager和kafka-offset-monitor的安装和使用
- 计算机图像处理顶级教授,【科研新成果】我院两项成果被图像处理领域顶级期刊录用...
- ARP缓存表过期问题
- 王强 河南大学计算机学院,王强-河南大学生命科学学院
- 绝对最大额定值(ABSOLUTE MAXIMUM RATINGS: ABS)是否可以超过
- 团队作业8----第二次项目冲刺(Beta阶段) 第二天
- 深度学习研究生常用网站||图像处理||医学影像||使用评价||汇总
- 【xubuntu】 在xubuntu系统上开启自动登陆,并自动启动一个应用程序。
- 妙味课堂:JavaScript初级--第11课:字符串、查找高亮显示