summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/display/BrightnessInfo.aidl19
-rw-r--r--core/java/android/hardware/display/BrightnessInfo.java109
-rw-r--r--core/java/android/hardware/display/DisplayManager.java13
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java18
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl4
-rw-r--r--core/java/android/view/Display.java11
-rw-r--r--core/java/com/android/internal/display/BrightnessSynchronizer.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java79
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java11
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java45
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java78
-rw-r--r--services/core/java/com/android/server/display/HighBrightnessModeController.java65
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java275
14 files changed, 705 insertions, 98 deletions
diff --git a/core/java/android/hardware/display/BrightnessInfo.aidl b/core/java/android/hardware/display/BrightnessInfo.aidl
new file mode 100644
index 000000000000..5da55c34f3b4
--- /dev/null
+++ b/core/java/android/hardware/display/BrightnessInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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 BrightnessInfo;
diff --git a/core/java/android/hardware/display/BrightnessInfo.java b/core/java/android/hardware/display/BrightnessInfo.java
new file mode 100644
index 000000000000..4289860d4e8a
--- /dev/null
+++ b/core/java/android/hardware/display/BrightnessInfo.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 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.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Data about the current brightness state.
+ * {@see android.view.Display.getBrightnessInfo()}
+ *
+ * @hide
+ */
+public final class BrightnessInfo implements Parcelable {
+
+ @IntDef(prefix = {"HIGH_BRIGHTNESS_MODE_"}, value = {
+ HIGH_BRIGHTNESS_MODE_OFF,
+ HIGH_BRIGHTNESS_MODE_SUNLIGHT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface HighBrightnessMode {}
+
+ /**
+ * High brightness mode is OFF. The high brightness range is not currently accessible to the
+ * user.
+ */
+ public static final int HIGH_BRIGHTNESS_MODE_OFF = 0;
+
+ /**
+ * High brightness mode is ON due to high ambient light (sunlight). The high brightness range is
+ * currently accessible to the user.
+ */
+ public static final int HIGH_BRIGHTNESS_MODE_SUNLIGHT = 1;
+
+ /** Brightness */
+ public final float brightness;
+
+ /** Current minimum supported brightness. */
+ public final float brightnessMinimum;
+
+ /** Current maximum supported brightness. */
+ public final float brightnessMaximum;
+
+ /**
+ * Current state of high brightness mode.
+ * Can be any of HIGH_BRIGHTNESS_MODE_* values.
+ */
+ public final int highBrightnessMode;
+
+ public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum,
+ @HighBrightnessMode int highBrightnessMode) {
+ this.brightness = brightness;
+ this.brightnessMinimum = brightnessMinimum;
+ this.brightnessMaximum = brightnessMaximum;
+ this.highBrightnessMode = highBrightnessMode;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(brightness);
+ dest.writeFloat(brightnessMinimum);
+ dest.writeFloat(brightnessMaximum);
+ dest.writeInt(highBrightnessMode);
+ }
+
+ public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR =
+ new Creator<BrightnessInfo>() {
+ @Override
+ public BrightnessInfo createFromParcel(Parcel source) {
+ return new BrightnessInfo(source);
+ }
+
+ @Override
+ public BrightnessInfo[] newArray(int size) {
+ return new BrightnessInfo[size];
+ }
+ };
+
+ private BrightnessInfo(Parcel source) {
+ brightness = source.readFloat();
+ brightnessMinimum = source.readFloat();
+ brightnessMaximum = source.readFloat();
+ highBrightnessMode = source.readInt();
+ }
+
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 6c2d1402b303..de32adb1f545 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -418,6 +418,7 @@ public final class DisplayManager {
EVENT_FLAG_DISPLAY_ADDED,
EVENT_FLAG_DISPLAY_CHANGED,
EVENT_FLAG_DISPLAY_REMOVED,
+ EVENT_FLAG_DISPLAY_BRIGHTNESS
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventsMask {}
@@ -449,6 +450,17 @@ public final class DisplayManager {
*/
public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
+ /**
+ * Event flag to register for a display's brightness changes. This notification is sent
+ * through the {@link DisplayListener#onDisplayChanged} callback method. New brightness
+ * values can be retrieved via {@link android.view.Display#getBrightnessInfo()}.
+ *
+ * @see #registerDisplayListener(DisplayListener, Handler, long)
+ *
+ * @hide
+ */
+ public static final long EVENT_FLAG_DISPLAY_BRIGHTNESS = 1L << 3;
+
/** @hide */
public DisplayManager(Context context) {
mContext = context;
@@ -583,6 +595,7 @@ public final class DisplayManager {
* @see #EVENT_FLAG_DISPLAY_ADDED
* @see #EVENT_FLAG_DISPLAY_CHANGED
* @see #EVENT_FLAG_DISPLAY_REMOVED
+ * @see #EVENT_FLAG_DISPLAY_BRIGHTNESS
* @see #registerDisplayListener(DisplayListener, Handler)
* @see #unregisterDisplayListener
*
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 983a43af0802..df51734bc17d 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -79,6 +79,7 @@ public final class DisplayManagerGlobal {
EVENT_DISPLAY_ADDED,
EVENT_DISPLAY_CHANGED,
EVENT_DISPLAY_REMOVED,
+ EVENT_DISPLAY_BRIGHTNESS_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayEvent {}
@@ -86,6 +87,7 @@ public final class DisplayManagerGlobal {
public static final int EVENT_DISPLAY_ADDED = 1;
public static final int EVENT_DISPLAY_CHANGED = 2;
public static final int EVENT_DISPLAY_REMOVED = 3;
+ public static final int EVENT_DISPLAY_BRIGHTNESS_CHANGED = 4;
@UnsupportedAppUsage
private static DisplayManagerGlobal sInstance;
@@ -665,6 +667,17 @@ public final class DisplayManagerGlobal {
}
/**
+ * Retrieves Brightness Info for the specified display.
+ */
+ public BrightnessInfo getBrightnessInfo(int displayId) {
+ try {
+ return mDm.getBrightnessInfo(displayId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the preferred wide gamut color space for all displays.
* The wide gamut color space is returned from composition pipeline
* based on hardware capability.
@@ -934,6 +947,11 @@ public final class DisplayManagerGlobal {
}
}
break;
+ case EVENT_DISPLAY_BRIGHTNESS_CHANGED:
+ if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0) {
+ mListener.onDisplayChanged(msg.arg1);
+ }
+ break;
case EVENT_DISPLAY_REMOVED:
if ((mEventsMask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
mListener.onDisplayRemoved(msg.arg1);
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 5ca4e0cc657c..2303353ad101 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -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.BrightnessInfo;
import android.hardware.display.Curve;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
@@ -143,6 +144,9 @@ interface IDisplayManager {
// Get the minimum brightness curve.
Curve getMinimumBrightnessCurve();
+ // Get Brightness Information for the specified display.
+ BrightnessInfo getBrightnessInfo(int displayId);
+
// Gets the id of the preferred wide gamut color space for all displays.
// The wide gamut color space is returned from composition pipeline
// based on hardware capability.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index c87db65c9de2..9cb0d1ff2c3f 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -17,6 +17,7 @@
package android.view;
import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
+import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -36,6 +37,7 @@ import android.graphics.ColorSpace;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
+import android.hardware.display.BrightnessInfo;
import android.hardware.display.DeviceProductInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
@@ -730,6 +732,15 @@ public final class Display {
}
/**
+ * @return Brightness information about the display.
+ * @hide
+ */
+ @RequiresPermission(CONTROL_DISPLAY_BRIGHTNESS)
+ public @Nullable BrightnessInfo getBrightnessInfo() {
+ return mGlobal.getBrightnessInfo(mDisplayId);
+ }
+
+ /**
* Gets the size of the display, in pixels.
* Value returned by this method does not necessarily represent the actual raw size
* (native resolution) of the display.
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index 6776c27fc16e..bd908900fccc 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -16,11 +16,11 @@
package com.android.internal.display;
-
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -95,7 +95,7 @@ public class BrightnessSynchronizer {
}
final BrightnessSyncObserver brightnessSyncObserver;
- brightnessSyncObserver = new BrightnessSyncObserver(mHandler);
+ brightnessSyncObserver = new BrightnessSyncObserver();
brightnessSyncObserver.startObserving();
final float currentFloatBrightness = getScreenBrightnessFloat();
@@ -232,47 +232,52 @@ public class BrightnessSynchronizer {
}
}
- private class BrightnessSyncObserver extends ContentObserver {
- /**
- * Creates a content observer.
- * @param handler The handler to run {@link #onChange} on, or null if none.
- */
- BrightnessSyncObserver(Handler handler) {
- super(handler);
- }
+ private class BrightnessSyncObserver {
+ private final DisplayListener mListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {}
- @Override
- public void onChange(boolean selfChange) {
- onChange(selfChange, null);
- }
+ @Override
+ public void onDisplayRemoved(int displayId) {}
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (selfChange) {
- return;
- }
- if (BRIGHTNESS_URI.equals(uri)) {
- int currentBrightness = getScreenBrightnessInt(mContext);
- mHandler.removeMessages(MSG_UPDATE_FLOAT);
- mHandler.obtainMessage(MSG_UPDATE_FLOAT, currentBrightness, 0).sendToTarget();
- } else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
+ @Override
+ public void onDisplayChanged(int displayId) {
float currentFloat = getScreenBrightnessFloat();
int toSend = Float.floatToIntBits(currentFloat);
mHandler.removeMessages(MSG_UPDATE_INT);
mHandler.obtainMessage(MSG_UPDATE_INT, toSend, 0).sendToTarget();
}
- }
+ };
+
+ private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (selfChange) {
+ return;
+ }
+ if (BRIGHTNESS_URI.equals(uri)) {
+ int currentBrightness = getScreenBrightnessInt(mContext);
+ mHandler.removeMessages(MSG_UPDATE_FLOAT);
+ mHandler.obtainMessage(MSG_UPDATE_FLOAT, currentBrightness, 0).sendToTarget();
+ }
+ }
+ };
public void startObserving() {
final ContentResolver cr = mContext.getContentResolver();
- cr.unregisterContentObserver(this);
- cr.registerContentObserver(BRIGHTNESS_URI, false, this, UserHandle.USER_ALL);
- cr.registerContentObserver(BRIGHTNESS_FLOAT_URI, false, this, UserHandle.USER_ALL);
+ cr.unregisterContentObserver(mContentObserver);
+ cr.registerContentObserver(BRIGHTNESS_URI, false, mContentObserver,
+ UserHandle.USER_ALL);
+
+ mDisplayManager.registerDisplayListener(mListener, mHandler,
+ DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
public void stopObserving() {
final ContentResolver cr = mContext.getContentResolver();
- cr.unregisterContentObserver(this);
+ cr.unregisterContentObserver(mContentObserver);
+ mDisplayManager.unregisterDisplayListener(mListener);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 357256cba131..1ad253e7f867 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -24,7 +24,9 @@ import android.animation.ValueAnimator;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
@@ -64,17 +66,11 @@ public class BrightnessController implements ToggleSlider.Listener {
private static final Uri BRIGHTNESS_MODE_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
- private static final Uri BRIGHTNESS_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
- private static final Uri BRIGHTNESS_FLOAT_URI =
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT);
- private final float mDefaultBacklight;
private final float mMinimumBacklightForVr;
private final float mMaximumBacklightForVr;
- private final float mDefaultBacklightForVr;
private final int mDisplayId;
private final Context mContext;
@@ -86,6 +82,20 @@ public class BrightnessController implements ToggleSlider.Listener {
private final Handler mBackgroundHandler;
private final BrightnessObserver mBrightnessObserver;
+ private final DisplayListener mDisplayListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {}
+
+ @Override
+ public void onDisplayRemoved(int displayId) {}
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ mBackgroundHandler.post(mUpdateSliderRunnable);
+ notifyCallbacks();
+ }
+ };
+
private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
new ArrayList<BrightnessStateChangeCallback>();
@@ -94,6 +104,8 @@ public class BrightnessController implements ToggleSlider.Listener {
private boolean mListening;
private boolean mExternalChange;
private boolean mControlValueInitialized;
+ private float mBrightnessMin = PowerManager.BRIGHTNESS_MIN;
+ private float mBrightnessMax = PowerManager.BRIGHTNESS_MAX;
private ValueAnimator mSliderAnimator;
@@ -110,28 +122,19 @@ public class BrightnessController implements ToggleSlider.Listener {
}
@Override
- public void onChange(boolean selfChange) {
- onChange(selfChange, null);
- }
-
- @Override
public void onChange(boolean selfChange, Uri uri) {
if (selfChange) return;
if (BRIGHTNESS_MODE_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
- } else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
- mBackgroundHandler.post(mUpdateSliderRunnable);
} else if (BRIGHTNESS_FOR_VR_FLOAT_URI.equals(uri)) {
mBackgroundHandler.post(mUpdateSliderRunnable);
} else {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
}
- for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
- cb.onBrightnessLevelChanged();
- }
+ notifyCallbacks();
}
public void startObserving() {
@@ -141,19 +144,16 @@ public class BrightnessController implements ToggleSlider.Listener {
BRIGHTNESS_MODE_URI,
false, this, UserHandle.USER_ALL);
cr.registerContentObserver(
- BRIGHTNESS_URI,
- false, this, UserHandle.USER_ALL);
- cr.registerContentObserver(
- BRIGHTNESS_FLOAT_URI,
- false, this, UserHandle.USER_ALL);
- cr.registerContentObserver(
BRIGHTNESS_FOR_VR_FLOAT_URI,
false, this, UserHandle.USER_ALL);
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler,
+ DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
public void stopObserving() {
final ContentResolver cr = mContext.getContentResolver();
cr.unregisterContentObserver(this);
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
}
}
@@ -233,11 +233,15 @@ public class BrightnessController implements ToggleSlider.Listener {
private final Runnable mUpdateSliderRunnable = new Runnable() {
@Override
public void run() {
- final float valFloat;
final boolean inVrMode = mIsVrModeEnabled;
- valFloat = mDisplayManager.getBrightness(mDisplayId);
+ final BrightnessInfo info = mContext.getDisplay().getBrightnessInfo();
+ if (info == null) {
+ return;
+ }
+ mBrightnessMax = info.brightnessMaximum;
+ mBrightnessMin = info.brightnessMinimum;
// Value is passed as intbits, since this is what the message takes.
- final int valueAsIntBits = Float.floatToIntBits(valFloat);
+ final int valueAsIntBits = Float.floatToIntBits(info.brightness);
mHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
inVrMode ? 1 : 0).sendToTarget();
}
@@ -295,13 +299,10 @@ public class BrightnessController implements ToggleSlider.Listener {
mDisplayId = mContext.getDisplayId();
PowerManager pm = context.getSystemService(PowerManager.class);
- mDefaultBacklight = mContext.getDisplay().getBrightnessDefault();
mMinimumBacklightForVr = pm.getBrightnessConstraint(
PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
mMaximumBacklightForVr = pm.getBrightnessConstraint(
PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR);
- mDefaultBacklightForVr = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR);
mDisplayManager = context.getSystemService(DisplayManager.class);
mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
@@ -337,7 +338,6 @@ public class BrightnessController implements ToggleSlider.Listener {
final float minBacklight;
final float maxBacklight;
final int metric;
- final String settingToChange;
if (mIsVrModeEnabled) {
metric = MetricsEvent.ACTION_BRIGHTNESS_FOR_VR;
@@ -347,12 +347,12 @@ public class BrightnessController implements ToggleSlider.Listener {
metric = mAutomatic
? MetricsEvent.ACTION_BRIGHTNESS_AUTO
: MetricsEvent.ACTION_BRIGHTNESS;
- minBacklight = PowerManager.BRIGHTNESS_MIN;
- maxBacklight = PowerManager.BRIGHTNESS_MAX;
+ minBacklight = mBrightnessMin;
+ maxBacklight = mBrightnessMax;
}
- final float valFloat = MathUtils.min(convertGammaToLinearFloat(value,
- minBacklight, maxBacklight),
- 1.0f);
+ final float valFloat = MathUtils.min(
+ convertGammaToLinearFloat(value, minBacklight, maxBacklight),
+ maxBacklight);
if (stopTracking) {
// TODO(brightnessfloat): change to use float value instead.
MetricsLogger.action(mContext, metric,
@@ -403,8 +403,8 @@ public class BrightnessController implements ToggleSlider.Listener {
min = mMinimumBacklightForVr;
max = mMaximumBacklightForVr;
} else {
- min = PowerManager.BRIGHTNESS_MIN;
- max = PowerManager.BRIGHTNESS_MAX;
+ min = mBrightnessMin;
+ max = mBrightnessMax;
}
// convertGammaToLinearFloat returns 0-1
if (BrightnessSynchronizer.floatEquals(brightnessValue,
@@ -439,6 +439,13 @@ public class BrightnessController implements ToggleSlider.Listener {
mSliderAnimator.start();
}
+ private void notifyCallbacks() {
+ final int size = mChangeCallbacks.size();
+ for (int i = 0; i < size; i++) {
+ mChangeCallbacks.get(i).onBrightnessLevelChanged();
+ }
+ }
+
/** Factory for creating a {@link BrightnessController}. */
public static class Factory {
private final Context mContext;
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index ace466acdaf9..2d7145fef69c 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -695,6 +695,17 @@ public class DisplayDeviceConfig {
/** Minimum time that HBM can be on before being enabled. */
public long timeMinMillis;
+ HighBrightnessModeData() {}
+
+ HighBrightnessModeData(float minimumLux, float transitionPoint,
+ long timeWindowMillis, long timeMaxMillis, long timeMinMillis) {
+ this.minimumLux = minimumLux;
+ this.transitionPoint = transitionPoint;
+ this.timeWindowMillis = timeWindowMillis;
+ this.timeMaxMillis = timeMaxMillis;
+ this.timeMinMillis = timeMinMillis;
+ }
+
/**
* Copies the HBM data to the specified parameter instance.
* @param other the instance to copy data to.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 393a4eb83dd6..3f7ec32cb430 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -55,6 +55,7 @@ import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.BrightnessInfo;
import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
@@ -842,8 +843,6 @@ public final class DisplayManagerService extends SystemService {
return overriddenInfo;
}
-
-
return info;
}
@@ -2062,10 +2061,16 @@ public final class DisplayManagerService extends SystemService {
display, mContext);
final DisplayPowerController displayPowerController = new DisplayPowerController(
mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
- mDisplayBlanker, display, mBrightnessTracker, brightnessSetting);
+ mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
+ () -> handleBrightnessChange(display));
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
}
+ private void handleBrightnessChange(LogicalDisplay display) {
+ sendDisplayEventLocked(display.getDisplayIdLocked(),
+ DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED);
+ }
+
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -2219,6 +2224,8 @@ public final class DisplayManagerService extends SystemService {
return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
+ case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
+ return (mask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0;
case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
default:
@@ -2781,6 +2788,25 @@ public final class DisplayManagerService extends SystemService {
}
}
+ @Override
+ public BrightnessInfo getBrightnessInfo(int displayId) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
+ "Permission required to read the display's brightness info.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSyncRoot) {
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
+ if (dpc != null) {
+ return dpc.getBrightnessInfo();
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return null;
+ }
+
@Override // Binder call
public boolean isMinimalPostProcessingRequested(int displayId) {
synchronized (mSyncRoot) {
@@ -3232,4 +3258,17 @@ public final class DisplayManagerService extends SystemService {
}
}
};
+
+ /**
+ * Functional interface for providing time.
+ * TODO(b/184781936): merge with PowerManagerService.Clock
+ */
+ @VisibleForTesting
+ public interface Clock {
+ /**
+ * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
+ */
+ long uptimeMillis();
+ }
+
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 86e4fd00db7f..7c0709e48fa0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -32,6 +32,7 @@ import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
+import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.metrics.LogMaker;
@@ -53,6 +54,7 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
@@ -146,6 +148,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
+ private static final Uri BRIGHTNESS_FLOAT_URI =
+ Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FLOAT);
+
private final Object mLock = new Object();
private final Context mContext;
@@ -215,6 +220,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Whether or not the color fade on screen on / off is enabled.
private final boolean mColorFadeEnabled;
+ @GuardedBy("mCachedBrightnessInfo")
+ private final CachedBrightnessInfo mCachedBrightnessInfo = new CachedBrightnessInfo();
+
// True if we should fade the screen while turning it off, false if we should play
// a stylish color fade animation instead.
private boolean mColorFadeFadesConfig;
@@ -359,6 +367,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private final BrightnessSetting mBrightnessSetting;
+ private final Runnable mOnBrightnessChangeRunnable;
+
// A record of state for skipping brightness ramps.
private int mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -428,7 +438,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
public DisplayPowerController(Context context,
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
- BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting) {
+ BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
+ Runnable onBrightnessChangeRunnable) {
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
mHandler = new DisplayControllerHandler(handler.getLooper());
@@ -446,8 +457,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBlanker = blanker;
mContext = context;
mBrightnessTracker = brightnessTracker;
-
mBrightnessSetting = brightnessSetting;
+ mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
+
PowerManager pm = context.getSystemService(PowerManager.class);
final Resources resources = context.getResources();
@@ -493,6 +505,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mHbmController = createHbmController();
+ // Seed the cached brightness
+ saveBrightnessInfo(getScreenBrightnessSetting());
+
if (mUseSoftwareAutoBrightnessConfig) {
final float dozeScaleFactor = resources.getFraction(
com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
@@ -1163,6 +1178,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
+ // Save out the brightness info now that the brightness state for this iteration has been
+ // finalized and before we send out notifications about the brightness changing.
+ saveBrightnessInfo(brightnessState);
+
if (updateScreenBrightnessSetting) {
// Tell the rest of the system about the new brightness in case we had to change it
// for things like auto-brightness or high-brightness-mode. Note that we do this
@@ -1395,13 +1414,36 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
msg.sendToTarget();
}
+ public BrightnessInfo getBrightnessInfo() {
+ synchronized (mCachedBrightnessInfo) {
+ return new BrightnessInfo(
+ mCachedBrightnessInfo.brightness,
+ mCachedBrightnessInfo.brightnessMin,
+ mCachedBrightnessInfo.brightnessMax,
+ mCachedBrightnessInfo.hbmMode);
+ }
+ }
+
+ private void saveBrightnessInfo(float brightness) {
+ synchronized (mCachedBrightnessInfo) {
+ mCachedBrightnessInfo.brightness = brightness;
+ mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin();
+ mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax();
+ mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode();
+ }
+ }
+
private HighBrightnessModeController createHbmController() {
final DisplayDeviceConfig ddConfig =
mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
final DisplayDeviceConfig.HighBrightnessModeData hbmData =
ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
return new HighBrightnessModeController(mHandler, PowerManager.BRIGHTNESS_MIN,
- PowerManager.BRIGHTNESS_MAX, hbmData, () -> sendUpdatePowerStateLocked());
+ PowerManager.BRIGHTNESS_MAX, hbmData,
+ () -> {
+ sendUpdatePowerStateLocked();
+ mHandler.post(mOnBrightnessChangeRunnable);
+ });
}
private void blockScreenOn() {
@@ -1832,7 +1874,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPendingScreenBrightnessSetting = getScreenBrightnessSetting();
if (userSwitch) {
// Don't treat user switches as user initiated change.
- mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
+ setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.resetShortTermModel();
}
@@ -1871,11 +1913,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private void putScreenBrightnessSetting(float brightnessValue, boolean updateCurrent) {
if (updateCurrent) {
- mCurrentScreenBrightnessSetting = brightnessValue;
+ setCurrentScreenBrightness(brightnessValue);
}
mBrightnessSetting.setBrightness(brightnessValue);
}
+ private void setCurrentScreenBrightness(float brightnessValue) {
+ if (brightnessValue != mCurrentScreenBrightnessSetting) {
+ mCurrentScreenBrightnessSetting = brightnessValue;
+ mHandler.post(mOnBrightnessChangeRunnable);
+ }
+ }
+
private void putAutoBrightnessAdjustmentSetting(float adjustment) {
if (mDisplayId == Display.DEFAULT_DISPLAY) {
mAutoBrightnessAdjustment = adjustment;
@@ -1908,7 +1957,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
return false;
}
- mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
+ setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
@@ -2051,10 +2100,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mPendingProximityDebounceTime="
+ TimeUtils.formatUptime(mPendingProximityDebounceTime));
pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
- pw.println(" mLastUserSetScreenBrightnessFloat=" + mLastUserSetScreenBrightness);
- pw.println(" mPendingScreenBrightnessSettingFloat="
+ pw.println(" mLastUserSetScreenBrightness=" + mLastUserSetScreenBrightness);
+ pw.println(" mPendingScreenBrightnessSetting="
+ mPendingScreenBrightnessSetting);
- pw.println(" mTemporaryScreenBrightnessFloat=" + mTemporaryScreenBrightness);
+ pw.println(" mTemporaryScreenBrightness=" + mTemporaryScreenBrightness);
pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mBrightnessReason=" + mBrightnessReason);
pw.println(" mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
@@ -2097,6 +2146,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.dump(pw);
}
+ if (mHbmController != null) {
+ mHbmController.dump(pw);
+ }
+
pw.println();
if (mDisplayWhiteBalanceController != null) {
mDisplayWhiteBalanceController.dump(pw);
@@ -2425,4 +2478,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
}
+
+ static class CachedBrightnessInfo {
+ public float brightness;
+ public float brightnessMin;
+ public float brightnessMax;
+ public int hbmMode;
+ }
}
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 2e5561dc0aea..e6486bd2a79a 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -16,13 +16,17 @@
package com.android.server.display;
+import android.hardware.display.BrightnessInfo;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
+import com.android.server.display.DisplayManagerService.Clock;
+import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedList;
@@ -45,11 +49,13 @@ class HighBrightnessModeController {
private final Handler mHandler;
private final Runnable mHbmChangeCallback;
private final Runnable mRecalcRunnable;
+ private final Clock mClock;
private boolean mIsInAllowedAmbientRange = false;
private boolean mIsTimeAvailable = false;
private boolean mIsAutoBrightnessEnabled = false;
private float mAutoBrightness;
+ private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
/**
* If HBM is currently running, this is the start time for the current HBM session.
@@ -65,28 +71,25 @@ class HighBrightnessModeController {
HighBrightnessModeController(Handler handler, float brightnessMin, float brightnessMax,
HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
+ this(SystemClock::uptimeMillis, handler, brightnessMin, brightnessMax, hbmData,
+ hbmChangeCallback);
+ }
+
+ @VisibleForTesting
+ HighBrightnessModeController(Clock clock, Handler handler, float brightnessMin,
+ float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
+ mClock = clock;
mHandler = handler;
mBrightnessMin = brightnessMin;
mBrightnessMax = brightnessMax;
mHbmData = hbmData;
mHbmChangeCallback = hbmChangeCallback;
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-
- mRecalcRunnable = () -> {
- boolean oldIsAllowed = isCurrentlyAllowed();
- recalculateTimeAllowance();
- if (oldIsAllowed != isCurrentlyAllowed()) {
- // Our allowed state has changed; tell AutomaticBrightnessController
- // to update the brightness.
- if (mHbmChangeCallback != null) {
- mHbmChangeCallback.run();
- }
- }
- };
+ mRecalcRunnable = this::recalculateTimeAllowance;
}
void setAutoBrightnessEnabled(boolean isEnabled) {
- if (isEnabled == mIsAutoBrightnessEnabled) {
+ if (!deviceSupportsHbm() || isEnabled == mIsAutoBrightnessEnabled) {
return;
}
if (DEBUG) {
@@ -94,6 +97,7 @@ class HighBrightnessModeController {
}
mIsAutoBrightnessEnabled = isEnabled;
mIsInAllowedAmbientRange = false; // reset when auto-brightness switches
+ recalculateTimeAllowance();
}
float getCurrentBrightnessMin() {
@@ -137,7 +141,7 @@ class HighBrightnessModeController {
final boolean wasOldBrightnessHigh = oldAutoBrightness > mHbmData.transitionPoint;
final boolean isNewBrightnessHigh = mAutoBrightness > mHbmData.transitionPoint;
if (wasOldBrightnessHigh != isNewBrightnessHigh) {
- final long currentTime = SystemClock.uptimeMillis();
+ final long currentTime = mClock.uptimeMillis();
if (isNewBrightnessHigh) {
mRunningStartTimeMillis = currentTime;
} else {
@@ -153,6 +157,21 @@ class HighBrightnessModeController {
recalculateTimeAllowance();
}
+ int getHighBrightnessMode() {
+ return mHbmMode;
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println("HighBrightnessModeController:");
+ pw.println(" mBrightnessMin=" + mBrightnessMin);
+ pw.println(" mBrightnessMax=" + mBrightnessMax);
+ pw.println(" mHbmData=" + mHbmData);
+ pw.println(" mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
+ pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
+ pw.println(" mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
+ pw.println(" mAutoBrightness=" + mAutoBrightness);
+ }
+
private boolean isCurrentlyAllowed() {
return mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange;
}
@@ -165,7 +184,7 @@ class HighBrightnessModeController {
* Recalculates the allowable HBM time.
*/
private void recalculateTimeAllowance() {
- final long currentTime = SystemClock.uptimeMillis();
+ final long currentTime = mClock.uptimeMillis();
long timeAlreadyUsed = 0;
// First, lets see how much time we've taken for any currently running
@@ -247,8 +266,22 @@ class HighBrightnessModeController {
if (nextTimeout != -1) {
mHandler.removeCallbacks(mRecalcRunnable);
- mHandler.postAtTime(mRecalcRunnable, nextTimeout);
+ mHandler.postAtTime(mRecalcRunnable, nextTimeout + 1);
+ }
+
+ // Update the state of the world
+ int newHbmMode = calculateHighBrightnessMode();
+ if (mHbmMode != newHbmMode) {
+ mHbmMode = newHbmMode;
+ mHbmChangeCallback.run();
+ }
+ }
+
+ private int calculateHighBrightnessMode() {
+ if (deviceSupportsHbm() && isCurrentlyAllowed()) {
+ return BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
}
+ return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 7cd60284627f..f156779034ab 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -93,9 +93,10 @@ public class DisplayManagerServiceTest {
private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
- private static final long ALL_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ private static final long STANDARD_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
| DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
+
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -764,7 +765,8 @@ public class DisplayManagerServiceTest {
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
+ displayManagerBinderService.registerCallbackWithEventMask(
+ callback, STANDARD_DISPLAY_EVENTS);
waitForIdleHandler(handler);
@@ -793,7 +795,7 @@ public class DisplayManagerServiceTest {
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- long allEventsExceptDisplayAdded = ALL_DISPLAY_EVENTS
+ long allEventsExceptDisplayAdded = STANDARD_DISPLAY_EVENTS
& ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED;
displayManagerBinderService.registerCallbackWithEventMask(callback,
allEventsExceptDisplayAdded);
@@ -862,7 +864,7 @@ public class DisplayManagerServiceTest {
waitForIdleHandler(handler);
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- long allEventsExceptDisplayRemoved = ALL_DISPLAY_EVENTS
+ long allEventsExceptDisplayRemoved = STANDARD_DISPLAY_EVENTS
& ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
displayManagerBinderService.registerCallbackWithEventMask(callback,
allEventsExceptDisplayRemoved);
@@ -1032,7 +1034,8 @@ public class DisplayManagerServiceTest {
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
- displayManagerBinderService.registerCallbackWithEventMask(callback, ALL_DISPLAY_EVENTS);
+ displayManagerBinderService.registerCallbackWithEventMask(
+ callback, STANDARD_DISPLAY_EVENTS);
return callback;
}
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
new file mode 100644
index 000000000000..88a21b4a8fa8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
+import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
+import com.android.server.testutils.OffsettableClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class HighBrightnessModeControllerTest {
+
+ private static final int MINIMUM_LUX = 100;
+ private static final float TRANSITION_POINT = 0.763f;
+ private static final long TIME_WINDOW_MILLIS = 55 * 1000;
+ private static final long TIME_ALLOWED_IN_WINDOW_MILLIS = 12 * 1000;
+ private static final long TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS = 5 * 1000;
+
+ private static final float DEFAULT_MIN = 0.01f;
+ private static final float DEFAULT_MAX = 0.80f;
+
+ private static final float EPSILON = 0.000001f;
+
+ private OffsettableClock mClock;
+ private TestLooper mTestLooper;
+ private Handler mHandler;
+
+ private static final HighBrightnessModeData DEFAULT_HBM_DATA =
+ new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
+ TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS);
+
+ @Before
+ public void setUp() {
+ mClock = new OffsettableClock.Stopped();
+ mTestLooper = new TestLooper(mClock::now);
+ mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ return true;
+ }
+ });
+ }
+
+ /////////////////
+ // Test Methods
+ /////////////////
+
+ @Test
+ public void testNoHbmData() {
+ final HighBrightnessModeController hbmc = new HighBrightnessModeController(
+ mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testNoHbmData_Enabled() {
+ final HighBrightnessModeController hbmc = new HighBrightnessModeController(
+ mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testOffByDefault() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testAutoBrightnessEnabled_NoLux() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testAutoBrightnessEnabled_LowLux() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testAutoBrightnessEnabled_HighLux() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+ }
+
+ @Test
+ public void testAutoBrightnessEnabled_HighLux_ThenDisable() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ hbmc.setAutoBrightnessEnabled(false);
+
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testWithinHighRange_thenOverTime_thenEarnBackTime() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f);
+
+ // Verify we are in HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ // Use up all the time in the window.
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS);
+
+ // Verify we are not out of HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ // Shift time so that the HBM event is at the beginning of the current window
+ advanceTime(TIME_WINDOW_MILLIS - TIME_ALLOWED_IN_WINDOW_MILLIS);
+ // Shift time again so that we are just below the minimum allowable
+ advanceTime(TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS - 1);
+
+ // Verify we are not out of HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ // Advance the necessary millisecond
+ advanceTime(1);
+
+ // Verify we are allowed HBM again.
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+ }
+
+ @Test
+ public void testInHBM_ThenLowLux() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f);
+
+ // Verify we are in HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2);
+
+ // Verify we are in HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ hbmc.onAmbientLuxChange(1);
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2 + 1);
+
+ // Verify we are out of HBM
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+
+ }
+
+ @Test
+ public void testInHBM_TestMultipleEvents_DueToAutoBrightness() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f);
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2);
+
+ // Verify we are in HBM
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT - 0.01f);
+ advanceTime(1);
+
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f);
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2);
+
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ advanceTime(2);
+
+ // Now we should be out again.
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ @Test
+ public void testInHBM_TestMultipleEvents_DueToLux() {
+ final HighBrightnessModeController hbmc = createDefaultHbm();
+
+ hbmc.setAutoBrightnessEnabled(true);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+
+ // Go into HBM for half the allowed window
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 0.01f);
+ advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2);
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ // Move lux below threshold (ending first event);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX - 1);
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT);
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+
+ // Move up some amount of time so that there's still time in the window even after a
+ // second event.
+ advanceTime((TIME_WINDOW_MILLIS - TIME_ALLOWED_IN_WINDOW_MILLIS) / 2);
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+
+ // Go into HBM for just under the second half of allowed window
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ hbmc.onAutoBrightnessChanged(TRANSITION_POINT + 1);
+ advanceTime((TIME_ALLOWED_IN_WINDOW_MILLIS / 2) - 1);
+
+ assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
+
+ // Now exhaust the time
+ advanceTime(2);
+ assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
+ }
+
+ private void assertState(HighBrightnessModeController hbmc,
+ float brightnessMin, float brightnessMax, int hbmMode) {
+ assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
+ assertEquals(brightnessMax, hbmc.getCurrentBrightnessMax(), EPSILON);
+ assertEquals(hbmMode, hbmc.getHighBrightnessMode());
+ }
+
+ // Creates instance with standard initialization values.
+ private HighBrightnessModeController createDefaultHbm() {
+ return new HighBrightnessModeController(mClock::now, mHandler, DEFAULT_MIN, DEFAULT_MAX,
+ DEFAULT_HBM_DATA, () -> {});
+ }
+
+ private void advanceTime(long timeMs) {
+ mClock.fastForward(timeMs);
+ mTestLooper.dispatchAll();
+ }
+}