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

Commit b6e7f156 authored by Long Ling's avatar Long Ling Committed by android-build-merger
Browse files

DO NOT MERGE Move device config key high_refresh_rate_blacklist to display_manager

am: 6f13f122

Change-Id: I51153a17807bccd6dc4220dbdb053f01bc1eed3d
parents e4971d89 6f13f122
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -820,4 +820,51 @@ public final class DisplayManager {
         */
        void onDisplayChanged(int displayId);
    }

    /**
     * Interface for accessing keys belonging to {@link
     * android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER}.
     * @hide
     */
    public interface DeviceConfig {

        /**
         * Key for accessing the 60 hz only regions.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @hide
         */
        String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS =
                "peak_refresh_rate_brightness_thresholds";

        /**
         * Key for accessing the 60 hz only regions.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
         * @hide
         */
        String KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS = "peak_refresh_rate_ambient_thresholds";

        /**
         * Key for default peak refresh rate
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.integer#config_defaultPeakRefreshRate
         * @hide
         */
        String KEY_PEAK_REFRESH_RATE_DEFAULT = "peak_refresh_rate_default";

        /**
         * Key for controlling which packages are explicitly blocked from running at refresh rates
         * higher than 60hz. An app may be added to this list if they exhibit performance issues at
         * higher refresh rates.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.array#config_highRefreshRateBlacklist
         * @hide
         */
        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
    }
}
+8 −9
Original line number Diff line number Diff line
@@ -135,6 +135,14 @@ public final class DeviceConfig {
    @SystemApi
    public static final String NAMESPACE_DEX_BOOT = "dex_boot";

    /**
     * Namespace for display manager related features. The names to access the properties in this
     * namespace should be defined in {@link android.hardware.display.DisplayManager}.
     *
     * @hide
     */
    public static final String NAMESPACE_DISPLAY_MANAGER = "display_manager";

    /**
     * Namespace for all Game Driver features.
     *
@@ -350,15 +358,6 @@ public final class DeviceConfig {
         */
        String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
                "system_gesture_exclusion_log_debounce_millis";

        /**
         * Key for controlling which packages are explicitly blocked from running at refresh rates
         * higher than 60hz.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
         * @hide
         */
        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
    }

    private static final Object sLock = new Object();
+232 −54
Original line number Diff line number Diff line
@@ -38,13 +38,16 @@ import android.os.Message;
import android.os.UserHandle;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;

import com.android.internal.os.BackgroundThread;
import com.android.internal.R;
import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
import com.android.server.display.whitebalance.AmbientFilter;
@@ -64,6 +67,8 @@ public class DisplayModeDirector {
    private static final boolean DEBUG = false;

    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;

    // Special ID used to indicate that given vote is to be applied globally, rather than to a
    // specific display.
@@ -91,6 +96,7 @@ public class DisplayModeDirector {
    private final DisplayObserver mDisplayObserver;
    private final BrightnessObserver mBrightnessObserver;

    private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
    private Listener mListener;

    public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
@@ -103,7 +109,7 @@ public class DisplayModeDirector {
        mSettingsObserver = new SettingsObserver(context, handler);
        mDisplayObserver = new DisplayObserver(context, handler);
        mBrightnessObserver = new BrightnessObserver(context, handler);

        mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
    }

    /**
@@ -405,7 +411,7 @@ public class DisplayModeDirector {
        void onAllowedDisplayModesChanged();
    }

    private static final class DisplayModeDirectorHandler extends Handler {
    private final class DisplayModeDirectorHandler extends Handler {
        DisplayModeDirectorHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }
@@ -417,6 +423,23 @@ public class DisplayModeDirector {
                    Listener listener = (Listener) msg.obj;
                    listener.onAllowedDisplayModesChanged();
                    break;

                case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
                    Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;

                    if (thresholds != null) {
                        mBrightnessObserver.onDeviceConfigThresholdsChanged(
                                thresholds.first, thresholds.second);
                    } else {
                        mBrightnessObserver.onDeviceConfigThresholdsChanged(null, null);
                    }
                    break;

                case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
                    Float defaultPeakRefreshRate = (Float) msg.obj;
                    mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
                            defaultPeakRefreshRate);
                    break;
            }
        }
    }
@@ -508,7 +531,7 @@ public class DisplayModeDirector {
                Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);

        private final Context mContext;
        private final float mDefaultPeakRefreshRate;
        private float mDefaultPeakRefreshRate;

        SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
            super(handler);
@@ -523,12 +546,33 @@ public class DisplayModeDirector {
                    UserHandle.USER_SYSTEM);
            cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
                    UserHandle.USER_SYSTEM);

            Float deviceConfigDefaultPeakRefresh =
                    mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
            if (deviceConfigDefaultPeakRefresh != null) {
                mDefaultPeakRefreshRate = deviceConfigDefaultPeakRefresh;
            }

            synchronized (mLock) {
                updateRefreshRateSettingLocked();
                updateLowPowerModeSettingLocked();
            }
        }

        public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) {
            if (defaultPeakRefreshRate == null) {
                defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
                        R.integer.config_defaultPeakRefreshRate);
            }

            if (mDefaultPeakRefreshRate != defaultPeakRefreshRate) {
                synchronized (mLock) {
                    mDefaultPeakRefreshRate = defaultPeakRefreshRate;
                    updateRefreshRateSettingLocked();
                }
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            synchronized (mLock) {
@@ -720,8 +764,8 @@ public class DisplayModeDirector {
                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);

        private final static int LIGHT_SENSOR_RATE_MS = 250;
        private final int[] mDisplayBrightnessThresholds;
        private final int[] mAmbientBrightnessThresholds;
        private int[] mDisplayBrightnessThresholds;
        private int[] mAmbientBrightnessThresholds;
        // valid threshold if any item from the array >= 0
        private boolean mShouldObserveDisplayChange;
        private boolean mShouldObserveAmbientChange;
@@ -734,10 +778,11 @@ public class DisplayModeDirector {
        private AmbientFilter mAmbientFilter;

        private final Context mContext;
        private ScreenStateReceiver mScreenStateReceiver;
        private final ScreenStateReceiver mScreenStateReceiver;

        // Enable light sensor only when screen is on, peak refresh rate enabled and low power mode
        // off. After initialization, these states will be updated from the same handler thread.
        // Enable light sensor only when mShouldObserveAmbientChange is true, screen is on, peak
        // refresh rate enabled and low power mode off. After initialization, these states will
        // be updated from the same handler thread.
        private boolean mScreenOn = false;
        private boolean mPeakRefreshRateEnabled = false;
        private boolean mLowPowerModeEnabled = false;
@@ -745,24 +790,95 @@ public class DisplayModeDirector {
        BrightnessObserver(Context context, Handler handler) {
            super(handler);
            mContext = context;
            mScreenStateReceiver = new ScreenStateReceiver(mContext);
            mDisplayBrightnessThresholds = context.getResources().getIntArray(
                    R.array.config_brightnessThresholdsOfPeakRefreshRate);
            mAmbientBrightnessThresholds = context.getResources().getIntArray(
                    R.array.config_ambientThresholdsOfPeakRefreshRate);

            if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) {
                throw new RuntimeException("display brightness threshold array and ambient "
                        + "brightness threshold array have different length");
            }
        }

        public void observe(SensorManager sensorManager) {
            mSensorManager = sensorManager;
            // DeviceConfig is accessible after system ready.
            int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
            int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();

            if (brightnessThresholds != null && ambientThresholds != null
                    && brightnessThresholds.length == ambientThresholds.length) {
                mDisplayBrightnessThresholds = brightnessThresholds;
                mAmbientBrightnessThresholds = ambientThresholds;
            }
            restartObserver();
            mDeviceConfigDisplaySettings.startListening();
        }

        public void onPeakRefreshRateEnabled(boolean b) {
            if (mPeakRefreshRateEnabled != b) {
                mPeakRefreshRateEnabled = b;
                updateSensorStatus();
            }
        }

        public void onLowPowerModeEnabled(boolean b) {
            if (mLowPowerModeEnabled != b) {
                mLowPowerModeEnabled = b;
                updateSensorStatus();
            }
        }

        public void onDeviceConfigThresholdsChanged(int[] brightnessThresholds,
                int[] ambientThresholds) {
            if (brightnessThresholds != null && ambientThresholds != null
                    && brightnessThresholds.length == ambientThresholds.length) {
                mDisplayBrightnessThresholds = brightnessThresholds;
                mAmbientBrightnessThresholds = ambientThresholds;
            } else {
                // Invalid or empty. Use device default.
                mDisplayBrightnessThresholds = mContext.getResources().getIntArray(
                        R.array.config_brightnessThresholdsOfPeakRefreshRate);
                mAmbientBrightnessThresholds = mContext.getResources().getIntArray(
                        R.array.config_ambientThresholdsOfPeakRefreshRate);
            }
            restartObserver();
        }

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

            for (int d: mDisplayBrightnessThresholds) {
                pw.println("    mDisplayBrightnessThreshold: " + d);
            }

            for (int d: mAmbientBrightnessThresholds) {
                pw.println("    mAmbientBrightnessThreshold: " + d);
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            synchronized (mLock) {
                onBrightnessChangedLocked();
            }
        }

        private void restartObserver() {
            mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
            mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
        }

        public void observe(SensorManager sensorManager) {
            if (mShouldObserveDisplayChange) {
            final ContentResolver cr = mContext.getContentResolver();
            if (mShouldObserveDisplayChange) {
                // Content Service does not check if an listener has already been registered.
                // To ensure only one listener is registered, force an unregistration first.
                cr.unregisterContentObserver(this);
                cr.registerContentObserver(mDisplayBrightnessSetting,
                        false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
            } else {
                cr.unregisterContentObserver(this);
            }

            if (mShouldObserveAmbientChange) {
@@ -772,7 +888,7 @@ public class DisplayModeDirector {

                Sensor lightSensor = null;
                if (!TextUtils.isEmpty(lightSensorType)) {
                    List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
                    List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
                    for (int i = 0; i < sensors.size(); i++) {
                        Sensor sensor = sensors.get(i);
                        if (lightSensorType.equals(sensor.getStringType())) {
@@ -783,59 +899,29 @@ public class DisplayModeDirector {
                }

                if (lightSensor == null) {
                    lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
                    lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
                }

                if (lightSensor != null) {
                    final Resources res = mContext.getResources();

                    mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res);
                    mSensorManager = sensorManager;
                    mLightSensor = lightSensor;

                    // Intent.ACTION_SCREEN_ON is not sticky. Check current screen status.
                    if (mContext.getSystemService(PowerManager.class).isInteractive()) {
                        onScreenOn(true);
                    }
                    mScreenStateReceiver = new ScreenStateReceiver(mContext);
                }
            }

            if (mShouldObserveDisplayChange || mShouldObserveAmbientChange) {
                synchronized (mLock) {
                    onBrightnessChangedLocked();
                }
                    mScreenStateReceiver.register();
                }
            } else {
                mAmbientFilter = null;
                mLightSensor = null;
                mScreenStateReceiver.unregister();
            }

        public void onPeakRefreshRateEnabled(boolean b) {
            if (mShouldObserveAmbientChange && mPeakRefreshRateEnabled != b) {
                mPeakRefreshRateEnabled = b;
            updateSensorStatus();
            }
        }

        public void onLowPowerModeEnabled(boolean b) {
            if (mShouldObserveAmbientChange && mLowPowerModeEnabled != b) {
                mLowPowerModeEnabled = b;
                updateSensorStatus();
            }
        }

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

            for (int d: mDisplayBrightnessThresholds) {
                pw.println("    mDisplayBrightnessThreshold: " + d);
            }

            for (int d: mAmbientBrightnessThresholds) {
                pw.println("    mAmbientBrightnessThreshold: " + d);
            }
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            synchronized (mLock) {
                onBrightnessChangedLocked();
            }
@@ -904,7 +990,8 @@ public class DisplayModeDirector {
                return;
            }

            if (mScreenOn && !mLowPowerModeEnabled && mPeakRefreshRateEnabled) {
            if (mShouldObserveAmbientChange && mScreenOn && !mLowPowerModeEnabled
                    && mPeakRefreshRateEnabled) {
                mSensorManager.registerListener(mLightSensorListener,
                        mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
            } else {
@@ -993,18 +1080,109 @@ public class DisplayModeDirector {
        };

        private final class ScreenStateReceiver extends BroadcastReceiver {
            final Context mContext;
            public ScreenStateReceiver(Context context) {
                mContext = context;
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
            }

            public void register() {
                IntentFilter filter = new IntentFilter();
                filter.addAction(Intent.ACTION_SCREEN_OFF);
                filter.addAction(Intent.ACTION_SCREEN_ON);
                filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
                context.registerReceiver(this, filter, null, mHandler);
                mContext.registerReceiver(this, filter, null, mHandler);
            }

            public void unregister() {
                mContext.unregisterReceiver(this);
            }
        }
    }

    private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {

        public DeviceConfigDisplaySettings() {
        }

        public void startListening() {
            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                    BackgroundThread.getExecutor(), this);
        }

        /*
         * Return null if no such property or wrong format (not comma separated integers).
         */
        public int[] getBrightnessThresholds() {
            return getIntArrayProperty(
                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS);
        }

        /*
         * Return null if no such property or wrong format (not comma separated integers).
         */
        public int[] getAmbientThresholds() {
            return getIntArrayProperty(
                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS);
        }

        /*
         * Return null if no such property
         */
        public Float getDefaultPeakRefreshRate() {
            float defaultPeakRefreshRate = DeviceConfig.getFloat(
                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);

            if (defaultPeakRefreshRate == -1) {
                return null;
            }
            return defaultPeakRefreshRate;
        }

        @Override
            public void onReceive(Context context, Intent intent) {
                onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
            int[] brightnessThresholds = getBrightnessThresholds();
            int[] ambientThresholds = getAmbientThresholds();
            Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();

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

        private int[] getIntArrayProperty(String prop) {
            String strArray = DeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
                    null);

            if (strArray != null) {
                return parseIntArray(strArray);
            }

            return null;
        }

        private int[] parseIntArray(@NonNull String strArray) {
            String[] items = strArray.split(",");
            int[] array = new int[items.length];

            try {
                for (int i = 0; i < array.length; i++) {
                    array[i] = Integer.parseInt(items[i]);
                }
            } catch (NumberFormatException e) {
                Slog.e(TAG, "Incorrect format for array: '" + strArray + "'", e);
                array = null;
            }

            return array;
        }
    }

}
+3 −3
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.server.wm;

import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -58,9 +58,9 @@ class HighRefreshRateBlacklist {
    @VisibleForTesting
    HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
        mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
        deviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
        deviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                BackgroundThread.getExecutor(), new OnPropertyChangedListener());
        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                KEY_HIGH_REFRESH_RATE_BLACKLIST);
        updateBlacklist(property);
    }
+6 −6
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.server.wm;

import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -126,9 +126,9 @@ public class HighRefreshRateBlacklistTest {

        @Override
        public String getProperty(String namespace, String name) {
            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)
            if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)
                    || !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
                throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
                        + "supported.");
            }
            return mBlacklist;
@@ -138,8 +138,8 @@ public class HighRefreshRateBlacklistTest {
        public void addOnPropertyChangedListener(String namespace, Executor executor,
                DeviceConfig.OnPropertyChangedListener listener) {

            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)) {
                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
            if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)) {
                throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
                        + "supported.");
            }
            mListeners.add(new Pair<>(listener, executor));
@@ -153,7 +153,7 @@ public class HighRefreshRateBlacklistTest {
                final Executor executor = listenerInfo.second;
                final DeviceConfig.OnPropertyChangedListener listener = listenerInfo.first;
                executor.execute(() -> {
                    listener.onPropertyChanged(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                    listener.onPropertyChanged(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                            KEY_HIGH_REFRESH_RATE_BLACKLIST, blacklist);
                    latch.countDown();
                });