Merge "Add low-power/thermal checks to highBrightnessMode" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
77a21b7099
@@ -68,6 +68,7 @@ class AutomaticBrightnessController {
|
|||||||
private static final int MSG_INVALIDATE_SHORT_TERM_MODEL = 3;
|
private static final int MSG_INVALIDATE_SHORT_TERM_MODEL = 3;
|
||||||
private static final int MSG_UPDATE_FOREGROUND_APP = 4;
|
private static final int MSG_UPDATE_FOREGROUND_APP = 4;
|
||||||
private static final int MSG_UPDATE_FOREGROUND_APP_SYNC = 5;
|
private static final int MSG_UPDATE_FOREGROUND_APP_SYNC = 5;
|
||||||
|
private static final int MSG_RUN_UPDATE = 6;
|
||||||
|
|
||||||
// Length of the ambient light horizon used to calculate the long term estimate of ambient
|
// Length of the ambient light horizon used to calculate the long term estimate of ambient
|
||||||
// light.
|
// light.
|
||||||
@@ -360,6 +361,13 @@ class AutomaticBrightnessController {
|
|||||||
return mBrightnessMapper.getDefaultConfig();
|
return mBrightnessMapper.getDefaultConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force recalculate of the state of automatic brightness.
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
mHandler.sendEmptyMessage(MSG_RUN_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean setDisplayPolicy(int policy) {
|
private boolean setDisplayPolicy(int policy) {
|
||||||
if (mDisplayPolicy == policy) {
|
if (mDisplayPolicy == policy) {
|
||||||
return false;
|
return false;
|
||||||
@@ -910,6 +918,10 @@ class AutomaticBrightnessController {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
case MSG_RUN_UPDATE:
|
||||||
|
updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
|
||||||
|
break;
|
||||||
|
|
||||||
case MSG_UPDATE_AMBIENT_LUX:
|
case MSG_UPDATE_AMBIENT_LUX:
|
||||||
updateAmbientLux();
|
updateAmbientLux();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.android.server.display.config.NitsMap;
|
|||||||
import com.android.server.display.config.Point;
|
import com.android.server.display.config.Point;
|
||||||
import com.android.server.display.config.RefreshRateRange;
|
import com.android.server.display.config.RefreshRateRange;
|
||||||
import com.android.server.display.config.SensorDetails;
|
import com.android.server.display.config.SensorDetails;
|
||||||
|
import com.android.server.display.config.ThermalStatus;
|
||||||
import com.android.server.display.config.XmlParser;
|
import com.android.server.display.config.XmlParser;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
@@ -657,6 +658,8 @@ public class DisplayDeviceConfig {
|
|||||||
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
|
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
|
||||||
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
|
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
|
||||||
mHbmData.timeMinMillis = hbmTiming.getTimeMinSecs_all().longValue() * 1000;
|
mHbmData.timeMinMillis = hbmTiming.getTimeMinSecs_all().longValue() * 1000;
|
||||||
|
mHbmData.thermalStatusLimit = convertThermalStatus(hbm.getThermalStatusLimit_all());
|
||||||
|
mHbmData.allowInLowPowerMode = hbm.getAllowInLowPowerMode_all();
|
||||||
final RefreshRateRange rr = hbm.getRefreshRate_all();
|
final RefreshRateRange rr = hbm.getRefreshRate_all();
|
||||||
if (rr != null) {
|
if (rr != null) {
|
||||||
final float min = rr.getMinimum().floatValue();
|
final float min = rr.getMinimum().floatValue();
|
||||||
@@ -743,6 +746,31 @@ public class DisplayDeviceConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
|
||||||
|
if (value == null) {
|
||||||
|
return PowerManager.THERMAL_STATUS_NONE;
|
||||||
|
}
|
||||||
|
switch (value) {
|
||||||
|
case none:
|
||||||
|
return PowerManager.THERMAL_STATUS_NONE;
|
||||||
|
case light:
|
||||||
|
return PowerManager.THERMAL_STATUS_LIGHT;
|
||||||
|
case moderate:
|
||||||
|
return PowerManager.THERMAL_STATUS_MODERATE;
|
||||||
|
case severe:
|
||||||
|
return PowerManager.THERMAL_STATUS_SEVERE;
|
||||||
|
case critical:
|
||||||
|
return PowerManager.THERMAL_STATUS_CRITICAL;
|
||||||
|
case emergency:
|
||||||
|
return PowerManager.THERMAL_STATUS_EMERGENCY;
|
||||||
|
case shutdown:
|
||||||
|
return PowerManager.THERMAL_STATUS_SHUTDOWN;
|
||||||
|
default:
|
||||||
|
Slog.wtf(TAG, "Unexpected Thermal Status: " + value);
|
||||||
|
return PowerManager.THERMAL_STATUS_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class SensorData {
|
static class SensorData {
|
||||||
public String type;
|
public String type;
|
||||||
public String name;
|
public String name;
|
||||||
@@ -781,6 +809,12 @@ public class DisplayDeviceConfig {
|
|||||||
/** Brightness level at which we transition from normal to high-brightness. */
|
/** Brightness level at which we transition from normal to high-brightness. */
|
||||||
public float transitionPoint;
|
public float transitionPoint;
|
||||||
|
|
||||||
|
/** Enable HBM only if the thermal status is not higher than this. */
|
||||||
|
public @PowerManager.ThermalStatus int thermalStatusLimit;
|
||||||
|
|
||||||
|
/** Whether HBM is allowed when {@code Settings.Global.LOW_POWER_MODE} is active. */
|
||||||
|
public boolean allowInLowPowerMode;
|
||||||
|
|
||||||
/** Time window for HBM. */
|
/** Time window for HBM. */
|
||||||
public long timeWindowMillis;
|
public long timeWindowMillis;
|
||||||
|
|
||||||
@@ -792,13 +826,16 @@ public class DisplayDeviceConfig {
|
|||||||
|
|
||||||
HighBrightnessModeData() {}
|
HighBrightnessModeData() {}
|
||||||
|
|
||||||
HighBrightnessModeData(float minimumLux, float transitionPoint,
|
HighBrightnessModeData(float minimumLux, float transitionPoint, long timeWindowMillis,
|
||||||
long timeWindowMillis, long timeMaxMillis, long timeMinMillis) {
|
long timeMaxMillis, long timeMinMillis,
|
||||||
|
@PowerManager.ThermalStatus int thermalStatusLimit, boolean allowInLowPowerMode) {
|
||||||
this.minimumLux = minimumLux;
|
this.minimumLux = minimumLux;
|
||||||
this.transitionPoint = transitionPoint;
|
this.transitionPoint = transitionPoint;
|
||||||
this.timeWindowMillis = timeWindowMillis;
|
this.timeWindowMillis = timeWindowMillis;
|
||||||
this.timeMaxMillis = timeMaxMillis;
|
this.timeMaxMillis = timeMaxMillis;
|
||||||
this.timeMinMillis = timeMinMillis;
|
this.timeMinMillis = timeMinMillis;
|
||||||
|
this.thermalStatusLimit = thermalStatusLimit;
|
||||||
|
this.allowInLowPowerMode = allowInLowPowerMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -807,10 +844,12 @@ public class DisplayDeviceConfig {
|
|||||||
*/
|
*/
|
||||||
public void copyTo(@NonNull HighBrightnessModeData other) {
|
public void copyTo(@NonNull HighBrightnessModeData other) {
|
||||||
other.minimumLux = minimumLux;
|
other.minimumLux = minimumLux;
|
||||||
other.transitionPoint = transitionPoint;
|
|
||||||
other.timeWindowMillis = timeWindowMillis;
|
other.timeWindowMillis = timeWindowMillis;
|
||||||
other.timeMaxMillis = timeMaxMillis;
|
other.timeMaxMillis = timeMaxMillis;
|
||||||
other.timeMinMillis = timeMinMillis;
|
other.timeMinMillis = timeMinMillis;
|
||||||
|
other.transitionPoint = transitionPoint;
|
||||||
|
other.thermalStatusLimit = thermalStatusLimit;
|
||||||
|
other.allowInLowPowerMode = allowInLowPowerMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -821,6 +860,8 @@ public class DisplayDeviceConfig {
|
|||||||
+ ", timeWindow: " + timeWindowMillis + "ms"
|
+ ", timeWindow: " + timeWindowMillis + "ms"
|
||||||
+ ", timeMax: " + timeMaxMillis + "ms"
|
+ ", timeMax: " + timeMaxMillis + "ms"
|
||||||
+ ", timeMin: " + timeMinMillis + "ms"
|
+ ", timeMin: " + timeMinMillis + "ms"
|
||||||
|
+ ", thermalStatusLimit: " + thermalStatusLimit
|
||||||
|
+ ", allowInLowPowerMode: " + allowInLowPowerMode
|
||||||
+ "} ";
|
+ "} ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1518,7 +1518,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
|||||||
() -> {
|
() -> {
|
||||||
sendUpdatePowerStateLocked();
|
sendUpdatePowerStateLocked();
|
||||||
mHandler.post(mOnBrightnessChangeRunnable);
|
mHandler.post(mOnBrightnessChangeRunnable);
|
||||||
});
|
// TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
|
||||||
|
mAutomaticBrightnessController.update();
|
||||||
|
}, mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void blockScreenOn() {
|
private void blockScreenOn() {
|
||||||
|
|||||||
@@ -16,11 +16,21 @@
|
|||||||
|
|
||||||
package com.android.server.display;
|
package com.android.server.display;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.hardware.display.BrightnessInfo;
|
import android.hardware.display.BrightnessInfo;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.IThermalEventListener;
|
||||||
|
import android.os.IThermalService;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.os.Temperature;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.TimeUtils;
|
import android.util.TimeUtils;
|
||||||
import android.view.SurfaceControlHdrLayerInfoListener;
|
import android.view.SurfaceControlHdrLayerInfoListener;
|
||||||
@@ -52,6 +62,10 @@ class HighBrightnessModeController {
|
|||||||
private final Runnable mHbmChangeCallback;
|
private final Runnable mHbmChangeCallback;
|
||||||
private final Runnable mRecalcRunnable;
|
private final Runnable mRecalcRunnable;
|
||||||
private final Clock mClock;
|
private final Clock mClock;
|
||||||
|
private final SkinThermalStatusObserver mSkinThermalStatusObserver;
|
||||||
|
private final Context mContext;
|
||||||
|
private final SettingsObserver mSettingsObserver;
|
||||||
|
private final Injector mInjector;
|
||||||
|
|
||||||
private SurfaceControlHdrLayerInfoListener mHdrListener;
|
private SurfaceControlHdrLayerInfoListener mHdrListener;
|
||||||
private HighBrightnessModeData mHbmData;
|
private HighBrightnessModeData mHbmData;
|
||||||
@@ -63,6 +77,8 @@ class HighBrightnessModeController {
|
|||||||
private float mAutoBrightness;
|
private float mAutoBrightness;
|
||||||
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||||
private boolean mIsHdrLayerPresent = false;
|
private boolean mIsHdrLayerPresent = false;
|
||||||
|
private boolean mIsThermalStatusWithinLimit = true;
|
||||||
|
private boolean mIsBlockedByLowPowerMode = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If HBM is currently running, this is the start time for the current HBM session.
|
* If HBM is currently running, this is the start time for the current HBM session.
|
||||||
@@ -72,29 +88,33 @@ class HighBrightnessModeController {
|
|||||||
/**
|
/**
|
||||||
* List of previous HBM-events ordered from most recent to least recent.
|
* List of previous HBM-events ordered from most recent to least recent.
|
||||||
* Meant to store only the events that fall into the most recent
|
* Meant to store only the events that fall into the most recent
|
||||||
* {@link mHbmData.timeWindowSecs}.
|
* {@link mHbmData.timeWindowMillis}.
|
||||||
*/
|
*/
|
||||||
private LinkedList<HbmEvent> mEvents = new LinkedList<>();
|
private LinkedList<HbmEvent> mEvents = new LinkedList<>();
|
||||||
|
|
||||||
HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin,
|
HighBrightnessModeController(Handler handler, IBinder displayToken, float brightnessMin,
|
||||||
float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback) {
|
float brightnessMax, HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
|
||||||
this(SystemClock::uptimeMillis, handler, displayToken, brightnessMin, brightnessMax,
|
Context context) {
|
||||||
hbmData, hbmChangeCallback);
|
this(new Injector(), handler, displayToken, brightnessMin, brightnessMax,
|
||||||
|
hbmData, hbmChangeCallback, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
HighBrightnessModeController(Clock clock, Handler handler, IBinder displayToken,
|
HighBrightnessModeController(Injector injector, Handler handler, IBinder displayToken,
|
||||||
float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
|
float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
|
||||||
Runnable hbmChangeCallback) {
|
Runnable hbmChangeCallback, Context context) {
|
||||||
mClock = clock;
|
mInjector = injector;
|
||||||
|
mClock = injector.getClock();
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mBrightnessMin = brightnessMin;
|
mBrightnessMin = brightnessMin;
|
||||||
mBrightnessMax = brightnessMax;
|
mBrightnessMax = brightnessMax;
|
||||||
mHbmChangeCallback = hbmChangeCallback;
|
mHbmChangeCallback = hbmChangeCallback;
|
||||||
|
mContext = context;
|
||||||
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
mAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||||
mRecalcRunnable = this::recalculateTimeAllowance;
|
mRecalcRunnable = this::recalculateTimeAllowance;
|
||||||
mHdrListener = new HdrListener();
|
mHdrListener = new HdrListener();
|
||||||
|
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
|
||||||
|
mSettingsObserver = new SettingsObserver(mHandler);
|
||||||
resetHbmData(displayToken, hbmData);
|
resetHbmData(displayToken, hbmData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,14 +198,26 @@ class HighBrightnessModeController {
|
|||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
registerHdrListener(null /*displayToken*/);
|
registerHdrListener(null /*displayToken*/);
|
||||||
|
mSkinThermalStatusObserver.stopObserving();
|
||||||
|
mSettingsObserver.stopObserving();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) {
|
void resetHbmData(IBinder displayToken, HighBrightnessModeData hbmData) {
|
||||||
mHbmData = hbmData;
|
mHbmData = hbmData;
|
||||||
unregisterHdrListener();
|
unregisterHdrListener();
|
||||||
|
mSkinThermalStatusObserver.stopObserving();
|
||||||
|
mSettingsObserver.stopObserving();
|
||||||
if (deviceSupportsHbm()) {
|
if (deviceSupportsHbm()) {
|
||||||
registerHdrListener(displayToken);
|
registerHdrListener(displayToken);
|
||||||
recalculateTimeAllowance();
|
recalculateTimeAllowance();
|
||||||
|
if (mHbmData.thermalStatusLimit > PowerManager.THERMAL_STATUS_NONE) {
|
||||||
|
mIsThermalStatusWithinLimit = true;
|
||||||
|
mSkinThermalStatusObserver.startObserving();
|
||||||
|
}
|
||||||
|
if (!mHbmData.allowInLowPowerMode) {
|
||||||
|
mIsBlockedByLowPowerMode = false;
|
||||||
|
mSettingsObserver.startObserving();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,6 +240,8 @@ class HighBrightnessModeController {
|
|||||||
pw.println(" mBrightnessMin=" + mBrightnessMin);
|
pw.println(" mBrightnessMin=" + mBrightnessMin);
|
||||||
pw.println(" mBrightnessMax=" + mBrightnessMax);
|
pw.println(" mBrightnessMax=" + mBrightnessMax);
|
||||||
pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
|
pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
|
||||||
|
pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
|
||||||
|
pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
|
||||||
pw.println(" mEvents=");
|
pw.println(" mEvents=");
|
||||||
final long currentTime = mClock.uptimeMillis();
|
final long currentTime = mClock.uptimeMillis();
|
||||||
long lastStartTime = currentTime;
|
long lastStartTime = currentTime;
|
||||||
@@ -221,6 +255,8 @@ class HighBrightnessModeController {
|
|||||||
}
|
}
|
||||||
lastStartTime = dumpHbmEvent(pw, event);
|
lastStartTime = dumpHbmEvent(pw, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSkinThermalStatusObserver.dump(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
|
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
|
||||||
@@ -234,7 +270,8 @@ class HighBrightnessModeController {
|
|||||||
|
|
||||||
private boolean isCurrentlyAllowed() {
|
private boolean isCurrentlyAllowed() {
|
||||||
return mIsHdrLayerPresent
|
return mIsHdrLayerPresent
|
||||||
|| (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange);
|
|| (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange
|
||||||
|
&& mIsThermalStatusWithinLimit && !mIsBlockedByLowPowerMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean deviceSupportsHbm() {
|
private boolean deviceSupportsHbm() {
|
||||||
@@ -327,6 +364,12 @@ class HighBrightnessModeController {
|
|||||||
+ ", remainingAllowedTime: " + remainingTime
|
+ ", remainingAllowedTime: " + remainingTime
|
||||||
+ ", isLuxHigh: " + mIsInAllowedAmbientRange
|
+ ", isLuxHigh: " + mIsInAllowedAmbientRange
|
||||||
+ ", isHBMCurrentlyAllowed: " + isCurrentlyAllowed()
|
+ ", isHBMCurrentlyAllowed: " + isCurrentlyAllowed()
|
||||||
|
+ ", isHdrLayerPresent: " + mIsHdrLayerPresent
|
||||||
|
+ ", isAutoBrightnessEnabled: " + mIsAutoBrightnessEnabled
|
||||||
|
+ ", mIsTimeAvailable: " + mIsTimeAvailable
|
||||||
|
+ ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange
|
||||||
|
+ ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit
|
||||||
|
+ ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode
|
||||||
+ ", brightness: " + mAutoBrightness
|
+ ", brightness: " + mAutoBrightness
|
||||||
+ ", RunningStartTimeMillis: " + mRunningStartTimeMillis
|
+ ", RunningStartTimeMillis: " + mRunningStartTimeMillis
|
||||||
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
|
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
|
||||||
@@ -337,8 +380,11 @@ class HighBrightnessModeController {
|
|||||||
mHandler.removeCallbacks(mRecalcRunnable);
|
mHandler.removeCallbacks(mRecalcRunnable);
|
||||||
mHandler.postAtTime(mRecalcRunnable, nextTimeout + 1);
|
mHandler.postAtTime(mRecalcRunnable, nextTimeout + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state of the world
|
// Update the state of the world
|
||||||
|
updateHbmMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateHbmMode() {
|
||||||
int newHbmMode = calculateHighBrightnessMode();
|
int newHbmMode = calculateHighBrightnessMode();
|
||||||
if (mHbmMode != newHbmMode) {
|
if (mHbmMode != newHbmMode) {
|
||||||
mHbmMode = newHbmMode;
|
mHbmMode = newHbmMode;
|
||||||
@@ -409,4 +455,141 @@ class HighBrightnessModeController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
|
||||||
|
private final Injector mInjector;
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
|
private IThermalService mThermalService;
|
||||||
|
private boolean mStarted;
|
||||||
|
|
||||||
|
SkinThermalStatusObserver(Injector injector, Handler handler) {
|
||||||
|
mInjector = injector;
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyThrottling(Temperature temp) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "New thermal throttling status "
|
||||||
|
+ ", current thermal status = " + temp.getStatus()
|
||||||
|
+ ", threshold = " + mHbmData.thermalStatusLimit);
|
||||||
|
}
|
||||||
|
mHandler.post(() -> {
|
||||||
|
mIsThermalStatusWithinLimit = temp.getStatus() <= mHbmData.thermalStatusLimit;
|
||||||
|
// This recalculates HbmMode and runs mHbmChangeCallback if the mode has changed
|
||||||
|
updateHbmMode();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void startObserving() {
|
||||||
|
if (mStarted) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Thermal status observer already started");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mThermalService = mInjector.getThermalService();
|
||||||
|
if (mThermalService == null) {
|
||||||
|
Slog.w(TAG, "Could not observe thermal status. Service not available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// We get a callback immediately upon registering so there's no need to query
|
||||||
|
// for the current value.
|
||||||
|
mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
|
||||||
|
mStarted = true;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to register thermal status listener", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopObserving() {
|
||||||
|
mIsThermalStatusWithinLimit = true;
|
||||||
|
if (!mStarted) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Stop skipped because thermal status observer not started");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mThermalService.unregisterThermalEventListener(this);
|
||||||
|
mStarted = false;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to unregister thermal status listener", e);
|
||||||
|
}
|
||||||
|
mThermalService = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(PrintWriter writer) {
|
||||||
|
writer.println(" SkinThermalStatusObserver:");
|
||||||
|
writer.println(" mStarted: " + mStarted);
|
||||||
|
if (mThermalService != null) {
|
||||||
|
writer.println(" ThermalService available");
|
||||||
|
} else {
|
||||||
|
writer.println(" ThermalService not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class SettingsObserver extends ContentObserver {
|
||||||
|
private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(
|
||||||
|
Settings.Global.LOW_POWER_MODE);
|
||||||
|
private boolean mStarted;
|
||||||
|
|
||||||
|
SettingsObserver(Handler handler) {
|
||||||
|
super(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange, Uri uri) {
|
||||||
|
updateLowPower();
|
||||||
|
}
|
||||||
|
|
||||||
|
void startObserving() {
|
||||||
|
if (!mStarted) {
|
||||||
|
mContext.getContentResolver().registerContentObserver(mLowPowerModeSetting,
|
||||||
|
false /*notifyForDescendants*/, this, UserHandle.USER_ALL);
|
||||||
|
mStarted = true;
|
||||||
|
updateLowPower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopObserving() {
|
||||||
|
mIsBlockedByLowPowerMode = false;
|
||||||
|
if (mStarted) {
|
||||||
|
mContext.getContentResolver().unregisterContentObserver(this);
|
||||||
|
mStarted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLowPower() {
|
||||||
|
final boolean isLowPowerMode = isLowPowerMode();
|
||||||
|
if (isLowPowerMode == mIsBlockedByLowPowerMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Settings.Global.LOW_POWER_MODE enabled: " + isLowPowerMode);
|
||||||
|
}
|
||||||
|
mIsBlockedByLowPowerMode = isLowPowerMode;
|
||||||
|
// this recalculates HbmMode and runs mHbmChangeCallback if the mode has changed
|
||||||
|
updateHbmMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLowPowerMode() {
|
||||||
|
return Settings.Global.getInt(
|
||||||
|
mContext.getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Injector {
|
||||||
|
public Clock getClock() {
|
||||||
|
return SystemClock::uptimeMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IThermalService getThermalService() {
|
||||||
|
return IThermalService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.THERMAL_SERVICE));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,16 @@
|
|||||||
<xs:annotation name="nullable"/>
|
<xs:annotation name="nullable"/>
|
||||||
<xs:annotation name="final"/>
|
<xs:annotation name="final"/>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
<!-- The highest (most severe) thermal status at which high-brightness-mode is allowed
|
||||||
|
to operate. -->
|
||||||
|
<xs:element name="thermalStatusLimit" type="thermalStatus" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:annotation name="nonnull"/>
|
||||||
|
<xs:annotation name="final"/>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="allowInLowPowerMode" type="xs:boolean" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:annotation name="nonnull"/>
|
||||||
|
<xs:annotation name="final"/>
|
||||||
|
</xs:element>
|
||||||
</xs:all>
|
</xs:all>
|
||||||
<xs:attribute name="enabled" type="xs:boolean" use="optional"/>
|
<xs:attribute name="enabled" type="xs:boolean" use="optional"/>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
@@ -102,6 +112,19 @@
|
|||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<!-- Maps to PowerManager.THERMAL_STATUS_* values. -->
|
||||||
|
<xs:simpleType name="thermalStatus">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="none"/>
|
||||||
|
<xs:enumeration value="light"/>
|
||||||
|
<xs:enumeration value="moderate"/>
|
||||||
|
<xs:enumeration value="severe"/>
|
||||||
|
<xs:enumeration value="critical"/>
|
||||||
|
<xs:enumeration value="emergency"/>
|
||||||
|
<xs:enumeration value="shutdown"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:complexType name="nitsMap">
|
<xs:complexType name="nitsMap">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
|
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
|
||||||
|
|||||||
@@ -42,14 +42,18 @@ package com.android.server.display.config {
|
|||||||
|
|
||||||
public class HighBrightnessMode {
|
public class HighBrightnessMode {
|
||||||
ctor public HighBrightnessMode();
|
ctor public HighBrightnessMode();
|
||||||
|
method @NonNull public final boolean getAllowInLowPowerMode_all();
|
||||||
method public boolean getEnabled();
|
method public boolean getEnabled();
|
||||||
method @NonNull public final java.math.BigDecimal getMinimumLux_all();
|
method @NonNull public final java.math.BigDecimal getMinimumLux_all();
|
||||||
method @Nullable public final com.android.server.display.config.RefreshRateRange getRefreshRate_all();
|
method @Nullable public final com.android.server.display.config.RefreshRateRange getRefreshRate_all();
|
||||||
|
method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatusLimit_all();
|
||||||
method public com.android.server.display.config.HbmTiming getTiming_all();
|
method public com.android.server.display.config.HbmTiming getTiming_all();
|
||||||
method @NonNull public final java.math.BigDecimal getTransitionPoint_all();
|
method @NonNull public final java.math.BigDecimal getTransitionPoint_all();
|
||||||
|
method public final void setAllowInLowPowerMode_all(@NonNull boolean);
|
||||||
method public void setEnabled(boolean);
|
method public void setEnabled(boolean);
|
||||||
method public final void setMinimumLux_all(@NonNull java.math.BigDecimal);
|
method public final void setMinimumLux_all(@NonNull java.math.BigDecimal);
|
||||||
method public final void setRefreshRate_all(@Nullable com.android.server.display.config.RefreshRateRange);
|
method public final void setRefreshRate_all(@Nullable com.android.server.display.config.RefreshRateRange);
|
||||||
|
method public final void setThermalStatusLimit_all(@NonNull com.android.server.display.config.ThermalStatus);
|
||||||
method public void setTiming_all(com.android.server.display.config.HbmTiming);
|
method public void setTiming_all(com.android.server.display.config.HbmTiming);
|
||||||
method public final void setTransitionPoint_all(@NonNull java.math.BigDecimal);
|
method public final void setTransitionPoint_all(@NonNull java.math.BigDecimal);
|
||||||
}
|
}
|
||||||
@@ -85,6 +89,17 @@ package com.android.server.display.config {
|
|||||||
method public final void setType(@Nullable String);
|
method public final void setType(@Nullable String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ThermalStatus {
|
||||||
|
method public String getRawName();
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus critical;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus emergency;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus light;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus moderate;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus none;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus severe;
|
||||||
|
enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
public class XmlParser {
|
public class XmlParser {
|
||||||
ctor public XmlParser();
|
ctor public XmlParser();
|
||||||
method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|||||||
@@ -20,22 +20,43 @@ import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
|||||||
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
|
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.eq;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IThermalEventListener;
|
||||||
|
import android.os.IThermalService;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.os.Temperature;
|
||||||
|
import android.os.Temperature.ThrottlingStatus;
|
||||||
import android.os.test.TestLooper;
|
import android.os.test.TestLooper;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.internal.util.test.FakeSettingsProvider;
|
||||||
|
import com.android.internal.util.test.FakeSettingsProviderRule;
|
||||||
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
|
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
|
||||||
|
import com.android.server.display.HighBrightnessModeController.Injector;
|
||||||
import com.android.server.testutils.OffsettableClock;
|
import com.android.server.testutils.OffsettableClock;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@@ -47,6 +68,8 @@ public class HighBrightnessModeControllerTest {
|
|||||||
private static final long TIME_WINDOW_MILLIS = 55 * 1000;
|
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_ALLOWED_IN_WINDOW_MILLIS = 12 * 1000;
|
||||||
private static final long TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS = 5 * 1000;
|
private static final long TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS = 5 * 1000;
|
||||||
|
private static final int THERMAL_STATUS_LIMIT = PowerManager.THERMAL_STATUS_SEVERE;
|
||||||
|
private static final boolean ALLOW_IN_LOW_POWER_MODE = false;
|
||||||
|
|
||||||
private static final float DEFAULT_MIN = 0.01f;
|
private static final float DEFAULT_MIN = 0.01f;
|
||||||
private static final float DEFAULT_MAX = 0.80f;
|
private static final float DEFAULT_MAX = 0.80f;
|
||||||
@@ -57,22 +80,30 @@ public class HighBrightnessModeControllerTest {
|
|||||||
private TestLooper mTestLooper;
|
private TestLooper mTestLooper;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private Binder mDisplayToken;
|
private Binder mDisplayToken;
|
||||||
|
private Context mContextSpy;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||||
|
|
||||||
|
@Mock IThermalService mThermalServiceMock;
|
||||||
|
@Mock Injector mInjectorMock;
|
||||||
|
|
||||||
|
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
|
||||||
|
|
||||||
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
|
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
|
||||||
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
|
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
|
||||||
TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS);
|
TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS,
|
||||||
|
THERMAL_STATUS_LIMIT, ALLOW_IN_LOW_POWER_MODE);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mClock = new OffsettableClock.Stopped();
|
MockitoAnnotations.initMocks(this);
|
||||||
mTestLooper = new TestLooper(mClock::now);
|
|
||||||
mDisplayToken = null;
|
mDisplayToken = null;
|
||||||
mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
|
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
|
||||||
@Override
|
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||||
public boolean handleMessage(Message msg) {
|
when(mContextSpy.getContentResolver()).thenReturn(resolver);
|
||||||
return true;
|
|
||||||
}
|
when(mInjectorMock.getThermalService()).thenReturn(mThermalServiceMock);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
@@ -81,15 +112,19 @@ public class HighBrightnessModeControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoHbmData() {
|
public void testNoHbmData() {
|
||||||
|
initHandler(null);
|
||||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||||
mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null,
|
||||||
|
() -> {}, mContextSpy);
|
||||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoHbmData_Enabled() {
|
public void testNoHbmData_Enabled() {
|
||||||
|
initHandler(null);
|
||||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||||
mClock::now, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {});
|
mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null,
|
||||||
|
() -> {}, mContextSpy);
|
||||||
hbmc.setAutoBrightnessEnabled(true);
|
hbmc.setAutoBrightnessEnabled(true);
|
||||||
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
|
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
|
||||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||||
@@ -258,6 +293,54 @@ public class HighBrightnessModeControllerTest {
|
|||||||
assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
|
assertState(hbmc, DEFAULT_MIN, TRANSITION_POINT, HIGH_BRIGHTNESS_MODE_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoHbmInHighThermalState() throws Exception {
|
||||||
|
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||||
|
|
||||||
|
verify(mThermalServiceMock).registerThermalEventListenerWithType(
|
||||||
|
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
|
||||||
|
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
|
||||||
|
|
||||||
|
// Set the thermal status too high.
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
|
||||||
|
|
||||||
|
// Try to go into HBM mode but fail
|
||||||
|
hbmc.setAutoBrightnessEnabled(true);
|
||||||
|
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||||
|
advanceTime(10);
|
||||||
|
|
||||||
|
assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHbmTurnsOffInHighThermalState() throws Exception {
|
||||||
|
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||||
|
|
||||||
|
verify(mThermalServiceMock).registerThermalEventListenerWithType(
|
||||||
|
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
|
||||||
|
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
|
||||||
|
|
||||||
|
// Set the thermal status tolerable
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_LIGHT));
|
||||||
|
|
||||||
|
// Try to go into HBM mode
|
||||||
|
hbmc.setAutoBrightnessEnabled(true);
|
||||||
|
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||||
|
advanceTime(1);
|
||||||
|
|
||||||
|
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
|
||||||
|
|
||||||
|
// Set the thermal status too high and verify we're off.
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
|
||||||
|
advanceTime(10);
|
||||||
|
assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
|
||||||
|
|
||||||
|
// Set the thermal status low again and verify we're back on.
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
|
||||||
|
advanceTime(1);
|
||||||
|
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
|
||||||
|
}
|
||||||
|
|
||||||
private void assertState(HighBrightnessModeController hbmc,
|
private void assertState(HighBrightnessModeController hbmc,
|
||||||
float brightnessMin, float brightnessMax, int hbmMode) {
|
float brightnessMin, float brightnessMax, int hbmMode) {
|
||||||
assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
|
assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
|
||||||
@@ -265,14 +348,35 @@ public class HighBrightnessModeControllerTest {
|
|||||||
assertEquals(hbmMode, hbmc.getHighBrightnessMode());
|
assertEquals(hbmMode, hbmc.getHighBrightnessMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates instance with standard initialization values.
|
|
||||||
private HighBrightnessModeController createDefaultHbm() {
|
private HighBrightnessModeController createDefaultHbm() {
|
||||||
return new HighBrightnessModeController(mClock::now, mHandler, mDisplayToken, DEFAULT_MIN,
|
return createDefaultHbm(null);
|
||||||
DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {});
|
}
|
||||||
|
|
||||||
|
// Creates instance with standard initialization values.
|
||||||
|
private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) {
|
||||||
|
initHandler(clock);
|
||||||
|
return new HighBrightnessModeController(mInjectorMock, mHandler, mDisplayToken, DEFAULT_MIN,
|
||||||
|
DEFAULT_MAX, DEFAULT_HBM_DATA, () -> {}, mContextSpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initHandler(OffsettableClock clock) {
|
||||||
|
mClock = clock != null ? clock : new OffsettableClock.Stopped();
|
||||||
|
when(mInjectorMock.getClock()).thenReturn(mClock::now);
|
||||||
|
mTestLooper = new TestLooper(mClock::now);
|
||||||
|
mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
|
||||||
|
@Override
|
||||||
|
public boolean handleMessage(Message msg) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void advanceTime(long timeMs) {
|
private void advanceTime(long timeMs) {
|
||||||
mClock.fastForward(timeMs);
|
mClock.fastForward(timeMs);
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Temperature getSkinTemp(@ThrottlingStatus int status) {
|
||||||
|
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user