diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 36673cd66ca2f..4de4880b7c171 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -655,6 +655,34 @@ public final class DisplayManager {
mGlobal.setBrightnessConfigurationForUser(c, userId, packageName);
}
+ /**
+ * Temporarily sets the brightness of the display.
+ *
+ * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
+ *
+ *
+ * @param brightness The brightness value from 0 to 255.
+ *
+ * @hide Requires signature permission.
+ */
+ public void setTemporaryBrightness(int brightness) {
+ mGlobal.setTemporaryBrightness(brightness);
+ }
+
+ /**
+ * Temporarily sets the auto brightness adjustment factor.
+ *
+ * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
+ *
+ *
+ * @param adjustment The adjustment factor from -1.0 to 1.0.
+ *
+ * @hide Requires signature permission.
+ */
+ public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
+ mGlobal.setTemporaryAutoBrightnessAdjustment(adjustment);
+ }
+
/**
* Listens for changes in available display devices.
*/
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 9c851f1fd1066..2d5f5e0414868 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -489,6 +489,42 @@ public final class DisplayManagerGlobal {
}
}
+ /**
+ * Temporarily sets the brightness of the display.
+ *
+ * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
+ *
+ *
+ * @param brightness The brightness value from 0 to 255.
+ *
+ * @hide Requires signature permission.
+ */
+ public void setTemporaryBrightness(int brightness) {
+ try {
+ mDm.setTemporaryBrightness(brightness);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Temporarily sets the auto brightness adjustment factor.
+ *
+ * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission.
+ *
+ *
+ * @param adjustment The adjustment factor from -1.0 to 1.0.
+ *
+ * @hide Requires signature permission.
+ */
+ public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
+ try {
+ mDm.setTemporaryAutoBrightnessAdjustment(adjustment);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
public void onDisplayEvent(int displayId, int event) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 078958ad881a5..1cfad4f0168f4 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -214,23 +214,12 @@ public abstract class DisplayManagerInternal {
// nearby, turning it off temporarily until the object is moved away.
public boolean useProximitySensor;
- // The desired screen brightness in the range 0 (minimum / off) to 255 (brightest).
- // The display power controller may choose to clamp the brightness.
- // When auto-brightness is enabled, this field should specify a nominal default
- // value to use while waiting for the light sensor to report enough data.
- public int screenBrightness;
+ // An override of the screen brightness. Set to -1 is used if there's no override.
+ public int screenBrightnessOverride;
- // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter).
- public float screenAutoBrightnessAdjustment;
-
- // Set to true if screenBrightness and screenAutoBrightnessAdjustment were both
- // set by the user as opposed to being programmatically controlled by apps.
- public boolean brightnessSetByUser;
-
- // Set to true if screenBrightness or screenAutoBrightnessAdjustment are being set
- // temporarily. This is typically set while the user has their finger on the brightness
- // control, before they've selected the final brightness value.
- public boolean brightnessIsTemporary;
+ // An override of the screen auto-brightness adjustment factor in the range -1 (dimmer) to
+ // 1 (brighter). Set to Float.NaN if there's no override.
+ public float screenAutoBrightnessAdjustmentOverride;
// If true, enables automatic brightness control.
public boolean useAutoBrightness;
@@ -262,10 +251,10 @@ public abstract class DisplayManagerInternal {
public DisplayPowerRequest() {
policy = POLICY_BRIGHT;
useProximitySensor = false;
- screenBrightness = PowerManager.BRIGHTNESS_ON;
- screenAutoBrightnessAdjustment = 0.0f;
- screenLowPowerBrightnessFactor = 0.5f;
+ screenBrightnessOverride = -1;
useAutoBrightness = false;
+ screenAutoBrightnessAdjustmentOverride = Float.NaN;
+ screenLowPowerBrightnessFactor = 0.5f;
blockScreenOn = false;
dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
dozeScreenState = Display.STATE_UNKNOWN;
@@ -286,12 +275,10 @@ public abstract class DisplayManagerInternal {
public void copyFrom(DisplayPowerRequest other) {
policy = other.policy;
useProximitySensor = other.useProximitySensor;
- screenBrightness = other.screenBrightness;
- screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
- screenLowPowerBrightnessFactor = other.screenLowPowerBrightnessFactor;
- brightnessSetByUser = other.brightnessSetByUser;
- brightnessIsTemporary = other.brightnessIsTemporary;
+ screenBrightnessOverride = other.screenBrightnessOverride;
useAutoBrightness = other.useAutoBrightness;
+ screenAutoBrightnessAdjustmentOverride = other.screenAutoBrightnessAdjustmentOverride;
+ screenLowPowerBrightnessFactor = other.screenLowPowerBrightnessFactor;
blockScreenOn = other.blockScreenOn;
lowPowerMode = other.lowPowerMode;
boostScreenBrightness = other.boostScreenBrightness;
@@ -309,13 +296,12 @@ public abstract class DisplayManagerInternal {
return other != null
&& policy == other.policy
&& useProximitySensor == other.useProximitySensor
- && screenBrightness == other.screenBrightness
- && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+ && screenBrightnessOverride == other.screenBrightnessOverride
+ && useAutoBrightness == other.useAutoBrightness
+ && floatEquals(screenAutoBrightnessAdjustmentOverride,
+ other.screenAutoBrightnessAdjustmentOverride)
&& screenLowPowerBrightnessFactor
== other.screenLowPowerBrightnessFactor
- && brightnessSetByUser == other.brightnessSetByUser
- && brightnessIsTemporary == other.brightnessIsTemporary
- && useAutoBrightness == other.useAutoBrightness
&& blockScreenOn == other.blockScreenOn
&& lowPowerMode == other.lowPowerMode
&& boostScreenBrightness == other.boostScreenBrightness
@@ -323,6 +309,10 @@ public abstract class DisplayManagerInternal {
&& dozeScreenState == other.dozeScreenState;
}
+ private boolean floatEquals(float f1, float f2) {
+ return f1 == f2 || Float.isNaN(f1) && Float.isNaN(f2);
+ }
+
@Override
public int hashCode() {
return 0; // don't care
@@ -332,12 +322,11 @@ public abstract class DisplayManagerInternal {
public String toString() {
return "policy=" + policyToString(policy)
+ ", useProximitySensor=" + useProximitySensor
- + ", screenBrightness=" + screenBrightness
- + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
- + ", screenLowPowerBrightnessFactor=" + screenLowPowerBrightnessFactor
- + ", brightnessSetByUser=" + brightnessSetByUser
- + ", brightnessIsTemporary=" + brightnessIsTemporary
+ + ", screenBrightnessOverride=" + screenBrightnessOverride
+ ", useAutoBrightness=" + useAutoBrightness
+ + ", screenAutoBrightnessAdjustmentOverride="
+ + screenAutoBrightnessAdjustmentOverride
+ + ", screenLowPowerBrightnessFactor=" + screenLowPowerBrightnessFactor
+ ", blockScreenOn=" + blockScreenOn
+ ", lowPowerMode=" + lowPowerMode
+ ", boostScreenBrightness=" + boostScreenBrightness
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 5b7b32fe52012..13599cfa0b7d5 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -92,4 +92,10 @@ interface IDisplayManager {
// the same as the calling user.
void setBrightnessConfigurationForUser(in BrightnessConfiguration c, int userId,
String packageName);
+
+ // Temporarily sets the display brightness.
+ void setTemporaryBrightness(int brightness);
+
+ // Temporarily sets the auto brightness adjustment factor.
+ void setTemporaryAutoBrightnessAdjustment(float adjustment);
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 75f7c1f58ab94..1681f11fa5263 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -63,11 +63,6 @@ interface IPowerManager
// --- deprecated ---
boolean isScreenBrightnessBoosted();
- // temporarily overrides the screen brightness settings to allow the user to
- // see the effect of a settings change without applying it immediately
- void setTemporaryScreenBrightnessSettingOverride(int brightness);
- void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);
-
// sets the attention light (used by phone app only)
void setAttentionLight(boolean on, int color);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 61172e11fec26..3d17ffb7329f1 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1001,24 +1001,6 @@ public final class PowerManager {
return false;
}
- /**
- * Sets the brightness of the backlights (screen, keyboard, button).
- *
- * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
- *
- *
- * @param brightness The brightness value from 0 to 255.
- *
- * @hide Requires signature permission.
- */
- public void setBacklightBrightness(int brightness) {
- try {
- mService.setTemporaryScreenBrightnessSettingOverride(brightness);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* Returns true if the specified wake lock level is supported.
*
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f1a9bd480a732..ea791a5da5ad0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3000,6 +3000,11 @@
+
+
+
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index 43cd373ef8505..fabcf3d920a94 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -16,12 +16,9 @@
package android.os;
-import android.os.IPowerManager;
-
import android.app.Activity;
+import android.hardware.display.DisplayManager;
import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.provider.Settings;
import android.view.View;
import android.view.View.OnClickListener;
@@ -37,23 +34,16 @@ public class BrightnessLimit extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
setContentView(R.layout.brightness_limit);
-
+
Button b = findViewById(R.id.go);
b.setOnClickListener(this);
}
public void onClick(View v) {
- IPowerManager power = IPowerManager.Stub.asInterface(
- ServiceManager.getService("power"));
- if (power != null) {
- try {
- power.setTemporaryScreenBrightnessSettingOverride(0);
- } catch (RemoteException darn) {
-
- }
- }
+ DisplayManager dm = getSystemService(DisplayManager.class);
+ dm.setTemporaryBrightness(0);
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0);
}
}
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 9893c161fec86..0d250b825d97c 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -21,9 +21,9 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
public class PowerManagerTest extends AndroidTestCase {
-
+
private PowerManager mPm;
-
+
/**
* Setup any common data for the upcoming tests.
*/
@@ -32,10 +32,10 @@ public class PowerManagerTest extends AndroidTestCase {
super.setUp();
mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
}
-
+
/**
* Confirm that the setup is good.
- *
+ *
* @throws Exception
*/
@SmallTest
@@ -45,7 +45,7 @@ public class PowerManagerTest extends AndroidTestCase {
/**
* Confirm that we can create functional wakelocks.
- *
+ *
* @throws Exception
*/
@SmallTest
@@ -61,22 +61,19 @@ public class PowerManagerTest extends AndroidTestCase {
wl = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
doTestWakeLock(wl);
-
- doTestSetBacklightBrightness();
- // TODO: Some sort of functional test (maybe not in the unit test here?)
+ // TODO: Some sort of functional test (maybe not in the unit test here?)
// that confirms that things are really happening e.g. screen power, keyboard power.
}
-
+
/**
* Confirm that we can't create dysfunctional wakelocks.
- *
+ *
* @throws Exception
*/
@SmallTest
public void testBadNewWakeLock() throws Exception {
-
- final int badFlags = PowerManager.SCREEN_BRIGHT_WAKE_LOCK
+ final int badFlags = PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.SCREEN_DIM_WAKE_LOCK;
// wrap in try because we want the error here
try {
@@ -86,10 +83,10 @@ public class PowerManagerTest extends AndroidTestCase {
}
fail("Bad WakeLock flag was not caught.");
}
-
+
/**
* Apply a few tests to a wakelock to make sure it's healthy.
- *
+ *
* @param wl The wakelock to be tested.
*/
private void doTestWakeLock(PowerManager.WakeLock wl) {
@@ -98,7 +95,7 @@ public class PowerManagerTest extends AndroidTestCase {
assertTrue(wl.isHeld());
wl.release();
assertFalse(wl.isHeld());
-
+
// Try ref-counted acquire/release
wl.setReferenceCounted(true);
wl.acquire();
@@ -109,7 +106,7 @@ public class PowerManagerTest extends AndroidTestCase {
assertTrue(wl.isHeld());
wl.release();
assertFalse(wl.isHeld());
-
+
// Try non-ref-counted
wl.setReferenceCounted(false);
wl.acquire();
@@ -118,24 +115,7 @@ public class PowerManagerTest extends AndroidTestCase {
assertTrue(wl.isHeld());
wl.release();
assertFalse(wl.isHeld());
-
+
// TODO: Threaded test (needs handler) to make sure timed wakelocks work too
}
-
-
- /**
- * Test that calling {@link android.os.IHardwareService#setBacklights(int)} requires
- * permissions.
- * Tests permission:
- * {@link android.Manifest.permission#DEVICE_POWER}
- */
- private void doTestSetBacklightBrightness() {
- try {
- mPm.setBacklightBrightness(0);
- fail("setBacklights did not throw SecurityException as expected");
- } catch (SecurityException e) {
- // expected
- }
- }
-
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index cfd33a19baf90..91957e1ff05cd 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -30,6 +30,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.hardware.display.DisplayManager;
import android.icu.util.ULocale;
import android.location.LocationManager;
import android.media.AudioManager;
@@ -306,15 +307,7 @@ public class SettingsHelper {
}
private void setBrightness(int brightness) {
- try {
- IPowerManager power = IPowerManager.Stub.asInterface(
- ServiceManager.getService("power"));
- if (power != null) {
- power.setTemporaryScreenBrightnessSettingOverride(brightness);
- }
- } catch (RemoteException doe) {
-
- }
+ mContext.getSystemService(DisplayManager.class).setTemporaryBrightness(brightness);
}
/* package */ byte[] getLocaleData() {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0b6e11bf86384..42b7213e84f05 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -72,6 +72,7 @@
+
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index d3f997a045003..3db30fcbbe6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -16,9 +16,11 @@
package com.android.systemui.settings;
+import android.animation.ValueAnimator;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
@@ -45,11 +47,7 @@ public class BrightnessController implements ToggleSlider.Listener {
private static final String TAG = "StatusBar.BrightnessController";
private static final boolean SHOW_AUTOMATIC_ICON = false;
- /**
- * {@link android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ} uses the range [-1, 1].
- * Using this factor, it is converted to [0, BRIGHTNESS_ADJ_RESOLUTION] for the SeekBar.
- */
- private static final float BRIGHTNESS_ADJ_RESOLUTION = 2048;
+ private static final int SLIDER_ANIMATION_DURATION = 3000;
private static final int MSG_UPDATE_ICON = 0;
private static final int MSG_UPDATE_SLIDER = 1;
@@ -67,7 +65,7 @@ public class BrightnessController implements ToggleSlider.Listener {
private final ImageView mIcon;
private final ToggleSlider mControl;
private final boolean mAutomaticAvailable;
- private final IPowerManager mPower;
+ private final DisplayManager mDisplayManager;
private final CurrentUserTracker mUserTracker;
private final IVrManager mVrManager;
@@ -81,6 +79,9 @@ public class BrightnessController implements ToggleSlider.Listener {
private volatile boolean mIsVrModeEnabled;
private boolean mListening;
private boolean mExternalChange;
+ private boolean mControlInitialized;
+
+ private ValueAnimator mSliderAnimator;
public interface BrightnessStateChangeCallback {
public void onBrightnessLevelChanged();
@@ -95,8 +96,6 @@ public class BrightnessController implements ToggleSlider.Listener {
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
private final Uri BRIGHTNESS_FOR_VR_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
- private final Uri BRIGHTNESS_ADJ_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
public BrightnessObserver(Handler handler) {
super(handler);
@@ -114,12 +113,10 @@ public class BrightnessController implements ToggleSlider.Listener {
if (BRIGHTNESS_MODE_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
- } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
+ } else if (BRIGHTNESS_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateSliderRunnable);
} else if (BRIGHTNESS_FOR_VR_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateSliderRunnable);
- } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
- mBackgroundHandler.post(mUpdateSliderRunnable);
} else {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
@@ -141,9 +138,6 @@ public class BrightnessController implements ToggleSlider.Listener {
cr.registerContentObserver(
BRIGHTNESS_FOR_VR_URI,
false, this, UserHandle.USER_ALL);
- cr.registerContentObserver(
- BRIGHTNESS_ADJ_URI,
- false, this, UserHandle.USER_ALL);
}
public void stopObserving() {
@@ -214,12 +208,6 @@ public class BrightnessController implements ToggleSlider.Listener {
mHandler.obtainMessage(MSG_UPDATE_SLIDER,
mMaximumBacklightForVr - mMinimumBacklightForVr,
value - mMinimumBacklightForVr).sendToTarget();
- } else if (mAutomatic) {
- float value = Settings.System.getFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0,
- UserHandle.USER_CURRENT);
- mHandler.obtainMessage(MSG_UPDATE_SLIDER, (int) BRIGHTNESS_ADJ_RESOLUTION,
- (int) ((value + 1) * BRIGHTNESS_ADJ_RESOLUTION / 2f)).sendToTarget();
} else {
int value;
value = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -250,7 +238,7 @@ public class BrightnessController implements ToggleSlider.Listener {
break;
case MSG_UPDATE_SLIDER:
mControl.setMax(msg.arg1);
- mControl.setValue(msg.arg2);
+ animateSliderTo(msg.arg2);
break;
case MSG_SET_CHECKED:
mControl.setChecked(msg.arg1 != 0);
@@ -295,8 +283,7 @@ public class BrightnessController implements ToggleSlider.Listener {
mAutomaticAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
- mPower = IPowerManager.Stub.asInterface(ServiceManager.getService(
- Context.POWER_SERVICE));
+ mDisplayManager = context.getSystemService(DisplayManager.class);
mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
Context.VR_SERVICE));
}
@@ -356,6 +343,10 @@ public class BrightnessController implements ToggleSlider.Listener {
updateIcon(mAutomatic);
if (mExternalChange) return;
+ if (mSliderAnimator != null) {
+ mSliderAnimator.cancel();
+ }
+
if (mIsVrModeEnabled) {
final int val = value + mMinimumBacklightForVr;
if (stopTracking) {
@@ -371,7 +362,7 @@ public class BrightnessController implements ToggleSlider.Listener {
}
});
}
- } else if (!mAutomatic) {
+ } else {
final int val = value + mMinimumBacklight;
if (stopTracking) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
@@ -386,21 +377,6 @@ public class BrightnessController implements ToggleSlider.Listener {
}
});
}
- } else {
- final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
- if (stopTracking) {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_AUTO, value);
- }
- setBrightnessAdj(adj);
- if (!tracking) {
- AsyncTask.execute(new Runnable() {
- public void run() {
- Settings.System.putFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj,
- UserHandle.USER_CURRENT);
- }
- });
- }
}
for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
@@ -415,17 +391,11 @@ public class BrightnessController implements ToggleSlider.Listener {
}
private void setBrightness(int brightness) {
- try {
- mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
- } catch (RemoteException ex) {
- }
+ mDisplayManager.setTemporaryBrightness(brightness);
}
private void setBrightnessAdj(float adj) {
- try {
- mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);
- } catch (RemoteException ex) {
- }
+ mDisplayManager.setTemporaryAutoBrightnessAdjustment(adj);
}
private void updateIcon(boolean automatic) {
@@ -442,4 +412,23 @@ public class BrightnessController implements ToggleSlider.Listener {
mBackgroundHandler.post(mUpdateSliderRunnable);
}
}
+
+ private void animateSliderTo(int target) {
+ if (!mControlInitialized) {
+ // Don't animate the first value since it's default state isn't meaningful to users.
+ mControl.setValue(target);
+ mControlInitialized = true;
+ }
+ if (mSliderAnimator != null && mSliderAnimator.isStarted()) {
+ mSliderAnimator.cancel();
+ }
+ mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
+ mSliderAnimator.addUpdateListener((ValueAnimator animation) -> {
+ mExternalChange = true;
+ mControl.setValue((int)animation.getAnimatedValue());
+ mExternalChange = false;
+ });
+ mSliderAnimator.setDuration(SLIDER_ANIMATION_DURATION);
+ mSliderAnimator.start();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index 62abf3d6c3e21..135f89d3f3431 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -28,4 +28,5 @@ public interface ToggleSlider {
default boolean isChecked() { return false; }
void setMax(int max);
void setValue(int value);
+ int getValue();
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
index 5b234e9c55768..07b9ec27629f5 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
@@ -125,6 +125,11 @@ public class ToggleSliderView extends RelativeLayout implements ToggleSlider {
}
}
+ @Override
+ public int getValue() {
+ return mSlider.getProgress();
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mMirror != null) {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 6c5bfc7933303..e445d27151965 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -25,6 +25,7 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -57,8 +58,16 @@ class AutomaticBrightnessController {
// the user is satisfied with the result before storing the sample.
private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000;
+ // Timeout after which we remove the effects any user interactions might've had on the
+ // brightness mapping. This timeout doesn't start until we transition to a non-interactive
+ // display policy so that we don't reset while users are using their devices, but also so that
+ // we don't erroneously keep the short-term model if the device is dozing but the display is
+ // fully on.
+ private static final int SHORT_TERM_MODEL_TIMEOUT_MILLIS = 30000;
+
private static final int MSG_UPDATE_AMBIENT_LUX = 1;
private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2;
+ private static final int MSG_RESET_SHORT_TERM_MODEL = 3;
// Length of the ambient light horizon used to calculate the long term estimate of ambient
// light.
@@ -173,8 +182,9 @@ class AutomaticBrightnessController {
// The last screen auto-brightness gamma. (For printing in dump() only.)
private float mLastScreenAutoBrightnessGamma = 1.0f;
- // Are we going to adjust brightness while dozing.
- private boolean mDozing;
+ // The current display policy. This is useful, for example, for knowing when we're dozing,
+ // where the light sensor may not be available.
+ private int mDisplayPolicy = DisplayPowerRequest.POLICY_OFF;
// True if we are collecting a brightness adjustment sample, along with some data
// for the initial state of the sample.
@@ -221,31 +231,72 @@ class AutomaticBrightnessController {
}
public int getAutomaticScreenBrightness() {
- if (mDozing) {
+ if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {
return (int) (mScreenAutoBrightness * mDozeScaleFactor);
}
return mScreenAutoBrightness;
}
public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
- float adjustment, boolean dozing, boolean userInitiatedChange) {
+ float brightness, float adjustment, int displayPolicy, boolean userInitiatedChange) {
// While dozing, the application processor may be suspended which will prevent us from
// receiving new information from the light sensor. On some devices, we may be able to
// switch to a wake-up light sensor instead but for now we will simply disable the sensor
// and hold onto the last computed screen auto brightness. We save the dozing flag for
// debugging purposes.
- mDozing = dozing;
+ boolean dozing = (displayPolicy == DisplayPowerRequest.POLICY_DOZE);
boolean changed = setBrightnessConfiguration(configuration);
- changed |= setLightSensorEnabled(enable && !dozing);
- if (enable && !dozing && userInitiatedChange) {
+ changed |= setDisplayPolicy(displayPolicy);
+ if (userInitiatedChange && enable && !dozing) {
+ // Update the current brightness value.
+ changed |= setScreenBrightnessByUser(brightness);
prepareBrightnessAdjustmentSample();
}
changed |= setScreenAutoBrightnessAdjustment(adjustment);
+ changed |= setLightSensorEnabled(enable && !dozing);
if (changed) {
updateAutoBrightness(false /*sendUpdate*/);
}
}
+ private boolean setDisplayPolicy(int policy) {
+ if (mDisplayPolicy == policy) {
+ return false;
+ }
+ final int oldPolicy = mDisplayPolicy;
+ mDisplayPolicy = policy;
+ if (DEBUG) {
+ Slog.d(TAG, "Display policy transitioning from " + mDisplayPolicy + " to " + policy);
+ }
+ if (!isInteractivePolicy(policy) && isInteractivePolicy(oldPolicy)) {
+ mHandler.sendEmptyMessageDelayed(MSG_RESET_SHORT_TERM_MODEL,
+ SHORT_TERM_MODEL_TIMEOUT_MILLIS);
+ } else if (isInteractivePolicy(policy) && !isInteractivePolicy(oldPolicy)) {
+ mHandler.removeMessages(MSG_RESET_SHORT_TERM_MODEL);
+ }
+ return true;
+ }
+
+ private static boolean isInteractivePolicy(int policy) {
+ return policy == DisplayPowerRequest.POLICY_BRIGHT
+ || policy == DisplayPowerRequest.POLICY_DIM
+ || policy == DisplayPowerRequest.POLICY_VR;
+ }
+
+ private boolean setScreenBrightnessByUser(float brightness) {
+ if (!mAmbientLuxValid) {
+ // If we don't have a valid ambient lux then we don't have a valid brightness anyways,
+ // and we can't use this data to add a new control point to the short-term model.
+ return false;
+ }
+ mBrightnessMapper.addUserDataPoint(mAmbientLux, brightness);
+ return true;
+ }
+
+ private void resetShortTermModel() {
+ mBrightnessMapper.clearUserDataPoints();
+ }
+
public boolean setBrightnessConfiguration(BrightnessConfiguration configuration) {
return mBrightnessMapper.setBrightnessConfiguration(configuration);
}
@@ -280,7 +331,7 @@ class AutomaticBrightnessController {
pw.println(" mScreenAutoBrightnessAdjustmentMaxGamma="
+ mScreenAutoBrightnessAdjustmentMaxGamma);
pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
- pw.println(" mDozing=" + mDozing);
+ pw.println(" mDisplayPolicy=" + mDisplayPolicy);
pw.println();
mBrightnessMapper.dump(pw);
@@ -364,6 +415,10 @@ class AutomaticBrightnessController {
if (DEBUG) {
Slog.d(TAG, "setAmbientLux(" + lux + ")");
}
+ if (lux < 0) {
+ Slog.w(TAG, "Ambient lux was negative, ignoring and setting to 0.");
+ lux = 0;
+ }
mAmbientLux = lux;
mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux);
mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux);
@@ -647,6 +702,10 @@ class AutomaticBrightnessController {
case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE:
collectBrightnessAdjustmentSample();
break;
+
+ case MSG_RESET_SHORT_TERM_MODEL:
+ resetShortTermModel();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index ac0e1b5c35502..436ebff0ad86e 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -30,6 +30,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.Arrays;
/**
* A utility to map from an ambient brightness to a display's "backlight" brightness based on the
@@ -42,6 +43,9 @@ public abstract class BrightnessMappingStrategy {
private static final String TAG = "BrightnessMappingStrategy";
private static final boolean DEBUG = false;
+ private static final float LUX_GRAD_SMOOTHING = 0.25f;
+ private static final float MAX_GRAD = 1.0f;
+
@Nullable
public static BrightnessMappingStrategy create(Resources resources) {
float[] luxLevels = getLuxLevels(resources.getIntArray(
@@ -169,11 +173,28 @@ public abstract class BrightnessMappingStrategy {
public abstract float getBrightness(float lux);
/**
- * Gets the display's brightness in nits for the given backlight value.
+ * Converts the provided backlight value to nits if possible.
*
* Returns -1.0f if there's no available mapping for the backlight to nits.
*/
- public abstract float getNits(int backlight);
+ public abstract float convertToNits(int backlight);
+
+ /**
+ * Adds a user interaction data point to the brightness mapping.
+ *
+ * Currently, we only keep track of one of these at a time to constrain what can happen to the
+ * curve.
+ */
+ public abstract void addUserDataPoint(float lux, float brightness);
+
+ /**
+ * Removes any short term adjustments made to the curve from user interactions.
+ *
+ * Note that this does *not* reset the mapping to its initial state, any brightness
+ * configurations that have been applied will continue to be in effect. This solely removes the
+ * effects of user interactions on the model.
+ */
+ public abstract void clearUserDataPoints();
public abstract void dump(PrintWriter pw);
@@ -183,6 +204,112 @@ public abstract class BrightnessMappingStrategy {
return (float) brightness / PowerManager.BRIGHTNESS_ON;
}
+ private static Spline createSpline(float[] x, float[] y) {
+ Spline spline = Spline.createSpline(x, y);
+ if (DEBUG) {
+ Slog.d(TAG, "Spline: " + spline);
+ for (float v = 1f; v < x[x.length - 1] * 1.25f; v *= 1.25f) {
+ Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
+ }
+ }
+ return spline;
+ }
+
+ private static Pair insertControlPoint(
+ float[] luxLevels, float[] brightnessLevels, float lux, float brightness) {
+ if (DEBUG) {
+ Slog.d(TAG, "Inserting new control point at (" + lux + ", " + brightness + ")");
+ }
+ final int idx = findInsertionPoint(luxLevels, lux);
+ final float[] newLuxLevels;
+ final float[] newBrightnessLevels;
+ if (idx == luxLevels.length) {
+ newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length + 1);
+ newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length + 1);
+ newLuxLevels[idx] = lux;
+ newBrightnessLevels[idx] = brightness;
+ } else if (luxLevels[idx] == lux) {
+ newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length);
+ newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length);
+ newBrightnessLevels[idx] = brightness;
+ } else {
+ newLuxLevels = Arrays.copyOf(luxLevels, luxLevels.length + 1);
+ System.arraycopy(newLuxLevels, idx, newLuxLevels, idx+1, luxLevels.length - idx);
+ newLuxLevels[idx] = lux;
+ newBrightnessLevels = Arrays.copyOf(brightnessLevels, brightnessLevels.length + 1);
+ System.arraycopy(newBrightnessLevels, idx, newBrightnessLevels, idx+1,
+ brightnessLevels.length - idx);
+ newBrightnessLevels[idx] = brightness;
+ }
+ smoothCurve(newLuxLevels, newBrightnessLevels, idx);
+ return Pair.create(newLuxLevels, newBrightnessLevels);
+ }
+
+ /**
+ * Returns the index of the first value that's less than or equal to {@code val}.
+ *
+ * This assumes that {@code arr} is sorted. If all values in {@code arr} are greater
+ * than val, then it will return the length of arr as the insertion point.
+ */
+ private static int findInsertionPoint(float[] arr, float val) {
+ for (int i = 0; i < arr.length; i++) {
+ if (val <= arr[i]) {
+ return i;
+ }
+ }
+ return arr.length;
+ }
+
+ private static void smoothCurve(float[] lux, float[] brightness, int idx) {
+ if (DEBUG) {
+ Slog.d(TAG, "smoothCurve(lux=" + Arrays.toString(lux)
+ + ", brightness=" + Arrays.toString(brightness)
+ + ", idx=" + idx + ")");
+ }
+ float prevLux = lux[idx];
+ float prevBrightness = brightness[idx];
+ // Smooth curve for data points above the newly introduced point
+ for (int i = idx+1; i < lux.length; i++) {
+ float currLux = lux[i];
+ float currBrightness = brightness[i];
+ float maxBrightness = prevBrightness * permissibleRatio(currLux, prevLux);
+ float newBrightness = MathUtils.constrain(
+ currBrightness, prevBrightness, maxBrightness);
+ if (newBrightness == currBrightness) {
+ break;
+ }
+ prevLux = currLux;
+ prevBrightness = newBrightness;
+ brightness[i] = newBrightness;
+ }
+
+ // Smooth curve for data points below the newly introduced point
+ prevLux = lux[idx];
+ prevBrightness = brightness[idx];
+ for (int i = idx-1; i >= 0; i--) {
+ float currLux = lux[i];
+ float currBrightness = brightness[i];
+ float minBrightness = prevBrightness * permissibleRatio(currLux, prevLux);
+ float newBrightness = MathUtils.constrain(
+ currBrightness, minBrightness, prevBrightness);
+ if (newBrightness == currBrightness) {
+ break;
+ }
+ prevLux = currLux;
+ prevBrightness = newBrightness;
+ brightness[i] = newBrightness;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Smoothed Curve: lux=" + Arrays.toString(lux)
+ + ", brightness=" + Arrays.toString(brightness));
+ }
+ }
+
+ private static float permissibleRatio(float currLux, float prevLux) {
+ return MathUtils.exp(MAX_GRAD
+ * (MathUtils.log(currLux + LUX_GRAD_SMOOTHING)
+ - MathUtils.log(prevLux + LUX_GRAD_SMOOTHING)));
+ }
/**
* A {@link BrightnessMappingStrategy} that maps from ambient room brightness directly to the
@@ -192,7 +319,14 @@ public abstract class BrightnessMappingStrategy {
* configurations that are set are just ignored.
*/
private static class SimpleMappingStrategy extends BrightnessMappingStrategy {
- private final Spline mSpline;
+ // Lux control points
+ private final float[] mLux;
+ // Brightness control points normalized to [0, 1]
+ private final float[] mBrightness;
+
+ private Spline mSpline;
+ private float mUserLux;
+ private float mUserBrightness;
public SimpleMappingStrategy(float[] lux, int[] brightness) {
Preconditions.checkArgument(lux.length != 0 && brightness.length != 0,
@@ -204,20 +338,16 @@ public abstract class BrightnessMappingStrategy {
0, Integer.MAX_VALUE, "brightness");
final int N = brightness.length;
- float[] x = new float[N];
- float[] y = new float[N];
+ mLux = new float[N];
+ mBrightness = new float[N];
for (int i = 0; i < N; i++) {
- x[i] = lux[i];
- y[i] = normalizeAbsoluteBrightness(brightness[i]);
+ mLux[i] = lux[i];
+ mBrightness[i] = normalizeAbsoluteBrightness(brightness[i]);
}
- mSpline = Spline.createSpline(x, y);
- if (DEBUG) {
- Slog.d(TAG, "Auto-brightness spline: " + mSpline);
- for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(" %7.1f: %7.1f", v, mSpline.interpolate(v)));
- }
- }
+ mSpline = createSpline(mLux, mBrightness);
+ mUserLux = -1;
+ mUserBrightness = -1;
}
@Override
@@ -231,14 +361,36 @@ public abstract class BrightnessMappingStrategy {
}
@Override
- public float getNits(int backlight) {
+ public float convertToNits(int backlight) {
return -1.0f;
}
+ @Override
+ public void addUserDataPoint(float lux, float brightness) {
+ if (DEBUG){
+ Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", brightness=" + brightness + ")");
+ }
+ Pair curve = insertControlPoint(mLux, mBrightness, lux, brightness);
+ mSpline = createSpline(curve.first, curve.second);
+ mUserLux = lux;
+ mUserBrightness = brightness;
+ }
+
+ @Override
+ public void clearUserDataPoints() {
+ if (mUserLux != -1) {
+ mSpline = createSpline(mLux, mBrightness);
+ mUserLux = -1;
+ mUserBrightness = -1;
+ }
+ }
+
@Override
public void dump(PrintWriter pw) {
pw.println("SimpleMappingStrategy");
pw.println(" mSpline=" + mSpline);
+ pw.println(" mUserLux=" + mUserLux);
+ pw.println(" mUserBrightness=" + mUserBrightness);
}
}
@@ -261,13 +413,16 @@ public abstract class BrightnessMappingStrategy {
// [0, 1.0].
private final Spline mNitsToBacklightSpline;
- // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to
- // a brightness in nits.
- private final Spline mBacklightToNitsSpline;
-
// The default brightness configuration.
private final BrightnessConfiguration mDefaultConfig;
+ // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to
+ // a brightness in nits.
+ private Spline mBacklightToNitsSpline;
+
+ private float mUserLux;
+ private float mUserBrightness;
+
public PhysicalMappingStrategy(BrightnessConfiguration config,
float[] nits, int[] backlight) {
Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
@@ -279,6 +434,9 @@ public abstract class BrightnessMappingStrategy {
Preconditions.checkArrayElementsInRange(backlight,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
+ mUserLux = -1;
+ mUserBrightness = -1;
+
// Setup the backlight spline
final int N = nits.length;
float[] normalizedBacklight = new float[N];
@@ -286,15 +444,8 @@ public abstract class BrightnessMappingStrategy {
normalizedBacklight[i] = normalizeAbsoluteBrightness(backlight[i]);
}
- mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
- mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
- if (DEBUG) {
- Slog.d(TAG, "Backlight spline: " + mNitsToBacklightSpline);
- for (float v = 1f; v < nits[nits.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(
- " %7.1f: %7.1f", v, mNitsToBacklightSpline.interpolate(v)));
- }
- }
+ mNitsToBacklightSpline = createSpline(nits, normalizedBacklight);
+ mBacklightToNitsSpline = createSpline(normalizedBacklight, nits);
mDefaultConfig = config;
setBrightnessConfiguration(config);
@@ -306,42 +457,59 @@ public abstract class BrightnessMappingStrategy {
config = mDefaultConfig;
}
if (config.equals(mConfig)) {
- if (DEBUG) {
- Slog.d(TAG, "Tried to set an identical brightness config, ignoring");
- }
return false;
}
Pair curve = config.getCurve();
- mBrightnessSpline = Spline.createSpline(curve.first /*lux*/, curve.second /*nits*/);
- if (DEBUG) {
- Slog.d(TAG, "Brightness spline: " + mBrightnessSpline);
- final float[] lux = curve.first;
- for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(
- " %7.1f: %7.1f", v, mBrightnessSpline.interpolate(v)));
- }
- }
+ mBrightnessSpline = createSpline(curve.first /*lux*/, curve.second /*nits*/);
mConfig = config;
return true;
}
@Override
public float getBrightness(float lux) {
- return mNitsToBacklightSpline.interpolate(mBrightnessSpline.interpolate(lux));
+ float nits = mBrightnessSpline.interpolate(lux);
+ float backlight = mNitsToBacklightSpline.interpolate(nits);
+ return backlight;
}
@Override
- public float getNits(int backlight) {
+ public float convertToNits(int backlight) {
return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight));
}
+ @Override
+ public void addUserDataPoint(float lux, float backlight) {
+ if (DEBUG){
+ Slog.d(TAG, "addUserDataPoint(lux=" + lux + ", backlight=" + backlight + ")");
+ }
+ float brightness = mBacklightToNitsSpline.interpolate(backlight);
+ Pair defaultCurve = mConfig.getCurve();
+ Pair newCurve =
+ insertControlPoint(defaultCurve.first, defaultCurve.second, lux, brightness);
+ mBrightnessSpline = createSpline(newCurve.first, newCurve.second);
+ mUserLux = lux;
+ mUserBrightness = brightness;
+ }
+
+ @Override
+ public void clearUserDataPoints() {
+ if (mUserLux != -1) {
+ Pair defaultCurve = mConfig.getCurve();
+ mBrightnessSpline = createSpline(defaultCurve.first, defaultCurve.second);
+ mUserLux = -1;
+ mUserBrightness = -1;
+ }
+ }
+
@Override
public void dump(PrintWriter pw) {
pw.println("PhysicalMappingStrategy");
pw.println(" mConfig=" + mConfig);
pw.println(" mBrightnessSpline=" + mBrightnessSpline);
pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline);
+ pw.println(" mUserLux=" + mUserLux);
+ pw.println(" mUserBrightness=" + mUserBrightness);
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index c77ec20afa3b9..0c2ff05196150 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1857,6 +1857,36 @@ public final class DisplayManagerService extends SystemService {
}
}
+ @Override // Binder call
+ public void setTemporaryBrightness(int brightness) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
+ "Permission required to set the display's brightness");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ mDisplayPowerController.setTemporaryBrightness(brightness);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
+ "Permission required to set the display's auto brightness adjustment");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean validatePackageName(int uid, String packageName) {
if (packageName != null) {
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index d2b8e5c677b46..056c3e641c4a8 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -29,6 +29,7 @@ import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -37,6 +38,7 @@ import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -44,6 +46,8 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.MathUtils;
import android.util.Slog;
import android.util.Spline;
@@ -99,6 +103,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
private static final int MSG_SCREEN_OFF_UNBLOCKED = 4;
private static final int MSG_CONFIGURE_BRIGHTNESS = 5;
+ private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
+ private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -144,6 +150,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The display blanker.
private final DisplayBlanker mBlanker;
+ // Tracker for brightness changes.
+ private final BrightnessTracker mBrightnessTracker;
+
+ // Tracker for brightness settings changes.
+ private final SettingsObserver mSettingsObserver;
+
// The proximity sensor, or null if not available or needed.
private Sensor mProximitySensor;
@@ -159,6 +171,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The maximum allowed brightness.
private final int mScreenBrightnessRangeMaximum;
+ // The default screen brightness.
+ private final int mScreenBrightnessDefault;
+
+ // The default screen brightness for VR.
+ private final int mScreenBrightnessForVrDefault;
+
// True if auto-brightness should be used.
private boolean mUseSoftwareAutoBrightnessConfig;
@@ -298,20 +316,42 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// The last brightness that was set by the user and not temporary. Set to -1 when a brightness
// has yet to be recorded.
- private int mLastBrightness;
+ private int mLastUserSetScreenBrightness;
+
+ // The screen brightenss setting has changed but not taken effect yet. If this is different
+ // from the current screen brightness setting then this is coming from something other than us
+ // and should be considered a user interaction.
+ private int mPendingScreenBrightnessSetting;
+
+ // The last observed screen brightness setting, either set by us or by the settings app on
+ // behalf of the user.
+ private int mCurrentScreenBrightnessSetting;
+
+ // The temporary screen brightness. Typically set when a user is interacting with the
+ // brightness slider but hasn't settled on a choice yet. Set to -1 when there's no temporary
+ // brightness set.
+ private int mTemporaryScreenBrightness;
+
+ // The current screen brightness while in VR mode.
+ private int mScreenBrightnessForVr;
// The last auto brightness adjustment that was set by the user and not temporary. Set to
// Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
- private float mLastAutoBrightnessAdjustment;
+ private float mAutoBrightnessAdjustment;
+
+ // The pending auto brightness adjustment that will take effect on the next power state update.
+ private float mPendingAutoBrightnessAdjustment;
+
+ // The temporary auto brightness adjustment. Typically set when a user is interacting with the
+ // adjustment slider but hasn't settled on a choice yet. Set to Float.NaN when there's no
+ // temporary adjustment set.
+ private float mTemporaryAutoBrightnessAdjustment;
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
private RampAnimator mScreenBrightnessRampAnimator;
- // Tracker for brightness changes
- private final BrightnessTracker mBrightnessTracker;
-
/**
* Creates the display power controller.
*/
@@ -320,6 +360,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
SensorManager sensorManager, DisplayBlanker blanker) {
mHandler = new DisplayControllerHandler(handler.getLooper());
mBrightnessTracker = new BrightnessTracker(context, null);
+ mSettingsObserver = new SettingsObserver(mHandler);
mCallbacks = callbacks;
mBatteryStats = BatteryStatsService.getService();
@@ -343,6 +384,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(resources.getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMaximum));
+ mScreenBrightnessDefault = clampAbsoluteBrightness(resources.getInteger(
+ com.android.internal.R.integer.config_screenBrightnessSettingDefault));
+ mScreenBrightnessForVrDefault = clampAbsoluteBrightness(resources.getInteger(
+ com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault));
mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
@@ -429,8 +474,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- mLastBrightness = -1;
- mLastAutoBrightnessAdjustment = Float.NaN;
+ mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
+ mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
+ mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
+ mTemporaryScreenBrightness = -1;
+ mTemporaryAutoBrightnessAdjustment = Float.NaN;
}
/**
@@ -553,10 +601,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
// Initialize all of the brightness tracking state
- final float brightness = getNits(mPowerState.getScreenBrightness());
+ final float brightness = convertToNits(mPowerState.getScreenBrightness());
if (brightness >= 0.0f) {
mBrightnessTracker.start(brightness);
}
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
+ false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
+ false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
}
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@@ -586,7 +641,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Update the power state request.
final boolean mustNotify;
boolean mustInitialize = false;
- boolean autoBrightnessAdjustmentChanged = false;
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
@@ -601,8 +655,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPendingRequestChangedLocked = false;
mustInitialize = true;
} else if (mPendingRequestChangedLocked) {
- autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
- != mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
@@ -691,6 +743,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
brightness = PowerManager.BRIGHTNESS_OFF;
}
+ // Always use the VR brightness when in the VR state.
+ if (state == Display.STATE_VR) {
+ brightness = mScreenBrightnessForVr;
+ }
+
+ if (brightness < 0 && mPowerRequest.screenBrightnessOverride > 0) {
+ brightness = mPowerRequest.screenBrightnessOverride;
+ }
final boolean autoBrightnessEnabledInDoze =
mAllowAutoBrightnessWhileDozingConfig && Display.isDozeState(state);
@@ -698,38 +758,54 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
&& brightness < 0
&& mAutomaticBrightnessController != null;
- final boolean brightnessAdjustmentChanged =
- !Float.isNaN(mLastAutoBrightnessAdjustment)
- && mPowerRequest.screenAutoBrightnessAdjustment != mLastAutoBrightnessAdjustment;
- final boolean brightnessChanged = mLastBrightness >= 0
- && mPowerRequest.screenBrightness != mLastBrightness;
+ boolean brightnessIsTemporary = false;
- // Update the last set brightness values.
- final boolean userInitiatedChange;
- if (mPowerRequest.brightnessSetByUser && !mPowerRequest.brightnessIsTemporary) {
- userInitiatedChange = autoBrightnessEnabled && brightnessAdjustmentChanged
- || !autoBrightnessEnabled && brightnessChanged;
- mLastBrightness = mPowerRequest.screenBrightness;
- mLastAutoBrightnessAdjustment = mPowerRequest.screenAutoBrightnessAdjustment;
- } else {
- userInitiatedChange = false;
+ final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
+ if (userSetBrightnessChanged) {
+ mTemporaryScreenBrightness = -1;
}
+ // Use the temporary screen brightness if there isn't an override, either from
+ // WindowManager or based on the display state.
+ if (mTemporaryScreenBrightness > 0) {
+ brightness = mTemporaryScreenBrightness;
+ brightnessIsTemporary = true;
+ }
+
+ final boolean autoBrightnessAdjustmentChanged = updateAutoBrightnessAdjustment();
+ if (autoBrightnessAdjustmentChanged) {
+ mTemporaryAutoBrightnessAdjustment = Float.NaN;
+ }
+
+ // Use the autobrightness adjustment override if set.
+ final float autoBrightnessAdjustment;
+ if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
+ autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
+ brightnessIsTemporary = true;
+ } else {
+ autoBrightnessAdjustment = mAutoBrightnessAdjustment;
+ }
+
+ // Apply brightness boost.
+ // We do this here after deciding whether auto-brightness is enabled so that we don't
+ // disable the light sensor during this temporary state. That way when boost ends we will
+ // be able to resume normal auto-brightness behavior without any delay.
+ if (mPowerRequest.boostScreenBrightness
+ && brightness != PowerManager.BRIGHTNESS_OFF) {
+ brightness = PowerManager.BRIGHTNESS_ON;
+ }
+
+ // If the brightness is already set then it's been overriden by something other than the
+ // user, or is a temporary adjustment.
+ final boolean userInitiatedChange = brightness < 0
+ && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
+
// Configure auto-brightness.
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
- mBrightnessConfiguration, mPowerRequest.screenAutoBrightnessAdjustment,
- state != Display.STATE_ON, userInitiatedChange);
- }
-
- // Apply brightness boost.
- // We do this here after configuring auto-brightness so that we don't
- // disable the light sensor during this temporary state. That way when
- // boost ends we will be able to resume normal auto-brightness behavior
- // without any delay.
- if (mPowerRequest.boostScreenBrightness
- && brightness != PowerManager.BRIGHTNESS_OFF) {
- brightness = PowerManager.BRIGHTNESS_ON;
+ mBrightnessConfiguration,
+ mLastUserSetScreenBrightness / (float) PowerManager.BRIGHTNESS_ON,
+ autoBrightnessAdjustment, mPowerRequest.policy, userInitiatedChange);
}
// Apply auto-brightness.
@@ -744,6 +820,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
slowChange = true; // slowly adapt to auto-brightness
}
+ // Tell the rest of the system about the new brightness. Note that we do this
+ // before applying the low power or dim transformations so that the slider
+ // accurately represents the full possible range, even if they range changes what
+ // it means in absolute terms.
+ putScreenBrightnessSetting(brightness);
mAppliedAutoBrightness = true;
} else {
mAppliedAutoBrightness = false;
@@ -762,9 +843,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// provide a nominal default value for the case where auto-brightness
// is not ready yet.
if (brightness < 0) {
- brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
+ brightness = clampScreenBrightness(mLastUserSetScreenBrightness);
}
+
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -833,19 +915,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean isDisplayContentVisible =
mColorFadeEnabled && mPowerState.getColorFadeLevel() == 1.0f;
if (initialRampSkip || hasBrightnessBuckets
- || wasOrWillBeInVr || !isDisplayContentVisible) {
+ || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(brightness, 0);
} else {
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
}
- final float brightnessInNits = getNits(brightness);
- if (!mPowerRequest.brightnessIsTemporary && brightnessInNits >= 0.0f) {
- // We only want to track changes made by the user and on devices that can actually
- // map the display backlight values into a physical brightness unit.
- mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiatedChange);
+ if (!brightnessIsTemporary) {
+ notifyBrightnessChanged(brightness, userInitiatedChange);
}
+
}
// Determine whether the display is ready for use in the newly requested state.
@@ -913,6 +993,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
msg.sendToTarget();
}
+ public void setTemporaryBrightness(int brightness) {
+ Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
+ brightness, 0 /*unused*/);
+ msg.sendToTarget();
+ }
+
+ public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
+ Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
+ Float.floatToIntBits(adjustment), 0 /*unused*/);
+ msg.sendToTarget();
+ }
+
private void blockScreenOn() {
if (mPendingScreenOnUnblocker == null) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
@@ -1304,9 +1396,79 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mHandler.post(mOnStateChangedRunnable);
}
- private float getNits(int backlight) {
+ private void handleSettingsChange() {
+ mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
+ mPendingAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
+ // We don't bother with a pending variable for VR screen brightness since we just
+ // immediately adapt to it.
+ mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
+ sendUpdatePowerState();
+ }
+
+ private float getAutoBrightnessAdjustmentSetting() {
+ final float adj = Settings.System.getFloatForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
+ return Float.isNaN(adj) ? 0.0f : clampAutoBrightnessAdjustment(adj);
+ }
+
+ private int getScreenBrightnessSetting() {
+ final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessDefault,
+ UserHandle.USER_CURRENT);
+ return clampAbsoluteBrightness(brightness);
+ }
+
+ private int getScreenBrightnessForVrSetting() {
+ final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrDefault,
+ UserHandle.USER_CURRENT);
+ return clampAbsoluteBrightness(brightness);
+ }
+
+ private void putScreenBrightnessSetting(int brightness) {
+ mCurrentScreenBrightnessSetting = brightness;
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, brightness,
+ UserHandle.USER_CURRENT);
+ }
+
+ private boolean updateAutoBrightnessAdjustment() {
+ if (Float.isNaN(mPendingAutoBrightnessAdjustment)) {
+ return false;
+ }
+ if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
+ return false;
+ }
+ mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
+ mPendingAutoBrightnessAdjustment = Float.NaN;
+ return true;
+ }
+
+ private boolean updateUserSetScreenBrightness() {
+ if (mPendingScreenBrightnessSetting < 0) {
+ return false;
+ }
+ if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
+ return false;
+ }
+ mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
+ mPendingScreenBrightnessSetting = -1;
+ return true;
+ }
+
+ private void notifyBrightnessChanged(int brightness, boolean userInitiated) {
+ final float brightnessInNits = convertToNits(brightness);
+ if (brightnessInNits >= 0.0f) {
+ // We only want to track changes on devices that can actually map the display backlight
+ // values into a physical brightness unit since the value provided by the API is in
+ // nits and not using the arbitrary backlight units.
+ mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated);
+ }
+ }
+
+ private float convertToNits(int backlight) {
if (mBrightnessMapper != null) {
- return mBrightnessMapper.getNits(backlight);
+ return mBrightnessMapper.convertToNits(backlight);
} else {
return -1.0f;
}
@@ -1390,8 +1552,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mPendingProximityDebounceTime="
+ TimeUtils.formatUptime(mPendingProximityDebounceTime));
pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
- pw.println(" mLastBrightness=" + mLastBrightness);
- pw.println(" mLastAutoBrightnessAdjustment=" + mLastAutoBrightnessAdjustment);
+ pw.println(" mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness);
+ pw.println(" mCurrentScreenBrightnessSetting=" + mCurrentScreenBrightnessSetting);
+ pw.println(" mPendingScreenBrightnessSetting=" + mPendingScreenBrightnessSetting);
+ pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
+ pw.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
pw.println(" mAppliedDimming=" + mAppliedDimming);
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
@@ -1456,6 +1621,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
}
+ private static float clampAutoBrightnessAdjustment(float value) {
+ return MathUtils.constrain(value, -1.0f, 1.0f);
+ }
+
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -1488,6 +1657,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessConfiguration = (BrightnessConfiguration)msg.obj;
updatePowerState();
break;
+
+ case MSG_SET_TEMPORARY_BRIGHTNESS:
+ // TODO: Should we have a a timeout for the temporary brightness?
+ mTemporaryScreenBrightness = msg.arg1;
+ updatePowerState();
+ break;
+
+ case MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT:
+ mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1);
+ updatePowerState();
+ break;
}
}
}
@@ -1509,6 +1689,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
};
+
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ handleSettingsChange();
+ }
+ }
+
private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
@Override
public void onScreenOn() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index fbdedceabb3b3..cf36166757e23 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -70,6 +70,7 @@ import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
import android.util.KeyValueListParser;
+import android.util.MathUtils;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
@@ -458,19 +459,11 @@ public final class PowerManagerService extends SystemService
private int mScreenBrightnessSettingMinimum;
private int mScreenBrightnessSettingMaximum;
private int mScreenBrightnessSettingDefault;
- private int mScreenBrightnessForVrSettingDefault;
// The screen brightness setting, from 0 to 255.
// Use -1 if no value has been set.
private int mScreenBrightnessSetting;
- // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
- private int mScreenBrightnessForVrSetting;
-
- // The screen auto-brightness adjustment setting, from -1 to 1.
- // Use 0 if there is no adjustment.
- private float mScreenAutoBrightnessAdjustmentSetting;
-
// The screen brightness mode.
// One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
private int mScreenBrightnessModeSetting;
@@ -493,17 +486,6 @@ public final class PowerManagerService extends SystemService
// Use -1 to disable.
private long mUserActivityTimeoutOverrideFromWindowManager = -1;
- // The screen brightness setting override from the settings application
- // to temporarily adjust the brightness until next updated,
- // Use -1 to disable.
- private int mTemporaryScreenBrightnessSettingOverride = -1;
-
- // The screen brightness adjustment setting override from the settings
- // application to temporarily adjust the auto-brightness adjustment factor
- // until next updated, in the range -1..1.
- // Use NaN to disable.
- private float mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
-
// The screen state to use while dozing.
private int mDozeScreenStateOverrideFromDreamManager = Display.STATE_UNKNOWN;
@@ -774,7 +756,6 @@ public final class PowerManagerService extends SystemService
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
- mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -836,12 +817,6 @@ public final class PowerManagerService extends SystemService
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
false, mSettingsObserver, UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.SCREEN_BRIGHTNESS),
- false, mSettingsObserver, UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
- false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS_MODE),
false, mSettingsObserver, UserHandle.USER_ALL);
@@ -978,29 +953,6 @@ public final class PowerManagerService extends SystemService
SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
}
- final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
-
- mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
- Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrSettingDefault,
- UserHandle.USER_CURRENT);
-
- mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
- Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
- UserHandle.USER_CURRENT);
-
- if (oldScreenBrightnessSetting != getCurrentBrightnessSettingLocked()) {
- mTemporaryScreenBrightnessSettingOverride = -1;
- }
-
- final float oldScreenAutoBrightnessAdjustmentSetting =
- mScreenAutoBrightnessAdjustmentSetting;
- mScreenAutoBrightnessAdjustmentSetting = Settings.System.getFloatForUser(resolver,
- Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f,
- UserHandle.USER_CURRENT);
- if (oldScreenAutoBrightnessAdjustmentSetting != mScreenAutoBrightnessAdjustmentSetting) {
- mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
- }
-
mScreenBrightnessModeSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
@@ -1019,10 +971,6 @@ public final class PowerManagerService extends SystemService
mDirty |= DIRTY_SETTINGS;
}
- private int getCurrentBrightnessSettingLocked() {
- return mIsVrModeEnabled ? mScreenBrightnessForVrSetting : mScreenBrightnessSetting;
- }
-
private void postAfterBootCompleted(Runnable r) {
if (mBootCompleted) {
BackgroundThread.getHandler().post(r);
@@ -2450,53 +2398,24 @@ public final class PowerManagerService extends SystemService
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
- boolean brightnessSetByUser = true;
- int screenBrightness = mScreenBrightnessSettingDefault;
- float screenAutoBrightnessAdjustment = 0.0f;
- boolean autoBrightness = (mScreenBrightnessModeSetting ==
- Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
- boolean brightnessIsTemporary = false;
+ final boolean autoBrightness;
+ final int screenBrightnessOverride;
if (!mBootCompleted) {
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
- brightnessSetByUser = false;
- } else if (mIsVrModeEnabled) {
- screenBrightness = mScreenBrightnessForVrSetting;
- autoBrightness = false;
+ screenBrightnessOverride = mScreenBrightnessSettingDefault;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
- screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
- brightnessSetByUser = false;
- } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
- screenBrightness = mTemporaryScreenBrightnessSettingOverride;
- brightnessIsTemporary = true;
- } else if (isValidBrightness(mScreenBrightnessSetting)) {
- screenBrightness = mScreenBrightnessSetting;
+ screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
+ } else {
+ autoBrightness = (mScreenBrightnessModeSetting ==
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+ screenBrightnessOverride = -1;
}
- if (autoBrightness) {
- screenBrightness = mScreenBrightnessSettingDefault;
- if (isValidAutoBrightnessAdjustment(
- mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
- screenAutoBrightnessAdjustment =
- mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
- brightnessIsTemporary = true;
- } else if (isValidAutoBrightnessAdjustment(
- mScreenAutoBrightnessAdjustmentSetting)) {
- screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
- }
- }
- screenBrightness = Math.max(Math.min(screenBrightness,
- mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
- screenAutoBrightnessAdjustment = Math.max(Math.min(
- screenAutoBrightnessAdjustment, 1.0f), -1.0f);
// Update display power request.
- mDisplayPowerRequest.screenBrightness = screenBrightness;
- mDisplayPowerRequest.screenAutoBrightnessAdjustment =
- screenAutoBrightnessAdjustment;
- mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
- mDisplayPowerRequest.brightnessIsTemporary = brightnessIsTemporary;
+ mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
@@ -2534,6 +2453,8 @@ public final class PowerManagerService extends SystemService
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ + ", screenBrightnessOverride=" + screenBrightnessOverride
+ + ", useAutoBrightness=" + autoBrightness
+ ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+ ", mIsVrModeEnabled= " + mIsVrModeEnabled
+ ", sQuiescent=" + sQuiescent);
@@ -2573,11 +2494,6 @@ public final class PowerManagerService extends SystemService
return value >= 0 && value <= 255;
}
- private static boolean isValidAutoBrightnessAdjustment(float value) {
- // Handles NaN by always returning false.
- return value >= -1.0f && value <= 1.0f;
- }
-
@VisibleForTesting
int getDesiredScreenPolicyLocked() {
if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
@@ -3247,28 +3163,6 @@ public final class PowerManagerService extends SystemService
}
}
- private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
- synchronized (mLock) {
- if (mTemporaryScreenBrightnessSettingOverride != brightness) {
- mTemporaryScreenBrightnessSettingOverride = brightness;
- mDirty |= DIRTY_SETTINGS;
- updatePowerStateLocked();
- }
- }
- }
-
- private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) {
- synchronized (mLock) {
- // Note: This condition handles NaN because NaN is not equal to any other
- // value, including itself.
- if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverride != adj) {
- mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = adj;
- mDirty |= DIRTY_SETTINGS;
- updatePowerStateLocked();
- }
- }
- }
-
private void setDozeOverrideFromDreamManagerInternal(
int screenState, int screenBrightness) {
synchronized (mLock) {
@@ -3478,8 +3372,6 @@ public final class PowerManagerService extends SystemService
+ isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
pw.println(" mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
pw.println(" mScreenBrightnessSetting=" + mScreenBrightnessSetting);
- pw.println(" mScreenAutoBrightnessAdjustmentSetting="
- + mScreenAutoBrightnessAdjustmentSetting);
pw.println(" mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
pw.println(" mScreenBrightnessOverrideFromWindowManager="
+ mScreenBrightnessOverrideFromWindowManager);
@@ -3487,10 +3379,6 @@ public final class PowerManagerService extends SystemService
+ mUserActivityTimeoutOverrideFromWindowManager);
pw.println(" mUserInactiveOverrideFromWindowManager="
+ mUserInactiveOverrideFromWindowManager);
- pw.println(" mTemporaryScreenBrightnessSettingOverride="
- + mTemporaryScreenBrightnessSettingOverride);
- pw.println(" mTemporaryScreenAutoBrightnessAdjustmentSettingOverride="
- + mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
pw.println(" mDozeScreenStateOverrideFromDreamManager="
+ mDozeScreenStateOverrideFromDreamManager);
pw.println(" mDozeScreenBrightnessOverrideFromDreamManager="
@@ -3498,9 +3386,6 @@ public final class PowerManagerService extends SystemService
pw.println(" mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
pw.println(" mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
pw.println(" mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
- pw.println(" mScreenBrightnessForVrSettingDefault="
- + mScreenBrightnessForVrSettingDefault);
- pw.println(" mScreenBrightnessForVrSetting=" + mScreenBrightnessForVrSetting);
pw.println(" mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
pw.println(" mIsVrModeEnabled=" + mIsVrModeEnabled);
pw.println(" mForegroundProfile=" + mForegroundProfile);
@@ -3811,13 +3696,6 @@ public final class PowerManagerService extends SystemService
!= 0));
proto.end(stayOnWhilePluggedInToken);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_SETTING,
- mScreenBrightnessSetting);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto
- .SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING,
- mScreenAutoBrightnessAdjustmentSetting);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_MODE_SETTING,
mScreenBrightnessModeSetting);
@@ -3833,14 +3711,6 @@ public final class PowerManagerService extends SystemService
PowerServiceSettingsAndConfigurationDumpProto
.IS_USER_INACTIVE_OVERRIDE_FROM_WINDOW_MANAGER,
mUserInactiveOverrideFromWindowManager);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto
- .TEMPORARY_SCREEN_BRIGHTNESS_SETTING_OVERRIDE,
- mTemporaryScreenBrightnessSettingOverride);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto
- .TEMPORARY_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING_OVERRIDE,
- mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto
.DOZE_SCREEN_STATE_OVERRIDE_FROM_DREAM_MANAGER,
@@ -3866,15 +3736,8 @@ public final class PowerManagerService extends SystemService
PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
.SETTING_DEFAULT,
mScreenBrightnessSettingDefault);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
- .SETTING_FOR_VR_DEFAULT,
- mScreenBrightnessForVrSettingDefault);
proto.end(screenBrightnessSettingLimitsToken);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_FOR_VR_SETTING,
- mScreenBrightnessForVrSetting);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.IS_DOUBLE_TAP_WAKE_ENABLED,
mDoubleTapWakeEnabled);
@@ -4708,56 +4571,6 @@ public final class PowerManagerService extends SystemService
}
}
- /**
- * Used by the settings application and brightness control widgets to
- * temporarily override the current screen brightness setting so that the
- * user can observe the effect of an intended settings change without applying
- * it immediately.
- *
- * The override will be canceled when the setting value is next updated.
- *
- * @param brightness The overridden brightness.
- *
- * @see android.provider.Settings.System#SCREEN_BRIGHTNESS
- */
- @Override // Binder call
- public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- /**
- * Used by the settings application and brightness control widgets to
- * temporarily override the current screen auto-brightness adjustment setting so that the
- * user can observe the effect of an intended settings change without applying
- * it immediately.
- *
- * The override will be canceled when the setting value is next updated.
- *
- * @param adj The overridden brightness, or Float.NaN to disable the override.
- *
- * @see android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
- */
- @Override // Binder call
- public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.DEVICE_POWER, null);
-
- final long ident = Binder.clearCallingIdentity();
- try {
- setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
/**
* Used by the phone application to make the attention LED flash when ringing.
*/
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index 9e7ef6539c2bb..fb25cf3f01e0b 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -281,6 +281,68 @@ public class BrightnessMappingStrategyTest {
assertNull(physical);
}
+ @Test
+ public void testStrategiesAdaptToUserDataPoint() {
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
+ DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
+ assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+ res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
+ assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+ }
+
+ private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) {
+ // Save out all of the initial brightness data for comparison after reset.
+ float[] initialBrightnessLevels = new float[LUX_LEVELS.length];
+ for (int i = 0; i < LUX_LEVELS.length; i++) {
+ initialBrightnessLevels[i] = strategy.getBrightness(LUX_LEVELS[i]);
+ }
+
+ // Add a data point in the middle of the curve where the user has set the brightness max
+ final int idx = LUX_LEVELS.length / 2;
+ strategy.addUserDataPoint(LUX_LEVELS[idx], 1.0f);
+
+ // Then make sure that all control points after the middle lux level are also set to max...
+ for (int i = idx; i < LUX_LEVELS.length; i++) {
+ assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.01 /*tolerance*/);
+ }
+
+ // ...and that all control points before the middle lux level are strictly less than the
+ // previous one still.
+ float prevBrightness = strategy.getBrightness(LUX_LEVELS[idx]);
+ for (int i = idx - 1; i >= 0; i--) {
+ float brightness = strategy.getBrightness(LUX_LEVELS[i]);
+ assertTrue("Brightness levels must be monotonic after adapting to user data",
+ prevBrightness >= brightness);
+ prevBrightness = brightness;
+ }
+
+ // Now reset the curve and make sure we go back to the initial brightness levels recorded
+ // before adding the user data point.
+ strategy.clearUserDataPoints();
+ for (int i = 0; i < LUX_LEVELS.length; i++) {
+ assertEquals(initialBrightnessLevels[i], strategy.getBrightness(LUX_LEVELS[i]),
+ 0.01 /*tolerance*/);
+ }
+
+ // Now set the middle of the lux range to something just above the minimum.
+ final float minBrightness = strategy.getBrightness(LUX_LEVELS[0]);
+ strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.01f);
+
+ // Then make sure the curve is still monotonic.
+ prevBrightness = 0f;
+ for (float lux : LUX_LEVELS) {
+ float brightness = strategy.getBrightness(lux);
+ assertTrue("Brightness levels must be monotonic after adapting to user data",
+ prevBrightness <= brightness);
+ prevBrightness = brightness;
+ }
+
+ // And that the lowest lux level still gives the absolute minimum brightness. This should
+ // be true assuming that there are more than two lux levels in the curve since we picked a
+ // brightness just barely above the minimum for the middle of the curve.
+ assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.001 /*tolerance*/);
+ }
+
private static float[] toFloatArray(int[] vals) {
float[] newVals = new float[vals.length];
for (int i = 0; i < vals.length; i++) {