Loading core/java/android/hardware/display/DisplayManagerInternal.java +86 −0 Original line number Diff line number Diff line Loading @@ -22,12 +22,15 @@ import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import java.util.Objects; /** * Display manager local system service interface. * Loading Loading @@ -292,6 +295,23 @@ public abstract class DisplayManagerInternal { @DisplayManager.SwitchingType public abstract int getRefreshRateSwitchingType(); /** * Return the refresh rate restriction for the specified display and sensor pairing. If the * specified sensor is identified as an associated sensor in the specified display's * display-device-config file, then return any refresh rate restrictions that it might specify. * If no restriction is specified, or the sensor is not associated with the display, then null * will be returned. * * @param displayId The display to check against. * @param name The name of the sensor. * @param type The type of sensor. * * @return The min/max refresh-rate restriction as a {@link Pair} of floats, or null if not * restricted. */ public abstract RefreshRateRange getRefreshRateForDisplayAndSensor( int displayId, String name, String type); /** * Describes the requested power state of the display. * Loading Loading @@ -527,4 +547,70 @@ public abstract class DisplayManagerInternal { */ void onDisplayGroupChanged(int groupId); } /** * Information about the min and max refresh rate DM would like to set the display to. */ public static final class RefreshRateRange { public static final String TAG = "RefreshRateRange"; // The tolerance within which we consider something approximately equals. public static final float FLOAT_TOLERANCE = 0.01f; /** * The lowest desired refresh rate. */ public float min; /** * The highest desired refresh rate. */ public float max; public RefreshRateRange() {} public RefreshRateRange(float min, float max) { if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) { Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : " + min + " " + max); this.min = this.max = 0; return; } if (min > max) { // Min and max are within epsilon of each other, but in the wrong order. float t = min; min = max; max = t; } this.min = min; this.max = max; } /** * Checks whether the two objects have the same values. */ @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof RefreshRateRange)) { return false; } RefreshRateRange refreshRateRange = (RefreshRateRange) other; return (min == refreshRateRange.min && max == refreshRateRange.max); } @Override public int hashCode() { return Objects.hash(min, max); } @Override public String toString() { return "(" + min + " " + max + ")"; } } } services/core/java/com/android/server/display/DisplayDeviceConfig.java +46 −14 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context; import android.content.res.Resources; import android.os.Environment; import android.os.PowerManager; import android.text.TextUtils; import android.util.MathUtils; import android.util.Slog; import android.util.Spline; Loading @@ -34,6 +35,7 @@ import com.android.server.display.config.HbmTiming; import com.android.server.display.config.HighBrightnessMode; import com.android.server.display.config.NitsMap; import com.android.server.display.config.Point; import com.android.server.display.config.RefreshRateRange; import com.android.server.display.config.SensorDetails; import com.android.server.display.config.XmlParser; Loading Loading @@ -79,10 +81,10 @@ public class DisplayDeviceConfig { private final Context mContext; // The details of the ambient light sensor associated with this display. private final SensorIdentifier mAmbientLightSensor = new SensorIdentifier(); private final SensorData mAmbientLightSensor = new SensorData(); // The details of the proximity sensor associated with this display. private final SensorIdentifier mProximitySensor = new SensorIdentifier(); private final SensorData mProximitySensor = new SensorData(); // Nits and backlight values that are loaded from either the display device config file, or // config.xml. These are the raw values and just used for the dumpsys Loading Loading @@ -113,6 +115,7 @@ public class DisplayDeviceConfig { private List<String> mQuirks; private boolean mIsHighBrightnessModeEnabled = false; private HighBrightnessModeData mHbmData; private String mLoadedFrom = null; private DisplayDeviceConfig(Context context) { mContext = context; Loading Loading @@ -273,11 +276,11 @@ public class DisplayDeviceConfig { return mBrightnessRampSlowIncrease; } SensorIdentifier getAmbientLightSensor() { SensorData getAmbientLightSensor() { return mAmbientLightSensor; } SensorIdentifier getProximitySensor() { SensorData getProximitySensor() { return mProximitySensor; } Loading Loading @@ -306,7 +309,8 @@ public class DisplayDeviceConfig { @Override public String toString() { String str = "DisplayDeviceConfig{" + "mBacklight=" + Arrays.toString(mBacklight) + "mLoadedFrom=" + mLoadedFrom + ", mBacklight=" + Arrays.toString(mBacklight) + ", mNits=" + Arrays.toString(mNits) + ", mRawBacklight=" + Arrays.toString(mRawBacklight) + ", mRawNits=" + Arrays.toString(mRawNits) Loading Loading @@ -336,9 +340,8 @@ public class DisplayDeviceConfig { final String filename = String.format(CONFIG_FILE_FORMAT, suffix); final File filePath = Environment.buildPath( baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename); if (filePath.exists()) { final DisplayDeviceConfig config = new DisplayDeviceConfig(context); config.initFromFile(filePath); if (config.initFromFile(filePath)) { return config; } return null; Loading @@ -356,15 +359,15 @@ public class DisplayDeviceConfig { return config; } private void initFromFile(File configFile) { private boolean initFromFile(File configFile) { if (!configFile.exists()) { // Display configuration files aren't required to exist. return; return false; } if (!configFile.isFile()) { Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping"); return; return false; } try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { Loading @@ -385,6 +388,8 @@ public class DisplayDeviceConfig { Slog.e(TAG, "Encountered an error while reading/parsing display config file: " + configFile, e); } mLoadedFrom = configFile.toString(); return true; } private void initFromGlobalXml() { Loading @@ -395,10 +400,12 @@ public class DisplayDeviceConfig { loadBrightnessRampsFromConfigXml(); loadAmbientLightSensorFromConfigXml(); setProxSensorUnspecified(); mLoadedFrom = "<config.xml>"; } private void initFromDefaultValues() { // Set all to basic values mLoadedFrom = "Static values"; mBacklightMinimum = PowerManager.BRIGHTNESS_MIN; mBacklightMaximum = PowerManager.BRIGHTNESS_MAX; mBrightnessDefault = BRIGHTNESS_DEFAULT; Loading Loading @@ -689,6 +696,11 @@ public class DisplayDeviceConfig { if (sensorDetails != null) { mAmbientLightSensor.type = sensorDetails.getType(); mAmbientLightSensor.name = sensorDetails.getName(); final RefreshRateRange rr = sensorDetails.getRefreshRate(); if (rr != null) { mAmbientLightSensor.minRefreshRate = rr.getMinimum().floatValue(); mAmbientLightSensor.maxRefreshRate = rr.getMaximum().floatValue(); } } else { loadAmbientLightSensorFromConfigXml(); } Loading @@ -704,22 +716,42 @@ public class DisplayDeviceConfig { if (sensorDetails != null) { mProximitySensor.name = sensorDetails.getName(); mProximitySensor.type = sensorDetails.getType(); final RefreshRateRange rr = sensorDetails.getRefreshRate(); if (rr != null) { mProximitySensor.minRefreshRate = rr.getMinimum().floatValue(); mProximitySensor.maxRefreshRate = rr.getMaximum().floatValue(); } } else { setProxSensorUnspecified(); } } static class SensorIdentifier { static class SensorData { public String type; public String name; public float minRefreshRate = 0.0f; public float maxRefreshRate = Float.POSITIVE_INFINITY; @Override public String toString() { return "Sensor{" + "type: \"" + type + "\"" + ", name: \"" + name + "\"" + "type: " + type + ", name: " + name + ", refreshRateRange: [" + minRefreshRate + ", " + maxRefreshRate + "]" + "} "; } /** * @return True if the sensor matches both the specified name and type, or one if only * one is specified (not-empty). Always returns false if both parameters are null or empty. */ public boolean matches(String sensorName, String sensorType) { final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); return (isNameSpecified || isTypeSpecified) && (!isNameSpecified || sensorName.equals(name)) && (!isTypeSpecified || sensorType.equals(type)); } } /** Loading services/core/java/com/android/server/display/DisplayManagerService.java +38 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.ColorSpace; import android.graphics.Point; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.AmbientBrightnessDayStats; Loading @@ -62,6 +63,7 @@ import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayGroupListener; import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; import android.hardware.display.DisplayManagerInternal.RefreshRateRange; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; Loading Loading @@ -119,6 +121,8 @@ import com.android.server.DisplayThread; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; import com.android.server.display.DisplayDeviceConfig.SensorData; import com.android.server.display.utils.SensorUtils; import com.android.server.wm.SurfaceAnimationThread; import com.android.server.wm.WindowManagerInternal; Loading Loading @@ -3257,6 +3261,40 @@ public final class DisplayManagerService extends SystemService { public int getRefreshRateSwitchingType() { return getRefreshRateSwitchingTypeInternal(); } @Override public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName, String sensorType) { final SensorManager sensorManager; synchronized (mSyncRoot) { sensorManager = mSensorManager; } if (sensorManager == null) { return null; } // Verify that the specified sensor exists. final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName, SensorUtils.NO_FALLBACK); if (sensor == null) { return null; } synchronized (mSyncRoot) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device == null) { return null; } final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); SensorData sensorData = config.getProximitySensor(); if (sensorData.matches(sensorName, sensorType)) { return new RefreshRateRange(sensorData.minRefreshRate, sensorData.maxRefreshRate); } } return null; } } class DesiredDisplayModeSpecsObserver Loading services/core/java/com/android/server/display/DisplayModeDirector.java +79 −63 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.RefreshRateRange; import android.hardware.fingerprint.IUdfpsHbmListener; import android.net.Uri; import android.os.Handler; Loading @@ -51,6 +53,8 @@ import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.display.utils.AmbientFilter; import com.android.server.display.utils.AmbientFilterFactory; import com.android.server.sensors.SensorManagerInternal; import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.utils.DeviceConfigInterface; Loading Loading @@ -85,8 +89,7 @@ public class DisplayModeDirector { private static final int INVALID_DISPLAY_MODE_ID = -1; // The tolerance within which we consider something approximately equals. private static final float FLOAT_TOLERANCE = 0.01f; private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE; private final Object mLock = new Object(); private final Context mContext; Loading @@ -98,6 +101,7 @@ public class DisplayModeDirector { private final SettingsObserver mSettingsObserver; private final DisplayObserver mDisplayObserver; private final UdfpsObserver mUdfpsObserver; private final SensorObserver mSensorObserver; private final DeviceConfigInterface mDeviceConfig; private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; Loading Loading @@ -139,6 +143,11 @@ public class DisplayModeDirector { mDisplayObserver = new DisplayObserver(context, handler); mBrightnessObserver = new BrightnessObserver(context, handler); mUdfpsObserver = new UdfpsObserver(); mSensorObserver = new SensorObserver(context, (displayId, priority, vote) -> { synchronized (mLock) { updateVoteLocked(displayId, priority, vote); } }); mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings(); mDeviceConfig = injector.getDeviceConfig(); mAlwaysRespectAppRequest = false; Loading @@ -155,6 +164,7 @@ public class DisplayModeDirector { mSettingsObserver.observe(); mDisplayObserver.observe(); mBrightnessObserver.observe(sensorManager); mSensorObserver.observe(); synchronized (mLock) { // We may have a listener already registered before the call to start, so go ahead and // notify them to pick up our newly initialized state. Loading Loading @@ -585,6 +595,7 @@ public class DisplayModeDirector { mAppRequestObserver.dumpLocked(pw); mBrightnessObserver.dumpLocked(pw); mUdfpsObserver.dumpLocked(pw); mSensorObserver.dumpLocked(pw); } } Loading Loading @@ -767,66 +778,6 @@ public class DisplayModeDirector { } } /** * Information about the min and max refresh rate DM would like to set the display to. */ public static final class RefreshRateRange { /** * The lowest desired refresh rate. */ public float min; /** * The highest desired refresh rate. */ public float max; public RefreshRateRange() {} public RefreshRateRange(float min, float max) { if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) { Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : " + min + " " + max); this.min = this.max = 0; return; } if (min > max) { // Min and max are within epsilon of each other, but in the wrong order. float t = min; min = max; max = t; } this.min = min; this.max = max; } /** * Checks whether the two objects have the same values. */ @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof RefreshRateRange)) { return false; } RefreshRateRange refreshRateRange = (RefreshRateRange) other; return (min == refreshRateRange.min && max == refreshRateRange.max); } @Override public int hashCode() { return Objects.hash(min, max); } @Override public String toString() { return "(" + min + " " + max + ")"; } } /** * Information about the desired display mode to be set by the system. Includes the base * mode ID and the primary and app request refresh rate ranges. Loading Loading @@ -987,9 +938,13 @@ public class DisplayModeDirector { // user seeing the display flickering when the switches occur. public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. public static final int PRIORITY_PROXIMITY = 9; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. public static final int PRIORITY_UDFPS = 9; public static final int PRIORITY_UDFPS = 10; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. Loading Loading @@ -1086,6 +1041,8 @@ public class DisplayModeDirector { return "PRIORITY_LOW_POWER_MODE"; case PRIORITY_UDFPS: return "PRIORITY_UDFPS"; case PRIORITY_PROXIMITY: return "PRIORITY_PROXIMITY"; default: return Integer.toString(priority); Loading Loading @@ -2142,6 +2099,62 @@ public class DisplayModeDirector { } } private static class SensorObserver implements ProximityActiveListener { private static final String PROXIMITY_SENSOR_NAME = null; private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY; private final BallotBox mBallotBox; private final Context mContext; private DisplayManager mDisplayManager; private DisplayManagerInternal mDisplayManagerInternal; private boolean mIsProxActive = false; SensorObserver(Context context, BallotBox ballotBox) { mContext = context; mBallotBox = ballotBox; } @Override public void onProximityActive(boolean isActive) { if (mIsProxActive != isActive) { mIsProxActive = isActive; recalculateVotes(); } } public void observe() { mDisplayManager = mContext.getSystemService(DisplayManager.class); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); final SensorManagerInternal sensorManager = LocalServices.getService(SensorManagerInternal.class); sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this); } private void recalculateVotes() { final Display[] displays = mDisplayManager.getDisplays(); for (Display d : displays) { int displayId = d.getDisplayId(); Vote vote = null; if (mIsProxActive) { final RefreshRateRange rate = mDisplayManagerInternal.getRefreshRateForDisplayAndSensor( displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE); if (rate != null) { vote = Vote.forRefreshRates(rate.min, rate.max); } } mBallotBox.vote(displayId, Vote.PRIORITY_PROXIMITY, vote); } } void dumpLocked(PrintWriter pw) { pw.println(" SensorObserver"); pw.println(" mIsProxActive=" + mIsProxActive); } } private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener { public DeviceConfigDisplaySettings() { } Loading Loading @@ -2328,4 +2341,7 @@ public class DisplayModeDirector { } } interface BallotBox { void vote(int displayId, int priority, Vote vote); } } services/core/java/com/android/server/display/DisplayPowerController.java +11 −33 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.util.MathUtils; import android.util.Slog; Loading @@ -65,13 +64,13 @@ import com.android.server.am.BatteryStatsService; import com.android.server.display.RampAnimator.DualRampAnimator; import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal; import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener; import com.android.server.display.utils.SensorUtils; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory; import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; import java.util.List; /** * Controls the power state of the display. Loading Loading @@ -586,26 +585,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits); } private Sensor findSensor(String sensorType, String sensorName, int fallbackType, boolean useFallback) { final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); if (isNameSpecified || isTypeSpecified) { for (Sensor sensor : sensors) { if ((!isNameSpecified || sensorName.equals(sensor.getName())) && (!isTypeSpecified || sensorType.equals(sensor.getStringType()))) { return sensor; } } } if (useFallback) { return mSensorManager.getDefaultSensor(fallbackType); } else { return null; } } /** * Returns true if the proximity sensor screen-off function is available. */ Loading Loading @@ -1654,24 +1633,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private void loadAmbientLightSensor() { DisplayDeviceConfig.SensorIdentifier lightSensor = mDisplayDeviceConfig.getAmbientLightSensor(); String lightSensorName = lightSensor.name; String lightSensorType = lightSensor.type; mLightSensor = findSensor(lightSensorType, lightSensorName, Sensor.TYPE_LIGHT, mDisplayId == Display.DEFAULT_DISPLAY); DisplayDeviceConfig.SensorData lightSensor = mDisplayDeviceConfig.getAmbientLightSensor(); final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK; mLightSensor = SensorUtils.findSensor(mSensorManager, lightSensor.type, lightSensor.name, fallbackType); } private void loadProximitySensor() { if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { return; } final DisplayDeviceConfig.SensorIdentifier proxSensor = final DisplayDeviceConfig.SensorData proxSensor = mDisplayDeviceConfig.getProximitySensor(); final String proxSensorName = proxSensor.name; final String proxSensorType = proxSensor.type; mProximitySensor = findSensor(proxSensorType, proxSensorName, Sensor.TYPE_PROXIMITY, mDisplayId == Display.DEFAULT_DISPLAY); final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK; mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name, fallbackType); if (mProximitySensor != null) { mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), TYPICAL_PROXIMITY_THRESHOLD); Loading Loading
core/java/android/hardware/display/DisplayManagerInternal.java +86 −0 Original line number Diff line number Diff line Loading @@ -22,12 +22,15 @@ import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import java.util.Objects; /** * Display manager local system service interface. * Loading Loading @@ -292,6 +295,23 @@ public abstract class DisplayManagerInternal { @DisplayManager.SwitchingType public abstract int getRefreshRateSwitchingType(); /** * Return the refresh rate restriction for the specified display and sensor pairing. If the * specified sensor is identified as an associated sensor in the specified display's * display-device-config file, then return any refresh rate restrictions that it might specify. * If no restriction is specified, or the sensor is not associated with the display, then null * will be returned. * * @param displayId The display to check against. * @param name The name of the sensor. * @param type The type of sensor. * * @return The min/max refresh-rate restriction as a {@link Pair} of floats, or null if not * restricted. */ public abstract RefreshRateRange getRefreshRateForDisplayAndSensor( int displayId, String name, String type); /** * Describes the requested power state of the display. * Loading Loading @@ -527,4 +547,70 @@ public abstract class DisplayManagerInternal { */ void onDisplayGroupChanged(int groupId); } /** * Information about the min and max refresh rate DM would like to set the display to. */ public static final class RefreshRateRange { public static final String TAG = "RefreshRateRange"; // The tolerance within which we consider something approximately equals. public static final float FLOAT_TOLERANCE = 0.01f; /** * The lowest desired refresh rate. */ public float min; /** * The highest desired refresh rate. */ public float max; public RefreshRateRange() {} public RefreshRateRange(float min, float max) { if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) { Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : " + min + " " + max); this.min = this.max = 0; return; } if (min > max) { // Min and max are within epsilon of each other, but in the wrong order. float t = min; min = max; max = t; } this.min = min; this.max = max; } /** * Checks whether the two objects have the same values. */ @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof RefreshRateRange)) { return false; } RefreshRateRange refreshRateRange = (RefreshRateRange) other; return (min == refreshRateRange.min && max == refreshRateRange.max); } @Override public int hashCode() { return Objects.hash(min, max); } @Override public String toString() { return "(" + min + " " + max + ")"; } } }
services/core/java/com/android/server/display/DisplayDeviceConfig.java +46 −14 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.Context; import android.content.res.Resources; import android.os.Environment; import android.os.PowerManager; import android.text.TextUtils; import android.util.MathUtils; import android.util.Slog; import android.util.Spline; Loading @@ -34,6 +35,7 @@ import com.android.server.display.config.HbmTiming; import com.android.server.display.config.HighBrightnessMode; import com.android.server.display.config.NitsMap; import com.android.server.display.config.Point; import com.android.server.display.config.RefreshRateRange; import com.android.server.display.config.SensorDetails; import com.android.server.display.config.XmlParser; Loading Loading @@ -79,10 +81,10 @@ public class DisplayDeviceConfig { private final Context mContext; // The details of the ambient light sensor associated with this display. private final SensorIdentifier mAmbientLightSensor = new SensorIdentifier(); private final SensorData mAmbientLightSensor = new SensorData(); // The details of the proximity sensor associated with this display. private final SensorIdentifier mProximitySensor = new SensorIdentifier(); private final SensorData mProximitySensor = new SensorData(); // Nits and backlight values that are loaded from either the display device config file, or // config.xml. These are the raw values and just used for the dumpsys Loading Loading @@ -113,6 +115,7 @@ public class DisplayDeviceConfig { private List<String> mQuirks; private boolean mIsHighBrightnessModeEnabled = false; private HighBrightnessModeData mHbmData; private String mLoadedFrom = null; private DisplayDeviceConfig(Context context) { mContext = context; Loading Loading @@ -273,11 +276,11 @@ public class DisplayDeviceConfig { return mBrightnessRampSlowIncrease; } SensorIdentifier getAmbientLightSensor() { SensorData getAmbientLightSensor() { return mAmbientLightSensor; } SensorIdentifier getProximitySensor() { SensorData getProximitySensor() { return mProximitySensor; } Loading Loading @@ -306,7 +309,8 @@ public class DisplayDeviceConfig { @Override public String toString() { String str = "DisplayDeviceConfig{" + "mBacklight=" + Arrays.toString(mBacklight) + "mLoadedFrom=" + mLoadedFrom + ", mBacklight=" + Arrays.toString(mBacklight) + ", mNits=" + Arrays.toString(mNits) + ", mRawBacklight=" + Arrays.toString(mRawBacklight) + ", mRawNits=" + Arrays.toString(mRawNits) Loading Loading @@ -336,9 +340,8 @@ public class DisplayDeviceConfig { final String filename = String.format(CONFIG_FILE_FORMAT, suffix); final File filePath = Environment.buildPath( baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename); if (filePath.exists()) { final DisplayDeviceConfig config = new DisplayDeviceConfig(context); config.initFromFile(filePath); if (config.initFromFile(filePath)) { return config; } return null; Loading @@ -356,15 +359,15 @@ public class DisplayDeviceConfig { return config; } private void initFromFile(File configFile) { private boolean initFromFile(File configFile) { if (!configFile.exists()) { // Display configuration files aren't required to exist. return; return false; } if (!configFile.isFile()) { Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping"); return; return false; } try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { Loading @@ -385,6 +388,8 @@ public class DisplayDeviceConfig { Slog.e(TAG, "Encountered an error while reading/parsing display config file: " + configFile, e); } mLoadedFrom = configFile.toString(); return true; } private void initFromGlobalXml() { Loading @@ -395,10 +400,12 @@ public class DisplayDeviceConfig { loadBrightnessRampsFromConfigXml(); loadAmbientLightSensorFromConfigXml(); setProxSensorUnspecified(); mLoadedFrom = "<config.xml>"; } private void initFromDefaultValues() { // Set all to basic values mLoadedFrom = "Static values"; mBacklightMinimum = PowerManager.BRIGHTNESS_MIN; mBacklightMaximum = PowerManager.BRIGHTNESS_MAX; mBrightnessDefault = BRIGHTNESS_DEFAULT; Loading Loading @@ -689,6 +696,11 @@ public class DisplayDeviceConfig { if (sensorDetails != null) { mAmbientLightSensor.type = sensorDetails.getType(); mAmbientLightSensor.name = sensorDetails.getName(); final RefreshRateRange rr = sensorDetails.getRefreshRate(); if (rr != null) { mAmbientLightSensor.minRefreshRate = rr.getMinimum().floatValue(); mAmbientLightSensor.maxRefreshRate = rr.getMaximum().floatValue(); } } else { loadAmbientLightSensorFromConfigXml(); } Loading @@ -704,22 +716,42 @@ public class DisplayDeviceConfig { if (sensorDetails != null) { mProximitySensor.name = sensorDetails.getName(); mProximitySensor.type = sensorDetails.getType(); final RefreshRateRange rr = sensorDetails.getRefreshRate(); if (rr != null) { mProximitySensor.minRefreshRate = rr.getMinimum().floatValue(); mProximitySensor.maxRefreshRate = rr.getMaximum().floatValue(); } } else { setProxSensorUnspecified(); } } static class SensorIdentifier { static class SensorData { public String type; public String name; public float minRefreshRate = 0.0f; public float maxRefreshRate = Float.POSITIVE_INFINITY; @Override public String toString() { return "Sensor{" + "type: \"" + type + "\"" + ", name: \"" + name + "\"" + "type: " + type + ", name: " + name + ", refreshRateRange: [" + minRefreshRate + ", " + maxRefreshRate + "]" + "} "; } /** * @return True if the sensor matches both the specified name and type, or one if only * one is specified (not-empty). Always returns false if both parameters are null or empty. */ public boolean matches(String sensorName, String sensorType) { final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); return (isNameSpecified || isTypeSpecified) && (!isNameSpecified || sensorName.equals(name)) && (!isTypeSpecified || sensorType.equals(type)); } } /** Loading
services/core/java/com/android/server/display/DisplayManagerService.java +38 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.ColorSpace; import android.graphics.Point; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.AmbientBrightnessDayStats; Loading @@ -62,6 +63,7 @@ import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayGroupListener; import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; import android.hardware.display.DisplayManagerInternal.RefreshRateRange; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; Loading Loading @@ -119,6 +121,8 @@ import com.android.server.DisplayThread; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; import com.android.server.display.DisplayDeviceConfig.SensorData; import com.android.server.display.utils.SensorUtils; import com.android.server.wm.SurfaceAnimationThread; import com.android.server.wm.WindowManagerInternal; Loading Loading @@ -3257,6 +3261,40 @@ public final class DisplayManagerService extends SystemService { public int getRefreshRateSwitchingType() { return getRefreshRateSwitchingTypeInternal(); } @Override public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName, String sensorType) { final SensorManager sensorManager; synchronized (mSyncRoot) { sensorManager = mSensorManager; } if (sensorManager == null) { return null; } // Verify that the specified sensor exists. final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName, SensorUtils.NO_FALLBACK); if (sensor == null) { return null; } synchronized (mSyncRoot) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device == null) { return null; } final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); SensorData sensorData = config.getProximitySensor(); if (sensorData.matches(sensorName, sensorType)) { return new RefreshRateRange(sensorData.minRefreshRate, sensorData.maxRefreshRate); } } return null; } } class DesiredDisplayModeSpecsObserver Loading
services/core/java/com/android/server/display/DisplayModeDirector.java +79 −63 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.RefreshRateRange; import android.hardware.fingerprint.IUdfpsHbmListener; import android.net.Uri; import android.os.Handler; Loading @@ -51,6 +53,8 @@ import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.display.utils.AmbientFilter; import com.android.server.display.utils.AmbientFilterFactory; import com.android.server.sensors.SensorManagerInternal; import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.utils.DeviceConfigInterface; Loading Loading @@ -85,8 +89,7 @@ public class DisplayModeDirector { private static final int INVALID_DISPLAY_MODE_ID = -1; // The tolerance within which we consider something approximately equals. private static final float FLOAT_TOLERANCE = 0.01f; private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE; private final Object mLock = new Object(); private final Context mContext; Loading @@ -98,6 +101,7 @@ public class DisplayModeDirector { private final SettingsObserver mSettingsObserver; private final DisplayObserver mDisplayObserver; private final UdfpsObserver mUdfpsObserver; private final SensorObserver mSensorObserver; private final DeviceConfigInterface mDeviceConfig; private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; Loading Loading @@ -139,6 +143,11 @@ public class DisplayModeDirector { mDisplayObserver = new DisplayObserver(context, handler); mBrightnessObserver = new BrightnessObserver(context, handler); mUdfpsObserver = new UdfpsObserver(); mSensorObserver = new SensorObserver(context, (displayId, priority, vote) -> { synchronized (mLock) { updateVoteLocked(displayId, priority, vote); } }); mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings(); mDeviceConfig = injector.getDeviceConfig(); mAlwaysRespectAppRequest = false; Loading @@ -155,6 +164,7 @@ public class DisplayModeDirector { mSettingsObserver.observe(); mDisplayObserver.observe(); mBrightnessObserver.observe(sensorManager); mSensorObserver.observe(); synchronized (mLock) { // We may have a listener already registered before the call to start, so go ahead and // notify them to pick up our newly initialized state. Loading Loading @@ -585,6 +595,7 @@ public class DisplayModeDirector { mAppRequestObserver.dumpLocked(pw); mBrightnessObserver.dumpLocked(pw); mUdfpsObserver.dumpLocked(pw); mSensorObserver.dumpLocked(pw); } } Loading Loading @@ -767,66 +778,6 @@ public class DisplayModeDirector { } } /** * Information about the min and max refresh rate DM would like to set the display to. */ public static final class RefreshRateRange { /** * The lowest desired refresh rate. */ public float min; /** * The highest desired refresh rate. */ public float max; public RefreshRateRange() {} public RefreshRateRange(float min, float max) { if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) { Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : " + min + " " + max); this.min = this.max = 0; return; } if (min > max) { // Min and max are within epsilon of each other, but in the wrong order. float t = min; min = max; max = t; } this.min = min; this.max = max; } /** * Checks whether the two objects have the same values. */ @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof RefreshRateRange)) { return false; } RefreshRateRange refreshRateRange = (RefreshRateRange) other; return (min == refreshRateRange.min && max == refreshRateRange.max); } @Override public int hashCode() { return Objects.hash(min, max); } @Override public String toString() { return "(" + min + " " + max + ")"; } } /** * Information about the desired display mode to be set by the system. Includes the base * mode ID and the primary and app request refresh rate ranges. Loading Loading @@ -987,9 +938,13 @@ public class DisplayModeDirector { // user seeing the display flickering when the switches occur. public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. public static final int PRIORITY_PROXIMITY = 9; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. public static final int PRIORITY_UDFPS = 9; public static final int PRIORITY_UDFPS = 10; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. Loading Loading @@ -1086,6 +1041,8 @@ public class DisplayModeDirector { return "PRIORITY_LOW_POWER_MODE"; case PRIORITY_UDFPS: return "PRIORITY_UDFPS"; case PRIORITY_PROXIMITY: return "PRIORITY_PROXIMITY"; default: return Integer.toString(priority); Loading Loading @@ -2142,6 +2099,62 @@ public class DisplayModeDirector { } } private static class SensorObserver implements ProximityActiveListener { private static final String PROXIMITY_SENSOR_NAME = null; private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY; private final BallotBox mBallotBox; private final Context mContext; private DisplayManager mDisplayManager; private DisplayManagerInternal mDisplayManagerInternal; private boolean mIsProxActive = false; SensorObserver(Context context, BallotBox ballotBox) { mContext = context; mBallotBox = ballotBox; } @Override public void onProximityActive(boolean isActive) { if (mIsProxActive != isActive) { mIsProxActive = isActive; recalculateVotes(); } } public void observe() { mDisplayManager = mContext.getSystemService(DisplayManager.class); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); final SensorManagerInternal sensorManager = LocalServices.getService(SensorManagerInternal.class); sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this); } private void recalculateVotes() { final Display[] displays = mDisplayManager.getDisplays(); for (Display d : displays) { int displayId = d.getDisplayId(); Vote vote = null; if (mIsProxActive) { final RefreshRateRange rate = mDisplayManagerInternal.getRefreshRateForDisplayAndSensor( displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE); if (rate != null) { vote = Vote.forRefreshRates(rate.min, rate.max); } } mBallotBox.vote(displayId, Vote.PRIORITY_PROXIMITY, vote); } } void dumpLocked(PrintWriter pw) { pw.println(" SensorObserver"); pw.println(" mIsProxActive=" + mIsProxActive); } } private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener { public DeviceConfigDisplaySettings() { } Loading Loading @@ -2328,4 +2341,7 @@ public class DisplayModeDirector { } } interface BallotBox { void vote(int displayId, int priority, Vote vote); } }
services/core/java/com/android/server/display/DisplayPowerController.java +11 −33 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.util.MathUtils; import android.util.Slog; Loading @@ -65,13 +64,13 @@ import com.android.server.am.BatteryStatsService; import com.android.server.display.RampAnimator.DualRampAnimator; import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal; import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener; import com.android.server.display.utils.SensorUtils; import com.android.server.display.whitebalance.DisplayWhiteBalanceController; import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory; import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; import java.util.List; /** * Controls the power state of the display. Loading Loading @@ -586,26 +585,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits); } private Sensor findSensor(String sensorType, String sensorName, int fallbackType, boolean useFallback) { final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); if (isNameSpecified || isTypeSpecified) { for (Sensor sensor : sensors) { if ((!isNameSpecified || sensorName.equals(sensor.getName())) && (!isTypeSpecified || sensorType.equals(sensor.getStringType()))) { return sensor; } } } if (useFallback) { return mSensorManager.getDefaultSensor(fallbackType); } else { return null; } } /** * Returns true if the proximity sensor screen-off function is available. */ Loading Loading @@ -1654,24 +1633,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } private void loadAmbientLightSensor() { DisplayDeviceConfig.SensorIdentifier lightSensor = mDisplayDeviceConfig.getAmbientLightSensor(); String lightSensorName = lightSensor.name; String lightSensorType = lightSensor.type; mLightSensor = findSensor(lightSensorType, lightSensorName, Sensor.TYPE_LIGHT, mDisplayId == Display.DEFAULT_DISPLAY); DisplayDeviceConfig.SensorData lightSensor = mDisplayDeviceConfig.getAmbientLightSensor(); final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK; mLightSensor = SensorUtils.findSensor(mSensorManager, lightSensor.type, lightSensor.name, fallbackType); } private void loadProximitySensor() { if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { return; } final DisplayDeviceConfig.SensorIdentifier proxSensor = final DisplayDeviceConfig.SensorData proxSensor = mDisplayDeviceConfig.getProximitySensor(); final String proxSensorName = proxSensor.name; final String proxSensorType = proxSensor.type; mProximitySensor = findSensor(proxSensorType, proxSensorName, Sensor.TYPE_PROXIMITY, mDisplayId == Display.DEFAULT_DISPLAY); final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK; mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name, fallbackType); if (mProximitySensor != null) { mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(), TYPICAL_PROXIMITY_THRESHOLD); Loading