Merge "Add listener for brightness-specific changes." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
33946ea33f
19
core/java/android/hardware/display/BrightnessInfo.aidl
Normal file
19
core/java/android/hardware/display/BrightnessInfo.aidl
Normal file
@@ -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;
|
||||
109
core/java/android/hardware/display/BrightnessInfo.java
Normal file
109
core/java/android/hardware/display/BrightnessInfo.java
Normal file
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
@@ -664,6 +666,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
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
@@ -729,6 +731,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -109,11 +121,6 @@ public class BrightnessController implements ToggleSlider.Listener {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
onChange(selfChange, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
if (selfChange) return;
|
||||
@@ -121,17 +128,13 @@ public class BrightnessController implements ToggleSlider.Listener {
|
||||
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() {
|
||||
@@ -140,20 +143,17 @@ public class BrightnessController implements ToggleSlider.Listener {
|
||||
cr.registerContentObserver(
|
||||
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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user