Merge "Add support for brightness as a float"
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index dc15b51..a52ee54 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8723,6 +8723,7 @@
     @StringDef({
             Settings.System.SCREEN_BRIGHTNESS_MODE,
             Settings.System.SCREEN_BRIGHTNESS,
+            Settings.System.SCREEN_BRIGHTNESS_FLOAT,
             Settings.System.SCREEN_OFF_TIMEOUT
     })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index d67de09..25b84c5 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -766,11 +766,11 @@
      * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
      * </p>
      *
-     * @param brightness The brightness value from 0 to 255.
+     * @param brightness The brightness value from 0.0f to 1.0f.
      *
      * @hide Requires signature permission.
      */
-    public void setTemporaryBrightness(int brightness) {
+    public void setTemporaryBrightness(float brightness) {
         mGlobal.setTemporaryBrightness(brightness);
     }
 
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index fd539e8..9d92c89 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -616,7 +616,7 @@
      *
      * @hide Requires signature permission.
      */
-    public void setTemporaryBrightness(int brightness) {
+    public void setTemporaryBrightness(float brightness) {
         try {
             mDm.setTemporaryBrightness(brightness);
         } catch (RemoteException ex) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 79a339f..ea2b9e7 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -268,8 +268,9 @@
         // nearby, turning it off temporarily until the object is moved away.
         public boolean useProximitySensor;
 
-        // An override of the screen brightness. Set to -1 is used if there's no override.
-        public int screenBrightnessOverride;
+        // An override of the screen brightness.
+        // Set to PowerManager.BRIGHTNESS_INVALID if there's no override.
+        public float screenBrightnessOverride;
 
         // An override of the screen auto-brightness adjustment factor in the range -1 (dimmer) to
         // 1 (brighter). Set to Float.NaN if there's no override.
@@ -300,18 +301,18 @@
         public boolean blockScreenOn;
 
         // Overrides the policy for adjusting screen brightness and state while dozing.
-        public int dozeScreenBrightness;
         public int dozeScreenState;
+        public float dozeScreenBrightness;
 
         public DisplayPowerRequest() {
             policy = POLICY_BRIGHT;
             useProximitySensor = false;
-            screenBrightnessOverride = -1;
+            screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
             useAutoBrightness = false;
             screenAutoBrightnessAdjustmentOverride = Float.NaN;
             screenLowPowerBrightnessFactor = 0.5f;
             blockScreenOn = false;
-            dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+            dozeScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
             dozeScreenState = Display.STATE_UNKNOWN;
         }
 
@@ -351,7 +352,8 @@
             return other != null
                     && policy == other.policy
                     && useProximitySensor == other.useProximitySensor
-                    && screenBrightnessOverride == other.screenBrightnessOverride
+                    && floatEquals(screenBrightnessOverride,
+                            other.screenBrightnessOverride)
                     && useAutoBrightness == other.useAutoBrightness
                     && floatEquals(screenAutoBrightnessAdjustmentOverride,
                             other.screenAutoBrightnessAdjustmentOverride)
@@ -360,7 +362,7 @@
                     && blockScreenOn == other.blockScreenOn
                     && lowPowerMode == other.lowPowerMode
                     && boostScreenBrightness == other.boostScreenBrightness
-                    && dozeScreenBrightness == other.dozeScreenBrightness
+                    && floatEquals(dozeScreenBrightness, other.dozeScreenBrightness)
                     && dozeScreenState == other.dozeScreenState;
         }
 
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index ccf221b..d22188e 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -115,7 +115,7 @@
     boolean isMinimalPostProcessingRequested(int displayId);
 
     // Temporarily sets the display brightness.
-    void setTemporaryBrightness(int brightness);
+    void setTemporaryBrightness(float brightness);
 
     // Temporarily sets the auto brightness adjustment factor.
     void setTemporaryAutoBrightnessAdjustment(float adjustment);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 3ae5700..1cefbd9 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -49,6 +49,7 @@
     void goToSleep(long time, int reason, int flags);
     @UnsupportedAppUsage(maxTargetSdk = 28)
     void nap(long time);
+    float getBrightnessConstraint(int constraint);
     @UnsupportedAppUsage
     boolean isInteractive();
     boolean isPowerSaveMode();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index f3d3837..267613f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -248,8 +248,27 @@
     public static final int BRIGHTNESS_DEFAULT = -1;
 
     /**
+     * Brightness value for an invalid value having been stored.
+     * @hide
+     */
+    public static final int BRIGHTNESS_INVALID = -1;
+
+    //Brightness values for new float implementation:
+    /**
+     * Brightness value for fully on as float.
+     * @hide
+     */
+    public static final float BRIGHTNESS_MAX = 1.0f;
+
+    /**
+     * Brightness value for minimum valid brightness as float.
+     * @hide
+     */
+    public static final float BRIGHTNESS_MIN = 0.0f;
+
+    /**
      * Brightness value for fully off in float.
-     * TODO: rename this to BRIGHTNES_OFF and remove the integer-based constant.
+     * TODO(brightnessfloat): rename this to BRIGHTNES_OFF and remove the integer-based constant.
      * @hide
      */
     public static final float BRIGHTNESS_OFF_FLOAT = -1.0f;
@@ -424,6 +443,69 @@
     /**
      * @hide
      */
+    @IntDef(prefix = { "BRIGHTNESS_CONSTRAINT_TYPE" }, value = {
+            BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM,
+            BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM,
+            BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT,
+            BRIGHTNESS_CONSTRAINT_TYPE_DIM,
+            BRIGHTNESS_CONSTRAINT_TYPE_DOZE,
+            BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR,
+            BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR,
+            BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BrightnessConstraint{}
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM = 0;
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM = 1;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT = 2;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_DIM = 3;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_DOZE = 4;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR = 5;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR = 6;
+
+    /**
+     * Brightness constraint type: minimum allowed value.
+     * @hide
+     */
+    public static final int BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR = 7;
+
+    /**
+     * @hide
+     */
     @IntDef(prefix = { "WAKE_REASON_" }, value = {
             WAKE_REASON_UNKNOWN,
             WAKE_REASON_POWER_BUTTON,
@@ -889,6 +971,19 @@
     }
 
     /**
+     * Gets a float screen brightness setting.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    public float getBrightnessConstraint(int constraint) {
+        try {
+            return mService.getBrightnessConstraint(constraint);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Creates a new wake lock with the specified level and flags.
      * <p>
      * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ea0afa9..713cfc6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3915,6 +3915,19 @@
         public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
 
         /**
+         * The screen backlight brightness between 0.0f and 1.0f.
+         * @hide
+         */
+        public static final String SCREEN_BRIGHTNESS_FOR_VR_FLOAT =
+                "screen_brightness_for_vr_float";
+
+        /**
+         * The screen backlight brightness between 0.0f and 1.0f.
+         * @hide
+         */
+        public static final String SCREEN_BRIGHTNESS_FLOAT = "screen_brightness_float";
+
+        /**
          * Control whether to enable automatic brightness mode.
          */
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
@@ -4727,7 +4740,9 @@
             PUBLIC_SETTINGS.add(DIM_SCREEN);
             PUBLIC_SETTINGS.add(SCREEN_OFF_TIMEOUT);
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS);
+            PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_FLOAT);
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_FOR_VR);
+            PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_FOR_VR_FLOAT);
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_MODE);
             PUBLIC_SETTINGS.add(ADAPTIVE_SLEEP);
             PUBLIC_SETTINGS.add(MODE_RINGER_STREAMS_AFFECTED);
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
new file mode 100644
index 0000000..aa23251
--- /dev/null
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2019 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.internal;
+
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.MathUtils;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * BrightnessSynchronizer helps convert between the int (old) system and float
+ * (new) system for storing the brightness. It has methods to convert between the two and also
+ * observes for when one of the settings is changed and syncs this with the other.
+ */
+public class BrightnessSynchronizer{
+
+    private static final int MSG_UPDATE_FLOAT = 1;
+    private static final int MSG_UPDATE_INT = 2;
+
+    private static final String TAG = "BrightnessSynchronizer";
+    private static final Uri BRIGHTNESS_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+    private static final Uri BRIGHTNESS_FLOAT_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
+
+    // The tolerance within which we consider brightness values approximately equal to eachother.
+    // This value is approximately 1/3 of the smallest possible brightness value.
+    public static final float EPSILON = 0.001f;
+
+    private final Context mContext;
+
+    private final Queue<Object> mWriteHistory = new LinkedList<>();
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UPDATE_FLOAT:
+                    updateBrightnessFloatFromInt(msg.arg1);
+                    break;
+                case MSG_UPDATE_INT:
+                    updateBrightnessIntFromFloat(Float.intBitsToFloat(msg.arg1));
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+
+        }
+    };
+
+
+    public BrightnessSynchronizer(Context context) {
+        final BrightnessSyncObserver mBrightnessSyncObserver;
+        mContext = context;
+        mBrightnessSyncObserver = new BrightnessSyncObserver(mHandler);
+        mBrightnessSyncObserver.startObserving();
+    }
+
+    /**
+     * Converts between the int brightness system and the float brightness system.
+     */
+    public static float brightnessIntToFloat(Context context, int brightnessInt) {
+        PowerManager pm = context.getSystemService(PowerManager.class);
+        float pmMinBrightness = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+        float pmMaxBrightness = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+        int minBrightnessInt = brightnessFloatToInt(pmMinBrightness, PowerManager.BRIGHTNESS_MIN,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
+                PowerManager.BRIGHTNESS_ON);
+        int maxBrightnessInt = brightnessFloatToInt(pmMaxBrightness, PowerManager.BRIGHTNESS_MIN,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
+                PowerManager.BRIGHTNESS_ON);
+
+        return brightnessIntToFloat(brightnessInt, minBrightnessInt, maxBrightnessInt,
+                pmMinBrightness, pmMaxBrightness);
+    }
+
+    /**
+     * Converts between the int brightness system and the float brightness system.
+     */
+    public static float brightnessIntToFloat(int brightnessInt, int minInt, int maxInt,
+            float minFloat, float maxFloat) {
+        if (brightnessInt == PowerManager.BRIGHTNESS_OFF) {
+            return PowerManager.BRIGHTNESS_OFF_FLOAT;
+        } else if (brightnessInt == PowerManager.BRIGHTNESS_INVALID) {
+            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        } else {
+            return MathUtils.constrainedMap(minFloat, maxFloat, (float) minInt, (float) maxInt,
+                    brightnessInt);
+        }
+    }
+
+    /**
+     * Converts between the float brightness system and the int brightness system.
+     */
+    public static int brightnessFloatToInt(Context context, float brightnessFloat) {
+        PowerManager pm = context.getSystemService(PowerManager.class);
+        float pmMinBrightness = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+        float pmMaxBrightness = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+        int minBrightnessInt = brightnessFloatToInt(pmMinBrightness, PowerManager.BRIGHTNESS_MIN,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
+                PowerManager.BRIGHTNESS_ON);
+        int maxBrightnessInt = brightnessFloatToInt(pmMaxBrightness, PowerManager.BRIGHTNESS_MIN,
+                PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_OFF + 1,
+                PowerManager.BRIGHTNESS_ON);
+
+        return brightnessFloatToInt(brightnessFloat, pmMinBrightness, pmMaxBrightness,
+                minBrightnessInt, maxBrightnessInt);
+    }
+
+    /**
+     * Converts between the float brightness system and the int brightness system.
+     */
+    public static int brightnessFloatToInt(float brightnessFloat, float minFloat, float maxFloat,
+            int minInt, int maxInt) {
+        if (floatEquals(brightnessFloat, PowerManager.BRIGHTNESS_OFF_FLOAT)) {
+            return PowerManager.BRIGHTNESS_OFF;
+        } else if (Float.isNaN(brightnessFloat)) {
+            return PowerManager.BRIGHTNESS_INVALID;
+        } else {
+            return Math.round(MathUtils.constrainedMap((float) minInt, (float) maxInt, minFloat,
+                    maxFloat, brightnessFloat));
+        }
+    }
+
+    private static float getScreenBrightnessFloat(Context context) {
+        return Settings.System.getFloatForUser(context.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_FLOAT, Float.NaN, UserHandle.USER_CURRENT);
+    }
+
+    private static int getScreenBrightnessInt(Context context) {
+        return Settings.System.getIntForUser(context.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS, 0, UserHandle.USER_CURRENT);
+    }
+
+    private float mPreferredSettingValue;
+
+    /**
+     * Updates the float setting based on a passed in int value. This is called whenever the int
+     * setting changes. mWriteHistory keeps a record of the values that been written to the settings
+     * from either this method or updateBrightnessIntFromFloat. This is to ensure that the value
+     * being set is due to an external value being set, rather than the updateBrightness* methods.
+     * The intention of this is to avoid race conditions when the setting is being changed
+     * frequently and to ensure we are not reacting to settings changes from this file.
+     * @param value Brightness value as int to store in the float setting.
+     */
+    private void updateBrightnessFloatFromInt(int value) {
+        Object topOfQueue = mWriteHistory.peek();
+        if (topOfQueue != null && topOfQueue.equals(value)) {
+            mWriteHistory.poll();
+        } else {
+            if (brightnessFloatToInt(mContext, mPreferredSettingValue) == value) {
+                return;
+            }
+            float newBrightnessFloat = brightnessIntToFloat(mContext, value);
+            mWriteHistory.offer(newBrightnessFloat);
+            mPreferredSettingValue = newBrightnessFloat;
+            Settings.System.putFloatForUser(mContext.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS_FLOAT, newBrightnessFloat,
+                    UserHandle.USER_CURRENT);
+        }
+    }
+
+    /**
+     * Updates the int setting based on a passed in float value. This is called whenever the float
+     * setting changes. mWriteHistory keeps a record of the values that been written to the settings
+     * from either this method or updateBrightnessFloatFromInt. This is to ensure that the value
+     * being set is due to an external value being set, rather than the updateBrightness* methods.
+     * The intention of this is to avoid race conditions when the setting is being changed
+     * frequently and to ensure we are not reacting to settings changes from this file.
+     * @param value Brightness setting as float to store in int setting.
+     */
+    private void updateBrightnessIntFromFloat(float value) {
+        int newBrightnessInt = brightnessFloatToInt(mContext, value);
+        Object topOfQueue = mWriteHistory.peek();
+        if (topOfQueue != null && topOfQueue.equals(value)) {
+            mWriteHistory.poll();
+        } else {
+            mWriteHistory.offer(newBrightnessInt);
+            mPreferredSettingValue = value;
+            Settings.System.putIntForUser(mContext.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS, newBrightnessInt, UserHandle.USER_CURRENT);
+        }
+    }
+
+    /**
+     * Tests whether two brightness float values are within a small enough tolerance
+     * of each other.
+     * @param a first float to compare
+     * @param b second float to compare
+     * @return whether the two values are within a small enough tolerance value
+     */
+    public static boolean floatEquals(float a, float b) {
+        if (a == b) {
+            return true;
+        } else if (Float.isNaN(a) && Float.isNaN(b)) {
+            return true;
+        } else if (Math.abs(a - b) < EPSILON) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private class BrightnessSyncObserver extends ContentObserver {
+        /**
+         * Creates a content observer.
+         * @param handler The handler to run {@link #onChange} on, or null if none.
+         */
+        BrightnessSyncObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            onChange(selfChange, null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (selfChange) {
+                return;
+            }
+            if (BRIGHTNESS_URI.equals(uri)) {
+                int currentBrightness = getScreenBrightnessInt(mContext);
+                mHandler.obtainMessage(MSG_UPDATE_FLOAT, currentBrightness, 0).sendToTarget();
+            } else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
+                float currentFloat = getScreenBrightnessFloat(mContext);
+                int toSend = Float.floatToIntBits(currentFloat);
+                mHandler.obtainMessage(MSG_UPDATE_INT, toSend, 0).sendToTarget();
+            }
+        }
+
+        public void startObserving() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.unregisterContentObserver(this);
+            cr.registerContentObserver(BRIGHTNESS_URI, false, this, UserHandle.USER_ALL);
+            cr.registerContentObserver(BRIGHTNESS_FLOAT_URI, false, this, UserHandle.USER_ALL);
+        }
+
+        public void stopObserving() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.unregisterContentObserver(this);
+        }
+    }
+}
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index f8143de8..b723b53 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -161,6 +161,8 @@
         optional SettingProto brightness_for_vr = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto brightness_mode = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto auto_brightness_adj = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto brightness_float = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto brightness_for_vr_float = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Screen screen = 22;
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index df63306..8080412 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1258,32 +1258,63 @@
     -->
     <integer name="config_doubleTapOnHomeBehavior">0</integer>
 
-    <!-- Minimum screen brightness setting allowed by the power manager.
-         The user is forbidden from setting the brightness below this level. -->
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingMinimumFloat instead -->
     <integer name="config_screenBrightnessSettingMinimum">10</integer>
 
-    <!-- Maximum screen brightness allowed by the power manager.
-         The user is forbidden from setting the brightness above this level. -->
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingMaximumFloat instead -->
     <integer name="config_screenBrightnessSettingMaximum">255</integer>
 
-    <!-- Default screen brightness setting.
-         Must be in the range specified by minimum and maximum. -->
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingDefaultFloat instead -->
     <integer name="config_screenBrightnessSettingDefault">102</integer>
 
-    <!-- Default screen brightness for VR setting. -->
+    <!-- Minimum screen brightness setting allowed by power manager.
+        The user is forbidden from setting the brightness below this level.
+        Equivalent to 10/255. -->
+    <item name="config_screenBrightnessSettingMinimumFloat" format="float" type="dimen">0.035433073</item>
+
+    <!-- Maximum screen brightness allowed by the power manager.
+         The user is forbidden from setting the brightness above this level.
+         This value is a fraction between 3.5% and 100%. -->
+    <item name="config_screenBrightnessSettingMaximumFloat" format="float" type="dimen">1.0</item>
+
+    <!-- Default screen brightness setting.
+         Must be in the range specified by minimum and maximum.
+         This value is a fraction between 3.5% and 100%.
+         Equivalent to 102/255 (default for this device)    -->
+    <item name="config_screenBrightnessSettingDefaultFloat" format="float" type="dimen">0.397637795276</item>
+
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingForVrDefaultFloat instead -->
     <integer name="config_screenBrightnessForVrSettingDefault">86</integer>
 
-    <!-- Minimum screen brightness setting allowed for VR. Device panels start increasing pulse
-         width as brightness decreases below this theshold. -->
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingForVrMinimumFloat instead -->
     <integer name="config_screenBrightnessForVrSettingMinimum">79</integer>
 
-    <!-- Maximum screen brightness setting allowed for VR. -->
+    <!-- Note: This setting is deprecated, please use
+    config_screenBrightnessSettingForVrMaximumFloat instead -->
     <integer name="config_screenBrightnessForVrSettingMaximum">255</integer>
 
+    <!-- Default screen brightness for VR setting as a float.
+    Equivalent to 86/255-->
+    <item name="config_screenBrightnessSettingForVrDefaultFloat" format="float" type="dimen">0.33464</item>
+
+    <!-- Minimum screen brightness setting allowed for VR. Device panels start increasing pulse
+     width as brightness decreases below this threshold as float.
+     Equivalent to 79/255 -->
+    <item name="config_screenBrightnessSettingForVrMinimumFloat" format="float" type="dimen">0.307087</item>
+
+    <!-- Maximum screen brightness setting allowed for VR as float. -->
+    <item name="config_screenBrightnessSettingForVrMaximumFloat" format="float" type="dimen">1.0</item>
+
     <!-- Screen brightness used to dim the screen while dozing in a very low power state.
          May be less than the minimum allowed brightness setting
          that can be set by the user. -->
     <integer name="config_screenBrightnessDoze">1</integer>
+    <item name="config_screenBrightnessDozeFloat" format="float" type="dimen">0.0</item>
 
     <!-- Delay that allows some content to arrive at the display before switching
          from DOZE to ON. -->
@@ -1339,6 +1370,7 @@
          timeout expires.  May be less than the minimum allowed brightness setting
          that can be set by the user. -->
     <integer name="config_screenBrightnessDim">10</integer>
+    <item name="config_screenBrightnessDimFloat" format="float" type="dimen">0.05</item>
 
     <!-- Minimum allowable screen brightness to use in a very dark room.
          This value sets the floor for the darkest possible auto-brightness
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0babe48..f8aa3dc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1980,6 +1980,14 @@
   <java-symbol type="integer" name="config_screenBrightnessForVrSettingDefault" />
   <java-symbol type="integer" name="config_screenBrightnessForVrSettingMaximum" />
   <java-symbol type="integer" name="config_screenBrightnessForVrSettingMinimum" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingForVrMinimumFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingForVrMaximumFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingForVrDefaultFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingMinimumFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingMaximumFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessSettingDefaultFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessDozeFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessDimFloat" />
   <java-symbol type="integer" name="config_screenBrightnessDark" />
   <java-symbol type="integer" name="config_screenBrightnessDim" />
   <java-symbol type="integer" name="config_screenBrightnessDoze" />
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index 5a3724f..be79355 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -42,7 +42,7 @@
 
     public void onClick(View v) {
         DisplayManager dm = getSystemService(DisplayManager.class);
-        dm.setTemporaryBrightness(0);
+        dm.setTemporaryBrightness(0.0f);
         Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
index 55723f9..57d9594 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
@@ -20,7 +20,8 @@
 
 public class BrightnessUtils {
 
-    public static final int GAMMA_SPACE_MAX = 1023;
+    public static final int GAMMA_SPACE_MIN = 0;
+    public static final int GAMMA_SPACE_MAX = 65535;
 
     // Hybrid Log Gamma constant values
     private static final float R = 0.5f;
@@ -51,7 +52,7 @@
      * @return The corresponding setting value.
      */
     public static final int convertGammaToLinear(int val, int min, int max) {
-        final float normalizedVal = MathUtils.norm(0, GAMMA_SPACE_MAX, val);
+        final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val);
         final float ret;
         if (normalizedVal <= R) {
             ret = MathUtils.sq(normalizedVal / R);
@@ -65,6 +66,29 @@
     }
 
     /**
+     * Version of {@link #convertGammaToLinear} that takes and returns float values.
+     * TODO: brightnessfloat Merge with above method later.
+     *
+     * @param val The slider value.
+     * @param min The minimum acceptable value for the setting.
+     * @param max The maximum acceptable value for the setting.
+     * @return The corresponding setting value.
+     */
+    public static final float convertGammaToLinearFloat(int val, float min, float max) {
+        final float normalizedVal = MathUtils.norm(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, val);
+        final float ret;
+        if (normalizedVal <= R) {
+            ret = MathUtils.sq(normalizedVal / R);
+        } else {
+            ret = MathUtils.exp((normalizedVal - C) / A) + B;
+        }
+
+        // HLG is normalized to the range [0, 12], so we need to re-normalize to the range [0, 1]
+        // in order to derive the correct setting value.
+        return MathUtils.lerp(min, max, ret / 12);
+    }
+
+    /**
      * A function for converting from the linear space that the setting works in to the
      * gamma space that the slider works in.
      *
@@ -96,6 +120,27 @@
             ret = A * MathUtils.log(normalizedVal - B) + C;
         }
 
-        return Math.round(MathUtils.lerp(0, GAMMA_SPACE_MAX, ret));
+        return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
+    }
+
+    /**
+     * Version of {@link #convertLinearToGamma} that takes float values.
+     * TODO: brightnessfloat merge with above method(?)
+     * @param val The brightness setting value.
+     * @param min The minimum acceptable value for the setting.
+     * @param max The maximum acceptable value for the setting.
+     * @return The corresponding slider value
+     */
+    public static final int convertLinearToGammaFloat(float val, float min, float max) {
+        // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1]
+        final float normalizedVal = MathUtils.norm(min, max, val) * 12;
+        final float ret;
+        if (normalizedVal <= 1f) {
+            ret = MathUtils.sqrt(normalizedVal) * R;
+        } else {
+            ret = A * MathUtils.log(normalizedVal - B) + C;
+        }
+
+        return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 78b9f16..66d8306 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2727,6 +2727,12 @@
         dumpSetting(s, p,
                 Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
                 SystemSettingsProto.Screen.AUTO_BRIGHTNESS_ADJ);
+        dumpSetting(s, p,
+                Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                SystemSettingsProto.Screen.BRIGHTNESS_FLOAT);
+        dumpSetting(s, p,
+                Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT,
+                SystemSettingsProto.Screen.BRIGHTNESS_FOR_VR_FLOAT);
         p.end(screenToken);
 
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index dee1d7e..bf817b1 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -99,7 +99,9 @@
                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
                     Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
                     Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
-                    Settings.System.PEAK_REFRESH_RATE // depends on hardware capabilities
+                    Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
+                    Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT
                     );
 
     private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index ca2226f..c45063a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -203,7 +203,7 @@
         mDozeService.setDozeScreenBrightness(clampToUserSetting(mDefaultDozeBrightness));
         mDozeHost.setAodDimmingScrim(0f);
     }
-
+    //TODO: brightnessfloat change usages to float.
     private int clampToUserSetting(int brightness) {
         int userSetting = Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.SCREEN_BRIGHTNESS, Integer.MAX_VALUE,
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index b1f1f38..821144a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -17,8 +17,8 @@
 package com.android.systemui.settings;
 
 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
-import static com.android.settingslib.display.BrightnessUtils.convertGammaToLinear;
-import static com.android.settingslib.display.BrightnessUtils.convertLinearToGamma;
+import static com.android.settingslib.display.BrightnessUtils.convertGammaToLinearFloat;
+import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat;
 
 import android.animation.ValueAnimator;
 import android.content.ContentResolver;
@@ -39,7 +39,9 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.Log;
+import android.util.MathUtils;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -58,12 +60,21 @@
     private static final int MSG_DETACH_LISTENER = 4;
     private static final int MSG_VR_MODE_CHANGED = 5;
 
-    private final int mMinimumBacklight;
-    private final int mMaximumBacklight;
-    private final int mDefaultBacklight;
-    private final int mMinimumBacklightForVr;
-    private final int mMaximumBacklightForVr;
-    private final int mDefaultBacklightForVr;
+    private static final Uri BRIGHTNESS_MODE_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
+    private static final Uri BRIGHTNESS_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+    private static final Uri BRIGHTNESS_FLOAT_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
+    private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI =
+            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT);
+
+    private final float mMinimumBacklight;
+    private final float mMaximumBacklight;
+    private final float mDefaultBacklight;
+    private final float mMinimumBacklightForVr;
+    private final float mMaximumBacklightForVr;
+    private final float mDefaultBacklightForVr;
 
     private final Context mContext;
     private final ToggleSlider mControl;
@@ -90,16 +101,9 @@
         public void onBrightnessLevelChanged();
     }
 
-    /** ContentObserver to watch brightness **/
+    /** ContentObserver to watch brightness */
     private class BrightnessObserver extends ContentObserver {
 
-        private final Uri BRIGHTNESS_MODE_URI =
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
-        private final Uri BRIGHTNESS_URI =
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
-        private final Uri BRIGHTNESS_FOR_VR_URI =
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
-
         public BrightnessObserver(Handler handler) {
             super(handler);
         }
@@ -116,9 +120,9 @@
             if (BRIGHTNESS_MODE_URI.equals(uri)) {
                 mBackgroundHandler.post(mUpdateModeRunnable);
                 mBackgroundHandler.post(mUpdateSliderRunnable);
-            } else if (BRIGHTNESS_URI.equals(uri)) {
+            } else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
-            } else if (BRIGHTNESS_FOR_VR_URI.equals(uri)) {
+            } else if (BRIGHTNESS_FOR_VR_FLOAT_URI.equals(uri)) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             } else {
                 mBackgroundHandler.post(mUpdateModeRunnable);
@@ -139,7 +143,10 @@
                     BRIGHTNESS_URI,
                     false, this, UserHandle.USER_ALL);
             cr.registerContentObserver(
-                    BRIGHTNESS_FOR_VR_URI,
+                    BRIGHTNESS_FLOAT_URI,
+                    false, this, UserHandle.USER_ALL);
+            cr.registerContentObserver(
+                    BRIGHTNESS_FOR_VR_FLOAT_URI,
                     false, this, UserHandle.USER_ALL);
         }
 
@@ -229,18 +236,21 @@
     private final Runnable mUpdateSliderRunnable = new Runnable() {
         @Override
         public void run() {
-            final int val;
+            final float valFloat;
             final boolean inVrMode = mIsVrModeEnabled;
             if (inVrMode) {
-                val = Settings.System.getIntForUser(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mDefaultBacklightForVr,
+                valFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mDefaultBacklightForVr,
                         UserHandle.USER_CURRENT);
             } else {
-                val = Settings.System.getIntForUser(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS, mDefaultBacklight,
+                valFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_FLOAT, mDefaultBacklight,
                         UserHandle.USER_CURRENT);
             }
-            mHandler.obtainMessage(MSG_UPDATE_SLIDER, val, inVrMode ? 1 : 0).sendToTarget();
+            // Value is passed as intbits, since this is what the message takes.
+            final int valueAsIntBits = Float.floatToIntBits(valFloat);
+            mHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
+                    inVrMode ? 1 : 0).sendToTarget();
         }
     };
 
@@ -259,7 +269,7 @@
             try {
                 switch (msg.what) {
                     case MSG_UPDATE_SLIDER:
-                        updateSlider(msg.arg1, msg.arg2 != 0);
+                        updateSlider(Float.intBitsToFloat(msg.arg1), msg.arg2 != 0);
                         break;
                     case MSG_SET_CHECKED:
                         mControl.setChecked(msg.arg1 != 0);
@@ -298,12 +308,19 @@
         mBrightnessObserver = new BrightnessObserver(mHandler);
 
         PowerManager pm = context.getSystemService(PowerManager.class);
-        mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
-        mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
-        mDefaultBacklight = pm.getDefaultScreenBrightnessSetting();
-        mMinimumBacklightForVr = pm.getMinimumScreenBrightnessForVrSetting();
-        mMaximumBacklightForVr = pm.getMaximumScreenBrightnessForVrSetting();
-        mDefaultBacklightForVr = pm.getDefaultScreenBrightnessForVrSetting();
+        mMinimumBacklight = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+        mMaximumBacklight = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+        mDefaultBacklight = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
+        mMinimumBacklightForVr = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
+        mMaximumBacklightForVr = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR);
+        mDefaultBacklightForVr = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR);
+
 
         mAutomaticAvailable = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
@@ -344,37 +361,39 @@
             mSliderAnimator.cancel();
         }
 
-        final int min;
-        final int max;
+        final float minBacklight;
+        final float maxBacklight;
         final int metric;
-        final String setting;
+        final String settingToChange;
 
         if (mIsVrModeEnabled) {
             metric = MetricsEvent.ACTION_BRIGHTNESS_FOR_VR;
-            min = mMinimumBacklightForVr;
-            max = mMaximumBacklightForVr;
-            setting = Settings.System.SCREEN_BRIGHTNESS_FOR_VR;
+            minBacklight = mMinimumBacklightForVr;
+            maxBacklight = mMaximumBacklightForVr;
+            settingToChange = Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT;
         } else {
             metric = mAutomatic
                     ? MetricsEvent.ACTION_BRIGHTNESS_AUTO
                     : MetricsEvent.ACTION_BRIGHTNESS;
-            min = mMinimumBacklight;
-            max = mMaximumBacklight;
-            setting = Settings.System.SCREEN_BRIGHTNESS;
+            minBacklight = mMinimumBacklight;
+            maxBacklight = mMaximumBacklight;
+            settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT;
         }
-
-        final int val = convertGammaToLinear(value, min, max);
-
+        final float valFloat = MathUtils.min(convertGammaToLinearFloat(value,
+                minBacklight, maxBacklight),
+                1.0f);
         if (stopTracking) {
-            MetricsLogger.action(mContext, metric, val);
-        }
+            // TODO(brightnessfloat): change to use float value instead.
+            MetricsLogger.action(mContext, metric,
+                    BrightnessSynchronizer.brightnessFloatToInt(mContext, valFloat));
 
-        setBrightness(val);
+        }
+        setBrightness(valFloat);
         if (!tracking) {
             AsyncTask.execute(new Runnable() {
                     public void run() {
-                        Settings.System.putIntForUser(mContext.getContentResolver(),
-                                setting, val, UserHandle.USER_CURRENT);
+                        Settings.System.putFloatForUser(mContext.getContentResolver(),
+                                settingToChange, valFloat, UserHandle.USER_CURRENT);
                     }
                 });
         }
@@ -402,7 +421,7 @@
                 mUserTracker.getCurrentUserId());
     }
 
-    private void setBrightness(int brightness) {
+    private void setBrightness(float brightness) {
         mDisplayManager.setTemporaryBrightness(brightness);
     }
 
@@ -413,9 +432,9 @@
         }
     }
 
-    private void updateSlider(int val, boolean inVrMode) {
-        final int min;
-        final int max;
+    private void updateSlider(float brightnessValue, boolean inVrMode) {
+        final float min;
+        final float max;
         if (inVrMode) {
             min = mMinimumBacklightForVr;
             max = mMaximumBacklightForVr;
@@ -423,7 +442,10 @@
             min = mMinimumBacklight;
             max = mMaximumBacklight;
         }
-        if (val == convertGammaToLinear(mControl.getValue(), min, max)) {
+        // convertGammaToLinearFloat returns 0-1
+        if (BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessValue)
+                == BrightnessSynchronizer.brightnessFloatToInt(mContext,
+                convertGammaToLinearFloat(mControl.getValue(), min, max))) {
             // If we have more resolution on the slider than we do in the actual setting, then
             // multiple slider positions will map to the same setting value. Thus, if we see a
             // setting value here that maps to the current slider position, we don't bother to
@@ -431,7 +453,8 @@
             // change to the user even though it isn't one.
             return;
         }
-        final int sliderVal = convertLinearToGamma(val, min, max);
+        // Returns GAMMA_SPACE_MIN - GAMMA_SPACE_MAX
+        final int sliderVal = convertLinearToGammaFloat(brightnessValue, min, max);
         animateSliderTo(sliderVal);
     }
 
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index c99774a..6178e6c 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -21,6 +21,7 @@
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
 import android.app.TaskStackListener;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.hardware.Sensor;
@@ -41,6 +42,7 @@
 import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.EventLogTags;
@@ -89,6 +91,8 @@
     // The minimum and maximum screen brightnesses.
     private final int mScreenBrightnessRangeMinimum;
     private final int mScreenBrightnessRangeMaximum;
+    private final float mScreenBrightnessRangeMinimumFloat;
+    private final float mScreenBrightnessRangeMaximumFloat;
 
     // How much to scale doze brightness by (should be (0, 1.0]).
     private final float mDozeScaleFactor;
@@ -174,7 +178,7 @@
     // that we can quickly revert to the previous auto-brightness level
     // while the light sensor warms up.
     // Use -1 if there is no current auto-brightness value available.
-    private int mScreenAutoBrightness = -1;
+    private int mScreenAutoBrightness = PowerManager.BRIGHTNESS_INVALID;
 
     // The current display policy. This is useful, for example,  for knowing when we're dozing,
     // where the light sensor may not be available.
@@ -204,39 +208,44 @@
     private TaskStackListenerImpl mTaskStackListener;
     private IActivityTaskManager mActivityTaskManager;
     private PackageManager mPackageManager;
+    private Context mContext;
 
     private final Injector mInjector;
 
     AutomaticBrightnessController(Callbacks callbacks, Looper looper,
             SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper,
-            int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
-            int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
-            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
-            HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds,
-            PackageManager packageManager) {
+            int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+            float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+            long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+            boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
+            HysteresisLevels screenBrightnessThresholds, Context context) {
         this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
                 lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
                 lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
                 darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
-                ambientBrightnessThresholds, screenBrightnessThresholds, packageManager);
+                ambientBrightnessThresholds, screenBrightnessThresholds, context);
     }
 
     @VisibleForTesting
     AutomaticBrightnessController(Injector injector, Callbacks callbacks, Looper looper,
             SensorManager sensorManager, Sensor lightSensor, BrightnessMappingStrategy mapper,
-            int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
-            int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
-            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
-            HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds,
-            PackageManager packageManager) {
+            int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+            float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+            long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+            boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
+            HysteresisLevels screenBrightnessThresholds, Context context) {
         mInjector = injector;
+        mContext = context;
         mCallbacks = callbacks;
         mSensorManager = sensorManager;
         mBrightnessMapper = mapper;
-        mScreenBrightnessRangeMinimum = brightnessMin;
-        mScreenBrightnessRangeMaximum = brightnessMax;
+        mScreenBrightnessRangeMinimum =
+                BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessMin);
+        mScreenBrightnessRangeMaximum =
+                com.android.internal.BrightnessSynchronizer.brightnessFloatToInt(
+                        mContext, brightnessMax);
+        mScreenBrightnessRangeMinimumFloat = brightnessMin;
+        mScreenBrightnessRangeMaximumFloat = brightnessMax;
         mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;
         mDozeScaleFactor = dozeScaleFactor;
         mNormalLightSensorRate = lightSensorRate;
@@ -261,7 +270,7 @@
         }
 
         mActivityTaskManager = ActivityTaskManager.getService();
-        mPackageManager = packageManager;
+        mPackageManager = mContext.getPackageManager();
         mTaskStackListener = new TaskStackListenerImpl();
         mForegroundAppPackageName = null;
         mPendingForegroundAppPackageName = null;
@@ -291,7 +300,7 @@
             return -1;
         }
         if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
-            return (int) (mScreenAutoBrightness * mDozeScaleFactor);
+            return Math.round(mScreenAutoBrightness * mDozeScaleFactor);
         }
         return mScreenAutoBrightness;
     }
@@ -473,7 +482,7 @@
         } else if (mLightSensorEnabled) {
             mLightSensorEnabled = false;
             mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
-            mScreenAutoBrightness = -1;
+            mScreenAutoBrightness = PowerManager.BRIGHTNESS_INVALID;
             mRecentLightSamples = 0;
             mAmbientLightRingBuffer.clear();
             mCurrentLightSensorRate = -1;
@@ -722,10 +731,8 @@
 
         float value = mBrightnessMapper.getBrightness(mAmbientLux, mForegroundAppPackageName,
                 mForegroundAppCategory);
-
-        int newScreenAutoBrightness = Math.round(clampScreenBrightness(
-                value * PowerManager.BRIGHTNESS_ON));
-
+        int newScreenAutoBrightness = BrightnessSynchronizer.brightnessFloatToInt(
+                mContext, clampScreenBrightnessFloat(value));
         // If screenAutoBrightness is set, we should have screen{Brightening,Darkening}Threshold,
         // in which case we ignore the new screen brightness if it doesn't differ enough from the
         // previous one.
@@ -759,11 +766,19 @@
         }
     }
 
+    // Clamps values with float range [1.0-255.0]
+    // TODO(brightnessfloat): convert everything that uses this to float system
     private float clampScreenBrightness(float value) {
         return MathUtils.constrain(value,
                 mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
     }
 
+    // Clamps values with float range [0.0-1.0]
+    private float clampScreenBrightnessFloat(float value) {
+        return MathUtils.constrain(value,
+                mScreenBrightnessRangeMinimumFloat, mScreenBrightnessRangeMaximumFloat);
+    }
+
     private void prepareBrightnessAdjustmentSample() {
         if (!mBrightnessAdjustmentSamplePending) {
             mBrightnessAdjustmentSamplePending = true;
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 6ff2767..a099606 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -28,6 +28,7 @@
 import android.util.Slog;
 import android.util.Spline;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
@@ -342,9 +343,9 @@
     }
 
     protected static float normalizeAbsoluteBrightness(int brightness) {
-        brightness = MathUtils.constrain(brightness,
-                PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
-        return (float) brightness / PowerManager.BRIGHTNESS_ON;
+        return BrightnessSynchronizer.brightnessIntToFloat(brightness,
+                PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
     }
 
     private Pair<float[], float[]> insertControlPoint(
diff --git a/services/core/java/com/android/server/display/DisplayBlanker.java b/services/core/java/com/android/server/display/DisplayBlanker.java
index 816dc13..d294898 100644
--- a/services/core/java/com/android/server/display/DisplayBlanker.java
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -20,5 +20,5 @@
  * Interface used to update the actual display state.
  */
 public interface DisplayBlanker {
-    void requestDisplayState(int state, int brightness);
+    void requestDisplayState(int state, float brightness);
 }
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index e69a3b8b..63a8d7c 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -129,11 +129,11 @@
      * Sets the display state, if supported.
      *
      * @param state The new display state.
-     * @param brightness The new display brightness.
+     * @param brightnessState The new display brightnessState.
      * @return A runnable containing work to be deferred until after we have
      * exited the critical section, or null if none.
      */
-    public Runnable requestDisplayStateLocked(int state, int brightness) {
+    public Runnable requestDisplayStateLocked(int state, float brightnessState) {
         return null;
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 71ade62..9140589 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -232,7 +232,7 @@
 
     // The overall display brightness.
     // For now, this only applies to the built-in display but we may split it up eventually.
-    private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+    private float mGlobalDisplayBrightness;
 
     // Set to true when there are pending display changes that have yet to be applied
     // to the surface flinger state.
@@ -340,7 +340,8 @@
         mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
 
         PowerManager pm = mContext.getSystemService(PowerManager.class);
-        mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
+        mGlobalDisplayBrightness = pm.getBrightnessConstraint(
+                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
         mCurrentUserId = UserHandle.USER_SYSTEM;
         ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
         mWideColorSpace = colorSpaces[1];
@@ -539,16 +540,16 @@
         }
     }
 
-    private void requestGlobalDisplayStateInternal(int state, int brightness) {
+    private void requestGlobalDisplayStateInternal(int state, float brightnessState) {
         if (state == Display.STATE_UNKNOWN) {
             state = Display.STATE_ON;
         }
         if (state == Display.STATE_OFF) {
-            brightness = PowerManager.BRIGHTNESS_OFF;
-        } else if (brightness < 0) {
-            brightness = PowerManager.BRIGHTNESS_DEFAULT;
-        } else if (brightness > PowerManager.BRIGHTNESS_ON) {
-            brightness = PowerManager.BRIGHTNESS_ON;
+            brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
+        } else if (brightnessState < PowerManager.BRIGHTNESS_MIN || Float.isNaN(brightnessState)) {
+            brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        } else if (brightnessState > PowerManager.BRIGHTNESS_MAX) {
+            brightnessState = PowerManager.BRIGHTNESS_MAX;
         }
 
         synchronized (mTempDisplayStateWorkQueue) {
@@ -558,15 +559,15 @@
                 // may happen as a side-effect of displays changing state.
                 synchronized (mSyncRoot) {
                     if (mGlobalDisplayState == state
-                            && mGlobalDisplayBrightness == brightness) {
+                            && mGlobalDisplayBrightness == brightnessState) {
                         return; // no change
                     }
 
                     Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
                             + Display.stateToString(state)
-                            + ", brightness=" + brightness + ")");
+                            + ", brightness=" + brightnessState + ")");
                     mGlobalDisplayState = state;
-                    mGlobalDisplayBrightness = brightness;
+                    mGlobalDisplayBrightness = brightnessState;
                     applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
                 }
 
@@ -1023,7 +1024,8 @@
         // by the display power controller (if known).
         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-            return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
+            return device.requestDisplayStateLocked(
+                    mGlobalDisplayState, mGlobalDisplayBrightness);
         }
         return null;
     }
@@ -2300,7 +2302,7 @@
         }
 
         @Override // Binder call
-        public void setTemporaryBrightness(int brightness) {
+        public void setTemporaryBrightness(float brightness) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
                     "Permission required to set the display's brightness");
@@ -2419,7 +2421,7 @@
             synchronized (mSyncRoot) {
                 DisplayBlanker blanker = new DisplayBlanker() {
                     @Override
-                    public void requestDisplayState(int state, int brightness) {
+                    public void requestDisplayState(int state, float brightness) {
                         // The order of operations is important for legacy reasons.
                         if (state == Display.STATE_OFF) {
                             requestGlobalDisplayStateInternal(state, brightness);
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index e87ad41..0c6c797 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -108,8 +108,8 @@
                 "Permission required to set the display's brightness");
         final long token = Binder.clearCallingIdentity();
         try {
-            Settings.System.putIntForUser(context.getContentResolver(),
-                    Settings.System.SCREEN_BRIGHTNESS, (int) (brightness * 255),
+            Settings.System.putFloatForUser(context.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightness,
                     UserHandle.USER_CURRENT);
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 96532f4..8bbeabf 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -946,9 +946,9 @@
      * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}.
      */
     private class BrightnessObserver extends ContentObserver {
+        // TODO: brightnessfloat: change this to the float setting
         private final Uri mDisplayBrightnessSetting =
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
-
         private final static int LIGHT_SENSOR_RATE_MS = 250;
         private int[] mDisplayBrightnessThresholds;
         private int[] mAmbientBrightnessThresholds;
@@ -1174,7 +1174,7 @@
 
             return false;
         }
-
+        // TODO: brightnessfloat: make it use float not int
         private void onBrightnessChangedLocked() {
             int brightness = Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.SCREEN_BRIGHTNESS, -1);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f1655f0..197842e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -51,6 +51,7 @@
 import android.util.TimeUtils;
 import android.view.Display;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -102,7 +103,8 @@
     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
 
     // The minimum reduction in brightness when dimmed.
-    private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
+    private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f;
+    private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
 
     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
     private static final int COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS = 400;
@@ -169,28 +171,27 @@
     private Sensor mProximitySensor;
 
     // The doze screen brightness.
-    private final int mScreenBrightnessDozeConfig;
+    private final float mScreenBrightnessDozeConfig;
 
     // The dim screen brightness.
-    private final int mScreenBrightnessDimConfig;
+    private final float mScreenBrightnessDimConfig;
 
     // The minimum allowed brightness.
-    private final int mScreenBrightnessRangeMinimum;
+    private final float mScreenBrightnessRangeMinimum;
 
     // The maximum allowed brightness.
-    private final int mScreenBrightnessRangeMaximum;
+    private final float mScreenBrightnessRangeMaximum;
 
-    // The default screen brightness.
-    private final int mScreenBrightnessDefault;
+    private final float mScreenBrightnessDefault;
 
     // The minimum allowed brightness while in VR.
-    private final int mScreenBrightnessForVrRangeMinimum;
+    private final float mScreenBrightnessForVrRangeMinimum;
 
     // The maximum allowed brightness while in VR.
-    private final int mScreenBrightnessForVrRangeMaximum;
+    private final float mScreenBrightnessForVrRangeMaximum;
 
     // The default screen brightness for VR.
-    private final int mScreenBrightnessForVrDefault;
+    private final float mScreenBrightnessForVrDefault;
 
     // True if auto-brightness should be used.
     private boolean mUseSoftwareAutoBrightnessConfig;
@@ -317,8 +318,9 @@
     private BrightnessReason mBrightnessReasonTemp = new BrightnessReason();
 
     // Brightness animation ramp rates in brightness units per second
-    private final int mBrightnessRampRateFast;
-    private final int mBrightnessRampRateSlow;
+    private final float mBrightnessRampRateSlow = 0.2352941f;
+    private final float mBrightnessRampRateFast = 0.7058823f;
+
 
     // Whether or not to skip the initial brightness ramps into STATE_ON.
     private final boolean mSkipScreenOnBrightnessRamp;
@@ -333,7 +335,7 @@
     private int mSkipRampState = RAMP_STATE_SKIP_NONE;
 
     // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
-    private int mInitialAutoBrightness;
+    private float mInitialAutoBrightness;
 
     // The controller for the automatic brightness level.
     private AutomaticBrightnessController mAutomaticBrightnessController;
@@ -348,24 +350,24 @@
 
     // The last brightness that was set by the user and not temporary. Set to -1 when a brightness
     // has yet to be recorded.
-    private int mLastUserSetScreenBrightness;
+    private float mLastUserSetScreenBrightness;
 
     // The screen brightenss setting has changed but not taken effect yet. If this is different
     // from the current screen brightness setting then this is coming from something other than us
     // and should be considered a user interaction.
-    private int mPendingScreenBrightnessSetting;
+    private float mPendingScreenBrightnessSetting;
 
     // The last observed screen brightness setting, either set by us or by the settings app on
     // behalf of the user.
-    private int mCurrentScreenBrightnessSetting;
+    private float mCurrentScreenBrightnessSetting;
 
     // The temporary screen brightness. Typically set when a user is interacting with the
-    // brightness slider but hasn't settled on a choice yet. Set to -1 when there's no temporary
-    // brightness set.
-    private int mTemporaryScreenBrightness;
+    // brightness slider but hasn't settled on a choice yet. Set to
+    // PowerManager.BRIGHNTESS_INVALID_FLOAT when there's no temporary brightness set.
+    private float mTemporaryScreenBrightness;
 
     // The current screen brightness while in VR mode.
-    private int mScreenBrightnessForVr;
+    private float mScreenBrightnessForVr;
 
     // The last auto brightness adjustment that was set by the user and not temporary. Set to
     // Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
@@ -384,6 +386,8 @@
     private ObjectAnimator mColorFadeOffAnimator;
     private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
 
+    private BrightnessSynchronizer mBrightnessSynchronizer;
+
     /**
      * Creates the display power controller.
      */
@@ -394,37 +398,39 @@
         mBrightnessTracker = new BrightnessTracker(context, null);
         mSettingsObserver = new SettingsObserver(mHandler);
         mCallbacks = callbacks;
-
+        mBrightnessSynchronizer = new BrightnessSynchronizer(context);
         mBatteryStats = BatteryStatsService.getService();
         mSensorManager = sensorManager;
         mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
         mBlanker = blanker;
         mContext = context;
 
+        PowerManager pm =  context.getSystemService(PowerManager.class);
         final Resources resources = context.getResources();
-        final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger(
-                com.android.internal.R.integer.config_screenBrightnessSettingMinimum));
+        final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
 
-        mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
-                com.android.internal.R.integer.config_screenBrightnessDoze));
+        // DOZE AND DIM SETTINGS
+        mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
+        mScreenBrightnessDimConfig = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
 
-        mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
-                com.android.internal.R.integer.config_screenBrightnessDim));
-
+        // NORMAL SCREEN SETTINGS
         mScreenBrightnessRangeMinimum =
-                Math.min(screenBrightnessSettingMinimum, mScreenBrightnessDimConfig);
+                Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig);
+        mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM));
+        mScreenBrightnessDefault = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT));
 
-        mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessSettingMaximum));
-        mScreenBrightnessDefault = clampAbsoluteBrightness(resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessSettingDefault));
-
-        mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessForVrSettingMinimum));
-        mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessForVrSettingMaximum));
-        mScreenBrightnessForVrDefault = clampAbsoluteBrightness(resources.getInteger(
-                    com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault));
+        // VR SETTINGS
+        mScreenBrightnessForVrDefault = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR));
+        mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR));
+        mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
+                pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
 
         mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
@@ -432,10 +438,6 @@
         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
 
-        mBrightnessRampRateFast = resources.getInteger(
-                com.android.internal.R.integer.config_brightness_ramp_rate_fast);
-        mBrightnessRampRateSlow = resources.getInteger(
-                com.android.internal.R.integer.config_brightness_ramp_rate_slow);
         mSkipScreenOnBrightnessRamp = resources.getBoolean(
                 com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
 
@@ -496,7 +498,7 @@
                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
-                        screenBrightnessThresholds, context.getPackageManager());
+                        screenBrightnessThresholds, context);
             } else {
                 mUseSoftwareAutoBrightnessConfig = false;
             }
@@ -519,14 +521,13 @@
                         TYPICAL_PROXIMITY_THRESHOLD);
             }
         }
-
         mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
         mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
-        mTemporaryScreenBrightness = -1;
-        mPendingScreenBrightnessSetting = -1;
-        mTemporaryAutoBrightnessAdjustment = Float.NaN;
-        mPendingAutoBrightnessAdjustment = Float.NaN;
+        mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
 
         DisplayWhiteBalanceSettings displayWhiteBalanceSettings = null;
         DisplayWhiteBalanceController displayWhiteBalanceController = null;
@@ -681,28 +682,28 @@
         }
 
         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
-                mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
+                mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS_FLOAT);
         mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
 
         // Initialize screen state for battery stats.
         try {
             mBatteryStats.noteScreenState(mPowerState.getScreenState());
-            mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
+            mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(mContext,
+                    mPowerState.getScreenBrightness()));
         } catch (RemoteException ex) {
             // same process
         }
-
         // Initialize all of the brightness tracking state
-        final float brightness = convertToNits(mPowerState.getScreenBrightness());
+        final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(mContext,
+                mPowerState.getScreenBrightness()));
         if (brightness >= 0.0f) {
             mBrightnessTracker.start(brightness);
         }
-
         mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT),
                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
         mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT),
                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
@@ -776,8 +777,9 @@
 
         // Compute the basic display state using the policy.
         // We might override this below based on other factors.
+        // Initialise brightness as invalid.
         int state;
-        int brightness = PowerManager.BRIGHTNESS_DEFAULT;
+        float brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         boolean performScreenOffTransition = false;
         switch (mPowerRequest.policy) {
             case DisplayPowerRequest.POLICY_OFF:
@@ -791,7 +793,7 @@
                     state = Display.STATE_DOZE;
                 }
                 if (!mAllowAutoBrightnessWhileDozingConfig) {
-                    brightness = mPowerRequest.dozeScreenBrightness;
+                    brightnessState = mPowerRequest.dozeScreenBrightness;
                     mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
                 }
                 break;
@@ -843,20 +845,20 @@
         animateScreenStateChange(state, performScreenOffTransition);
         state = mPowerState.getScreenState();
 
-        // Use zero brightness when screen is off.
         if (state == Display.STATE_OFF) {
-            brightness = PowerManager.BRIGHTNESS_OFF;
+            brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
         }
 
         // Always use the VR brightness when in the VR state.
         if (state == Display.STATE_VR) {
-            brightness = mScreenBrightnessForVr;
+            brightnessState = mScreenBrightnessForVr;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
         }
 
-        if (brightness < 0 && mPowerRequest.screenBrightnessOverride > 0) {
-            brightness = mPowerRequest.screenBrightnessOverride;
+        if ((Float.isNaN(brightnessState))
+                && isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
+            brightnessState = mPowerRequest.screenBrightnessOverride;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
             mAppliedScreenBrightnessOverride = true;
         } else {
@@ -867,15 +869,15 @@
                 mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
         final boolean autoBrightnessEnabled = mPowerRequest.useAutoBrightness
                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
-                    && brightness < 0
+                    && Float.isNaN(brightnessState)
                     && mAutomaticBrightnessController != null;
 
         final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
 
         // Use the temporary screen brightness if there isn't an override, either from
         // WindowManager or based on the display state.
-        if (mTemporaryScreenBrightness > 0) {
-            brightness = mTemporaryScreenBrightness;
+        if (isValidBrightnessValue(mTemporaryScreenBrightness)) {
+            brightnessState = mTemporaryScreenBrightness;
             mAppliedTemporaryBrightness = true;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
         } else {
@@ -898,14 +900,13 @@
             brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO;
             mAppliedTemporaryAutoBrightnessAdjustment = false;
         }
-
         // Apply brightness boost.
         // We do this here after deciding whether auto-brightness is enabled so that we don't
         // disable the light sensor during this temporary state.  That way when boost ends we will
         // be able to resume normal auto-brightness behavior without any delay.
         if (mPowerRequest.boostScreenBrightness
-                && brightness != PowerManager.BRIGHTNESS_OFF) {
-            brightness = PowerManager.BRIGHTNESS_ON;
+                && brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT) {
+            brightnessState = PowerManager.BRIGHTNESS_MAX;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
             mAppliedBrightnessBoost = true;
         } else {
@@ -914,16 +915,15 @@
 
         // If the brightness is already set then it's been overridden by something other than the
         // user, or is a temporary adjustment.
-        boolean userInitiatedChange = brightness < 0
+        boolean userInitiatedChange = (Float.isNaN(brightnessState))
                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
-
         boolean hadUserBrightnessPoint = false;
         // Configure auto-brightness.
         if (mAutomaticBrightnessController != null) {
             hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
                     mBrightnessConfiguration,
-                    mLastUserSetScreenBrightness / (float) PowerManager.BRIGHTNESS_ON,
+                    mLastUserSetScreenBrightness,
                     userSetBrightnessChanged, autoBrightnessAdjustment,
                     autoBrightnessAdjustmentChanged, mPowerRequest.policy);
         }
@@ -934,17 +934,18 @@
 
         // Apply auto-brightness.
         boolean slowChange = false;
-        if (brightness < 0) {
+        if (Float.isNaN(brightnessState)) {
             float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
             if (autoBrightnessEnabled) {
-                brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();
+                brightnessState = BrightnessSynchronizer.brightnessIntToFloat(
+                mContext, mAutomaticBrightnessController.getAutomaticScreenBrightness());
                 newAutoBrightnessAdjustment =
                         mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
             }
-
-            if (brightness >= 0) {
+            if (isValidBrightnessValue(brightnessState)
+                    || brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
                 // Use current auto-brightness value and slowly adjust to changes.
-                brightness = clampScreenBrightness(brightness);
+                brightnessState = clampScreenBrightness(brightnessState);
                 if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
                     slowChange = true; // slowly adapt to auto-brightness
                 }
@@ -952,7 +953,7 @@
                 // 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);
+                putScreenBrightnessSetting(brightnessState);
                 mAppliedAutoBrightness = true;
                 mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
             } else {
@@ -970,24 +971,25 @@
             mAppliedAutoBrightness = false;
             brightnessAdjustmentFlags = 0;
         }
-
         // Use default brightness when dozing unless overridden.
-        if (brightness < 0 && Display.isDozeState(state)) {
-            brightness = mScreenBrightnessDozeConfig;
+        if ((Float.isNaN(brightnessState))
+                && Display.isDozeState(state)) {
+            brightnessState = mScreenBrightnessDozeConfig;
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
         }
 
         // Apply manual brightness.
-        if (brightness < 0) {
-            brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting);
+        if (Float.isNaN(brightnessState)) {
+            brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
             mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
         }
 
         // Apply dimming by at least some minimum amount when user activity
         // timeout is about to expire.
         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
-            if (brightness > mScreenBrightnessRangeMinimum) {
-                brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
+            if (brightnessState > mScreenBrightnessRangeMinimum) {
+                brightnessState = Math.max(Math.min(brightnessState
+                                - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
                         mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
             }
@@ -999,15 +1001,15 @@
             slowChange = false;
             mAppliedDimming = false;
         }
-
         // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
         // as long as it is above the minimum threshold.
         if (mPowerRequest.lowPowerMode) {
-            if (brightness > mScreenBrightnessRangeMinimum) {
+            if (brightnessState > mScreenBrightnessRangeMinimum) {
                 final float brightnessFactor =
                         Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
-                final int lowPowerBrightness = (int) (brightness * brightnessFactor);
-                brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
+                final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
+                brightnessState = Math.max(lowPowerBrightnessFloat,
+                        mScreenBrightnessRangeMinimum);
                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
             }
             if (!mAppliedLowPower) {
@@ -1025,11 +1027,12 @@
             if (mSkipScreenOnBrightnessRamp) {
                 if (state == Display.STATE_ON) {
                     if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
-                        mInitialAutoBrightness = brightness;
+                        mInitialAutoBrightness = brightnessState;
                         mSkipRampState = RAMP_STATE_SKIP_INITIAL;
                     } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
                             && mUseSoftwareAutoBrightnessConfig
-                            && brightness != mInitialAutoBrightness) {
+                            && !BrightnessSynchronizer.floatEquals(brightnessState,
+                            mInitialAutoBrightness)) {
                         mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
                     } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
                         mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -1056,9 +1059,9 @@
                     mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
             if (initialRampSkip || hasBrightnessBuckets
                     || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
-                animateScreenBrightness(brightness, 0);
+                animateScreenBrightness(brightnessState, SCREEN_ANIMATION_RATE_MINIMUM);
             } else {
-                animateScreenBrightness(brightness,
+                animateScreenBrightness(brightnessState,
                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             }
 
@@ -1069,14 +1072,16 @@
                     // slider event so notify as if the system changed the brightness.
                     userInitiatedChange = false;
                 }
-                notifyBrightnessChanged(brightness, userInitiatedChange, hadUserBrightnessPoint);
+                notifyBrightnessChanged(
+                        BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessState),
+                        userInitiatedChange, hadUserBrightnessPoint);
             }
 
         }
 
         // Log any changes to what is currently driving the brightness setting.
         if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
-            Slog.v(TAG, "Brightness [" + brightness + "] reason changing to: '"
+            Slog.v(TAG, "Brightness [" + brightnessState + "] reason changing to: '"
                     + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
                     + "', previous reason: '" + mBrightnessReason + "'.");
             mBrightnessReason.set(mBrightnessReasonTemp);
@@ -1161,9 +1166,9 @@
         msg.sendToTarget();
     }
 
-    public void setTemporaryBrightness(int brightness) {
+    public void setTemporaryBrightness(float brightness) {
         Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
-                brightness, 0 /*unused*/);
+                Float.floatToIntBits(brightness), 0 /*unused*/);
         msg.sendToTarget();
     }
 
@@ -1282,24 +1287,38 @@
         mReportedScreenStateToPolicy = state;
     }
 
-    private int clampScreenBrightnessForVr(int value) {
+    private float clampScreenBrightnessForVr(float value) {
         return MathUtils.constrain(
-                value, mScreenBrightnessForVrRangeMinimum, mScreenBrightnessForVrRangeMaximum);
+                value, mScreenBrightnessForVrRangeMinimum,
+                mScreenBrightnessForVrRangeMaximum);
     }
 
-    private int clampScreenBrightness(int value) {
+    private float clampScreenBrightness(float value) {
+        if (Float.isNaN(value)) {
+            return mScreenBrightnessRangeMinimum;
+        }
         return MathUtils.constrain(
                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
     }
 
-    private void animateScreenBrightness(int target, int rate) {
+    // Checks whether the brightness is within the valid brightness range, not including the off or
+    // invalid states.
+    private boolean isValidBrightnessValue(float brightnessState) {
+        return brightnessState >= mScreenBrightnessRangeMinimum
+                && brightnessState <= mScreenBrightnessRangeMaximum;
+    }
+
+    private void animateScreenBrightness(float target, float rate) {
         if (DEBUG) {
             Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
         }
         if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
-            Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
+            Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", (int) target);
             try {
-                mBatteryStats.noteScreenBrightness(target);
+                // TODO(brightnessfloat): change BatteryStats to use float
+                mBatteryStats.noteScreenBrightness(
+                        BrightnessSynchronizer.brightnessFloatToInt(
+                        mContext, target));
             } catch (RemoteException ex) {
                 // same process
             }
@@ -1578,6 +1597,7 @@
 
     private void handleSettingsChange(boolean userSwitch) {
         mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
+
         if (userSwitch) {
             // Don't treat user switches as user initiated change.
             mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
@@ -1598,24 +1618,24 @@
         return Float.isNaN(adj) ? 0.0f : clampAutoBrightnessAdjustment(adj);
     }
 
-    private int getScreenBrightnessSetting() {
-        final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessDefault,
+    private float getScreenBrightnessSetting() {
+        final float brightness = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_FLOAT, mScreenBrightnessDefault,
                 UserHandle.USER_CURRENT);
         return clampAbsoluteBrightness(brightness);
     }
 
-    private int getScreenBrightnessForVrSetting() {
-        final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrDefault,
+    private float getScreenBrightnessForVrSetting() {
+        final float brightnessFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mScreenBrightnessForVrDefault,
                 UserHandle.USER_CURRENT);
-        return clampScreenBrightnessForVr(brightness);
+        return clampScreenBrightnessForVr(brightnessFloat);
     }
 
-    private void putScreenBrightnessSetting(int brightness) {
-        mCurrentScreenBrightnessSetting = brightness;
-        Settings.System.putIntForUser(mContext.getContentResolver(),
-                Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
+    private void putScreenBrightnessSetting(float brightnessValue) {
+        mCurrentScreenBrightnessSetting = brightnessValue;
+        Settings.System.putFloatForUser(mContext.getContentResolver(),
+                Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightnessValue, UserHandle.USER_CURRENT);
     }
 
     private void putAutoBrightnessAdjustmentSetting(float adjustment) {
@@ -1638,18 +1658,19 @@
     }
 
     private boolean updateUserSetScreenBrightness() {
-        if (mPendingScreenBrightnessSetting < 0) {
+        if ((Float.isNaN(mPendingScreenBrightnessSetting)
+                || mPendingScreenBrightnessSetting < 0.0f)) {
             return false;
         }
         if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
-            mPendingScreenBrightnessSetting = -1;
-            mTemporaryScreenBrightness = -1;
+            mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+            mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
             return false;
         }
         mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
         mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
-        mPendingScreenBrightnessSetting = -1;
-        mTemporaryScreenBrightness = -1;
+        mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         return true;
     }
 
@@ -1728,8 +1749,6 @@
         pw.println("Display Power Controller Configuration:");
         pw.println("  mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
         pw.println("  mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
-        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
-        pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
         pw.println("  mScreenBrightnessDefault=" + mScreenBrightnessDefault);
         pw.println("  mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
         pw.println("  mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
@@ -1737,8 +1756,6 @@
         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
         pw.println("  mAllowAutoBrightnessWhileDozingConfig=" +
                 mAllowAutoBrightnessWhileDozingConfig);
-        pw.println("  mBrightnessRampRateFast=" + mBrightnessRampRateFast);
-        pw.println("  mBrightnessRampRateSlow=" + mBrightnessRampRateSlow);
         pw.println("  mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
@@ -1767,15 +1784,15 @@
         pw.println("  mPendingProximityDebounceTime="
                 + TimeUtils.formatUptime(mPendingProximityDebounceTime));
         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
-        pw.println("  mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness);
-        pw.println("  mCurrentScreenBrightnessSetting=" + mCurrentScreenBrightnessSetting);
-        pw.println("  mPendingScreenBrightnessSetting=" + mPendingScreenBrightnessSetting);
-        pw.println("  mTemporaryScreenBrightness=" + mTemporaryScreenBrightness);
+        pw.println("  mLastUserSetScreenBrightnessFloat=" + mLastUserSetScreenBrightness);
+        pw.println("  mPendingScreenBrightnessSettingFloat="
+                + mPendingScreenBrightnessSetting);
+        pw.println("  mTemporaryScreenBrightnessFloat=" + mTemporaryScreenBrightness);
         pw.println("  mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
         pw.println("  mBrightnessReason=" + mBrightnessReason);
         pw.println("  mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
         pw.println("  mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
-        pw.println("  mScreenBrightnessForVr=" + mScreenBrightnessForVr);
+        pw.println("  mScreenBrightnessForVrFloat=" + mScreenBrightnessForVr);
         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
         pw.println("  mAppliedDimming=" + mAppliedDimming);
         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
@@ -1783,7 +1800,6 @@
         pw.println("  mAppliedTemporaryBrightness=" + mAppliedTemporaryBrightness);
         pw.println("  mDozing=" + mDozing);
         pw.println("  mSkipRampState=" + skipRampStateToString(mSkipRampState));
-        pw.println("  mInitialAutoBrightness=" + mInitialAutoBrightness);
         pw.println("  mScreenOnBlockStartRealTime=" + mScreenOnBlockStartRealTime);
         pw.println("  mScreenOffBlockStartRealTime=" + mScreenOffBlockStartRealTime);
         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
@@ -1869,6 +1885,11 @@
         return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
     }
 
+    private static float clampAbsoluteBrightness(float value) {
+        return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
+                PowerManager.BRIGHTNESS_MAX);
+    }
+
     private static float clampAutoBrightnessAdjustment(float value) {
         return MathUtils.constrain(value, -1.0f, 1.0f);
     }
@@ -1908,7 +1929,7 @@
 
                 case MSG_SET_TEMPORARY_BRIGHTNESS:
                     // TODO: Should we have a a timeout for the temporary brightness?
-                    mTemporaryScreenBrightness = msg.arg1;
+                    mTemporaryScreenBrightness = Float.intBitsToFloat(msg.arg1);
                     updatePowerState();
                     break;
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 763f56f..24e1b4e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -22,11 +22,12 @@
 import android.os.PowerManager;
 import android.os.Trace;
 import android.util.FloatProperty;
-import android.util.IntProperty;
 import android.util.Slog;
 import android.view.Choreographer;
 import android.view.Display;
 
+import com.android.internal.BrightnessSynchronizer;
+
 import java.io.PrintWriter;
 
 /**
@@ -59,7 +60,7 @@
     private final PhotonicModulator mPhotonicModulator;
 
     private int mScreenState;
-    private int mScreenBrightness;
+    private float mScreenBrightness;
     private boolean mScreenReady;
     private boolean mScreenUpdatePending;
 
@@ -85,7 +86,7 @@
         // will reset the brightness to a new level immediately before the changes
         // actually have a chance to be applied.
         mScreenState = Display.STATE_ON;
-        mScreenBrightness = PowerManager.BRIGHTNESS_ON;
+        mScreenBrightness = PowerManager.BRIGHTNESS_MAX;
         scheduleScreenUpdate();
 
         mColorFadePrepared = false;
@@ -106,18 +107,19 @@
         }
     };
 
-    public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
-            new IntProperty<DisplayPowerState>("screenBrightness") {
-        @Override
-        public void setValue(DisplayPowerState object, int value) {
-            object.setScreenBrightness(value);
-        }
 
-        @Override
-        public Integer get(DisplayPowerState object) {
-            return object.getScreenBrightness();
-        }
-    };
+    public static final FloatProperty<DisplayPowerState> SCREEN_BRIGHTNESS_FLOAT =
+            new FloatProperty<DisplayPowerState>("screenBrightnessFloat") {
+                @Override
+                public void setValue(DisplayPowerState object, float value) {
+                    object.setScreenBrightness(value);
+                }
+
+                @Override
+                public Float get(DisplayPowerState object) {
+                    return object.getScreenBrightness();
+                }
+            };
 
     /**
      * Sets whether the screen is on, off, or dozing.
@@ -146,7 +148,7 @@
      *
      * @param brightness The brightness, ranges from 0 (minimum / off) to 255 (brightest).
      */
-    public void setScreenBrightness(int brightness) {
+    public void setScreenBrightness(float brightness) {
         if (mScreenBrightness != brightness) {
             if (DEBUG) {
                 Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
@@ -163,7 +165,7 @@
     /**
      * Gets the screen brightness.
      */
-    public int getScreenBrightness() {
+    public float getScreenBrightness() {
         return mScreenBrightness;
     }
 
@@ -308,9 +310,9 @@
         public void run() {
             mScreenUpdatePending = false;
 
-            int brightness = mScreenState != Display.STATE_OFF
-                    && mColorFadeLevel > 0f ? mScreenBrightness : 0;
-            if (mPhotonicModulator.setState(mScreenState, brightness)) {
+            float brightnessState = mScreenState != Display.STATE_OFF
+                    && mColorFadeLevel > 0f ? mScreenBrightness : PowerManager.BRIGHTNESS_OFF_FLOAT;
+            if (mPhotonicModulator.setState(mScreenState, brightnessState)) {
                 if (DEBUG) {
                     Slog.d(TAG, "Screen ready");
                 }
@@ -345,14 +347,14 @@
      */
     private final class PhotonicModulator extends Thread {
         private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
-        private static final int INITIAL_BACKLIGHT = -1; // unknown
+        private static final float INITIAL_BACKLIGHT_FLOAT = PowerManager.BRIGHTNESS_INVALID_FLOAT;
 
         private final Object mLock = new Object();
 
         private int mPendingState = INITIAL_SCREEN_STATE;
-        private int mPendingBacklight = INITIAL_BACKLIGHT;
+        private float mPendingBacklight = INITIAL_BACKLIGHT_FLOAT;
         private int mActualState = INITIAL_SCREEN_STATE;
-        private int mActualBacklight = INITIAL_BACKLIGHT;
+        private float mActualBacklight = INITIAL_BACKLIGHT_FLOAT;
         private boolean mStateChangeInProgress;
         private boolean mBacklightChangeInProgress;
 
@@ -360,19 +362,19 @@
             super("PhotonicModulator");
         }
 
-        public boolean setState(int state, int backlight) {
+        public boolean setState(int state, float brightnessState) {
             synchronized (mLock) {
                 boolean stateChanged = state != mPendingState;
-                boolean backlightChanged = backlight != mPendingBacklight;
+                boolean backlightChanged = !BrightnessSynchronizer.floatEquals(
+                        brightnessState, mPendingBacklight);
                 if (stateChanged || backlightChanged) {
                     if (DEBUG) {
                         Slog.d(TAG, "Requesting new screen state: state="
-                                + Display.stateToString(state) + ", backlight=" + backlight);
+                                + Display.stateToString(state) + ", backlight=" + brightnessState);
                     }
 
                     mPendingState = state;
-                    mPendingBacklight = backlight;
-
+                    mPendingBacklight = brightnessState;
                     boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
                     mStateChangeInProgress = stateChanged || mStateChangeInProgress;
                     mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
@@ -404,13 +406,14 @@
                 // Get pending change.
                 final int state;
                 final boolean stateChanged;
-                final int backlight;
+                final float brightnessState;
                 final boolean backlightChanged;
                 synchronized (mLock) {
                     state = mPendingState;
                     stateChanged = (state != mActualState);
-                    backlight = mPendingBacklight;
-                    backlightChanged = (backlight != mActualBacklight);
+                    brightnessState = mPendingBacklight;
+                    backlightChanged = !BrightnessSynchronizer.floatEquals(
+                            brightnessState, mActualBacklight);
                     if (!stateChanged) {
                         // State changed applied, notify outer class.
                         postScreenUpdateThreadSafe();
@@ -426,15 +429,15 @@
                         continue;
                     }
                     mActualState = state;
-                    mActualBacklight = backlight;
+                    mActualBacklight = brightnessState;
                 }
 
                 // Apply pending change.
                 if (DEBUG) {
                     Slog.d(TAG, "Updating screen state: state="
-                            + Display.stateToString(state) + ", backlight=" + backlight);
+                            + Display.stateToString(state) + ", backlight=" + brightnessState);
                 }
-                mBlanker.requestDisplayState(state, backlight);
+                mBlanker.requestDisplayState(state, brightnessState);
             }
         }
     }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index fc9542a..2b225e5 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -38,6 +38,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
@@ -179,7 +180,7 @@
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
         private int mState = Display.STATE_UNKNOWN;
-        private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+        private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         private int mDefaultModeId;
         private int mActiveModeId;
         private boolean mActiveModeInvalid;
@@ -574,12 +575,14 @@
         }
 
         @Override
-        public Runnable requestDisplayStateLocked(final int state, final int brightness) {
+        public Runnable requestDisplayStateLocked(final int state, final float brightnessState) {
             // Assume that the brightness is off if the display is being turned off.
-            assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
-
+            assert state != Display.STATE_OFF || BrightnessSynchronizer.floatEquals(
+                    brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT);
             final boolean stateChanged = (mState != state);
-            final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
+            final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
+                    mBrightnessState, brightnessState))
+                    && mBacklight != null;
             if (stateChanged || brightnessChanged) {
                 final long physicalDisplayId = mPhysicalDisplayId;
                 final IBinder token = getDisplayTokenLocked();
@@ -591,7 +594,7 @@
                 }
 
                 if (brightnessChanged) {
-                    mBrightness = brightness;
+                    mBrightnessState = brightnessState;
                 }
 
                 // Defer actually setting the display state until after we have exited
@@ -630,10 +633,9 @@
                             vrModeChange = true;
                         }
 
-
                         // Apply brightness changes given that we are in a non-suspended state.
                         if (brightnessChanged || vrModeChange) {
-                            setDisplayBrightness(brightness);
+                            setDisplayBrightness(brightnessState);
                         }
 
                         // Enter the final desired state, possibly suspended.
@@ -694,7 +696,7 @@
                         }
                     }
 
-                    private void setDisplayBrightness(int brightness) {
+                    private void setDisplayBrightness(float brightness) {
                         if (DEBUG) {
                             Slog.d(TAG, "setDisplayBrightness("
                                     + "id=" + physicalDisplayId
@@ -704,26 +706,33 @@
                         Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
                                 + "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
                         try {
-                            if (mHalBrightnessSupport) {
-                                mBacklight.setBrightnessFloat(
-                                        displayBrightnessToHalBrightness(brightness));
-                            } else {
-                                mBacklight.setBrightness(brightness);
+                            // TODO: make it float
+                            if (isHalBrightnessRangeSpecified()) {
+                                brightness = displayBrightnessToHalBrightness(
+                                        BrightnessSynchronizer.brightnessFloatToInt(getContext(),
+                                                brightness));
                             }
+                            mBacklight.setBrightness(brightness);
                             Trace.traceCounter(Trace.TRACE_TAG_POWER,
-                                    "ScreenBrightness", brightness);
+                                    "ScreenBrightness",
+                                    BrightnessSynchronizer.brightnessFloatToInt(
+                                            getContext(), brightness));
                         } finally {
                             Trace.traceEnd(Trace.TRACE_TAG_POWER);
                         }
                     }
 
+                    private boolean isHalBrightnessRangeSpecified() {
+                        return !(mSystemBrightnessToNits == null || mNitsToHalBrightness == null);
+                    }
+
                     /**
                      * Converts brightness range from the framework's brightness space to the
                      * Hal brightness space if the HAL brightness space has been provided via
                      * a display device configuration file.
                      */
                     private float displayBrightnessToHalBrightness(int brightness) {
-                        if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) {
+                        if (!isHalBrightnessRangeSpecified()) {
                             return PowerManager.BRIGHTNESS_INVALID_FLOAT;
                         }
 
@@ -887,7 +896,7 @@
             pw.println("mActiveColorMode=" + mActiveColorMode);
             pw.println("mDefaultModeId=" + mDefaultModeId);
             pw.println("mState=" + Display.stateToString(mState));
-            pw.println("mBrightness=" + mBrightness);
+            pw.println("mBrightnessState=" + mBrightnessState);
             pw.println("mBacklight=" + mBacklight);
             pw.println("mAllmSupported=" + mAllmSupported);
             pw.println("mAllmRequested=" + mAllmRequested);
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index d71269f..7916d81 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -17,21 +17,23 @@
 package com.android.server.display;
 
 import android.animation.ValueAnimator;
-import android.util.IntProperty;
+import android.util.FloatProperty;
 import android.view.Choreographer;
 
+import com.android.internal.BrightnessSynchronizer;
+
 /**
  * A custom animator that progressively updates a property value at
  * a given variable rate until it reaches a particular target value.
  */
 final class RampAnimator<T> {
     private final T mObject;
-    private final IntProperty<T> mProperty;
+    private final FloatProperty<T> mProperty;
     private final Choreographer mChoreographer;
 
-    private int mCurrentValue;
-    private int mTargetValue;
-    private int mRate;
+    private float mCurrentValue;
+    private float mTargetValue;
+    private float mRate;
 
     private boolean mAnimating;
     private float mAnimatedValue; // higher precision copy of mCurrentValue
@@ -41,7 +43,7 @@
 
     private Listener mListener;
 
-    public RampAnimator(T object, IntProperty<T> property) {
+    public RampAnimator(T object, FloatProperty<T> property) {
         mObject = object;
         mProperty = property;
         mChoreographer = Choreographer.getInstance();
@@ -57,7 +59,8 @@
      * @param rate The convergence rate in units per second, or 0 to set the value immediately.
      * @return True if the target differs from the previous target.
      */
-    public boolean animateTo(int target, int rate) {
+    public boolean animateTo(float target, float rate) {
+
         // Immediately jump to the target the first time.
         if (mFirstTime || rate <= 0) {
             if (mFirstTime || target != mCurrentValue) {
@@ -152,14 +155,12 @@
                     mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
                 }
             }
-            final int oldCurrentValue = mCurrentValue;
-            mCurrentValue = Math.round(mAnimatedValue);
-
-            if (oldCurrentValue != mCurrentValue) {
+            final float oldCurrentValue = mCurrentValue;
+            mCurrentValue = mAnimatedValue;
+            if (!BrightnessSynchronizer.floatEquals(oldCurrentValue, mCurrentValue)) {
                 mProperty.setValue(mObject, mCurrentValue);
             }
-
-            if (mTargetValue != mCurrentValue) {
+            if (!BrightnessSynchronizer.floatEquals(mTargetValue, mCurrentValue)) {
                 postAnimationCallback();
             } else {
                 mAnimating = false;
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 1ca8dd3..f4f2ead 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -265,7 +265,7 @@
         }
 
         @Override
-        public Runnable requestDisplayStateLocked(int state, int brightness) {
+        public Runnable requestDisplayStateLocked(int state, float brightnessState) {
             if (state != mDisplayState) {
                 mDisplayState = state;
                 if (state == Display.STATE_OFF) {
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 5683e69..a42dec8 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -40,6 +40,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
+import com.android.internal.BrightnessSynchronizer;
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
@@ -249,28 +250,21 @@
         }
 
         @Override
-        public void setBrightnessFloat(float brightness) {
-            if (!Float.isNaN(brightness)) {
-                setBrightness(brightness, 0, BRIGHTNESS_MODE_USER);
-            }
-        }
-
-        @Override
-        public void setBrightness(int brightness) {
+        public void setBrightness(float brightness) {
             setBrightness(brightness, BRIGHTNESS_MODE_USER);
         }
 
         @Override
-        public void setBrightness(int brightness, int brightnessMode) {
-            setBrightness(Float.NaN, brightness, brightnessMode);
-        }
-
-        private void setBrightness(float brightnessFloat, int brightness, int brightnessMode) {
+        public void setBrightness(float brightness, int brightnessMode) {
+            if (Float.isNaN(brightness)) {
+                Slog.w(TAG, "Brightness is not valid: " + brightness);
+                return;
+            }
             synchronized (this) {
                 // LOW_PERSISTENCE cannot be manually set
                 if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
                     Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mHwLight.id
-                            + ": brightness=0x" + Integer.toHexString(brightness));
+                            + ": brightness=" + brightness);
                     return;
                 }
                 // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
@@ -278,6 +272,7 @@
                 // anything but USER or the device shouldBeInLowPersistenceMode().
                 if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
                         && mSurfaceControlMaximumBrightness == 255) {
+                    // New system
                     // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
                     // reason we enforce 255 right now is to stay consistent with the old path. In
                     // the future, the framework should be refactored so that brightness is a float
@@ -286,17 +281,12 @@
                     if (DEBUG) {
                         Slog.d(TAG, "Using new setBrightness path!");
                     }
-
-                    if (!Float.isNaN(brightnessFloat)) {
-                        SurfaceControl.setDisplayBrightness(mDisplayToken, brightnessFloat);
-                    } else if (brightness == 0) {
-                        SurfaceControl.setDisplayBrightness(mDisplayToken, -1.0f);
-                    } else {
-                        SurfaceControl.setDisplayBrightness(mDisplayToken,
-                                (float) (brightness - 1) / (mSurfaceControlMaximumBrightness - 1));
-                    }
+                    SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
                 } else {
-                    int color = brightness & 0x000000ff;
+                    // Old system
+                    int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(
+                            getContext(), brightness);
+                    int color = brightnessInt & 0x000000ff;
                     color = 0xff000000 | (color << 16) | (color << 8) | color;
                     setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
                 }
diff --git a/services/core/java/com/android/server/lights/LogicalLight.java b/services/core/java/com/android/server/lights/LogicalLight.java
index 33dfbb4..7491cec 100644
--- a/services/core/java/com/android/server/lights/LogicalLight.java
+++ b/services/core/java/com/android/server/lights/LogicalLight.java
@@ -57,18 +57,12 @@
     /**
      * Set the brightness of a display.
      */
-    public abstract void setBrightness(int brightness);
+    public abstract void setBrightness(float brightness);
 
     /**
      * Set the brightness and mode of a display.
      */
-    public abstract void setBrightness(int brightness, int brightnessMode);
-
-    /**
-     * Set the brightness of a display using the brightness range defines in a
-     * display-device-configuration file.
-     */
-    public abstract void setBrightnessFloat(float brightness);
+    public abstract void setBrightness(float brightness, int brightnessMode);
 
     /**
      * Set the color of a light.
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 91bd7ae..67b1008 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -783,6 +783,7 @@
                 break;
 
             case android.provider.Settings.System.SCREEN_BRIGHTNESS:
+            case android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT:
             case android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE:
                 if (callingUid == Process.SYSTEM_UID) {
                     return false;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ede04f3..6126787 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2729,21 +2729,23 @@
                             Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
                             UserHandle.USER_CURRENT_OR_SELF);
                 }
-
-                int min = mPowerManager.getMinimumScreenBrightnessSetting();
-                int max = mPowerManager.getMaximumScreenBrightnessSetting();
-                int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction;
-                int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS,
-                        mPowerManager.getDefaultScreenBrightnessSetting(),
+                float minFloat = mPowerManager.getBrightnessConstraint(
+                        PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+                float maxFloat = mPowerManager.getBrightnessConstraint(
+                        PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+                float stepFloat = (maxFloat - minFloat) / BRIGHTNESS_STEPS * direction;
+                float brightnessFloat = Settings.System.getFloatForUser(
+                        mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_FLOAT,
+                        mPowerManager.getBrightnessConstraint(
+                                PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT),
                         UserHandle.USER_CURRENT_OR_SELF);
-                brightness += step;
+                brightnessFloat += stepFloat;
                 // Make sure we don't go beyond the limits.
-                brightness = Math.min(max, brightness);
-                brightness = Math.max(min, brightness);
+                brightnessFloat = Math.min(maxFloat, brightnessFloat);
+                brightnessFloat = Math.max(minFloat, brightnessFloat);
 
-                Settings.System.putIntForUser(mContext.getContentResolver(),
-                        Settings.System.SCREEN_BRIGHTNESS, brightness,
+                Settings.System.putFloatForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_FLOAT, brightnessFloat,
                         UserHandle.USER_CURRENT_OR_SELF);
                 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
                         UserHandle.CURRENT_OR_SELF);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 4d13658..002ab9c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -83,6 +83,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 
+import com.android.internal.BrightnessSynchronizer;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
@@ -192,6 +193,9 @@
     // This should perhaps be a setting.
     private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;
 
+    // Float.NaN cannot be stored in config.xml so -2 is used instead
+    private static final float INVALID_BRIGHTNESS_IN_CONFIG = -2f;
+
     // How long a partial wake lock must be held until we consider it a long wake lock.
     static final long MIN_LONG_WAKE_CHECK_INTERVAL = 60*1000;
 
@@ -485,13 +489,17 @@
     private boolean mProximityPositive;
 
     // Screen brightness setting limits.
-    private int mScreenBrightnessSettingMinimum;
-    private int mScreenBrightnessSettingMaximum;
-    private int mScreenBrightnessSettingDefault;
-
-    // The screen brightness setting, from 0 to 255.
-    // Use -1 if no value has been set.
-    private int mScreenBrightnessSetting;
+    private float mScreenBrightnessSettingMinimum;
+    private float mScreenBrightnessSettingMaximum;
+    private float mScreenBrightnessSettingDefault;
+    public final float mScreenBrightnessMinimum;
+    public final float mScreenBrightnessMaximum;
+    public final float mScreenBrightnessDefault;
+    public final float mScreenBrightnessDoze;
+    public final float mScreenBrightnessDim;
+    public final float mScreenBrightnessMinimumVr;
+    public final float mScreenBrightnessMaximumVr;
+    public final float mScreenBrightnessDefaultVr;
 
     // The screen brightness mode.
     // One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
@@ -502,6 +510,9 @@
     // Use -1 to disable.
     private int mScreenBrightnessOverrideFromWindowManager = -1;
 
+    private float mScreenBrightnessOverrideFromWindowManagerFloat =
+            PowerManager.BRIGHTNESS_INVALID_FLOAT;
+
     // The window manager has determined the user to be inactive via other means.
     // Set this to false to disable.
     private boolean mUserInactiveOverrideFromWindowManager;
@@ -521,6 +532,8 @@
     // The screen brightness to use while dozing.
     private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT;
 
+    private float mDozeScreenBrightnessOverrideFromDreamManagerFloat =
+            PowerManager.BRIGHTNESS_INVALID_FLOAT;
     // Keep display state when dozing.
     private boolean mDrawWakeLockOverrideFromSidekick;
 
@@ -827,6 +840,91 @@
         mInattentiveSleepWarningOverlayController =
                 mInjector.createInattentiveSleepWarningController();
 
+        // Save brightness values:
+        // Get float values from config.
+        // Store float if valid
+        // Otherwise, get int values and convert to float and then store.
+        final float min = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingMinimumFloat);
+        final float max = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingMaximumFloat);
+        final float def = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingDefaultFloat);
+        final float doze = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessDozeFloat);
+        final float dim = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessDimFloat);
+
+        if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG
+                || def == INVALID_BRIGHTNESS_IN_CONFIG) {
+            mScreenBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessSettingMinimum),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+            mScreenBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessSettingMaximum),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+            mScreenBrightnessDefault = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessSettingDefault),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+        } else {
+            mScreenBrightnessMinimum = min;
+            mScreenBrightnessMaximum = max;
+            mScreenBrightnessDefault = def;
+        }
+        if (doze == INVALID_BRIGHTNESS_IN_CONFIG) {
+            mScreenBrightnessDoze = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessDoze), PowerManager.BRIGHTNESS_OFF + 1,
+                    PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
+                    PowerManager.BRIGHTNESS_MAX);
+        } else {
+            mScreenBrightnessDoze = doze;
+        }
+        if (dim == INVALID_BRIGHTNESS_IN_CONFIG) {
+            mScreenBrightnessDim = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessDim), PowerManager.BRIGHTNESS_OFF + 1,
+                    PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
+                    PowerManager.BRIGHTNESS_MAX);
+        } else {
+            mScreenBrightnessDim = dim;
+        }
+
+        final float vrMin = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingForVrMinimumFloat);
+        final float vrMax = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingForVrMaximumFloat);
+        final float vrDef = mContext.getResources().getFloat(com.android.internal.R.dimen
+                .config_screenBrightnessSettingForVrDefaultFloat);
+        if (vrMin == INVALID_BRIGHTNESS_IN_CONFIG || vrMax == INVALID_BRIGHTNESS_IN_CONFIG
+                || vrDef == INVALID_BRIGHTNESS_IN_CONFIG) {
+            mScreenBrightnessMinimumVr = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessForVrSettingMinimum),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+            mScreenBrightnessMaximumVr = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessForVrSettingMaximum),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+            mScreenBrightnessDefaultVr = BrightnessSynchronizer.brightnessIntToFloat(
+                    mContext.getResources().getInteger(com.android.internal.R.integer
+                            .config_screenBrightnessForVrSettingDefault),
+                    PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+                    PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+        } else {
+            mScreenBrightnessMinimumVr = vrMin;
+            mScreenBrightnessMaximumVr = vrMax;
+            mScreenBrightnessDefaultVr = vrDef;
+        }
+
         synchronized (mLock) {
             mWakeLockSuspendBlocker =
                     mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
@@ -895,9 +993,12 @@
             mAttentionDetector.systemReady(mContext);
 
             PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
-            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
-            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+            mScreenBrightnessSettingMinimum = pm.getBrightnessConstraint(
+                    PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+            mScreenBrightnessSettingMaximum = pm.getBrightnessConstraint(
+                    PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+            mScreenBrightnessSettingDefault = pm.getBrightnessConstraint(
+                    PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
 
@@ -2672,7 +2773,7 @@
 
             // Determine appropriate screen brightness and auto-brightness adjustments.
             final boolean autoBrightness;
-            final int screenBrightnessOverride;
+            final float screenBrightnessOverride;
             if (!mBootCompleted) {
                 // Keep the brightness steady during boot. This requires the
                 // bootloader brightness and the default brightness to be identical.
@@ -2680,11 +2781,11 @@
                 screenBrightnessOverride = mScreenBrightnessSettingDefault;
             } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                 autoBrightness = false;
-                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
+                screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManagerFloat;
             } else {
                 autoBrightness = (mScreenBrightnessModeSetting ==
                         Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
-                screenBrightnessOverride = -1;
+                screenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
             }
 
             // Update display power request.
@@ -2707,10 +2808,11 @@
                     }
                 }
                 mDisplayPowerRequest.dozeScreenBrightness =
-                        mDozeScreenBrightnessOverrideFromDreamManager;
+                        mDozeScreenBrightnessOverrideFromDreamManagerFloat;
             } else {
                 mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
-                mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+                mDisplayPowerRequest.dozeScreenBrightness =
+                        PowerManager.BRIGHTNESS_INVALID_FLOAT;
             }
 
             mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
@@ -3426,10 +3528,13 @@
         }
     }
 
+    // TODO(brightnessfloat): change to float
     private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
         synchronized (mLock) {
             if (mScreenBrightnessOverrideFromWindowManager != brightness) {
                 mScreenBrightnessOverrideFromWindowManager = brightness;
+                mScreenBrightnessOverrideFromWindowManagerFloat =
+                        BrightnessSynchronizer.brightnessIntToFloat(mContext, brightness);
                 mDirty |= DIRTY_SETTINGS;
                 updatePowerStateLocked();
             }
@@ -3462,6 +3567,9 @@
                     || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) {
                 mDozeScreenStateOverrideFromDreamManager = screenState;
                 mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness;
+                mDozeScreenBrightnessOverrideFromDreamManagerFloat =
+                        BrightnessSynchronizer.brightnessIntToFloat(mContext,
+                                mDozeScreenBrightnessOverrideFromDreamManager);
                 mDirty |= DIRTY_SETTINGS;
                 updatePowerStateLocked();
             }
@@ -3715,10 +3823,9 @@
                     + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
                     + isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
             pw.println("  mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
-            pw.println("  mScreenBrightnessSetting=" + mScreenBrightnessSetting);
             pw.println("  mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
-            pw.println("  mScreenBrightnessOverrideFromWindowManager="
-                    + mScreenBrightnessOverrideFromWindowManager);
+            pw.println("  mScreenBrightnessOverrideFromWindowManagerFloat="
+                    + mScreenBrightnessOverrideFromWindowManagerFloat);
             pw.println("  mUserActivityTimeoutOverrideFromWindowManager="
                     + mUserActivityTimeoutOverrideFromWindowManager);
             pw.println("  mUserInactiveOverrideFromWindowManager="
@@ -3728,9 +3835,9 @@
             pw.println("  mDrawWakeLockOverrideFromSidekick=" + mDrawWakeLockOverrideFromSidekick);
             pw.println("  mDozeScreenBrightnessOverrideFromDreamManager="
                     + mDozeScreenBrightnessOverrideFromDreamManager);
-            pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
-            pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
-            pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+            pw.println("  mScreenBrightnessSettingMinimumFloat=" + mScreenBrightnessSettingMinimum);
+            pw.println("  mScreenBrightnessSettingMaximumFloat=" + mScreenBrightnessSettingMaximum);
+            pw.println("  mScreenBrightnessSettingDefaultFloat=" + mScreenBrightnessSettingDefault);
             pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
             pw.println("  mIsVrModeEnabled=" + mIsVrModeEnabled);
             pw.println("  mForegroundProfile=" + mForegroundProfile);
@@ -4056,7 +4163,7 @@
             proto.write(
                     PowerServiceSettingsAndConfigurationDumpProto
                             .SCREEN_BRIGHTNESS_OVERRIDE_FROM_WINDOW_MANAGER,
-                    mScreenBrightnessOverrideFromWindowManager);
+                    mScreenBrightnessOverrideFromWindowManagerFloat);
             proto.write(
                     PowerServiceSettingsAndConfigurationDumpProto
                             .USER_ACTIVITY_TIMEOUT_OVERRIDE_FROM_WINDOW_MANAGER_MS,
@@ -4738,6 +4845,29 @@
             }
         }
 
+        public float getBrightnessConstraint(int constraint) {
+            switch (constraint) {
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM:
+                    return mScreenBrightnessMinimum;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM:
+                    return mScreenBrightnessMaximum;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT:
+                    return mScreenBrightnessDefault;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM:
+                    return mScreenBrightnessDim;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE:
+                    return mScreenBrightnessDoze;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR:
+                    return mScreenBrightnessMinimumVr;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR:
+                    return mScreenBrightnessMaximumVr;
+                case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR:
+                    return mScreenBrightnessDefaultVr;
+                default:
+                    return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+            }
+        }
+
         @Override // Binder call
         public boolean isInteractive() {
             final long ident = Binder.clearCallingIdentity();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb687c9..f700d71 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -490,6 +490,7 @@
 
         SYSTEM_SETTINGS_WHITELIST = new ArraySet<>();
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS);
+        SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
         SYSTEM_SETTINGS_WHITELIST.add(Settings.System.SCREEN_OFF_TIMEOUT);
 
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index ca00116..234c987 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -25,7 +25,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.hardware.Sensor;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
@@ -46,9 +45,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class AutomaticBrightnessControllerTest {
-
-    private static final int BRIGHTNESS_MIN = 1;
-    private static final int BRIGHTNESS_MAX = 255;
+    private static final float BRIGHTNESS_MIN_FLOAT = 0.0f;
+    private static final float BRIGHTNESS_MAX_FLOAT = 1.0f;
     private static final int LIGHT_SENSOR_RATE = 20;
     private static final int INITIAL_LIGHT_SENSOR_RATE = 20;
     private static final int BRIGHTENING_LIGHT_DEBOUNCE_CONFIG = 0;
@@ -61,7 +59,6 @@
     @Mock BrightnessMappingStrategy mBrightnessMappingStrategy;
     @Mock HysteresisLevels mAmbientBrightnessThresholds;
     @Mock HysteresisLevels mScreenBrightnessThresholds;
-    @Mock PackageManager mPackageManager;
     @Mock Handler mNoopHandler;
 
     private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
@@ -81,11 +78,11 @@
                     }
                 },
                 () -> { }, mContext.getMainLooper(), mSensorManager, lightSensor,
-                mBrightnessMappingStrategy, LIGHT_SENSOR_WARMUP_TIME, BRIGHTNESS_MIN,
-                BRIGHTNESS_MAX, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE, INITIAL_LIGHT_SENSOR_RATE,
-                BRIGHTENING_LIGHT_DEBOUNCE_CONFIG, DARKENING_LIGHT_DEBOUNCE_CONFIG,
-                RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds,
-                mScreenBrightnessThresholds, mPackageManager);
+                mBrightnessMappingStrategy, LIGHT_SENSOR_WARMUP_TIME, BRIGHTNESS_MIN_FLOAT,
+                BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
+                INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
+                DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
+                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mContext);
         controller.setLoggingEnabled(true);
 
         // Configure the brightness controller and grab an instance of the sensor listener,
@@ -110,7 +107,7 @@
 
         // Set up system to return 5 as a brightness value
         float lux1 = 100.0f;
-        float normalizedBrightness1 = 0.02f;
+        float normalizedBrightness1 = 0.0158f; //float equivalent of 5 out of 255
         when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux1))
                 .thenReturn(lux1);
         when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux1))
@@ -156,7 +153,7 @@
 
         // Set up system to return 250 as a brightness value
         float lux1 = 100.0f;
-        float normalizedBrightness1 = 0.98f;
+        float normalizedBrightness1 = 0.981f; //float equivalent of 250 out of 255
         when(mAmbientBrightnessThresholds.getBrighteningThreshold(lux1))
                 .thenReturn(lux1);
         when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux1))