自动调节安卓亮度

news/2024/12/29 14:52:58/

转自吴小龙公众号

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

源码版本

基于 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
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//省略部分代码mBrightnessController = new BrightnessController(this, icon, slider);
}

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

public BrightnessController(Context context, ImageView icon, ToggleSlider control) {//省略部分代码mBrightnessObserver = new BrightnessObserver(mHandler);//省略部分代码
}

又进行了 BrightnessObserver 初始化:

/** ContentObserver to watch brightness **/
private class BrightnessObserver extends ContentObserver {//省略部分代码private final Uri BRIGHTNESS_FOR_VR_URI =Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);//Add By WuXiaolong for AutomaticBrightnessprivate final Uri BRIGHTNESS_ADJ_URI =Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);public BrightnessObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange) {onChange(selfChange, null);}@Overridepublic void onChange(boolean selfChange, Uri uri) {if (selfChange) return;if (BRIGHTNESS_MODE_URI.equals(uri)) {mBackgroundHandler.post(mUpdateModeRunnable);mBackgroundHandler.post(mUpdateSliderRunnable);} //省略部分代码//Add By WuXiaolong for AutomaticBrightnesselse if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {mBackgroundHandler.post(mUpdateSliderRunnable);} else {mBackgroundHandler.post(mUpdateModeRunnable);mBackgroundHandler.post(mUpdateSliderRunnable);}for (BrightnessStateChangeCallback cb : mChangeCallbacks) {cb.onBrightnessLevelChanged();}}public void startObserving() {final ContentResolver cr = mContext.getContentResolver();cr.unregisterContentObserver(this);//省略部分代码cr.registerContentObserver(BRIGHTNESS_FOR_VR_URI,false, this, UserHandle.USER_ALL);//Add By WuXiaolong for AutomaticBrightnesscr.registerContentObserver(BRIGHTNESS_ADJ_URI,false, this, UserHandle.USER_ALL);}public void stopObserving() {final ContentResolver cr = mContext.getContentResolver();cr.unregisterContentObserver(this);}
}

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

3、回到 BrightnessDialog#onStart:

@Override
protected void onStart() {super.onStart();mBrightnessController.registerCallbacks();MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG);
}

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

private final Runnable mStartListeningRunnable = new Runnable() {@Overridepublic void run() {//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,最终走到:

private final Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {mExternalChange = true;try {switch (msg.what) {//省略部分代码case MSG_UPDATE_SLIDER:updateSlider(msg.arg1, msg.arg2 != 0);break;//省略部分代码default:super.handleMessage(msg);}} finally {mExternalChange = false;}}
};

走 updateSlider方法,到 :

private void animateSliderTo(int target) {if (!mControlValueInitialized) {// Don't animate the first value since it's default state isn't meamControl.setValue(target);mControlValueInitialized = true;}//省略部分代码
}

5、跳到 ToggleSliderView#setValue:

@Override
public void setValue(int value) {//这里正是修改进度条mSlider.setProgress(value);if (mMirror != null) {mMirror.setValue(value);}
}

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

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

private final class LocalService extends DisplayManagerInternal {@Overridepublic void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,SensorManager sensorManager) {synchronized (mSyncRoot) {//省略部分代码mDisplayPowerController = new DisplayPowerController(mContext, callbacks, handler, sensorManager, blanker);}mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);}

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

public DisplayPowerController(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 = new AutomaticBrightnessController(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():

private void updatePowerState() {// Update the power state request.//省略部分代码final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();if (autoBrightnessAdjustmentChanged) {mTemporaryAutoBrightnessAdjustment = Float.NaN;}// Use the autobrightness adjustment override if set.final float autoBrightnessAdjustment;if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;mAppliedTemporaryAutoBrightnessAdjustment = true;} else {autoBrightnessAdjustment = mAutoBrightnessAdjustment;mAppliedTemporaryAutoBrightnessAdjustment = false;}boolean hadUserBrightnessPoint = 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.boolean slowChange = false;if (brightness < 0) {float newAutoBrightnessAdjustment = 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():

private float getAutoBrightnessAdjustmentSetting() {final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);return Float.isNaN(adj) ? 0.0f : clampAutoBrightnessAdjustment(adj);
}

继续看下 clampAutoBrightnessAdjustment:

private static float clampAutoBrightnessAdjustment(float value) {return MathUtils.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
public boolean setAutoBrightnessAdjustment(float adjustment) {adjustment = MathUtils.constrain(adjustment, -1, 1);if (adjustment == mAutoBrightnessAdjustment) {return false;}if (DEBUG) {Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +adjustment);PLOG.start("auto-brightness adjustment");}mAutoBrightnessAdjustment = adjustment;computeSpline();return true;
}

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

private boolean setAutoBrightnessAdjustment(float adjustment) {return mBrightnessMapper.setAutoBrightnessAdjustment(adjustment);
}

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

public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,float brightness, boolean userChangedBrightness, float adjustment,boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {// 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.boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);boolean changed = 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);}final boolean userInitiatedChange =userChangedBrightness || userChangedAutoBrightnessAdjustment;if (userInitiatedChange && enable && !dozing) {prepareBrightnessAdjustmentSample();}changed |= setLightSensorEnabled(enable && !dozing);if (changed) {updateAutoBrightness(false /*sendUpdate*/);}
}

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

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

private void putAutoBrightnessAdjustmentSetting(float adjustment) {mAutoBrightnessAdjustment = adjustment;Settings.System.putFloatForUser(mContext.getContentResolver(),Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adjustment, UserHandle.USER_CURRENT);
}

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


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

相关文章

android自动调节屏幕亮度自动调节流程解析

屏幕亮度自动调节&#xff1a; 主要是从Sensor分析之中分离出来分析LIGHT 光线感应器&#xff0c;因此就分析一下自动调节屏幕亮度&#xff08;手机随着光线的强度自我调节&#xff0c;也就是在亮的光线下屏幕自动调亮一些&#xff0c;暗的时候就自动调暗一些&#xff0c;省得…

Android11 亮度自动调节

关键代码在frameworks/base/services/core/java/com/android/server/display BrightnessMappingStrategy.java AutomaticBrightnessController.java DisplayPowerController.java 这三个 AutomaticBrightnessController.java private void updateAutoBrightness(boolean se…

Win10关闭自动调节亮度

Win10关闭自动调节亮度问题 最近自己的笔记本电脑屏幕亮度总是自动调节&#xff0c;尤其是打开比较暗的应用&#xff0c;屏幕亮度也随之变暗了&#xff0c;让人很难受。解决方法如下 方法 看了很多解决方法。大致有这几种。 简单粗暴&#xff1a;拔了电源线再插上&#xff…

Win10关闭自动调节亮度问题

Win10关闭自动调节亮度问题 笔记本总是有个亮度自动调节&#xff0c;打开较暗的页面后就会慢慢地自动变暗&#xff0c;眼睛很难受。不知道是第多少次忍不住上网查这个问题了&#xff0c;最终用下面的最后一个方法成功解决。心情瞬间舒畅&#xff01; 方法 看了很多解决方法。…

亮度调节之自动调节

参考 https://blog.csdn.net/FightFightFight/article/details/83626332 自动调节和手动调节的分叉口在DisplayPowerController中的updatePowerState()方法处&#xff0c;这里先对自动调节控制器进行配置&#xff0c;然后若处于自动调节模式&#xff0c;那brightness就从自动调…

2306d的闭包问题

原文 首先,D的闭包是个好主意.我使用了C的成员函数指针;它们在语法上很糟糕,但概念很好,而闭包更好. D的闭包有些问题,有些是明显错误,有些是不应该不在语言中的改进. 不能调用某些闭包 这很奇怪,但这是真的. 一个问题是常和不变目前没有扩展到闭包环境.要求常和不变的传递性…

Qt 每月收支计算

Qt 每月收支计算&#xff0c;针对每月有支出&#xff08;房贷、车贷、花呗、借呗&#xff09;的情况&#xff0c;计算收支明细&#xff0c;直观看到未来的个人经济情况&#xff0c;培养良好的消费习惯&#xff0c;进行理性的财富支配&#xff0c;量入为出。 #include "mai…

哈希表--day3--(leetcode349/leetcode350)

leetcode349. 两个数组的交集 链接 基本思路 注意题目特意说明&#xff1a;输出结果中的每个元素一定是唯一的&#xff0c;也就是说输出的结果的去重的&#xff0c; 同时可以不考虑输出结果的顺序 这道题用暴力的解法时间复杂度是O(n^2)&#xff0c;那来看看使用哈希法进一…