blob: 0d824334d8736153a61a7913efa3f1abd18c1246 [file] [log] [blame]
/*
* 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.NitsMap;
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";
public static final float HIGH_BRIGHTNESS_MODE_UNSUPPORTED = Float.NaN;
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 NitsMap map = config.getScreenBrightnessMap();
final List<Point> points = map.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;
}
}