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

Commit d44f2edc authored by Long Ling's avatar Long Ling Committed by Android (Google) Code Review
Browse files

Merge "DMD: Support 90hz only in the refresh rate zone" into qt-r1-dev

parents 8e8a2d0c 73936631
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -829,23 +829,36 @@ public final class DisplayManager {
    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.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @hide
         */
        String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS =
        String KEY_PEAK_REFRESH_RATE_DISPLAY_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.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
         * @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
+4 −0
Original line number Diff line number Diff line
@@ -4167,6 +4167,10 @@
        -->
    </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
         auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
    <string name="config_displayLightSensorType" translatable="false" />
+1 −0
Original line number Diff line number Diff line
@@ -3791,6 +3791,7 @@

  <!-- For high refresh rate displays -->
  <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_ambientThresholdsOfPeakRefreshRate" />

+98 −30
Original line number 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_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
    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
    // specific display.
@@ -440,23 +441,48 @@ public class DisplayModeDirector {
                    mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
                            defaultPeakRefreshRate);
                    break;

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

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

        // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
        // 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
        // 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;

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

        public static String priorityToString(int 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:
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_SIZE:
                    return "PRIORITY_APP_REQUEST_SIZE";
                case PRIORITY_USER_SETTING_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_REFRESH_RATE";
                case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
                case PRIORITY_LOW_POWER_MODE:
                    return "PRIORITY_LOW_POWER_MODE";
                default:
@@ -608,12 +638,11 @@ public class DisplayModeDirector {
            float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                    Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);

            if (peakRefreshRate < minRefreshRate) {
                peakRefreshRate = minRefreshRate;
            }
            updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
                    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);
        }

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

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

        private int mRefreshRateInZone;

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

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

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

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

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

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

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

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

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

            Vote vote = null;
        private boolean isInsideZone(int brightness, float lux) {
            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
                int disp = mDisplayBrightnessThresholds[i];
                int ambi = mAmbientBrightnessThresholds[i];

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

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

        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) {
                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);
        }
@@ -1133,7 +1185,6 @@ public class DisplayModeDirector {
    }

    private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {

        public DeviceConfigDisplaySettings() {
        }

@@ -1147,7 +1198,8 @@ public class DisplayModeDirector {
         */
        public int[] getBrightnessThresholds() {
            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() {
            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;
        }

        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
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
            int[] brightnessThresholds = getBrightnessThresholds();
            int[] ambientThresholds = getAmbientThresholds();
            Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
            int refreshRateInZone = getRefreshRateInZone();

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

        private int[] getIntArrayProperty(String prop) {