Merge changes from topic "brightnessthrottler"
* changes: Add display brightness throttler Add BrightnessThrottler data to display device config Report HBM_ON_SUNLIGHT when display is in hbm mode
This commit is contained in:
committed by
Android (Google) Code Review
commit
f654a3ceb6
@@ -57,6 +57,23 @@ public final class BrightnessInfo implements Parcelable {
|
||||
*/
|
||||
public static final int HIGH_BRIGHTNESS_MODE_HDR = 2;
|
||||
|
||||
@IntDef(prefix = {"BRIGHTNESS_MAX_REASON_"}, value = {
|
||||
BRIGHTNESS_MAX_REASON_NONE,
|
||||
BRIGHTNESS_MAX_REASON_THERMAL
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface BrightnessMaxReason {}
|
||||
|
||||
/**
|
||||
* Maximum brightness is unrestricted.
|
||||
*/
|
||||
public static final int BRIGHTNESS_MAX_REASON_NONE = 0;
|
||||
|
||||
/**
|
||||
* Maximum brightness is restricted due to thermal throttling.
|
||||
*/
|
||||
public static final int BRIGHTNESS_MAX_REASON_THERMAL = 1;
|
||||
|
||||
/** Brightness */
|
||||
public final float brightness;
|
||||
|
||||
@@ -78,21 +95,29 @@ public final class BrightnessInfo implements Parcelable {
|
||||
*/
|
||||
public final int highBrightnessMode;
|
||||
|
||||
/**
|
||||
* The current reason for restricting maximum brightness.
|
||||
* Can be any of BRIGHTNESS_MAX_REASON_* values.
|
||||
*/
|
||||
public final int brightnessMaxReason;
|
||||
|
||||
public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum,
|
||||
@HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint) {
|
||||
@HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint,
|
||||
@BrightnessMaxReason int brightnessMaxReason) {
|
||||
this(brightness, brightness, brightnessMinimum, brightnessMaximum, highBrightnessMode,
|
||||
highBrightnessTransitionPoint);
|
||||
highBrightnessTransitionPoint, brightnessMaxReason);
|
||||
}
|
||||
|
||||
public BrightnessInfo(float brightness, float adjustedBrightness, float brightnessMinimum,
|
||||
float brightnessMaximum, @HighBrightnessMode int highBrightnessMode,
|
||||
float highBrightnessTransitionPoint) {
|
||||
float highBrightnessTransitionPoint, @BrightnessMaxReason int brightnessMaxReason) {
|
||||
this.brightness = brightness;
|
||||
this.adjustedBrightness = adjustedBrightness;
|
||||
this.brightnessMinimum = brightnessMinimum;
|
||||
this.brightnessMaximum = brightnessMaximum;
|
||||
this.highBrightnessMode = highBrightnessMode;
|
||||
this.highBrightnessTransitionPoint = highBrightnessTransitionPoint;
|
||||
this.brightnessMaxReason = brightnessMaxReason;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,6 +135,19 @@ public final class BrightnessInfo implements Parcelable {
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User-friendly string for specified {@link BrightnessMaxReason} parameter.
|
||||
*/
|
||||
public static String briMaxReasonToString(@BrightnessMaxReason int reason) {
|
||||
switch (reason) {
|
||||
case BRIGHTNESS_MAX_REASON_NONE:
|
||||
return "none";
|
||||
case BRIGHTNESS_MAX_REASON_THERMAL:
|
||||
return "thermal";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
@@ -123,6 +161,7 @@ public final class BrightnessInfo implements Parcelable {
|
||||
dest.writeFloat(brightnessMaximum);
|
||||
dest.writeInt(highBrightnessMode);
|
||||
dest.writeFloat(highBrightnessTransitionPoint);
|
||||
dest.writeInt(brightnessMaxReason);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR =
|
||||
@@ -145,6 +184,7 @@ public final class BrightnessInfo implements Parcelable {
|
||||
brightnessMaximum = source.readFloat();
|
||||
highBrightnessMode = source.readInt();
|
||||
highBrightnessTransitionPoint = source.readFloat();
|
||||
brightnessMaxReason = source.readInt();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 android.content.Context;
|
||||
import android.hardware.display.BrightnessInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.IThermalEventListener;
|
||||
import android.os.IThermalService;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.Temperature;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
|
||||
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* This class monitors various conditions, such as skin temperature throttling status, and limits
|
||||
* the allowed brightness range accordingly.
|
||||
*/
|
||||
class BrightnessThrottler {
|
||||
private static final String TAG = "BrightnessThrottler";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int THROTTLING_INVALID = -1;
|
||||
|
||||
private final Injector mInjector;
|
||||
private final Handler mHandler;
|
||||
private BrightnessThrottlingData mThrottlingData;
|
||||
private final Runnable mThrottlingChangeCallback;
|
||||
private final SkinThermalStatusObserver mSkinThermalStatusObserver;
|
||||
private int mThrottlingStatus;
|
||||
private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
|
||||
private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason =
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
|
||||
BrightnessThrottler(Handler handler, BrightnessThrottlingData throttlingData,
|
||||
Runnable throttlingChangeCallback) {
|
||||
this(new Injector(), handler, throttlingData, throttlingChangeCallback);
|
||||
}
|
||||
|
||||
BrightnessThrottler(Injector injector, Handler handler, BrightnessThrottlingData throttlingData,
|
||||
Runnable throttlingChangeCallback) {
|
||||
mInjector = injector;
|
||||
mHandler = handler;
|
||||
mThrottlingData = throttlingData;
|
||||
mThrottlingChangeCallback = throttlingChangeCallback;
|
||||
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
|
||||
|
||||
resetThrottlingData(mThrottlingData);
|
||||
}
|
||||
|
||||
boolean deviceSupportsThrottling() {
|
||||
return mThrottlingData != null;
|
||||
}
|
||||
|
||||
float getBrightnessCap() {
|
||||
return mBrightnessCap;
|
||||
}
|
||||
|
||||
int getBrightnessMaxReason() {
|
||||
return mBrightnessMaxReason;
|
||||
}
|
||||
|
||||
boolean isThrottled() {
|
||||
return mBrightnessMaxReason != BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
mSkinThermalStatusObserver.stopObserving();
|
||||
|
||||
// We're asked to stop throttling, so reset brightness restrictions.
|
||||
mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
|
||||
mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
|
||||
// We set throttling status to an invalid value here so that we act on the first throttling
|
||||
// value received from the thermal service after registration, even if that throttling value
|
||||
// is THROTTLING_NONE.
|
||||
mThrottlingStatus = THROTTLING_INVALID;
|
||||
}
|
||||
|
||||
void resetThrottlingData(BrightnessThrottlingData throttlingData) {
|
||||
stop();
|
||||
mThrottlingData = throttlingData;
|
||||
|
||||
if (deviceSupportsThrottling()) {
|
||||
mSkinThermalStatusObserver.startObserving();
|
||||
}
|
||||
}
|
||||
|
||||
private float verifyAndConstrainBrightnessCap(float brightness) {
|
||||
if (brightness < PowerManager.BRIGHTNESS_MIN) {
|
||||
Slog.e(TAG, "brightness " + brightness + " is lower than the minimum possible "
|
||||
+ "brightness " + PowerManager.BRIGHTNESS_MIN);
|
||||
brightness = PowerManager.BRIGHTNESS_MIN;
|
||||
}
|
||||
|
||||
if (brightness > PowerManager.BRIGHTNESS_MAX) {
|
||||
Slog.e(TAG, "brightness " + brightness + " is higher than the maximum possible "
|
||||
+ "brightness " + PowerManager.BRIGHTNESS_MAX);
|
||||
brightness = PowerManager.BRIGHTNESS_MAX;
|
||||
}
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
private void thermalStatusChanged(@Temperature.ThrottlingStatus int newStatus) {
|
||||
if (mThrottlingStatus != newStatus) {
|
||||
mThrottlingStatus = newStatus;
|
||||
updateThrottling();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThrottling() {
|
||||
if (!deviceSupportsThrottling()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float brightnessCap = PowerManager.BRIGHTNESS_MAX;
|
||||
int brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
|
||||
if (mThrottlingStatus != THROTTLING_INVALID) {
|
||||
// Throttling levels are sorted by increasing severity
|
||||
for (ThrottlingLevel level : mThrottlingData.throttlingLevels) {
|
||||
if (level.thermalStatus <= mThrottlingStatus) {
|
||||
brightnessCap = level.brightness;
|
||||
brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
|
||||
} else {
|
||||
// Throttling levels that are greater than the current status are irrelevant
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mBrightnessCap != brightnessCap || mBrightnessMaxReason != brightnessMaxReason) {
|
||||
mBrightnessCap = verifyAndConstrainBrightnessCap(brightnessCap);
|
||||
mBrightnessMaxReason = brightnessMaxReason;
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "State changed: mBrightnessCap = " + mBrightnessCap
|
||||
+ ", mBrightnessMaxReason = "
|
||||
+ BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason));
|
||||
}
|
||||
|
||||
if (mThrottlingChangeCallback != null) {
|
||||
mThrottlingChangeCallback.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw) {
|
||||
mHandler.runWithScissors(() -> dumpLocal(pw), 1000);
|
||||
}
|
||||
|
||||
private void dumpLocal(PrintWriter pw) {
|
||||
pw.println("BrightnessThrottler:");
|
||||
pw.println(" mThrottlingData=" + mThrottlingData);
|
||||
pw.println(" mThrottlingStatus=" + mThrottlingStatus);
|
||||
pw.println(" mBrightnessCap=" + mBrightnessCap);
|
||||
pw.println(" mBrightnessMaxReason=" +
|
||||
BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason));
|
||||
|
||||
mSkinThermalStatusObserver.dump(pw);
|
||||
}
|
||||
|
||||
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 = " + temp.getStatus());
|
||||
}
|
||||
mHandler.post(() -> {
|
||||
final @Temperature.ThrottlingStatus int status = temp.getStatus();
|
||||
thermalStatusChanged(status);
|
||||
});
|
||||
}
|
||||
|
||||
void startObserving() {
|
||||
if (mStarted) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Thermal status observer already started");
|
||||
}
|
||||
return;
|
||||
}
|
||||
mThermalService = mInjector.getThermalService();
|
||||
if (mThermalService == null) {
|
||||
Slog.e(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() {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Injector {
|
||||
public IThermalService getThermalService() {
|
||||
return IThermalService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.THERMAL_SERVICE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ import android.view.DisplayAddress;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.display.BrightnessSynchronizer;
|
||||
import com.android.server.display.config.BrightnessThresholds;
|
||||
import com.android.server.display.config.BrightnessThrottlingMap;
|
||||
import com.android.server.display.config.BrightnessThrottlingPoint;
|
||||
import com.android.server.display.config.Density;
|
||||
import com.android.server.display.config.DisplayConfiguration;
|
||||
import com.android.server.display.config.DisplayQuirks;
|
||||
@@ -43,6 +45,7 @@ import com.android.server.display.config.Point;
|
||||
import com.android.server.display.config.RefreshRateRange;
|
||||
import com.android.server.display.config.SensorDetails;
|
||||
import com.android.server.display.config.ThermalStatus;
|
||||
import com.android.server.display.config.ThermalThrottling;
|
||||
import com.android.server.display.config.Thresholds;
|
||||
import com.android.server.display.config.XmlParser;
|
||||
|
||||
@@ -145,6 +148,8 @@ public class DisplayDeviceConfig {
|
||||
private DensityMap mDensityMap;
|
||||
private String mLoadedFrom = null;
|
||||
|
||||
private BrightnessThrottlingData mBrightnessThrottlingData;
|
||||
|
||||
private DisplayDeviceConfig(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
@@ -424,6 +429,13 @@ public class DisplayDeviceConfig {
|
||||
return mDensityMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return brightness throttling data configuration data for the display.
|
||||
*/
|
||||
public BrightnessThrottlingData getBrightnessThrottlingData() {
|
||||
return BrightnessThrottlingData.create(mBrightnessThrottlingData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisplayDeviceConfig{"
|
||||
@@ -441,6 +453,7 @@ public class DisplayDeviceConfig {
|
||||
+ ", mQuirks=" + mQuirks
|
||||
+ ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
|
||||
+ ", mHbmData=" + mHbmData
|
||||
+ ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
|
||||
+ ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
|
||||
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
|
||||
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
|
||||
@@ -502,6 +515,7 @@ public class DisplayDeviceConfig {
|
||||
loadBrightnessDefaultFromDdcXml(config);
|
||||
loadBrightnessConstraintsFromConfigXml();
|
||||
loadBrightnessMap(config);
|
||||
loadBrightnessThrottlingMap(config);
|
||||
loadHighBrightnessModeData(config);
|
||||
loadQuirks(config);
|
||||
loadBrightnessRamps(config);
|
||||
@@ -664,6 +678,41 @@ public class DisplayDeviceConfig {
|
||||
constrainNitsAndBacklightArrays();
|
||||
}
|
||||
|
||||
private void loadBrightnessThrottlingMap(DisplayConfiguration config) {
|
||||
final ThermalThrottling throttlingConfig = config.getThermalThrottling();
|
||||
if (throttlingConfig == null) {
|
||||
Slog.i(TAG, "no thermal throttling config found");
|
||||
return;
|
||||
}
|
||||
|
||||
final BrightnessThrottlingMap map = throttlingConfig.getBrightnessThrottlingMap();
|
||||
if (map == null) {
|
||||
Slog.i(TAG, "no brightness throttling map found");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint();
|
||||
// At least 1 point is guaranteed by the display device config schema
|
||||
List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels =
|
||||
new ArrayList<>(points.size());
|
||||
|
||||
boolean badConfig = false;
|
||||
for (BrightnessThrottlingPoint point : points) {
|
||||
ThermalStatus status = point.getThermalStatus();
|
||||
if (!thermalStatusIsValid(status)) {
|
||||
badConfig = true;
|
||||
break;
|
||||
}
|
||||
|
||||
throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel(
|
||||
convertThermalStatus(status), point.getBrightness().floatValue()));
|
||||
}
|
||||
|
||||
if (!badConfig) {
|
||||
mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBrightnessMapFromConfigXml() {
|
||||
// Use the config.xml mapping
|
||||
final Resources res = mContext.getResources();
|
||||
@@ -931,6 +980,25 @@ public class DisplayDeviceConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean thermalStatusIsValid(ThermalStatus value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case none:
|
||||
case light:
|
||||
case moderate:
|
||||
case severe:
|
||||
case critical:
|
||||
case emergency:
|
||||
case shutdown:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
|
||||
if (value == null) {
|
||||
return PowerManager.THERMAL_STATUS_NONE;
|
||||
@@ -1061,4 +1129,91 @@ public class DisplayDeviceConfig {
|
||||
+ "} ";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for brightness throttling data.
|
||||
*/
|
||||
static class BrightnessThrottlingData {
|
||||
static class ThrottlingLevel {
|
||||
public @PowerManager.ThermalStatus int thermalStatus;
|
||||
public float brightness;
|
||||
|
||||
ThrottlingLevel(@PowerManager.ThermalStatus int thermalStatus, float brightness) {
|
||||
this.thermalStatus = thermalStatus;
|
||||
this.brightness = brightness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + thermalStatus + "," + brightness + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public List<ThrottlingLevel> throttlingLevels;
|
||||
|
||||
static public BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels)
|
||||
{
|
||||
if (throttlingLevels == null || throttlingLevels.size() == 0) {
|
||||
Slog.e(TAG, "BrightnessThrottlingData received null or empty throttling levels");
|
||||
return null;
|
||||
}
|
||||
|
||||
ThrottlingLevel prevLevel = throttlingLevels.get(0);
|
||||
final int numLevels = throttlingLevels.size();
|
||||
for (int i = 1; i < numLevels; i++) {
|
||||
ThrottlingLevel thisLevel = throttlingLevels.get(i);
|
||||
|
||||
if (thisLevel.thermalStatus <= prevLevel.thermalStatus) {
|
||||
Slog.e(TAG, "brightnessThrottlingMap must be strictly increasing, ignoring "
|
||||
+ "configuration. ThermalStatus " + thisLevel.thermalStatus + " <= "
|
||||
+ prevLevel.thermalStatus);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (thisLevel.brightness >= prevLevel.brightness) {
|
||||
Slog.e(TAG, "brightnessThrottlingMap must be strictly decreasing, ignoring "
|
||||
+ "configuration. Brightness " + thisLevel.brightness + " >= "
|
||||
+ thisLevel.brightness);
|
||||
return null;
|
||||
}
|
||||
|
||||
prevLevel = thisLevel;
|
||||
}
|
||||
|
||||
for (ThrottlingLevel level : throttlingLevels) {
|
||||
// Non-negative brightness values are enforced by device config schema
|
||||
if (level.brightness > PowerManager.BRIGHTNESS_MAX) {
|
||||
Slog.e(TAG, "brightnessThrottlingMap contains a brightness value exceeding "
|
||||
+ "system max. Brightness " + level.brightness + " > "
|
||||
+ PowerManager.BRIGHTNESS_MAX);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new BrightnessThrottlingData(throttlingLevels);
|
||||
}
|
||||
|
||||
static public BrightnessThrottlingData create(BrightnessThrottlingData other) {
|
||||
if (other == null)
|
||||
return null;
|
||||
|
||||
return BrightnessThrottlingData.create(other.throttlingLevels);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BrightnessThrottlingData{"
|
||||
+ "throttlingLevels:" + throttlingLevels
|
||||
+ "} ";
|
||||
}
|
||||
|
||||
private BrightnessThrottlingData(List<ThrottlingLevel> inLevels) {
|
||||
throttlingLevels = new ArrayList<>(inLevels.size());
|
||||
for (ThrottlingLevel level : inLevels) {
|
||||
throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +346,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
private boolean mAppliedTemporaryBrightness;
|
||||
private boolean mAppliedTemporaryAutoBrightnessAdjustment;
|
||||
private boolean mAppliedBrightnessBoost;
|
||||
private boolean mAppliedThrottling;
|
||||
|
||||
// Reason for which the brightness was last changed. See {@link BrightnessReason} for more
|
||||
// information.
|
||||
@@ -379,6 +380,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
private final HighBrightnessModeController mHbmController;
|
||||
|
||||
private final BrightnessThrottler mBrightnessThrottler;
|
||||
|
||||
private final BrightnessSetting mBrightnessSetting;
|
||||
|
||||
private final Runnable mOnBrightnessChangeRunnable;
|
||||
@@ -538,6 +541,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
mHbmController = createHbmControllerLocked();
|
||||
|
||||
mBrightnessThrottler = createBrightnessThrottlerLocked();
|
||||
|
||||
// Seed the cached brightness
|
||||
saveBrightnessInfo(getScreenBrightnessSetting());
|
||||
|
||||
@@ -827,6 +832,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
reloadReduceBrightColours();
|
||||
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
|
||||
mDisplayDeviceConfig.getHighBrightnessModeData());
|
||||
mBrightnessThrottler.resetThrottlingData(
|
||||
mDisplayDeviceConfig.getBrightnessThrottlingData());
|
||||
}
|
||||
|
||||
private void sendUpdatePowerState() {
|
||||
@@ -1039,6 +1046,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
private void cleanupHandlerThreadAfterStop() {
|
||||
setProximitySensorEnabled(false);
|
||||
mHbmController.stop();
|
||||
mBrightnessThrottler.stop();
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
if (mUnfinishedBusiness) {
|
||||
mCallbacks.releaseSuspendBlocker();
|
||||
@@ -1336,14 +1344,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
|
||||
}
|
||||
|
||||
// The current brightness to use has been calculated at this point (minus the adjustments
|
||||
// like low-power and dim), and HbmController should be notified so that it can accurately
|
||||
// calculate HDR or HBM levels. We specifically do it here instead of having HbmController
|
||||
// listen to the brightness setting because certain brightness sources (just as an app
|
||||
// override) are not saved to the setting, but should be reflected in HBM
|
||||
// calculations.
|
||||
mHbmController.onBrightnessChanged(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
|
||||
@@ -1390,6 +1390,28 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mAppliedLowPower = false;
|
||||
}
|
||||
|
||||
// Apply brightness throttling after applying all other transforms
|
||||
final float unthrottledBrightnessState = brightnessState;
|
||||
if (mBrightnessThrottler.isThrottled()) {
|
||||
brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
|
||||
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
|
||||
if (!mAppliedThrottling) {
|
||||
slowChange = false;
|
||||
}
|
||||
mAppliedThrottling = true;
|
||||
} else if (mAppliedThrottling) {
|
||||
slowChange = false;
|
||||
mAppliedThrottling = false;
|
||||
}
|
||||
|
||||
// The current brightness to use has been calculated at this point, and HbmController should
|
||||
// be notified so that it can accurately calculate HDR or HBM levels. We specifically do it
|
||||
// here instead of having HbmController listen to the brightness setting because certain
|
||||
// brightness sources (such as an app override) are not saved to the setting, but should be
|
||||
// reflected in HBM calculations.
|
||||
mHbmController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
|
||||
mBrightnessThrottler.getBrightnessMaxReason());
|
||||
|
||||
// Animate the screen brightness when the screen is on or dozing.
|
||||
// Skip the animation when the screen is off or suspended or transition to/from VR.
|
||||
boolean brightnessAdjusted = false;
|
||||
@@ -1441,6 +1463,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// use instead. We still preserve the calculated brightness for Standard Dynamic Range
|
||||
// (SDR) layers, but the main brightness value will be the one for HDR.
|
||||
float sdrAnimateValue = animateValue;
|
||||
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
|
||||
// done in HighBrightnessModeController.
|
||||
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
|
||||
&& ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
|
||||
|| (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
|
||||
@@ -1618,7 +1642,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mCachedBrightnessInfo.brightnessMin.value,
|
||||
mCachedBrightnessInfo.brightnessMax.value,
|
||||
mCachedBrightnessInfo.hbmMode.value,
|
||||
mCachedBrightnessInfo.hbmTransitionPoint.value);
|
||||
mCachedBrightnessInfo.hbmTransitionPoint.value,
|
||||
mCachedBrightnessInfo.brightnessMaxReason.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1648,6 +1673,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
changed |=
|
||||
mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
|
||||
mHbmController.getTransitionPoint());
|
||||
changed |=
|
||||
mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.brightnessMaxReason,
|
||||
mBrightnessThrottler.getBrightnessMaxReason());
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -1679,6 +1707,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}, mContext);
|
||||
}
|
||||
|
||||
private BrightnessThrottler createBrightnessThrottlerLocked() {
|
||||
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||
final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
|
||||
final DisplayDeviceConfig.BrightnessThrottlingData data =
|
||||
ddConfig != null ? ddConfig.getBrightnessThrottlingData() : null;
|
||||
return new BrightnessThrottler(mHandler, data,
|
||||
() -> {
|
||||
sendUpdatePowerStateLocked();
|
||||
postBrightnessChangeRunnable();
|
||||
});
|
||||
}
|
||||
|
||||
private void blockScreenOn() {
|
||||
if (mPendingScreenOnUnblocker == null) {
|
||||
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
|
||||
@@ -2346,6 +2386,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
|
||||
pw.println(" mCachedBrightnessInfo.hbmTransitionPoint=" +
|
||||
mCachedBrightnessInfo.hbmTransitionPoint.value);
|
||||
pw.println(" mCachedBrightnessInfo.brightnessMaxReason =" +
|
||||
mCachedBrightnessInfo.brightnessMaxReason .value);
|
||||
}
|
||||
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
|
||||
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
|
||||
@@ -2384,6 +2426,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
|
||||
pw.println(" mAppliedDimming=" + mAppliedDimming);
|
||||
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
|
||||
pw.println(" mAppliedThrottling=" + mAppliedThrottling);
|
||||
pw.println(" mAppliedScreenBrightnessOverride=" + mAppliedScreenBrightnessOverride);
|
||||
pw.println(" mAppliedTemporaryBrightness=" + mAppliedTemporaryBrightness);
|
||||
pw.println(" mDozing=" + mDozing);
|
||||
@@ -2422,6 +2465,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mHbmController.dump(pw);
|
||||
}
|
||||
|
||||
if (mBrightnessThrottler != null) {
|
||||
mBrightnessThrottler.dump(pw);
|
||||
}
|
||||
|
||||
pw.println();
|
||||
if (mDisplayWhiteBalanceController != null) {
|
||||
mDisplayWhiteBalanceController.dump(pw);
|
||||
@@ -2702,7 +2749,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
static final int MODIFIER_DIMMED = 0x1;
|
||||
static final int MODIFIER_LOW_POWER = 0x2;
|
||||
static final int MODIFIER_HDR = 0x4;
|
||||
static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR;
|
||||
static final int MODIFIER_THROTTLED = 0x8;
|
||||
static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR
|
||||
| MODIFIER_THROTTLED;
|
||||
|
||||
// ADJUSTMENT_*
|
||||
// These things can happen at any point, even if the main brightness reason doesn't
|
||||
@@ -2777,6 +2826,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
if ((modifier & MODIFIER_HDR) != 0) {
|
||||
sb.append(" hdr");
|
||||
}
|
||||
if ((modifier & MODIFIER_THROTTLED) != 0) {
|
||||
sb.append(" throttled");
|
||||
}
|
||||
int strlen = sb.length();
|
||||
if (sb.charAt(strlen - 1) == '[') {
|
||||
sb.setLength(strlen - 2);
|
||||
@@ -2813,6 +2865,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
|
||||
public MutableFloat hbmTransitionPoint =
|
||||
new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
|
||||
public MutableInt brightnessMaxReason =
|
||||
new MutableInt(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
|
||||
|
||||
public boolean checkAndSetFloat(MutableFloat mf, float f) {
|
||||
if (mf.value != f) {
|
||||
|
||||
@@ -82,7 +82,15 @@ class HighBrightnessModeController {
|
||||
private boolean mIsTimeAvailable = false;
|
||||
private boolean mIsAutoBrightnessEnabled = false;
|
||||
private boolean mIsAutoBrightnessOffByState = false;
|
||||
|
||||
// The following values are typically reported by DisplayPowerController.
|
||||
// This value includes brightness throttling effects.
|
||||
private float mBrightness;
|
||||
// This value excludes brightness throttling effects.
|
||||
private float mUnthrottledBrightness;
|
||||
private @BrightnessInfo.BrightnessMaxReason int mThrottlingReason =
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
|
||||
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
private boolean mIsHdrLayerPresent = false;
|
||||
private boolean mIsThermalStatusWithinLimit = true;
|
||||
@@ -192,11 +200,14 @@ class HighBrightnessModeController {
|
||||
}
|
||||
}
|
||||
|
||||
void onBrightnessChanged(float brightness) {
|
||||
void onBrightnessChanged(float brightness, float unthrottledBrightness,
|
||||
@BrightnessInfo.BrightnessMaxReason int throttlingReason) {
|
||||
if (!deviceSupportsHbm()) {
|
||||
return;
|
||||
}
|
||||
mBrightness = brightness;
|
||||
mUnthrottledBrightness = unthrottledBrightness;
|
||||
mThrottlingReason = throttlingReason;
|
||||
|
||||
// If we are starting or ending a high brightness mode session, store the current
|
||||
// session in mRunningStartTimeMillis, or the old one in mEvents.
|
||||
@@ -274,6 +285,8 @@ class HighBrightnessModeController {
|
||||
private void dumpLocal(PrintWriter pw) {
|
||||
pw.println("HighBrightnessModeController:");
|
||||
pw.println(" mBrightness=" + mBrightness);
|
||||
pw.println(" mUnthrottledBrightness=" + mUnthrottledBrightness);
|
||||
pw.println(" mThrottlingReason=" + BrightnessInfo.briMaxReasonToString(mThrottlingReason));
|
||||
pw.println(" mCurrentMin=" + getCurrentBrightnessMin());
|
||||
pw.println(" mCurrentMax=" + getCurrentBrightnessMax());
|
||||
pw.println(" mHbmMode=" + BrightnessInfo.hbmToString(mHbmMode)
|
||||
@@ -431,6 +444,9 @@ class HighBrightnessModeController {
|
||||
+ ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit
|
||||
+ ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode
|
||||
+ ", mBrightness: " + mBrightness
|
||||
+ ", mUnthrottledBrightness: " + mUnthrottledBrightness
|
||||
+ ", mThrottlingReason: "
|
||||
+ BrightnessInfo.briMaxReasonToString(mThrottlingReason)
|
||||
+ ", RunningStartTimeMillis: " + mRunningStartTimeMillis
|
||||
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
|
||||
+ ", events: " + mEvents);
|
||||
@@ -446,31 +462,44 @@ class HighBrightnessModeController {
|
||||
|
||||
private void updateHbmMode() {
|
||||
int newHbmMode = calculateHighBrightnessMode();
|
||||
updateHbmStats(mHbmMode, newHbmMode);
|
||||
updateHbmStats(newHbmMode);
|
||||
if (mHbmMode != newHbmMode) {
|
||||
mHbmMode = newHbmMode;
|
||||
mHbmChangeCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHbmStats(int mode, int newMode) {
|
||||
private void updateHbmStats(int newMode) {
|
||||
final float transitionPoint = mHbmData.transitionPoint;
|
||||
int state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;
|
||||
if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
|
||||
&& getHdrBrightnessValue() > mHbmData.transitionPoint) {
|
||||
&& getHdrBrightnessValue() > transitionPoint) {
|
||||
state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_HDR;
|
||||
} else if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
|
||||
} else if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT
|
||||
&& mBrightness > transitionPoint) {
|
||||
state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT;
|
||||
}
|
||||
if (state == mHbmStatsState) {
|
||||
return;
|
||||
}
|
||||
mHbmStatsState = state;
|
||||
|
||||
int reason =
|
||||
FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN;
|
||||
boolean oldHbmSv = (mode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
boolean newHbmSv = (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
final boolean oldHbmSv = (mHbmStatsState
|
||||
== FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT);
|
||||
final boolean newHbmSv =
|
||||
(state == FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT);
|
||||
if (oldHbmSv && !newHbmSv) {
|
||||
// HighBrightnessModeController (HBMC) currently supports throttling from two sources:
|
||||
// 1. Internal, received from HBMC.SkinThermalStatusObserver.notifyThrottling()
|
||||
// 2. External, received from HBMC.onBrightnessChanged()
|
||||
// TODO(b/216373254): Deprecate internal throttling source
|
||||
final boolean internalThermalThrottling = !mIsThermalStatusWithinLimit;
|
||||
final boolean externalThermalThrottling =
|
||||
mUnthrottledBrightness > transitionPoint && // We would've liked HBM brightness...
|
||||
mBrightness <= transitionPoint && // ...but we got NBM, because of...
|
||||
mThrottlingReason == BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL; // ...thermals.
|
||||
|
||||
// If more than one conditions are flipped and turn off HBM sunlight
|
||||
// visibility, only one condition will be reported to make it simple.
|
||||
if (!mIsAutoBrightnessEnabled && mIsAutoBrightnessOffByState) {
|
||||
@@ -483,7 +512,7 @@ class HighBrightnessModeController {
|
||||
reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LUX_DROP;
|
||||
} else if (!mIsTimeAvailable) {
|
||||
reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_TIME_LIMIT;
|
||||
} else if (!mIsThermalStatusWithinLimit) {
|
||||
} else if (internalThermalThrottling || externalThermalThrottling) {
|
||||
reason = FrameworkStatsLog
|
||||
.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT;
|
||||
} else if (mIsHdrLayerPresent) {
|
||||
@@ -496,6 +525,7 @@ class HighBrightnessModeController {
|
||||
}
|
||||
|
||||
mInjector.reportHbmStateChange(mDisplayStatsId, state, reason);
|
||||
mHbmStatsState = state;
|
||||
}
|
||||
|
||||
private String hbmStatsStateToString(int hbmStatsState) {
|
||||
@@ -572,7 +602,7 @@ class HighBrightnessModeController {
|
||||
>= ((float) (mWidth * mHeight) * HDR_PERCENT_OF_SCREEN_REQUIRED);
|
||||
// Calling the brightness update so that we can recalculate
|
||||
// brightness with HDR in mind.
|
||||
onBrightnessChanged(mBrightness);
|
||||
onBrightnessChanged(mBrightness, mUnthrottledBrightness, mThrottlingReason);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<xs:element type="thermalThrottling" name="thermalThrottling">
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
|
||||
maxOccurs="1"/>
|
||||
<xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
|
||||
@@ -154,6 +158,37 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="thermalThrottling">
|
||||
<xs:complexType>
|
||||
<xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap">
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="brightnessThrottlingMap">
|
||||
<xs:sequence>
|
||||
<xs:element name="brightnessThrottlingPoint" type="brightnessThrottlingPoint" maxOccurs="unbounded" minOccurs="1">
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="brightnessThrottlingPoint">
|
||||
<xs:sequence>
|
||||
<xs:element type="thermalStatus" name="thermalStatus">
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<xs:element type="nonNegativeDecimal" name="brightness">
|
||||
<xs:annotation name="nonnull"/>
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="nitsMap">
|
||||
<xs:sequence>
|
||||
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
|
||||
|
||||
@@ -7,6 +7,19 @@ package com.android.server.display.config {
|
||||
method public final void setMinimum(@NonNull java.math.BigDecimal);
|
||||
}
|
||||
|
||||
public class BrightnessThrottlingMap {
|
||||
ctor public BrightnessThrottlingMap();
|
||||
method @NonNull public final java.util.List<com.android.server.display.config.BrightnessThrottlingPoint> getBrightnessThrottlingPoint();
|
||||
}
|
||||
|
||||
public class BrightnessThrottlingPoint {
|
||||
ctor public BrightnessThrottlingPoint();
|
||||
method @NonNull public final java.math.BigDecimal getBrightness();
|
||||
method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
|
||||
method public final void setBrightness(@NonNull java.math.BigDecimal);
|
||||
method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
|
||||
}
|
||||
|
||||
public class Density {
|
||||
ctor public Density();
|
||||
method @NonNull public final java.math.BigInteger getDensity();
|
||||
@@ -39,6 +52,7 @@ package com.android.server.display.config {
|
||||
method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
|
||||
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
|
||||
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
|
||||
method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
|
||||
method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
|
||||
method public final void setAmbientLightHorizonLong(java.math.BigInteger);
|
||||
method public final void setAmbientLightHorizonShort(java.math.BigInteger);
|
||||
@@ -54,6 +68,7 @@ package com.android.server.display.config {
|
||||
method public final void setScreenBrightnessRampFastIncrease(java.math.BigDecimal);
|
||||
method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
|
||||
method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
|
||||
method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
|
||||
}
|
||||
|
||||
public class DisplayQuirks {
|
||||
@@ -131,6 +146,12 @@ package com.android.server.display.config {
|
||||
enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
|
||||
}
|
||||
|
||||
public class ThermalThrottling {
|
||||
ctor public ThermalThrottling();
|
||||
method @NonNull public final com.android.server.display.config.BrightnessThrottlingMap getBrightnessThrottlingMap();
|
||||
method public final void setBrightnessThrottlingMap(@NonNull com.android.server.display.config.BrightnessThrottlingMap);
|
||||
}
|
||||
|
||||
public class Thresholds {
|
||||
ctor public Thresholds();
|
||||
method @NonNull public final com.android.server.display.config.BrightnessThresholds getBrighteningThresholds();
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.display.BrightnessInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.IThermalEventListener;
|
||||
import android.os.IThermalService;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Temperature.ThrottlingStatus;
|
||||
import android.os.Temperature;
|
||||
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.BrightnessThrottler.Injector;
|
||||
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
|
||||
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BrightnessThrottlerTest {
|
||||
private static final float EPSILON = 0.000001f;
|
||||
|
||||
private Handler mHandler;
|
||||
private TestLooper mTestLooper;
|
||||
|
||||
@Mock IThermalService mThermalServiceMock;
|
||||
@Mock Injector mInjectorMock;
|
||||
|
||||
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mInjectorMock.getThermalService()).thenReturn(mThermalServiceMock);
|
||||
mTestLooper = new TestLooper();
|
||||
mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Test Methods
|
||||
/////////////////
|
||||
|
||||
@Test
|
||||
public void testBrightnessThrottlingData() {
|
||||
List<ThrottlingLevel> singleLevel = new ArrayList<>();
|
||||
singleLevel.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));
|
||||
|
||||
List<ThrottlingLevel> validLevels = new ArrayList<>();
|
||||
validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f));
|
||||
validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));
|
||||
|
||||
List<ThrottlingLevel> unsortedThermalLevels = new ArrayList<>();
|
||||
unsortedThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f));
|
||||
unsortedThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f));
|
||||
|
||||
List<ThrottlingLevel> unsortedBrightnessLevels = new ArrayList<>();
|
||||
unsortedBrightnessLevels.add(
|
||||
new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f));
|
||||
unsortedBrightnessLevels.add(
|
||||
new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f));
|
||||
|
||||
List<ThrottlingLevel> unsortedLevels = new ArrayList<>();
|
||||
unsortedLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f));
|
||||
unsortedLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f));
|
||||
|
||||
List<ThrottlingLevel> invalidLevel = new ArrayList<>();
|
||||
invalidLevel.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
|
||||
PowerManager.BRIGHTNESS_MAX + EPSILON));
|
||||
|
||||
// Test invalid data
|
||||
BrightnessThrottlingData data;
|
||||
data = BrightnessThrottlingData.create((List<ThrottlingLevel>)null);
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create((BrightnessThrottlingData)null);
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create(new ArrayList<ThrottlingLevel>());
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create(unsortedThermalLevels);
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create(unsortedBrightnessLevels);
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create(unsortedLevels);
|
||||
assertEquals(data, null);
|
||||
data = BrightnessThrottlingData.create(invalidLevel);
|
||||
assertEquals(data, null);
|
||||
|
||||
// Test valid data
|
||||
data = BrightnessThrottlingData.create(singleLevel);
|
||||
assertNotEquals(data, null);
|
||||
assertThrottlingLevelsEquals(singleLevel, data.throttlingLevels);
|
||||
|
||||
data = BrightnessThrottlingData.create(validLevels);
|
||||
assertNotEquals(data, null);
|
||||
assertThrottlingLevelsEquals(validLevels, data.throttlingLevels);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrottlingUnsupported() throws Exception {
|
||||
final BrightnessThrottler throttler = createThrottlerUnsupported();
|
||||
assertFalse(throttler.deviceSupportsThrottling());
|
||||
|
||||
// Thermal listener shouldn't be registered if throttling is unsupported
|
||||
verify(mInjectorMock, never()).getThermalService();
|
||||
|
||||
// Ensure that brightness is uncapped when the device doesn't support throttling
|
||||
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrottlingSingleLevel() throws Exception {
|
||||
final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
|
||||
0.25f);
|
||||
|
||||
List<ThrottlingLevel> levels = new ArrayList<>();
|
||||
levels.add(level);
|
||||
final BrightnessThrottlingData data = BrightnessThrottlingData.create(levels);
|
||||
final BrightnessThrottler throttler = createThrottlerSupported(data);
|
||||
assertTrue(throttler.deviceSupportsThrottling());
|
||||
|
||||
verify(mThermalServiceMock).registerThermalEventListenerWithType(
|
||||
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
|
||||
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
|
||||
|
||||
// Set status too low to trigger throttling
|
||||
listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
|
||||
assertFalse(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status just high enough to trigger throttling
|
||||
listener.notifyThrottling(getSkinTemp(level.thermalStatus));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(level.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status more than high enough to trigger throttling
|
||||
listener.notifyThrottling(getSkinTemp(level.thermalStatus + 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(level.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Return to the lower throttling level
|
||||
listener.notifyThrottling(getSkinTemp(level.thermalStatus));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(level.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Cool down
|
||||
listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
|
||||
assertFalse(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE,
|
||||
throttler.getBrightnessMaxReason());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrottlingMultiLevel() throws Exception {
|
||||
final ThrottlingLevel levelLo = new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE,
|
||||
0.62f);
|
||||
final ThrottlingLevel levelHi = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
|
||||
0.25f);
|
||||
|
||||
List<ThrottlingLevel> levels = new ArrayList<>();
|
||||
levels.add(levelLo);
|
||||
levels.add(levelHi);
|
||||
final BrightnessThrottlingData data = BrightnessThrottlingData.create(levels);
|
||||
final BrightnessThrottler throttler = createThrottlerSupported(data);
|
||||
assertTrue(throttler.deviceSupportsThrottling());
|
||||
|
||||
verify(mThermalServiceMock).registerThermalEventListenerWithType(
|
||||
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
|
||||
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
|
||||
|
||||
// Set status too low to trigger throttling
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus - 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
|
||||
assertFalse(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status just high enough to trigger throttling
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status to an intermediate throttling level
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus + 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status to the highest configured throttling level
|
||||
listener.notifyThrottling(getSkinTemp(levelHi.thermalStatus));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelHi.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Set status to exceed the highest configured throttling level
|
||||
listener.notifyThrottling(getSkinTemp(levelHi.thermalStatus + 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelHi.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Return to an intermediate throttling level
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus + 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Return to the lowest configured throttling level
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f);
|
||||
assertTrue(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
|
||||
throttler.getBrightnessMaxReason());
|
||||
|
||||
// Cool down
|
||||
listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus - 1));
|
||||
mTestLooper.dispatchAll();
|
||||
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
|
||||
assertFalse(throttler.isThrottled());
|
||||
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());
|
||||
}
|
||||
|
||||
private void assertThrottlingLevelsEquals(
|
||||
List<ThrottlingLevel> expected,
|
||||
List<ThrottlingLevel> actual) {
|
||||
assertEquals(expected.size(), actual.size());
|
||||
|
||||
for (int i = 0; i < expected.size(); i++) {
|
||||
ThrottlingLevel expectedLevel = expected.get(i);
|
||||
ThrottlingLevel actualLevel = actual.get(i);
|
||||
|
||||
assertEquals(expectedLevel.thermalStatus, actualLevel.thermalStatus);
|
||||
assertEquals(expectedLevel.brightness, actualLevel.brightness, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private BrightnessThrottler createThrottlerUnsupported() {
|
||||
return new BrightnessThrottler(mInjectorMock, mHandler, null, () -> {});
|
||||
}
|
||||
|
||||
private BrightnessThrottler createThrottlerSupported(BrightnessThrottlingData data) {
|
||||
assertNotNull(data);
|
||||
return new BrightnessThrottler(mInjectorMock, mHandler, data, () -> {});
|
||||
}
|
||||
|
||||
private Temperature getSkinTemp(@ThrottlingStatus int status) {
|
||||
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
||||
}
|
||||
}
|
||||
@@ -1461,7 +1461,8 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM, with brightness in the HBM range
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f,
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, hbmRefreshRate);
|
||||
@@ -1469,7 +1470,8 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM, with brightness below the HBM range
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f,
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1477,7 +1479,8 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1485,7 +1488,8 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM, with brightness in the HBM range
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f,
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, hbmRefreshRate);
|
||||
@@ -1493,7 +1497,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1501,7 +1505,8 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM, with brightness below the HBM range
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f,
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1509,7 +1514,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1580,7 +1585,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, initialRefreshRate);
|
||||
@@ -1598,7 +1603,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1606,7 +1611,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn HBM on again and ensure the updated vote value stuck
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, updatedRefreshRate);
|
||||
@@ -1622,7 +1627,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1654,7 +1659,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1662,7 +1667,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1694,7 +1699,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM when HBM is supported; expect a valid transition point and a vote.
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, 60.0f);
|
||||
@@ -1702,7 +1707,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1711,7 +1716,7 @@ public class DisplayModeDirectorTest {
|
||||
// no vote.
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
HBM_TRANSITION_POINT_INVALID));
|
||||
HBM_TRANSITION_POINT_INVALID, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1720,7 +1725,7 @@ public class DisplayModeDirectorTest {
|
||||
// no vote.
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR,
|
||||
HBM_TRANSITION_POINT_INVALID));
|
||||
HBM_TRANSITION_POINT_INVALID, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1728,7 +1733,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
@@ -1737,7 +1742,8 @@ public class DisplayModeDirectorTest {
|
||||
private void setHbmAndAssertRefreshRate(
|
||||
DisplayModeDirector director, DisplayListener listener, int mode, float rr) {
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID))
|
||||
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT));
|
||||
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
|
||||
final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
@@ -1817,7 +1823,7 @@ public class DisplayModeDirectorTest {
|
||||
// Turn on HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
|
||||
TRANSITION_POINT));
|
||||
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, 60.f);
|
||||
@@ -1978,7 +1984,8 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f,
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT));
|
||||
BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT,
|
||||
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.display;
|
||||
|
||||
import static android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
|
||||
import static android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
|
||||
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
|
||||
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
|
||||
@@ -201,7 +203,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
|
||||
// Verify we are in HBM
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
@@ -233,7 +235,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
|
||||
// Verify we are in HBM
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
@@ -258,18 +260,18 @@ public class HighBrightnessModeControllerTest {
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, 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.onBrightnessChanged(TRANSITION_POINT - 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT - 0.01f);
|
||||
advanceTime(1);
|
||||
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
advanceTime(TIME_ALLOWED_IN_WINDOW_MILLIS / 2);
|
||||
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
@@ -288,13 +290,13 @@ public class HighBrightnessModeControllerTest {
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
|
||||
// Go into HBM for half the allowed window
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, 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.onBrightnessChanged(TRANSITION_POINT);
|
||||
hbmcOnBrightnessChanged(hbmc, 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
|
||||
@@ -304,7 +306,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
// Go into HBM for just under the second half of allowed window
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 1);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 1);
|
||||
advanceTime((TIME_ALLOWED_IN_WINDOW_MILLIS / 2) - 1);
|
||||
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_SUNLIGHT);
|
||||
@@ -434,7 +436,7 @@ public class HighBrightnessModeControllerTest {
|
||||
float brightness = 0.5f;
|
||||
float expectedHdrBrightness = MathUtils.map(DEFAULT_MIN, TRANSITION_POINT,
|
||||
DEFAULT_MIN, DEFAULT_MAX, brightness); // map value from normal range to hdr range
|
||||
hbmc.onBrightnessChanged(brightness);
|
||||
hbmcOnBrightnessChanged(hbmc, brightness);
|
||||
advanceTime(0);
|
||||
assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON);
|
||||
|
||||
@@ -442,21 +444,21 @@ public class HighBrightnessModeControllerTest {
|
||||
brightness = 0.33f;
|
||||
expectedHdrBrightness = MathUtils.map(DEFAULT_MIN, TRANSITION_POINT,
|
||||
DEFAULT_MIN, DEFAULT_MAX, brightness); // map value from normal range to hdr range
|
||||
hbmc.onBrightnessChanged(brightness);
|
||||
hbmcOnBrightnessChanged(hbmc, brightness);
|
||||
advanceTime(0);
|
||||
assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON);
|
||||
|
||||
// Try the min value
|
||||
brightness = DEFAULT_MIN;
|
||||
expectedHdrBrightness = DEFAULT_MIN;
|
||||
hbmc.onBrightnessChanged(brightness);
|
||||
hbmcOnBrightnessChanged(hbmc, brightness);
|
||||
advanceTime(0);
|
||||
assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON);
|
||||
|
||||
// Try the max value
|
||||
brightness = TRANSITION_POINT;
|
||||
expectedHdrBrightness = DEFAULT_MAX;
|
||||
hbmc.onBrightnessChanged(brightness);
|
||||
hbmcOnBrightnessChanged(hbmc, brightness);
|
||||
advanceTime(0);
|
||||
assertEquals(expectedHdrBrightness, hbmc.getHdrBrightnessValue(), EPSILON);
|
||||
}
|
||||
@@ -467,7 +469,7 @@ public class HighBrightnessModeControllerTest {
|
||||
final int displayStatsId = mDisplayUniqueId.hashCode();
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT);
|
||||
hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
|
||||
advanceTime(0);
|
||||
@@ -489,7 +491,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
|
||||
// Verify Stats HBM_ON_SUNLIGHT
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
@@ -506,12 +508,12 @@ public class HighBrightnessModeControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tetHbmStats_NbmHdrNoReport() {
|
||||
public void testHbmStats_NbmHdrNoReport() {
|
||||
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||
final int displayStatsId = mDisplayUniqueId.hashCode();
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onBrightnessChanged(DEFAULT_MIN);
|
||||
hbmcOnBrightnessChanged(hbmc, DEFAULT_MIN);
|
||||
hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
|
||||
DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
|
||||
advanceTime(0);
|
||||
@@ -524,7 +526,27 @@ public class HighBrightnessModeControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmStats_ThermalOff() throws Exception {
|
||||
public void testHbmStats_HighLuxLowBrightnessNoReport() {
|
||||
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||
final int displayStatsId = mDisplayUniqueId.hashCode();
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmcOnBrightnessChanged(hbmc, DEFAULT_MIN);
|
||||
advanceTime(0);
|
||||
// verify in HBM sunlight mode
|
||||
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
|
||||
|
||||
// Verify Stats HBM_ON_SUNLIGHT not report
|
||||
verify(mInjectorMock, never()).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
anyInt());
|
||||
}
|
||||
|
||||
// Test reporting of thermal throttling when triggered by HighBrightnessModeController's
|
||||
// internal thermal throttling.
|
||||
@Test
|
||||
public void testHbmStats_InternalThermalOff() throws Exception {
|
||||
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||
final int displayStatsId = mDisplayUniqueId.hashCode();
|
||||
|
||||
@@ -534,7 +556,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
advanceTime(1);
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
@@ -548,6 +570,37 @@ public class HighBrightnessModeControllerTest {
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT));
|
||||
}
|
||||
|
||||
// Test reporting of thermal throttling when triggered externally through
|
||||
// HighBrightnessModeController.onBrightnessChanged()
|
||||
@Test
|
||||
public void testHbmStats_ExternalThermalOff() throws Exception {
|
||||
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||
final int displayStatsId = mDisplayUniqueId.hashCode();
|
||||
final float hbmBrightness = TRANSITION_POINT + 0.01f;
|
||||
final float nbmBrightness = TRANSITION_POINT - 0.01f;
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
// Brightness is unthrottled, HBM brightness granted
|
||||
hbmc.onBrightnessChanged(hbmBrightness, hbmBrightness, BRIGHTNESS_MAX_REASON_NONE);
|
||||
advanceTime(1);
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
|
||||
|
||||
// Brightness is thermally throttled, HBM brightness denied (NBM brightness granted)
|
||||
hbmc.onBrightnessChanged(nbmBrightness, hbmBrightness, BRIGHTNESS_MAX_REASON_THERMAL);
|
||||
advanceTime(1);
|
||||
// We expect HBM mode to remain set to sunlight, indicating that HBMC *allows* this mode.
|
||||
// However, we expect the HBM state reported by HBMC to be off, since external thermal
|
||||
// throttling (reported to HBMC through onBrightnessChanged()) lowers brightness to below
|
||||
// the HBM transition point.
|
||||
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmStats_TimeOut() {
|
||||
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
|
||||
@@ -555,7 +608,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
advanceTime(0);
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
@@ -576,7 +629,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
advanceTime(0);
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
@@ -595,7 +648,7 @@ public class HighBrightnessModeControllerTest {
|
||||
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
|
||||
hbmc.onBrightnessChanged(TRANSITION_POINT + 0.01f);
|
||||
hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
|
||||
advanceTime(0);
|
||||
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
|
||||
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
|
||||
@@ -649,4 +702,8 @@ public class HighBrightnessModeControllerTest {
|
||||
private Temperature getSkinTemp(@ThrottlingStatus int status) {
|
||||
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
||||
}
|
||||
|
||||
private void hbmcOnBrightnessChanged(HighBrightnessModeController hbmc, float brightness) {
|
||||
hbmc.onBrightnessChanged(brightness, brightness, BRIGHTNESS_MAX_REASON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user