diff options
11 files changed, 206 insertions, 10 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7f64400a1cce..1a33b768a039 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8846,6 +8846,24 @@ public final class Settings { "reduce_bright_colors_persist_across_reboots"; /** + * Setting that specifies whether Even Dimmer - a feature that allows the brightness + * slider to go below what the display can conventionally do, should be enabled. + * + * @hide + */ + public static final String EVEN_DIMMER_ACTIVATED = + "even_dimmer_activated"; + + /** + * Setting that specifies which nits level Even Dimmer should allow the screen brightness + * to go down to. + * + * @hide + */ + public static final String EVEN_DIMMER_MIN_NITS = + "even_dimmer_min_nits"; + + /** * List of the enabled print services. * * N and beyond uses {@link #DISABLED_PRINT_SERVICES}. But this might be used in an upgrade diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 4d6ed80aa763..3887dd7a753f 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -268,6 +268,13 @@ message SecureSettingsProto { optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; + message EvenDimmer { + optional SettingProto even_dimmer_activated = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto even_dimmer_min_nits = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + } + + optional EvenDimmer even_dimmer = 98; + optional SettingProto font_weight_adjustment = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; message Gesture { @@ -712,5 +719,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 98; + // Next tag = 99; } diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 8412cbaaea36..5c09b1692453 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -251,6 +251,8 @@ public class SecureSettings { Settings.Secure.STYLUS_HANDWRITING_ENABLED, Settings.Secure.DEFAULT_NOTE_TASK_PROFILE, Settings.Secure.CREDENTIAL_SERVICE, - Settings.Secure.CREDENTIAL_SERVICE_PRIMARY + Settings.Secure.CREDENTIAL_SERVICE_PRIMARY, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + Settings.Secure.EVEN_DIMMER_MIN_NITS }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 9197554662d3..b0169a115ec5 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -110,6 +110,9 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.FONT_WEIGHT_ADJUSTMENT, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Secure.REDUCE_BRIGHT_COLORS_LEVEL, PERCENTAGE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.REDUCE_BRIGHT_COLORS_PERSIST_ACROSS_REBOOTS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.EVEN_DIMMER_ACTIVATED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.EVEN_DIMMER_MIN_NITS, + new InclusiveFloatRangeValidator(0.0f, Float.MAX_VALUE)); VALIDATORS.put(Secure.TTS_DEFAULT_RATE, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.TTS_DEFAULT_PITCH, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.TTS_DEFAULT_SYNTH, PACKAGE_NAME_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index a509ba33bad2..a97888949446 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2135,6 +2135,15 @@ class SettingsProtoDumpUtil { Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, SecureSettingsProto.ENHANCED_VOICE_PRIVACY_ENABLED); + final long evenDimmerToken = p.start(SecureSettingsProto.EVEN_DIMMER); + dumpSetting(s, p, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + SecureSettingsProto.EvenDimmer.EVEN_DIMMER_ACTIVATED); + dumpSetting(s, p, + Settings.Secure.EVEN_DIMMER_MIN_NITS, + SecureSettingsProto.EvenDimmer.EVEN_DIMMER_MIN_NITS); + p.end(evenDimmerToken); + final long gestureToken = p.start(SecureSettingsProto.GESTURE); dumpSetting(s, p, Settings.Secure.AWARE_ENABLED, diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java index 8a884b6221a2..42ebc401335e 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java @@ -25,7 +25,7 @@ import com.android.server.display.DisplayBrightnessState; import java.io.PrintWriter; /** - * Provides max allowed brightness + * Provides brightness range constraints */ abstract class BrightnessClamper<T> { @@ -74,6 +74,7 @@ abstract class BrightnessClamper<T> { protected enum Type { THERMAL, POWER, - BEDTIME_MODE + BEDTIME_MODE, + LUX, } } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 765608e88356..01694ddee06a 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -68,14 +68,14 @@ public class BrightnessClamperController { private boolean mClamperApplied = false; public BrightnessClamperController(Handler handler, - ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, + ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags) { this(new Injector(), handler, clamperChangeListener, data, context, flags); } @VisibleForTesting BrightnessClamperController(Injector injector, Handler handler, - ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, + ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags) { mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler = handler; @@ -147,7 +147,8 @@ public class BrightnessClamperController { * Should be moved to DisplayBrightnessState OR derived from DisplayBrightnessState * TODO: b/263362199 */ - @BrightnessInfo.BrightnessMaxReason public int getBrightnessMaxReason() { + @BrightnessInfo.BrightnessMaxReason + public int getBrightnessMaxReason() { if (mClamperType == null) { return BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; } else if (mClamperType == Type.THERMAL) { @@ -241,12 +242,15 @@ public class BrightnessClamperController { new BrightnessThermalClamper(handler, clamperChangeListener, data)); if (flags.isPowerThrottlingClamperEnabled()) { clampers.add(new BrightnessPowerClamper(handler, clamperChangeListener, - data)); + data)); } if (flags.isBrightnessWearBedtimeModeClamperEnabled()) { clampers.add(new BrightnessWearBedtimeModeClamper(handler, context, clamperChangeListener, data)); } + if (flags.isEvenDimmerEnabled()) { + clampers.add(new BrightnessMinClamper(handler, clamperChangeListener, context)); + } return clampers; } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java new file mode 100644 index 000000000000..71efca12f91c --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessMinClamper.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display.brightness.clamper; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.PowerManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.utils.DebugUtils; + +import java.io.PrintWriter; + +/** + * Class used to prevent the screen brightness dipping below a certain value, based on current + * lux conditions. + */ +public class BrightnessMinClamper extends BrightnessClamper { + + // To enable these logs, run: + // 'adb shell setprop persist.log.tag.BrightnessMinClamper DEBUG && adb reboot' + private static final String TAG = "BrightnessMinClamper"; + private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); + + private final SettingsObserver mSettingsObserver; + + ContentResolver mContentResolver; + private float mNitsLowerBound; + + @VisibleForTesting + BrightnessMinClamper(Handler handler, + BrightnessClamperController.ClamperChangeListener listener, Context context) { + super(handler, listener); + + mContentResolver = context.getContentResolver(); + mSettingsObserver = new SettingsObserver(mHandler); + mHandler.post(() -> { + start(); + }); + } + + private void recalculateLowerBound() { + final int userId = UserHandle.USER_CURRENT; + float settingNitsLowerBound = Settings.Secure.getFloatForUser( + mContentResolver, Settings.Secure.EVEN_DIMMER_MIN_NITS, + /* def= */ PowerManager.BRIGHTNESS_MIN, userId); + + boolean isActive = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.EVEN_DIMMER_ACTIVATED, + /* def= */ 0, userId) == 1; + + // TODO: luxBasedNitsLowerBound = mMinNitsToLuxSpline(currentLux); + float luxBasedNitsLowerBound = PowerManager.BRIGHTNESS_MIN; + final float nitsLowerBound = Math.max(settingNitsLowerBound, luxBasedNitsLowerBound); + + if (mNitsLowerBound != nitsLowerBound || mIsActive != isActive) { + mIsActive = isActive; + mNitsLowerBound = nitsLowerBound; + if (DEBUG) { + Slog.i(TAG, "mIsActive: " + mIsActive); + } + // TODO: mBrightnessCap = nitsToBrightnessSpline(mNitsLowerBound); + mChangeListener.onChanged(); + } + } + + void start() { + recalculateLowerBound(); + } + + + @Override + Type getType() { + return Type.LUX; + } + + @Override + void onDeviceConfigChanged() { + // TODO + } + + @Override + void onDisplayChanged(Object displayData) { + + } + + @Override + void stop() { + mContentResolver.unregisterContentObserver(mSettingsObserver); + } + + @Override + void dump(PrintWriter pw) { + pw.println("BrightnessMinClamper:"); + pw.println(" mBrightnessCap=" + mBrightnessCap); + pw.println(" mIsActive=" + mIsActive); + pw.println(" mNitsLowerBound=" + mNitsLowerBound); + super.dump(pw); + } + + private final class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_MIN_NITS), + false, this); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.EVEN_DIMMER_ACTIVATED), + false, this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + recalculateLowerBound(); + } + } +} diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index c71f0cf2dd91..2d5da715b585 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -78,6 +78,9 @@ public class DisplayManagerFlags { Flags.FLAG_ENABLE_POWER_THROTTLING_CLAMPER, Flags::enablePowerThrottlingClamper); + private final FlagState mEvenDimmerFlagState = new FlagState( + Flags.FLAG_EVEN_DIMMER, + Flags::evenDimmer); private final FlagState mSmallAreaDetectionFlagState = new FlagState( com.android.graphics.surfaceflinger.flags.Flags.FLAG_ENABLE_SMALL_AREA_DETECTION, com.android.graphics.surfaceflinger.flags.Flags::enableSmallAreaDetection); @@ -174,6 +177,11 @@ public class DisplayManagerFlags { return mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState.isEnabled(); } + /** Returns whether brightness range is allowed to extend below traditional range. */ + public boolean isEvenDimmerEnabled() { + return mEvenDimmerFlagState.isEnabled(); + } + public boolean isSmallAreaDetectionEnabled() { return mSmallAreaDetectionFlagState.isEnabled(); } diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 9dfa1ee41ad6..1b4d74cdff1f 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -106,6 +106,14 @@ flag { } flag { + name: "even_dimmer" + namespace: "display_manager" + description: "Feature flag for extending the brightness below traditional range" + bug: "179428400" + is_fixed_read_only: true +} + +flag { name: "brightness_int_range_user_perception" namespace: "display_manager" description: "Feature flag for converting the brightness integer range to the user perception scale" diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java index 9aa6136348b4..6ba7368f8f26 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java @@ -262,8 +262,7 @@ public class BrightnessClamperControllerTest { Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData data, - DisplayManagerFlags flags, - Context context) { + DisplayManagerFlags flags, Context context) { mCapturedChangeListener = clamperChangeListener; return mClampers; } |