Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73936631 authored by Long Ling's avatar Long Ling
Browse files

DMD: Support 90hz only in the refresh rate zone

Also allow DeviceConfig to change the zone behavior
to 60 Hz only.

Change BrightObserver priority to be the lowest so application
request won't be overriden by BrightnessObserver

Bug: 139487676
Change-Id: I959550350c1ea72f764984226350ebc6e7de591c
parent 13e2b970
Loading
Loading
Loading
Loading
+18 −5
Original line number Original line Diff line number Diff line
@@ -829,23 +829,36 @@ public final class DisplayManager {
    public interface DeviceConfig {
    public interface DeviceConfig {


        /**
        /**
         * Key for accessing the 60 hz only regions.
         * Key for refresh rate in the zone defined by thresholds.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.integer#config_defaultZoneBehavior
         */
        String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";

        /**
         * Key for accessing the 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]).
         *
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @hide
         * @hide
         */
         */
        String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS =
        String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
                "peak_refresh_rate_brightness_thresholds";
                "peak_refresh_rate_brightness_thresholds";


        /**
        /**
         * Key for accessing the 60 hz only regions.
         * Key for accessing the 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.
         *
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
         * @hide
         * @hide
         */
         */
        String KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS = "peak_refresh_rate_ambient_thresholds";
        String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
                "peak_refresh_rate_ambient_thresholds";


        /**
        /**
         * Key for default peak refresh rate
         * Key for default peak refresh rate
+4 −0
Original line number Original line Diff line number Diff line
@@ -4167,6 +4167,10 @@
        -->
        -->
    </integer-array>
    </integer-array>


    <!-- Default refresh rate in the zone defined by brightness and ambient thresholds.
         If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
    <integer name="config_defaultRefreshRateInZone">0</integer>

    <!-- The type of the light sensor to be used by the display framework for things like
    <!-- The type of the light sensor to be used by the display framework for things like
         auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
         auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
    <string name="config_displayLightSensorType" translatable="false" />
    <string name="config_displayLightSensorType" translatable="false" />
+1 −0
Original line number Original line Diff line number Diff line
@@ -3791,6 +3791,7 @@


  <!-- For high refresh rate displays -->
  <!-- For high refresh rate displays -->
  <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
  <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
  <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
  <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
  <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
  <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
  <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />


+98 −30
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ public class DisplayModeDirector {
    private static final int MSG_ALLOWED_MODES_CHANGED = 1;
    private static final int MSG_ALLOWED_MODES_CHANGED = 1;
    private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
    private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
    private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
    private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
    private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;


    // Special ID used to indicate that given vote is to be applied globally, rather than to a
    // Special ID used to indicate that given vote is to be applied globally, rather than to a
    // specific display.
    // specific display.
@@ -440,23 +441,48 @@ public class DisplayModeDirector {
                    mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
                    mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
                            defaultPeakRefreshRate);
                            defaultPeakRefreshRate);
                    break;
                    break;

                case MSG_REFRESH_RATE_IN_ZONE_CHANGED:
                    int refreshRateInZone = msg.arg1;
                    mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
                            refreshRateInZone);
                    break;
            }
            }
        }
        }
    }
    }


    private static final class Vote {
    private static final class Vote {
        // We split the app request into two priorities in case we can satisfy one desire without
        // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
        // the other.
        // If the higher voters result is a range, it will fix the rate to a single choice.
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 0;
        // It's used to avoid rate switch in certain conditions.
        public static final int PRIORITY_APP_REQUEST_SIZE = 1;
        public static final int PRIORITY_LOW_BRIGHTNESS = 0;
        public static final int PRIORITY_USER_SETTING_REFRESH_RATE = 2;

        public static final int PRIORITY_LOW_BRIGHTNESS = 3;
        // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
        public static final int PRIORITY_LOW_POWER_MODE = 4;
        // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 1;

        // We split the app request into different priorities in case we can satisfy one desire
        // without the other.

        // Application can specify preferred refresh rate with below attrs.
        // @see android.view.WindowManager.LayoutParams#preferredRefreshRate
        // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
        // System also forces some apps like blacklisted app to run at a lower refresh rate.
        // @see android.R.array#config_highRefreshRateBlacklist
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 2;
        public static final int PRIORITY_APP_REQUEST_SIZE = 3;

        // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
        // of low priority voters. It votes [0, max(PEAK, MIN)]
        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 4;

        // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
        public static final int PRIORITY_LOW_POWER_MODE = 5;


        // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
        // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
        // appropriate, as well as priorityToString.
        // appropriate, as well as priorityToString.


        public static final int MIN_PRIORITY = PRIORITY_APP_REQUEST_REFRESH_RATE;
        public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS;
        public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
        public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;


        /**
        /**
@@ -500,12 +526,16 @@ public class DisplayModeDirector {


        public static String priorityToString(int priority) {
        public static String priorityToString(int priority) {
            switch (priority) {
            switch (priority) {
                case PRIORITY_LOW_BRIGHTNESS:
                    return "PRIORITY_LOW_BRIGHTNESS";
                case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_REFRESH_RATE:
                case PRIORITY_APP_REQUEST_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_SIZE:
                case PRIORITY_APP_REQUEST_SIZE:
                    return "PRIORITY_APP_REQUEST_SIZE";
                    return "PRIORITY_APP_REQUEST_SIZE";
                case PRIORITY_USER_SETTING_REFRESH_RATE:
                case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_REFRESH_RATE";
                    return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
                case PRIORITY_LOW_POWER_MODE:
                case PRIORITY_LOW_POWER_MODE:
                    return "PRIORITY_LOW_POWER_MODE";
                    return "PRIORITY_LOW_POWER_MODE";
                default:
                default:
@@ -608,12 +638,11 @@ public class DisplayModeDirector {
            float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
            float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                    Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
                    Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);


            if (peakRefreshRate < minRefreshRate) {
            updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
                peakRefreshRate = minRefreshRate;
                    Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)));
            }
            updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
                    Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY));


            Vote vote = Vote.forRefreshRates(minRefreshRate, peakRefreshRate);
            updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
            mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
            mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
        }
        }


@@ -655,6 +684,7 @@ public class DisplayModeDirector {
                refreshRateVote = null;
                refreshRateVote = null;
                sizeVote = null;
                sizeVote = null;
            }
            }

            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
            return;
            return;
@@ -799,6 +829,8 @@ public class DisplayModeDirector {
        private boolean mRefreshRateChangeable = false;
        private boolean mRefreshRateChangeable = false;
        private boolean mLowPowerModeEnabled = false;
        private boolean mLowPowerModeEnabled = false;


        private int mRefreshRateInZone;

        BrightnessObserver(Context context, Handler handler) {
        BrightnessObserver(Context context, Handler handler) {
            super(handler);
            super(handler);
            mContext = context;
            mContext = context;
@@ -816,6 +848,7 @@ public class DisplayModeDirector {


        public void observe(SensorManager sensorManager) {
        public void observe(SensorManager sensorManager) {
            mSensorManager = sensorManager;
            mSensorManager = sensorManager;

            // DeviceConfig is accessible after system ready.
            // DeviceConfig is accessible after system ready.
            int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
            int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
            int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
            int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
@@ -825,6 +858,8 @@ public class DisplayModeDirector {
                mDisplayBrightnessThresholds = brightnessThresholds;
                mDisplayBrightnessThresholds = brightnessThresholds;
                mAmbientBrightnessThresholds = ambientThresholds;
                mAmbientBrightnessThresholds = ambientThresholds;
            }
            }

            mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
            restartObserver();
            restartObserver();
            mDeviceConfigDisplaySettings.startListening();
            mDeviceConfigDisplaySettings.startListening();
        }
        }
@@ -864,8 +899,16 @@ public class DisplayModeDirector {
            restartObserver();
            restartObserver();
        }
        }


        public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) {
            if (refreshRate != mRefreshRateInZone) {
                mRefreshRateInZone = refreshRate;
                restartObserver();
            }
        }

        public void dumpLocked(PrintWriter pw) {
        public void dumpLocked(PrintWriter pw) {
            pw.println("  BrightnessObserver");
            pw.println("  BrightnessObserver");
            pw.println("    mRefreshRateInZone: " + mRefreshRateInZone);


            for (int d: mDisplayBrightnessThresholds) {
            for (int d: mDisplayBrightnessThresholds) {
                pw.println("    mDisplayBrightnessThreshold: " + d);
                pw.println("    mDisplayBrightnessThreshold: " + d);
@@ -952,6 +995,10 @@ public class DisplayModeDirector {
         * to value changes.
         * to value changes.
         */
         */
        private boolean checkShouldObserve(int[] a) {
        private boolean checkShouldObserve(int[] a) {
            if (mRefreshRateInZone <= 0) {
                return false;
            }

            for (int d: a) {
            for (int d: a) {
                if (d >= 0) {
                if (d >= 0) {
                    return true;
                    return true;
@@ -961,37 +1008,42 @@ public class DisplayModeDirector {
            return false;
            return false;
        }
        }


        private void onBrightnessChangedLocked() {
        private boolean isInsideZone(int brightness, float lux) {
            int brightness = Settings.System.getInt(mContext.getContentResolver(),
                    Settings.System.SCREEN_BRIGHTNESS, -1);

            Vote vote = null;
            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
                int disp = mDisplayBrightnessThresholds[i];
                int disp = mDisplayBrightnessThresholds[i];
                int ambi = mAmbientBrightnessThresholds[i];
                int ambi = mAmbientBrightnessThresholds[i];


                if (disp >= 0 && ambi >= 0) {
                if (disp >= 0 && ambi >= 0) {
                    if (brightness <= disp && mAmbientLux <= ambi) {
                    if (brightness <= disp && mAmbientLux <= ambi) {
                        vote = Vote.forRefreshRates(0f, 60f);
                        return true;
                    }
                    }
                } else if (disp >= 0) {
                } else if (disp >= 0) {
                    if (brightness <= disp) {
                    if (brightness <= disp) {
                        vote = Vote.forRefreshRates(0f, 60f);
                        return true;
                    }
                    }
                } else if (ambi >= 0) {
                } else if (ambi >= 0) {
                    if (mAmbientLux <= ambi) {
                    if (mAmbientLux <= ambi) {
                        vote = Vote.forRefreshRates(0f, 60f);
                        return true;
                    }
                }
                }
            }
            }


                if (vote != null) {
            return false;
                    break;
        }
        }

        private void onBrightnessChangedLocked() {
            int brightness = Settings.System.getInt(mContext.getContentResolver(),
                    Settings.System.SCREEN_BRIGHTNESS, -1);

            Vote vote = null;
            boolean insideZone = isInsideZone(brightness, mAmbientLux);
            if (insideZone) {
                vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone);
            }
            }


            if (DEBUG) {
            if (DEBUG) {
                Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " +  mAmbientLux +
                Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " +  mAmbientLux +
                        (vote != null ? " 60hz only" : " no refresh rate limit"));
                        ", Vote " + vote);
            }
            }
            updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
            updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
        }
        }
@@ -1133,7 +1185,6 @@ public class DisplayModeDirector {
    }
    }


    private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
    private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {

        public DeviceConfigDisplaySettings() {
        public DeviceConfigDisplaySettings() {
        }
        }


@@ -1147,7 +1198,8 @@ public class DisplayModeDirector {
         */
         */
        public int[] getBrightnessThresholds() {
        public int[] getBrightnessThresholds() {
            return getIntArrayProperty(
            return getIntArrayProperty(
                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS);
                    DisplayManager.DeviceConfig.
                            KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
        }
        }


        /*
        /*
@@ -1155,7 +1207,8 @@ public class DisplayModeDirector {
         */
         */
        public int[] getAmbientThresholds() {
        public int[] getAmbientThresholds() {
            return getIntArrayProperty(
            return getIntArrayProperty(
                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS);
                    DisplayManager.DeviceConfig.
                            KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
        }
        }


        /*
        /*
@@ -1172,17 +1225,32 @@ public class DisplayModeDirector {
            return defaultPeakRefreshRate;
            return defaultPeakRefreshRate;
        }
        }


        public int getRefreshRateInZone() {
            int defaultRefreshRateInZone = mContext.getResources().getInteger(
                    R.integer.config_defaultRefreshRateInZone);

            int refreshRate = DeviceConfig.getInt(
                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
                    defaultRefreshRateInZone);

            return refreshRate;
        }

        @Override
        @Override
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
            int[] brightnessThresholds = getBrightnessThresholds();
            int[] brightnessThresholds = getBrightnessThresholds();
            int[] ambientThresholds = getAmbientThresholds();
            int[] ambientThresholds = getAmbientThresholds();
            Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
            Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
            int refreshRateInZone = getRefreshRateInZone();


            mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
            mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
                    new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
                    new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
                    .sendToTarget();
                    .sendToTarget();
            mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
            mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
                    defaultPeakRefreshRate).sendToTarget();
                    defaultPeakRefreshRate).sendToTarget();
            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone,
                    0).sendToTarget();
        }
        }


        private int[] getIntArrayProperty(String prop) {
        private int[] getIntArrayProperty(String prop) {