Merge "Added system-wide minimum brightness curve." into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
082147cfe1
@@ -1255,6 +1255,7 @@ package android.hardware.display {
|
||||
method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
|
||||
method public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents();
|
||||
method public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
|
||||
method public android.util.Pair<float[], float[]> getMinimumBrightnessCurve();
|
||||
method public android.graphics.Point getStableDisplaySize();
|
||||
method public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
|
||||
method public void setSaturationLevel(float);
|
||||
|
||||
@@ -86,7 +86,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
sb.append("(").append(mLux[i]).append(", ").append(mNits[i]).append(")");
|
||||
}
|
||||
sb.append("], '");
|
||||
sb.append(mDescription);
|
||||
if (mDescription != null) {
|
||||
sb.append(mDescription);
|
||||
}
|
||||
sb.append("'}");
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -96,7 +98,9 @@ public final class BrightnessConfiguration implements Parcelable {
|
||||
int result = 1;
|
||||
result = result * 31 + Arrays.hashCode(mLux);
|
||||
result = result * 31 + Arrays.hashCode(mNits);
|
||||
result = result * 31 + mDescription.hashCode();
|
||||
if (mDescription != null) {
|
||||
result = result * 31 + mDescription.hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
19
core/java/android/hardware/display/Curve.aidl
Normal file
19
core/java/android/hardware/display/Curve.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.hardware.display;
|
||||
|
||||
parcelable Curve;
|
||||
62
core/java/android/hardware/display/Curve.java
Normal file
62
core/java/android/hardware/display/Curve.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.hardware.display;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/** @hide */
|
||||
public final class Curve implements Parcelable {
|
||||
private final float[] mX;
|
||||
private final float[] mY;
|
||||
|
||||
public Curve(float[] x, float[] y) {
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
|
||||
public float[] getX() {
|
||||
return mX;
|
||||
}
|
||||
|
||||
public float[] getY() {
|
||||
return mY;
|
||||
}
|
||||
|
||||
public static final Creator<Curve> CREATOR = new Creator<Curve>() {
|
||||
public Curve createFromParcel(Parcel in) {
|
||||
float[] x = in.createFloatArray();
|
||||
float[] y = in.createFloatArray();
|
||||
return new Curve(x, y);
|
||||
}
|
||||
|
||||
public Curve[] newArray(int size) {
|
||||
return new Curve[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeFloatArray(mX);
|
||||
out.writeFloatArray(mY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.media.projection.MediaProjection;
|
||||
import android.os.Handler;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
@@ -747,6 +748,22 @@ public final class DisplayManager {
|
||||
mGlobal.setTemporaryAutoBrightnessAdjustment(adjustment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum brightness curve, which guarantess that any brightness curve that dips
|
||||
* below it is rejected by the system.
|
||||
* This prevent auto-brightness from setting the screen so dark as to prevent the user from
|
||||
* resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
|
||||
* in that ambient brightness.
|
||||
*
|
||||
* @return The minimum brightness curve (as lux values and their corresponding nits values).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public Pair<float[], float[]> getMinimumBrightnessCurve() {
|
||||
return mGlobal.getMinimumBrightnessCurve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in available display devices.
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayAdjustments;
|
||||
@@ -562,6 +563,24 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum brightness curve, which guarantess that any brightness curve that dips
|
||||
* below it is rejected by the system.
|
||||
* This prevent auto-brightness from setting the screen so dark as to prevent the user from
|
||||
* resetting or disabling it, and maps lux to the absolute minimum nits that are still readable
|
||||
* in that ambient brightness.
|
||||
*
|
||||
* @return The minimum brightness curve (as lux values and their corresponding nits values).
|
||||
*/
|
||||
public Pair<float[], float[]> getMinimumBrightnessCurve() {
|
||||
try {
|
||||
Curve curve = mDm.getMinimumBrightnessCurve();
|
||||
return Pair.create(curve.getX(), curve.getY());
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves ambient brightness stats.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.hardware.display;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.display.BrightnessConfiguration;
|
||||
import android.hardware.display.Curve;
|
||||
import android.hardware.display.IDisplayManagerCallback;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.display.WifiDisplay;
|
||||
@@ -112,4 +113,7 @@ interface IDisplayManager {
|
||||
|
||||
// Temporarily sets the auto brightness adjustment factor.
|
||||
void setTemporaryAutoBrightnessAdjustment(float adjustment);
|
||||
|
||||
// Get the minimum brightness curve.
|
||||
Curve getMinimumBrightnessCurve();
|
||||
}
|
||||
|
||||
@@ -1289,6 +1289,32 @@
|
||||
in darkness (although they may not be visible in a bright room). -->
|
||||
<integer name="config_screenBrightnessDark">1</integer>
|
||||
|
||||
<!-- Array of lux values to define the minimum brightness curve, which guarantees that any
|
||||
brightness curve that dips below it is rejected by the system.
|
||||
This prevents auto-brightness from setting the screen so dark as to prevent the user from
|
||||
resetting or disabling it.
|
||||
|
||||
The values must be non-negative and strictly increasing, and correspond to the values in
|
||||
the config_minimumBrightnessCurveNits array. -->
|
||||
<array name="config_minimumBrightnessCurveLux">
|
||||
<item>0.0</item>
|
||||
<item>2000.0</item>
|
||||
<item>4000.0</item>
|
||||
</array>
|
||||
|
||||
<!-- Array of nits values to define the minimum brightness curve, which guarantees that any
|
||||
brightness curve that dips below it is rejected by the system.
|
||||
This should map lux to the absolute minimum nits that are still readable in that ambient
|
||||
brightness.
|
||||
|
||||
The values must be non-negative and non-decreasing, and correspond to the values in the
|
||||
config_minimumBrightnessCurveLux array. -->
|
||||
<array name="config_minimumBrightnessCurveNits">
|
||||
<item>0.0</item>
|
||||
<item>50.0</item>
|
||||
<item>90.0</item>
|
||||
</array>
|
||||
|
||||
<!-- Array of light sensor lux values to define our levels for auto backlight brightness support.
|
||||
The N entries of this array define N + 1 control points as follows:
|
||||
(1-based arrays)
|
||||
|
||||
@@ -1810,6 +1810,8 @@
|
||||
<java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
|
||||
<java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
|
||||
<java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
|
||||
<java-symbol type="array" name="config_minimumBrightnessCurveLux" />
|
||||
<java-symbol type="array" name="config_minimumBrightnessCurveNits" />
|
||||
<java-symbol type="array" name="config_protectedNetworks" />
|
||||
<java-symbol type="array" name="config_statusBarIcons" />
|
||||
<java-symbol type="array" name="config_tether_bluetooth_regexs" />
|
||||
|
||||
@@ -41,7 +41,7 @@ public class BrightnessConfigurationTest {
|
||||
};
|
||||
|
||||
private static final float[] NITS_LEVELS = {
|
||||
0.5f,
|
||||
1f,
|
||||
90f,
|
||||
100f,
|
||||
};
|
||||
|
||||
@@ -36,11 +36,13 @@ import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.display.AmbientBrightnessDayStats;
|
||||
import android.hardware.display.BrightnessChangeEvent;
|
||||
import android.hardware.display.BrightnessConfiguration;
|
||||
import android.hardware.display.Curve;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.hardware.display.DisplayManagerInternal;
|
||||
import android.hardware.display.DisplayViewport;
|
||||
@@ -72,8 +74,10 @@ import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.IntArray;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Spline;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.Surface;
|
||||
@@ -276,6 +280,11 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
private final Injector mInjector;
|
||||
|
||||
// The minimum brightness curve, which guarantess that any brightness curve that dips below it
|
||||
// is rejected by the system.
|
||||
private final Curve mMinimumBrightnessCurve;
|
||||
private final Spline mMinimumBrightnessSpline;
|
||||
|
||||
public DisplayManagerService(Context context) {
|
||||
this(context, new Injector());
|
||||
}
|
||||
@@ -289,8 +298,15 @@ public final class DisplayManagerService extends SystemService {
|
||||
mUiHandler = UiThread.getHandler();
|
||||
mDisplayAdapterListener = new DisplayAdapterListener();
|
||||
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
|
||||
Resources resources = mContext.getResources();
|
||||
mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
|
||||
float[] lux = getFloatArray(resources.obtainTypedArray(
|
||||
com.android.internal.R.array.config_minimumBrightnessCurveLux));
|
||||
float[] nits = getFloatArray(resources.obtainTypedArray(
|
||||
com.android.internal.R.array.config_minimumBrightnessCurveNits));
|
||||
mMinimumBrightnessCurve = new Curve(lux, nits);
|
||||
mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
|
||||
|
||||
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
|
||||
@@ -1032,9 +1048,15 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Curve getMinimumBrightnessCurveInternal() {
|
||||
return mMinimumBrightnessCurve;
|
||||
}
|
||||
|
||||
private void setBrightnessConfigurationForUserInternal(
|
||||
@Nullable BrightnessConfiguration c, @UserIdInt int userId,
|
||||
@Nullable String packageName) {
|
||||
validateBrightnessConfiguration(c);
|
||||
final int userSerial = getUserManager().getUserSerialNumber(userId);
|
||||
synchronized (mSyncRoot) {
|
||||
try {
|
||||
@@ -1049,6 +1071,28 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateBrightnessConfiguration(BrightnessConfiguration config) {
|
||||
if (config == null) {
|
||||
return;
|
||||
}
|
||||
if (isBrightnessConfigurationTooDark(config)) {
|
||||
throw new IllegalArgumentException("brightness curve is too dark");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
|
||||
Pair<float[], float[]> curve = config.getCurve();
|
||||
float[] lux = curve.first;
|
||||
float[] nits = curve.second;
|
||||
for (int i = 0; i < lux.length; i++) {
|
||||
if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void loadBrightnessConfiguration() {
|
||||
synchronized (mSyncRoot) {
|
||||
final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
|
||||
@@ -1369,6 +1413,16 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private static float[] getFloatArray(TypedArray array) {
|
||||
int length = array.length();
|
||||
float[] floatArray = new float[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
floatArray[i] = array.getFloat(i, Float.NaN);
|
||||
}
|
||||
array.recycle();
|
||||
return floatArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the object that everything in the display manager locks on.
|
||||
* We make it an inner class within the {@link DisplayManagerService} to so that it is
|
||||
@@ -1999,6 +2053,16 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public Curve getMinimumBrightnessCurve() {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return getMinimumBrightnessCurveInternal();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
void setBrightness(int brightness) {
|
||||
Settings.System.putIntForUser(mContext.getContentResolver(),
|
||||
Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
package com.android.server.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.display.BrightnessConfiguration;
|
||||
import android.hardware.display.Curve;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayViewport;
|
||||
import android.hardware.display.IVirtualDisplayCallback;
|
||||
import android.hardware.input.InputManagerInternal;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.view.SurfaceControl;
|
||||
@@ -226,6 +229,62 @@ public class DisplayManagerServiceTest extends AndroidTestCase {
|
||||
+ " virtual display adapter");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an exception is raised for too dark a brightness configuration.
|
||||
*/
|
||||
public void testTooDarkBrightnessConfigurationThrowException() {
|
||||
DisplayManagerService displayManager =
|
||||
new DisplayManagerService(mContext, mShortMockedInjector);
|
||||
Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
|
||||
float[] lux = minimumBrightnessCurve.getX();
|
||||
float[] minimumNits = minimumBrightnessCurve.getY();
|
||||
float[] nits = new float[minimumNits.length];
|
||||
// For every control point, assert that making it slightly lower than the minimum throws an
|
||||
// exception.
|
||||
for (int i = 0; i < nits.length; i++) {
|
||||
for (int j = 0; j < nits.length; j++) {
|
||||
nits[j] = minimumNits[j];
|
||||
if (j == i) {
|
||||
nits[j] -= 0.1f;
|
||||
}
|
||||
if (nits[j] < 0) {
|
||||
nits[j] = 0;
|
||||
}
|
||||
}
|
||||
BrightnessConfiguration config =
|
||||
new BrightnessConfiguration.Builder(lux, nits).build();
|
||||
Exception thrown = null;
|
||||
try {
|
||||
displayManager.validateBrightnessConfiguration(config);
|
||||
} catch (IllegalArgumentException e) {
|
||||
thrown = e;
|
||||
}
|
||||
assertNotNull("Building too dark a brightness configuration must throw an exception");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that no exception is raised for not too dark a brightness configuration.
|
||||
*/
|
||||
public void testBrightEnoughBrightnessConfigurationDoesNotThrowException() {
|
||||
DisplayManagerService displayManager =
|
||||
new DisplayManagerService(mContext, mShortMockedInjector);
|
||||
Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
|
||||
float[] lux = minimumBrightnessCurve.getX();
|
||||
float[] nits = minimumBrightnessCurve.getY();
|
||||
BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits).build();
|
||||
displayManager.validateBrightnessConfiguration(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that null brightness configurations are alright.
|
||||
*/
|
||||
public void testNullBrightnessConfiguration() {
|
||||
DisplayManagerService displayManager =
|
||||
new DisplayManagerService(mContext, mShortMockedInjector);
|
||||
displayManager.validateBrightnessConfiguration(null);
|
||||
}
|
||||
|
||||
private void registerDefaultDisplays(DisplayManagerService displayManager) {
|
||||
Handler handler = displayManager.getDisplayHandler();
|
||||
// Would prefer to call displayManager.onStart() directly here but it performs binderService
|
||||
|
||||
Reference in New Issue
Block a user