当前位置:   article > 正文

自动调节安卓亮度_mathutils.constrain

mathutils.constrain

转自吴小龙公众号

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

源码版本

基于 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:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3.     super.onCreate(savedInstanceState);
  4.     //省略部分代码
  5.     mBrightnessController = new BrightnessController(this, icon, slider);
  6. }

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

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

又进行了 BrightnessObserver 初始化:

  1. /** ContentObserver to watch brightness **/
  2. private class BrightnessObserver extends ContentObserver {
  3.     //省略部分代码
  4.     private final Uri BRIGHTNESS_FOR_VR_URI =
  5.             Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
  6.     //Add By WuXiaolong for AutomaticBrightness
  7.     private final Uri BRIGHTNESS_ADJ_URI =
  8.             Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
  9.     public BrightnessObserver(Handler handler) {
  10.         super(handler);
  11.     }
  12.     @Override
  13.     public void onChange(boolean selfChange) {
  14.         onChange(selfChange, null);
  15.     }
  16.     @Override
  17.     public void onChange(boolean selfChange, Uri uri) {
  18.         if (selfChange) return;
  19.         if (BRIGHTNESS_MODE_URI.equals(uri)) {
  20.             mBackgroundHandler.post(mUpdateModeRunnable);
  21.             mBackgroundHandler.post(mUpdateSliderRunnable);
  22.         } 
  23.         //省略部分代码
  24.         //Add By WuXiaolong for AutomaticBrightness
  25.         else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
  26.             mBackgroundHandler.post(mUpdateSliderRunnable);
  27.         } else {
  28.             mBackgroundHandler.post(mUpdateModeRunnable);
  29.             mBackgroundHandler.post(mUpdateSliderRunnable);
  30.         }
  31.         for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
  32.             cb.onBrightnessLevelChanged();
  33.         }
  34.     }
  35.     public void startObserving() {
  36.         final ContentResolver cr = mContext.getContentResolver();
  37.         cr.unregisterContentObserver(this);
  38.         //省略部分代码
  39.         cr.registerContentObserver(
  40.                 BRIGHTNESS_FOR_VR_URI,
  41.                 false, this, UserHandle.USER_ALL);
  42.         //Add By WuXiaolong for AutomaticBrightness
  43.         cr.registerContentObserver(
  44.                 BRIGHTNESS_ADJ_URI,
  45.                 false, this, UserHandle.USER_ALL);
  46.     }
  47.     public void stopObserving() {
  48.         final ContentResolver cr = mContext.getContentResolver();
  49.         cr.unregisterContentObserver(this);
  50.     }
  51. }

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

3、回到 BrightnessDialog#onStart:

  1. @Override
  2. protected void onStart() {
  3.     super.onStart();
  4.     mBrightnessController.registerCallbacks();
  5.     MetricsLogger.visible(thisMetricsEvent.BRIGHTNESS_DIALOG);
  6. }

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

  1. private final Runnable mStartListeningRunnable = new Runnable() {
  2.     @Override
  3.     public void run() {
  4.         //BrightnessObserver 注册
  5.         mBrightnessObserver.startObserving();
  6.         mUserTracker.startTracking();
  7.         // Update the slider and mode before attaching the listener so we don't
  8.         // receive the onChanged notifications for the initial values.
  9.         mUpdateModeRunnable.run();
  10.         mUpdateSliderRunnable.run();
  11.         mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
  12.     }
  13. };

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

  1. private final Handler mHandler = new Handler() {
  2.     @Override
  3.     public void handleMessage(Message msg) {
  4.         mExternalChange = true;
  5.         try {
  6.             switch (msg.what) {
  7.                 //省略部分代码
  8.                 case MSG_UPDATE_SLIDER:
  9.                     updateSlider(msg.arg1, msg.arg2 != 0);
  10.                     break;
  11.                 //省略部分代码
  12.                 default:
  13.                     super.handleMessage(msg);
  14.             }
  15.         } finally {
  16.             mExternalChange = false;
  17.         }
  18.     }
  19. };

走 updateSlider方法,到 :

  1. private void animateSliderTo(int target) {
  2.     if (!mControlValueInitialized) {
  3.         // Don't animate the first value since it's default state isn't mea
  4.         mControl.setValue(target);
  5.         mControlValueInitialized = true;
  6.     }
  7.     //省略部分代码
  8. }

5、跳到 ToggleSliderView#setValue:

  1. @Override
  2. public void setValue(int value) {
  3.     //这里正是修改进度条
  4.     mSlider.setProgress(value);
  5.     if (mMirror != null) {
  6.         mMirror.setValue(value);
  7.     }
  8. }

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

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

  1. private final class LocalService extends DisplayManagerInternal {
  2.     @Override
  3.     public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
  4.             SensorManager sensorManager) {
  5.         synchronized (mSyncRoot) {
  6.             //省略部分代码
  7.             mDisplayPowerController = new DisplayPowerController(
  8.                     mContext, callbacks, handler, sensorManager, blanker);
  9.         }
  10.         mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
  11.     }

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

  1. public DisplayPowerController(Context context,
  2.         DisplayPowerCallbacks callbacks, Handler handler,
  3.         SensorManager sensorManager, DisplayBlanker blanker) {
  4.     //省略部分代码
  5.     mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
  6.             com.android.internal.R.bool.config_automatic_brightness_available);
  7.     //省略部分代码
  8.     if (mUseSoftwareAutoBrightnessConfig) {
  9.         //省略部分代码
  10.         mBrightnessMapper = BrightnessMappingStrategy.create(resources);
  11.         if (mBrightnessMapper != null) {
  12.             mAutomaticBrightnessController = new AutomaticBrightnessController(this,
  13.                     handler.getLooper(), sensorManager, mBrightnessMapper,
  14.                     lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
  15.                     mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
  16.                     initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
  17.                     autoBrightnessResetAmbientLuxAfterWarmUp, hysteresisLevels);
  18.         } else {
  19.             mUseSoftwareAutoBrightnessConfig = false;
  20.         }
  21.     }
  22.     //省略部分代码
  23.     mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
  24.     mTemporaryAutoBrightnessAdjustment = Float.NaN;
  25.     //省略部分代码
  26. }

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

  1. private void updatePowerState() {
  2.     // Update the power state request.
  3.     //省略部分代码
  4.     final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
  5.     if (autoBrightnessAdjustmentChanged) {
  6.         mTemporaryAutoBrightnessAdjustment = Float.NaN;
  7.     }
  8.     // Use the autobrightness adjustment override if set.
  9.     final float autoBrightnessAdjustment;
  10.     if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
  11.         autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
  12.         mAppliedTemporaryAutoBrightnessAdjustment = true;
  13.     } else {
  14.         autoBrightnessAdjustment = mAutoBrightnessAdjustment;
  15.         mAppliedTemporaryAutoBrightnessAdjustment = false;
  16.     }
  17.     boolean hadUserBrightnessPoint = false;
  18.     // Configure auto-brightness.
  19.     if (mAutomaticBrightnessController != null) {
  20.         hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
  21.         mAutomaticBrightnessController.configure(autoBrightnessEnabled,
  22.                 mBrightnessConfiguration,
  23.                 mLastUserSetScreenBrightness / (float) PowerManager.BRIGHTNESS_ON,
  24.                 userSetBrightnessChanged, autoBrightnessAdjustment,
  25.                 autoBrightnessAdjustmentChanged, mPowerRequest.policy);
  26.     }
  27.     // Apply auto-brightness.
  28.     boolean slowChange = false;
  29.     if (brightness < 0) {
  30.         float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
  31.         if (autoBrightnessEnabled) {
  32.             brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
  33.             newAutoBrightnessAdjustment =
  34.                     mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
  35.         }
  36.         if (brightness >= 0) {
  37.             // Use current auto-brightness value and slowly adjust to changes.
  38.             brightness = clampScreenBrightness(brightness);
  39.             if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
  40.                 slowChange = true// slowly adapt to auto-brightness
  41.             }
  42.             // Tell the rest of the system about the new brightness. Note that we do this
  43.             // before applying the low power or dim transformations so that the slider
  44.             // accurately represents the full possible range, even if they range changes what
  45.             // it means in absolute terms.
  46.             putScreenBrightnessSetting(brightness);
  47.             mAppliedAutoBrightness = true;
  48.         } else {
  49.             mAppliedAutoBrightness = false;
  50.         }
  51.         if (autoBrightnessAdjustment != newAutoBrightnessAdjustment) {
  52.             // If the autobrightness controller has decided to change the adjustment value
  53.             // used, make sure that's reflected in settings.
  54.             putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
  55.         }
  56.     } else {
  57.         mAppliedAutoBrightness = false;
  58.     }
  59.     //省略部分代码
  60. }

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

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

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

继续看下 clampAutoBrightnessAdjustment:

  1. private static float clampAutoBrightnessAdjustment(float value) {
  2.     return MathUtils.constrain(value-1.0f1.0f);
  3. }

这里注意下 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

  1. @Override
  2. public boolean setAutoBrightnessAdjustment(float adjustment) {
  3.     adjustment = MathUtils.constrain(adjustment, -11);
  4.     if (adjustment == mAutoBrightnessAdjustment) {
  5.         return false;
  6.     }
  7.     if (DEBUG) {
  8.         Slog.d(TAG, "setAutoBrightnessAdjustment: " + mAutoBrightnessAdjustment + " => " +
  9.                 adjustment);
  10.         PLOG.start("auto-brightness adjustment");
  11.     }
  12.     mAutoBrightnessAdjustment = adjustment;
  13.     computeSpline();
  14.     return true;
  15. }

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

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

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

  1. public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
  2.         float brightness, boolean userChangedBrightness, float adjustment,
  3.         boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {
  4.     // While dozing, the application processor may be suspended which will prevent us from
  5.     // receiving new information from the light sensor. On some devices, we may be able to
  6.     // switch to a wake-up light sensor instead but for now we will simply disable the sensor
  7.     // and hold onto the last computed screen auto brightness.  We save the dozing flag for
  8.     // debugging purposes.
  9.     boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);
  10.     boolean changed = setBrightnessConfiguration(configuration);
  11.     changed |= setDisplayPolicy(displayPolicy);
  12.     if (userChangedAutoBrightnessAdjustment) {
  13.         changed |= setAutoBrightnessAdjustment(adjustment);
  14.     }
  15.     if (userChangedBrightness && enable) {
  16.         // Update the brightness curve with the new user control point. It's critical this
  17.         // happens after we update the autobrightness adjustment since it may reset it.
  18.         changed |= setScreenBrightnessByUser(brightness);
  19.     }
  20.     final boolean userInitiatedChange =
  21.             userChangedBrightness || userChangedAutoBrightnessAdjustment;
  22.     if (userInitiatedChange && enable && !dozing) {
  23.         prepareBrightnessAdjustmentSample();
  24.     }
  25.     changed |= setLightSensorEnabled(enable && !dozing);
  26.     if (changed) {
  27.         updateAutoBrightness(false /*sendUpdate*/);
  28.     }
  29. }

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/642961
推荐阅读
相关标签
  

闽ICP备14008679号