diff options
author | Long Ling <longling@google.com> | 2019-08-08 16:05:44 -0700 |
---|---|---|
committer | Long Ling <longling@google.com> | 2019-08-21 10:45:29 -0700 |
commit | 67aae3f3226e41eb495ed2f73082daaeffa00e7c (patch) | |
tree | 5fb4a735d700275c4ab813f4f731c0165a1c473c | |
parent | 66e9298ac6386563e077c1b6b1e0bbe281a65455 (diff) | |
download | base-67aae3f3226e41eb495ed2f73082daaeffa00e7c.tar.gz |
DO NOT MERGE Allow DeviceConfig to change display settings
Allow DeviceConfig to change default refresh rate and 60 hz only
thresholds.
Bug: 139138964
Change-Id: I3bf5f8cf7a99e4723265138004fbbd08102119d9
-rw-r--r-- | services/core/java/com/android/server/display/DisplayModeDirector.java | 286 |
1 files changed, 232 insertions, 54 deletions
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index c45a314e39cc..5331aadec093 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -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) { + final ContentResolver cr = mContext.getContentResolver(); if (mShouldObserveDisplayChange) { - final ContentResolver cr = mContext.getContentResolver(); + // 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(); } - } - } - - 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); + } else { + mAmbientFilter = null; + mLightSensor = null; + mScreenStateReceiver.unregister(); } - for (int d: mAmbientBrightnessThresholds) { - pw.println(" mAmbientBrightnessThreshold: " + d); - } - } + updateSensorStatus(); - @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); } - @Override - public void onReceive(Context context, Intent intent) { - onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction())); + 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 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; + } + } + } |