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

Commit 4505e5e6 authored by Santos Cordon's avatar Santos Cordon
Browse files

Add display configuration files.

Adds a static display configuration file for specifying static display
configurations as a sustainable API.

Bug: 131813802
Test: Verify brightness changes work as expected.  Verify changes going
through system to HAL conversion.
Exempt-From-Owner-Approval: I am new owner of lights, but OWNERS rights hasnt yet propogated.
Change-Id: I17922267f4695bc042d7c0687d4dcc10554e1b85
parent f3f75809
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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.

+1 −0
Original line number Diff line number Diff line
@@ -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",
+9 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+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;
    }
}
+70 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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,
@@ -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
@@ -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<>();
@@ -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