Allow DeviceConfig to change display settings for high zone

Allow DeviceConfig to change the high zone behavior including
refresh rate and brightness thresholds.

Bug: 166581675
Test: atest DisplayModeDirectorTest
Test: adb shell device_config put display_manager refresh_rate_in_high_zone "90"
Test: adb shell device_config put display_manager fixed_refresh_rate_high_display_brightness_thresholds "200"
Test: adb shell device_config put display_manager fixed_refresh_rate_high_ambient_brightness_thresholds "8000"
Change-Id: I2ac8d95f976748d03f6dc2e60725e9ef1213ed6f
Merged-In: I2ac8d95f976748d03f6dc2e60725e9ef1213ed6f
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index c1ba209..0fa4ca8 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -875,12 +875,52 @@
     public interface DeviceConfig {
 
         /**
-         * Key for refresh rate in the zone defined by thresholds.
+         * Key for refresh rate in the low zone defined by thresholds.
          *
+         * Note that the name and value don't match because they were added before we had a high
+         * zone to consider.
          * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
          * @see android.R.integer#config_defaultZoneBehavior
          */
-        String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
+        String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone";
+
+        /**
+         * Key for accessing the low display brightness thresholds for the configured refresh
+         * rate zone.
+         * The value will be a pair of comma separated integers representing the minimum and maximum
+         * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
+         *
+         * Note that the name and value don't match because they were added before we had a high
+         * zone to consider.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
+         * @hide
+         */
+        String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS =
+                "peak_refresh_rate_brightness_thresholds";
+
+        /**
+         * Key for accessing the low ambient brightness thresholds for the configured refresh
+         * rate zone. The value will be a pair of comma separated integers representing the minimum
+         * and maximum thresholds of the zone, respectively, in lux.
+         *
+         * Note that the name and value don't match because they were added before we had a high
+         * zone to consider.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+         * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
+         * @hide
+         */
+        String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS =
+                "peak_refresh_rate_ambient_thresholds";
+        /**
+         * Key for refresh rate in the high zone defined by thresholds.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+         * @see android.R.integer#config_fixedRefreshRateInHighZone
+         */
+        String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone";
 
         /**
          * Key for accessing the display brightness thresholds for the configured refresh rate zone.
@@ -888,11 +928,11 @@
          * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
          *
          * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
-         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
+         * @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate
          * @hide
          */
-        String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
-                "peak_refresh_rate_brightness_thresholds";
+        String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS =
+                "fixed_refresh_rate_high_display_brightness_thresholds";
 
         /**
          * Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
@@ -900,12 +940,11 @@
          * thresholds of the zone, respectively, in lux.
          *
          * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
-         * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
+         * @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate
          * @hide
          */
-        String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
-                "peak_refresh_rate_ambient_thresholds";
-
+        String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
+                "fixed_refresh_rate_high_ambient_brightness_thresholds";
         /**
          * Key for default peak refresh rate
          *
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 2a60839a..02ee059 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -69,6 +69,8 @@
     private static final int MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
     private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
     private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4;
+    private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
+    private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
 
     // Special ID used to indicate that given vote is to be applied globally, rather than to a
     // specific display.
@@ -515,13 +517,6 @@
         }
     }
 
-    @VisibleForTesting
-    void updateSettingForHighZone(int refreshRate, int[] brightnessThresholds,
-            int[] ambientThresholds) {
-        mBrightnessObserver.updateThresholdsRefreshRateForHighZone(refreshRate,
-                brightnessThresholds, ambientThresholds);
-    }
-
     /**
      * Listens for changes refresh rate coordination.
      */
@@ -540,11 +535,35 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED:
+                case MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED: {
                     Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
                     mBrightnessObserver.onDeviceConfigLowBrightnessThresholdsChanged(
                             thresholds.first, thresholds.second);
                     break;
+                }
+
+                case MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED: {
+                    int refreshRateInZone = msg.arg1;
+                    mBrightnessObserver.onDeviceConfigRefreshRateInLowZoneChanged(
+                            refreshRateInZone);
+                    break;
+                }
+
+                case MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED: {
+                    Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
+
+                    mBrightnessObserver.onDeviceConfigHighBrightnessThresholdsChanged(
+                            thresholds.first, thresholds.second);
+
+                    break;
+                }
+
+                case MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED: {
+                    int refreshRateInZone = msg.arg1;
+                    mBrightnessObserver.onDeviceConfigRefreshRateInHighZoneChanged(
+                            refreshRateInZone);
+                    break;
+                }
 
                 case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
                     Float defaultPeakRefreshRate = (Float) msg.obj;
@@ -552,12 +571,6 @@
                             defaultPeakRefreshRate);
                     break;
 
-                case MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED:
-                    int refreshRateInZone = msg.arg1;
-                    mBrightnessObserver.onDeviceConfigRefreshRateInLowZoneChanged(
-                            refreshRateInZone);
-                    break;
-
                 case MSG_REFRESH_RATE_RANGE_CHANGED:
                     DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
                             (DesiredDisplayModeSpecsListener) msg.obj;
@@ -1220,13 +1233,6 @@
                     mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
         }
 
-        public void updateThresholdsRefreshRateForHighZone(int refreshRate,
-                int[] brightnessThresholds, int[] ambientThresholds) {
-            mRefreshRateInHighZone = refreshRate;
-            mHighDisplayBrightnessThresholds = brightnessThresholds;
-            mHighAmbientBrightnessThresholds = ambientThresholds;
-        }
-
         public void observe(SensorManager sensorManager) {
             mSensorManager = sensorManager;
             final ContentResolver cr = mContext.getContentResolver();
@@ -1246,7 +1252,22 @@
                 mLowAmbientBrightnessThresholds = lowAmbientBrightnessThresholds;
             }
 
+
+            int[] highDisplayBrightnessThresholds =
+                    mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds();
+            int[] highAmbientBrightnessThresholds =
+                    mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds();
+
+            if (highDisplayBrightnessThresholds != null && highAmbientBrightnessThresholds != null
+                    && highDisplayBrightnessThresholds.length
+                    == highAmbientBrightnessThresholds.length) {
+                mHighDisplayBrightnessThresholds = highDisplayBrightnessThresholds;
+                mHighAmbientBrightnessThresholds = highAmbientBrightnessThresholds;
+            }
+
             mRefreshRateInLowZone = mDeviceConfigDisplaySettings.getRefreshRateInLowZone();
+            mRefreshRateInHighZone = mDeviceConfigDisplaySettings.getRefreshRateInHighZone();
+
             restartObserver();
             mDeviceConfigDisplaySettings.startListening();
         }
@@ -1293,6 +1314,29 @@
             }
         }
 
+        public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
+                int[] ambientThresholds) {
+            if (displayThresholds != null && ambientThresholds != null
+                    && displayThresholds.length == ambientThresholds.length) {
+                mHighDisplayBrightnessThresholds = displayThresholds;
+                mHighAmbientBrightnessThresholds = ambientThresholds;
+            } else {
+                // Invalid or empty. Use device default.
+                mHighDisplayBrightnessThresholds = mContext.getResources().getIntArray(
+                        R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
+                mHighAmbientBrightnessThresholds = mContext.getResources().getIntArray(
+                        R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
+            }
+            restartObserver();
+        }
+
+        public void onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate) {
+            if (refreshRate != mRefreshRateInHighZone) {
+                mRefreshRateInHighZone = refreshRate;
+                restartObserver();
+            }
+        }
+
         public void dumpLocked(PrintWriter pw) {
             pw.println("  BrightnessObserver");
             pw.println("    mAmbientLux: " + mAmbientLux);
@@ -1668,7 +1712,7 @@
         public int[] getLowDisplayBrightnessThresholds() {
             return getIntArrayProperty(
                     DisplayManager.DeviceConfig.
-                            KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
+                            KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
         }
 
         /*
@@ -1677,7 +1721,7 @@
         public int[] getLowAmbientBrightnessThresholds() {
             return getIntArrayProperty(
                     DisplayManager.DeviceConfig.
-                            KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
+                            KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
         }
 
         public int getRefreshRateInLowZone() {
@@ -1686,7 +1730,37 @@
 
             int refreshRate = mDeviceConfig.getInt(
                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
-                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
+                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE,
+                    defaultRefreshRateInZone);
+
+            return refreshRate;
+        }
+
+        /*
+         * Return null if no such property or wrong format (not comma separated integers).
+         */
+        public int[] getHighDisplayBrightnessThresholds() {
+            return getIntArrayProperty(
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS);
+        }
+
+        /*
+         * Return null if no such property or wrong format (not comma separated integers).
+         */
+        public int[] getHighAmbientBrightnessThresholds() {
+            return getIntArrayProperty(
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS);
+        }
+
+        public int getRefreshRateInHighZone() {
+            int defaultRefreshRateInZone = mContext.getResources().getInteger(
+                    R.integer.config_fixedRefreshRateInHighZone);
+
+            int refreshRate = mDeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE,
                     defaultRefreshRateInZone);
 
             return refreshRate;
@@ -1721,6 +1795,16 @@
                     .sendToTarget();
             mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone, 0)
                     .sendToTarget();
+
+            int[] highDisplayBrightnessThresholds = getHighDisplayBrightnessThresholds();
+            int[] highAmbientBrightnessThresholds = getHighAmbientBrightnessThresholds();
+            int refreshRateInHighZone = getRefreshRateInHighZone();
+
+            mHandler.obtainMessage(MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED,
+                    new Pair<>(highDisplayBrightnessThresholds, highAmbientBrightnessThresholds))
+                    .sendToTarget();
+            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
+                    .sendToTarget();
         }
 
         private int[] getIntArrayProperty(String prop) {
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 4ee6a55..c467ee9 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -16,9 +16,12 @@
 
 package com.android.server.display;
 
-import static android.hardware.display.DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS;
-import static android.hardware.display.DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS;
-import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
 
 import static com.android.server.display.DisplayModeDirector.Vote.PRIORITY_FLICKER;
 
@@ -451,7 +454,11 @@
         setPeakRefreshRate(90 /*fps*/);
         director.getSettingsObserver().setDefaultRefreshRate(90);
         director.getBrightnessObserver().setDefaultDisplayState(true);
-        director.updateSettingForHighZone(60, new int[] {255}, new int[] {8000});
+
+        final FakeDeviceConfig config = mInjector.getDeviceConfig();
+        config.setRefreshRateInHighZone(60);
+        config.setHighDisplayBrightnessThresholds(new int[] { 255 });
+        config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
 
         Sensor lightSensor = createLightSensor();
         SensorManager sensorManager = createMockSensorManager(lightSensor);
@@ -508,7 +515,7 @@
 
         void setRefreshRateInLowZone(int fps) {
             putPropertyAndNotify(
-                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_ZONE,
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_LOW_ZONE,
                     String.valueOf(fps));
         }
 
@@ -521,7 +528,7 @@
 
             putPropertyAndNotify(
                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
-                    KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS,
+                    KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS,
                     thresholds);
         }
 
@@ -534,7 +541,39 @@
 
             putPropertyAndNotify(
                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
-                    KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS,
+                    KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS,
+                    thresholds);
+        }
+
+        void setRefreshRateInHighZone(int fps) {
+            putPropertyAndNotify(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_HIGH_ZONE,
+                    String.valueOf(fps));
+        }
+
+        void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
+            String thresholds = toPropertyValue(brightnessThresholds);
+
+            if (DEBUG) {
+                Slog.e(TAG, "Brightness Thresholds = " + thresholds);
+            }
+
+            putPropertyAndNotify(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS,
+                    thresholds);
+        }
+
+        void setHighAmbientBrightnessThresholds(int[] ambientThresholds) {
+            String thresholds = toPropertyValue(ambientThresholds);
+
+            if (DEBUG) {
+                Slog.e(TAG, "Ambient Thresholds = " + thresholds);
+            }
+
+            putPropertyAndNotify(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS,
                     thresholds);
         }