Loading core/java/android/os/PowerManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,19 @@ public final class PowerManager { */ public static final int BRIGHTNESS_DEFAULT = -1; /** * Brightness value for fully off in float. * TODO: rename this to BRIGHTNES_OFF and remove the integer-based constant. * @hide */ public static final float BRIGHTNESS_OFF_FLOAT = -1.0f; /** * Invalid brightness value. * @hide */ public static final float BRIGHTNESS_INVALID_FLOAT = Float.NaN; // Note: Be sure to update android.os.BatteryStats and PowerManager.h // if adding or modifying user activity event constants. Loading services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ java_library_static { ":storaged_aidl", ":vold_aidl", ":platform-compat-config", ":display-device-config", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", Loading services/core/java/com/android/server/display/BrightnessMappingStrategy.java +9 −3 Original line number Diff line number Diff line Loading @@ -109,11 +109,17 @@ public abstract class BrightnessMappingStrategy { return levels; } private static float[] getFloatArray(TypedArray array) { /** * Extracts a float array from the specified {@link TypedArray}. * * @param array The array to convert. * @return the given array as a float array. */ public static float[] getFloatArray(TypedArray array) { final int N = array.length(); float[] vals = new float[N]; for (int i = 0; i < N; i++) { vals[i] = array.getFloat(i, -1.0f); vals[i] = array.getFloat(i, PowerManager.BRIGHTNESS_OFF_FLOAT); } array.recycle(); return vals; Loading Loading @@ -335,7 +341,7 @@ public abstract class BrightnessMappingStrategy { } } protected float normalizeAbsoluteBrightness(int brightness) { protected static float normalizeAbsoluteBrightness(int brightness) { brightness = MathUtils.constrain(brightness, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); return (float) brightness / PowerManager.BRIGHTNESS_ON; Loading services/core/java/com/android/server/display/DisplayDeviceConfig.java 0 → 100644 +137 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.display; import android.os.Environment; import android.util.Slog; import com.android.server.display.config.DisplayConfiguration; import com.android.server.display.config.Point; import com.android.server.display.config.XmlParser; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.xml.datatype.DatatypeConfigurationException; /** * Reads and stores display-specific configurations. */ public class DisplayDeviceConfig { private static final String TAG = "DisplayDeviceConfig"; private static final String ETC_DIR = "etc"; private static final String DISPLAY_CONFIG_DIR = "displayconfig"; private static final String CONFIG_FILE_FORMAT = "display_%d.xml"; private float[] mNits; private float[] mBrightness; private DisplayDeviceConfig() { } /** * Creates an instance for the specified display. * * @param physicalDisplayId The display ID for which to load the configuration. * @return A configuration instance for the specified display. */ public static DisplayDeviceConfig create(long physicalDisplayId) { final DisplayDeviceConfig config = new DisplayDeviceConfig(); final String filename = String.format(CONFIG_FILE_FORMAT, physicalDisplayId); config.initFromFile(Environment.buildPath( Environment.getProductDirectory(), ETC_DIR, DISPLAY_CONFIG_DIR, filename)); return config; } /** * Return the brightness mapping nits array if one is defined in the configuration file. * * @return The brightness mapping nits array. */ public float[] getNits() { return mNits; } /** * Return the brightness mapping value array if one is defined in the configuration file. * * @return The brightness mapping value array. */ public float[] getBrightness() { return mBrightness; } private void initFromFile(File configFile) { if (!configFile.exists()) { // Display configuration files aren't required to exist. return; } if (!configFile.isFile()) { Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping"); return; } try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { final DisplayConfiguration config = XmlParser.read(in); loadBrightnessMap(config); } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { Slog.e(TAG, "Encountered an error while reading/parsing display config file: " + configFile, e); } } private void loadBrightnessMap(DisplayConfiguration config) { final List<Point> points = config.getScreenBrightnessMap().getPoint(); final int size = points.size(); float[] nits = new float[size]; float[] backlight = new float[size]; int i = 0; for (Point point : points) { nits[i] = point.getNits().floatValue(); backlight[i] = point.getValue().floatValue(); if (i > 0) { if (nits[i] < nits[i - 1]) { Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " + " of configuration. Nits: " + nits[i] + " < " + nits[i - 1]); return; } if (backlight[i] < backlight[i - 1]) { Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " + " of configuration. Value: " + backlight[i] + " < " + backlight[i - 1]); return; } } ++i; } mNits = nits; mBrightness = backlight; } } services/core/java/com/android/server/display/LocalDisplayAdapter.java +70 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.os.Trace; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; import android.util.Spline; import android.view.Display; import android.view.DisplayAddress; import android.view.DisplayCutout; Loading @@ -37,6 +38,7 @@ import android.view.DisplayEventReceiver; import android.view.Surface; import android.view.SurfaceControl; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.lights.Light; Loading Loading @@ -187,8 +189,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { private boolean mGameContentTypeRequested; private boolean mSidekickActive; private SidekickInternal mSidekickInternal; private SurfaceControl.PhysicalDisplayInfo[] mDisplayInfos; private Spline mSystemBrightnessToNits; private Spline mNitsToHalBrightness; private boolean mHalBrightnessSupport; LocalDisplayDevice(IBinder displayToken, long physicalDisplayId, SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo, Loading @@ -210,6 +214,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken); mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken); mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken); mHalBrightnessSupport = SurfaceControl.getDisplayBrightnessSupport(displayToken); // Defer configuration file loading BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage( LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this)); } @Override Loading Loading @@ -338,6 +347,41 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } private void loadDisplayConfigurationBrightnessMapping() { Spline nitsToHal = null; Spline sysToNits = null; // Load the mapping from nits to HAL brightness range (display-device-config.xml) DisplayDeviceConfig config = DisplayDeviceConfig.create(mPhysicalDisplayId); if (config == null) { return; } final float[] halNits = config.getNits(); final float[] halBrightness = config.getBrightness(); if (halNits == null || halBrightness == null) { return; } nitsToHal = Spline.createSpline(halNits, halBrightness); // Load the mapping from system brightness range to nits (config.xml) final Resources res = getOverlayContext().getResources(); final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray( com.android.internal.R.array.config_screenBrightnessNits)); final int[] sysBrightness = res.getIntArray( com.android.internal.R.array.config_screenBrightnessBacklight); if (sysNits.length == 0 || sysBrightness.length != sysNits.length) { return; } final float[] sysBrightnessFloat = new float[sysBrightness.length]; for (int i = 0; i < sysBrightness.length; i++) { sysBrightnessFloat[i] = sysBrightness[i]; } sysToNits = Spline.createSpline(sysBrightnessFloat, sysNits); mNitsToHalBrightness = nitsToHal; mSystemBrightnessToNits = sysToNits; } private boolean updateColorModesLocked(int[] colorModes, int activeColorMode) { List<Integer> pendingColorModes = new ArrayList<>(); Loading Loading @@ -628,13 +672,37 @@ final class LocalDisplayAdapter extends DisplayAdapter { Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" + "id=" + physicalDisplayId + ", brightness=" + brightness + ")"); try { if (mHalBrightnessSupport) { mBacklight.setBrightnessFloat( displayBrightnessToHalBrightness(brightness)); } else { mBacklight.setBrightness(brightness); } Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenBrightness", brightness); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } /** * Converts brightness range from the framework's brightness space to the * Hal brightness space if the HAL brightness space has been provided via * a display device configuration file. */ private float displayBrightnessToHalBrightness(int brightness) { if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) { return PowerManager.BRIGHTNESS_INVALID_FLOAT; } if (brightness == 0) { return PowerManager.BRIGHTNESS_OFF_FLOAT; } final float nits = mSystemBrightnessToNits.interpolate(brightness); final float halBrightness = mNitsToHalBrightness.interpolate(nits); return halBrightness; } }; } return null; Loading Loading
core/java/android/os/PowerManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,19 @@ public final class PowerManager { */ public static final int BRIGHTNESS_DEFAULT = -1; /** * Brightness value for fully off in float. * TODO: rename this to BRIGHTNES_OFF and remove the integer-based constant. * @hide */ public static final float BRIGHTNESS_OFF_FLOAT = -1.0f; /** * Invalid brightness value. * @hide */ public static final float BRIGHTNESS_INVALID_FLOAT = Float.NaN; // Note: Be sure to update android.os.BatteryStats and PowerManager.h // if adding or modifying user activity event constants. Loading
services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ java_library_static { ":storaged_aidl", ":vold_aidl", ":platform-compat-config", ":display-device-config", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", Loading
services/core/java/com/android/server/display/BrightnessMappingStrategy.java +9 −3 Original line number Diff line number Diff line Loading @@ -109,11 +109,17 @@ public abstract class BrightnessMappingStrategy { return levels; } private static float[] getFloatArray(TypedArray array) { /** * Extracts a float array from the specified {@link TypedArray}. * * @param array The array to convert. * @return the given array as a float array. */ public static float[] getFloatArray(TypedArray array) { final int N = array.length(); float[] vals = new float[N]; for (int i = 0; i < N; i++) { vals[i] = array.getFloat(i, -1.0f); vals[i] = array.getFloat(i, PowerManager.BRIGHTNESS_OFF_FLOAT); } array.recycle(); return vals; Loading Loading @@ -335,7 +341,7 @@ public abstract class BrightnessMappingStrategy { } } protected float normalizeAbsoluteBrightness(int brightness) { protected static float normalizeAbsoluteBrightness(int brightness) { brightness = MathUtils.constrain(brightness, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); return (float) brightness / PowerManager.BRIGHTNESS_ON; Loading
services/core/java/com/android/server/display/DisplayDeviceConfig.java 0 → 100644 +137 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.display; import android.os.Environment; import android.util.Slog; import com.android.server.display.config.DisplayConfiguration; import com.android.server.display.config.Point; import com.android.server.display.config.XmlParser; import org.xmlpull.v1.XmlPullParserException; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.xml.datatype.DatatypeConfigurationException; /** * Reads and stores display-specific configurations. */ public class DisplayDeviceConfig { private static final String TAG = "DisplayDeviceConfig"; private static final String ETC_DIR = "etc"; private static final String DISPLAY_CONFIG_DIR = "displayconfig"; private static final String CONFIG_FILE_FORMAT = "display_%d.xml"; private float[] mNits; private float[] mBrightness; private DisplayDeviceConfig() { } /** * Creates an instance for the specified display. * * @param physicalDisplayId The display ID for which to load the configuration. * @return A configuration instance for the specified display. */ public static DisplayDeviceConfig create(long physicalDisplayId) { final DisplayDeviceConfig config = new DisplayDeviceConfig(); final String filename = String.format(CONFIG_FILE_FORMAT, physicalDisplayId); config.initFromFile(Environment.buildPath( Environment.getProductDirectory(), ETC_DIR, DISPLAY_CONFIG_DIR, filename)); return config; } /** * Return the brightness mapping nits array if one is defined in the configuration file. * * @return The brightness mapping nits array. */ public float[] getNits() { return mNits; } /** * Return the brightness mapping value array if one is defined in the configuration file. * * @return The brightness mapping value array. */ public float[] getBrightness() { return mBrightness; } private void initFromFile(File configFile) { if (!configFile.exists()) { // Display configuration files aren't required to exist. return; } if (!configFile.isFile()) { Slog.e(TAG, "Display configuration is not a file: " + configFile + ", skipping"); return; } try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { final DisplayConfiguration config = XmlParser.read(in); loadBrightnessMap(config); } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { Slog.e(TAG, "Encountered an error while reading/parsing display config file: " + configFile, e); } } private void loadBrightnessMap(DisplayConfiguration config) { final List<Point> points = config.getScreenBrightnessMap().getPoint(); final int size = points.size(); float[] nits = new float[size]; float[] backlight = new float[size]; int i = 0; for (Point point : points) { nits[i] = point.getNits().floatValue(); backlight[i] = point.getValue().floatValue(); if (i > 0) { if (nits[i] < nits[i - 1]) { Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " + " of configuration. Nits: " + nits[i] + " < " + nits[i - 1]); return; } if (backlight[i] < backlight[i - 1]) { Slog.e(TAG, "screenBrightnessMap must be non-decreasing, ignoring rest " + " of configuration. Value: " + backlight[i] + " < " + backlight[i - 1]); return; } } ++i; } mNits = nits; mBrightness = backlight; } }
services/core/java/com/android/server/display/LocalDisplayAdapter.java +70 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.os.Trace; import android.util.LongSparseArray; import android.util.Slog; import android.util.SparseArray; import android.util.Spline; import android.view.Display; import android.view.DisplayAddress; import android.view.DisplayCutout; Loading @@ -37,6 +38,7 @@ import android.view.DisplayEventReceiver; import android.view.Surface; import android.view.SurfaceControl; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.lights.Light; Loading Loading @@ -187,8 +189,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { private boolean mGameContentTypeRequested; private boolean mSidekickActive; private SidekickInternal mSidekickInternal; private SurfaceControl.PhysicalDisplayInfo[] mDisplayInfos; private Spline mSystemBrightnessToNits; private Spline mNitsToHalBrightness; private boolean mHalBrightnessSupport; LocalDisplayDevice(IBinder displayToken, long physicalDisplayId, SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo, Loading @@ -210,6 +214,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { mHdrCapabilities = SurfaceControl.getHdrCapabilities(displayToken); mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken); mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken); mHalBrightnessSupport = SurfaceControl.getDisplayBrightnessSupport(displayToken); // Defer configuration file loading BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage( LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this)); } @Override Loading Loading @@ -338,6 +347,41 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } private void loadDisplayConfigurationBrightnessMapping() { Spline nitsToHal = null; Spline sysToNits = null; // Load the mapping from nits to HAL brightness range (display-device-config.xml) DisplayDeviceConfig config = DisplayDeviceConfig.create(mPhysicalDisplayId); if (config == null) { return; } final float[] halNits = config.getNits(); final float[] halBrightness = config.getBrightness(); if (halNits == null || halBrightness == null) { return; } nitsToHal = Spline.createSpline(halNits, halBrightness); // Load the mapping from system brightness range to nits (config.xml) final Resources res = getOverlayContext().getResources(); final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray( com.android.internal.R.array.config_screenBrightnessNits)); final int[] sysBrightness = res.getIntArray( com.android.internal.R.array.config_screenBrightnessBacklight); if (sysNits.length == 0 || sysBrightness.length != sysNits.length) { return; } final float[] sysBrightnessFloat = new float[sysBrightness.length]; for (int i = 0; i < sysBrightness.length; i++) { sysBrightnessFloat[i] = sysBrightness[i]; } sysToNits = Spline.createSpline(sysBrightnessFloat, sysNits); mNitsToHalBrightness = nitsToHal; mSystemBrightnessToNits = sysToNits; } private boolean updateColorModesLocked(int[] colorModes, int activeColorMode) { List<Integer> pendingColorModes = new ArrayList<>(); Loading Loading @@ -628,13 +672,37 @@ final class LocalDisplayAdapter extends DisplayAdapter { Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" + "id=" + physicalDisplayId + ", brightness=" + brightness + ")"); try { if (mHalBrightnessSupport) { mBacklight.setBrightnessFloat( displayBrightnessToHalBrightness(brightness)); } else { mBacklight.setBrightness(brightness); } Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenBrightness", brightness); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } /** * Converts brightness range from the framework's brightness space to the * Hal brightness space if the HAL brightness space has been provided via * a display device configuration file. */ private float displayBrightnessToHalBrightness(int brightness) { if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) { return PowerManager.BRIGHTNESS_INVALID_FLOAT; } if (brightness == 0) { return PowerManager.BRIGHTNESS_OFF_FLOAT; } final float nits = mSystemBrightnessToNits.interpolate(brightness); final float halBrightness = mNitsToHalBrightness.interpolate(nits); return halBrightness; } }; } return null; Loading