Merge "Revert "Revert "[hbm] Separate HBM times for multi-display devices."""
This commit is contained in:
committed by
Android (Google) Code Review
commit
df0f11cdfd
@@ -109,6 +109,7 @@ import android.os.UserManager;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.EventLog;
|
||||
import android.util.IntArray;
|
||||
@@ -260,6 +261,13 @@ public final class DisplayManagerService extends SystemService {
|
||||
final SparseArray<Pair<IVirtualDevice, DisplayWindowPolicyController>>
|
||||
mDisplayWindowPolicyControllers = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Map of every internal primary display device {@link HighBrightnessModeMetadata}s indexed by
|
||||
* {@link DisplayDevice#mUniqueId}.
|
||||
*/
|
||||
public final ArrayMap<String, HighBrightnessModeMetadata> mHighBrightnessModeMetadataMap =
|
||||
new ArrayMap<>();
|
||||
|
||||
// List of all currently registered display adapters.
|
||||
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
|
||||
|
||||
@@ -1640,7 +1648,16 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
|
||||
if (dpc != null) {
|
||||
dpc.onDisplayChanged();
|
||||
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
|
||||
+ display.getDisplayIdLocked());
|
||||
return;
|
||||
}
|
||||
|
||||
final String uniqueId = device.getUniqueId();
|
||||
HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
|
||||
dpc.onDisplayChanged(hbmMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1698,7 +1715,15 @@ public final class DisplayManagerService extends SystemService {
|
||||
final int displayId = display.getDisplayIdLocked();
|
||||
final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
|
||||
if (dpc != null) {
|
||||
dpc.onDisplayChanged();
|
||||
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
|
||||
+ display.getDisplayIdLocked());
|
||||
return;
|
||||
}
|
||||
final String uniqueId = device.getUniqueId();
|
||||
HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
|
||||
dpc.onDisplayChanged(hbmMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2651,6 +2676,31 @@ public final class DisplayManagerService extends SystemService {
|
||||
mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
|
||||
}
|
||||
|
||||
private HighBrightnessModeMetadata getHighBrightnessModeMetadata(LogicalDisplay display) {
|
||||
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
|
||||
+ display.getDisplayIdLocked());
|
||||
return null;
|
||||
}
|
||||
|
||||
// HBM brightness mode is only applicable to internal physical displays.
|
||||
if (display.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String uniqueId = device.getUniqueId();
|
||||
|
||||
if (mHighBrightnessModeMetadataMap.containsKey(uniqueId)) {
|
||||
return mHighBrightnessModeMetadataMap.get(uniqueId);
|
||||
}
|
||||
|
||||
// HBM Time info not present. Create a new one for this physical display.
|
||||
HighBrightnessModeMetadata hbmInfo = new HighBrightnessModeMetadata();
|
||||
mHighBrightnessModeMetadataMap.put(uniqueId, hbmInfo);
|
||||
return hbmInfo;
|
||||
}
|
||||
|
||||
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
|
||||
private void addDisplayPowerControllerLocked(LogicalDisplay display) {
|
||||
if (mPowerHandler == null) {
|
||||
@@ -2666,17 +2716,23 @@ public final class DisplayManagerService extends SystemService {
|
||||
display, mSyncRoot);
|
||||
final DisplayPowerControllerInterface displayPowerController;
|
||||
|
||||
// If display is internal and has a HighBrightnessModeMetadata mapping, use that.
|
||||
// Or create a new one and use that.
|
||||
// We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to
|
||||
// displayPowerController, so the hbm info can be correctly associated
|
||||
// with the corresponding displaydevice.
|
||||
HighBrightnessModeMetadata hbmMetadata = getHighBrightnessModeMetadata(display);
|
||||
if (DeviceConfig.getBoolean("display_manager",
|
||||
"use_newly_structured_display_power_controller", true)) {
|
||||
displayPowerController = new DisplayPowerController2(
|
||||
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
|
||||
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
|
||||
() -> handleBrightnessChange(display));
|
||||
() -> handleBrightnessChange(display), hbmMetadata);
|
||||
} else {
|
||||
displayPowerController = new DisplayPowerController(
|
||||
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
|
||||
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
|
||||
() -> handleBrightnessChange(display));
|
||||
() -> handleBrightnessChange(display), hbmMetadata);
|
||||
}
|
||||
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
|
||||
}
|
||||
|
||||
@@ -388,6 +388,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
private float[] mNitsRange;
|
||||
|
||||
private final HighBrightnessModeController mHbmController;
|
||||
private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
|
||||
|
||||
private final BrightnessThrottler mBrightnessThrottler;
|
||||
|
||||
@@ -505,13 +506,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
DisplayPowerCallbacks callbacks, Handler handler,
|
||||
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
|
||||
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
|
||||
Runnable onBrightnessChangeRunnable) {
|
||||
Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
|
||||
|
||||
mInjector = injector != null ? injector : new Injector();
|
||||
mClock = mInjector.getClock();
|
||||
mLogicalDisplay = logicalDisplay;
|
||||
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
|
||||
mTag = "DisplayPowerController[" + mDisplayId + "]";
|
||||
mHighBrightnessModeMetadata = hbmMetadata;
|
||||
mSuspendBlockerIdUnfinishedBusiness = getSuspendBlockerUnfinishedBusinessId(mDisplayId);
|
||||
mSuspendBlockerIdOnStateChanged = getSuspendBlockerOnStateChangedId(mDisplayId);
|
||||
mSuspendBlockerIdProxPositive = getSuspendBlockerProxPositiveId(mDisplayId);
|
||||
@@ -790,7 +792,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
* Make sure DisplayManagerService.mSyncRoot is held when this is called
|
||||
*/
|
||||
@Override
|
||||
public void onDisplayChanged() {
|
||||
public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
|
||||
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(mTag, "Display Device is null in DisplayPowerController for display: "
|
||||
@@ -812,7 +814,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mUniqueDisplayId = uniqueId;
|
||||
mDisplayStatsId = mUniqueDisplayId.hashCode();
|
||||
mDisplayDeviceConfig = config;
|
||||
loadFromDisplayDeviceConfig(token, info);
|
||||
loadFromDisplayDeviceConfig(token, info, hbmMetadata);
|
||||
|
||||
/// Since the underlying display-device changed, we really don't know the
|
||||
// last command that was sent to change it's state. Lets assume it is unknown so
|
||||
@@ -864,7 +866,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
|
||||
private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
|
||||
HighBrightnessModeMetadata hbmMetadata) {
|
||||
// All properties that depend on the associated DisplayDevice and the DDC must be
|
||||
// updated here.
|
||||
loadBrightnessRampRates();
|
||||
@@ -877,6 +880,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mBrightnessRampIncreaseMaxTimeMillis,
|
||||
mBrightnessRampDecreaseMaxTimeMillis);
|
||||
}
|
||||
mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
|
||||
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
|
||||
mDisplayDeviceConfig.getHighBrightnessModeData(),
|
||||
new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
|
||||
@@ -1961,7 +1965,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
if (mAutomaticBrightnessController != null) {
|
||||
mAutomaticBrightnessController.update();
|
||||
}
|
||||
}, mContext);
|
||||
}, mHighBrightnessModeMetadata, mContext);
|
||||
}
|
||||
|
||||
private BrightnessThrottler createBrightnessThrottlerLocked() {
|
||||
|
||||
@@ -327,6 +327,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
private float[] mNitsRange;
|
||||
|
||||
private final HighBrightnessModeController mHbmController;
|
||||
private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
|
||||
|
||||
private final BrightnessThrottler mBrightnessThrottler;
|
||||
|
||||
@@ -415,7 +416,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
DisplayPowerCallbacks callbacks, Handler handler,
|
||||
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
|
||||
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
|
||||
Runnable onBrightnessChangeRunnable) {
|
||||
Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
|
||||
|
||||
mInjector = injector != null ? injector : new Injector();
|
||||
mClock = mInjector.getClock();
|
||||
@@ -431,6 +432,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
|
||||
mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
|
||||
() -> updatePowerState(), mDisplayId, mSensorManager);
|
||||
mHighBrightnessModeMetadata = hbmMetadata;
|
||||
mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
|
||||
mTag = "DisplayPowerController2[" + mDisplayId + "]";
|
||||
|
||||
@@ -681,7 +683,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
* Make sure DisplayManagerService.mSyncRoot lock is held when this is called
|
||||
*/
|
||||
@Override
|
||||
public void onDisplayChanged() {
|
||||
public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
|
||||
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||
if (device == null) {
|
||||
Slog.wtf(mTag, "Display Device is null in DisplayPowerController2 for display: "
|
||||
@@ -695,6 +697,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
||||
final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
|
||||
final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
|
||||
|
||||
mHandler.post(() -> {
|
||||
boolean changed = false;
|
||||
if (mDisplayDevice != device) {
|
||||
@@ -703,7 +706,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
mUniqueDisplayId = uniqueId;
|
||||
mDisplayStatsId = mUniqueDisplayId.hashCode();
|
||||
mDisplayDeviceConfig = config;
|
||||
loadFromDisplayDeviceConfig(token, info);
|
||||
loadFromDisplayDeviceConfig(token, info, hbmMetadata);
|
||||
mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
|
||||
|
||||
// Since the underlying display-device changed, we really don't know the
|
||||
@@ -750,7 +753,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
|
||||
private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
|
||||
HighBrightnessModeMetadata hbmMetadata) {
|
||||
// All properties that depend on the associated DisplayDevice and the DDC must be
|
||||
// updated here.
|
||||
loadBrightnessRampRates();
|
||||
@@ -762,6 +766,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
mBrightnessRampIncreaseMaxTimeMillis,
|
||||
mBrightnessRampDecreaseMaxTimeMillis);
|
||||
}
|
||||
mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
|
||||
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
|
||||
mDisplayDeviceConfig.getHighBrightnessModeData(),
|
||||
new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
|
||||
@@ -1718,7 +1723,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
|
||||
if (mAutomaticBrightnessController != null) {
|
||||
mAutomaticBrightnessController.update();
|
||||
}
|
||||
}, mContext);
|
||||
}, mHighBrightnessModeMetadata, mContext);
|
||||
}
|
||||
|
||||
private BrightnessThrottler createBrightnessThrottlerLocked() {
|
||||
|
||||
@@ -31,10 +31,14 @@ import java.io.PrintWriter;
|
||||
public interface DisplayPowerControllerInterface {
|
||||
|
||||
/**
|
||||
* Notified when the display is changed. We use this to apply any changes that might be needed
|
||||
* Notified when the display is changed.
|
||||
* We use this to apply any changes that might be needed
|
||||
* when displays get swapped on foldable devices.
|
||||
* We also pass the High brightness mode metadata like
|
||||
* remaining time and hbm events for the corresponding
|
||||
* physical display, to update the values correctly.
|
||||
*/
|
||||
void onDisplayChanged();
|
||||
void onDisplayChanged(HighBrightnessModeMetadata hbmInfo);
|
||||
|
||||
/**
|
||||
* Unregisters all listeners and interrupts all running threads; halting future work.
|
||||
|
||||
46
services/core/java/com/android/server/display/HbmEvent.java
Normal file
46
services/core/java/com/android/server/display/HbmEvent.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an event in which High Brightness Mode was enabled.
|
||||
*/
|
||||
class HbmEvent {
|
||||
private long mStartTimeMillis;
|
||||
private long mEndTimeMillis;
|
||||
|
||||
HbmEvent(long startTimeMillis, long endTimeMillis) {
|
||||
this.mStartTimeMillis = startTimeMillis;
|
||||
this.mEndTimeMillis = endTimeMillis;
|
||||
}
|
||||
|
||||
public long getStartTimeMillis() {
|
||||
return mStartTimeMillis;
|
||||
}
|
||||
|
||||
public long getEndTimeMillis() {
|
||||
return mEndTimeMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HbmEvent: {startTimeMillis:" + mStartTimeMillis + ", endTimeMillis: "
|
||||
+ mEndTimeMillis + "}, total: "
|
||||
+ ((mEndTimeMillis - mStartTimeMillis) / 1000) + "]";
|
||||
}
|
||||
}
|
||||
@@ -105,30 +105,23 @@ class HighBrightnessModeController {
|
||||
private int mHbmStatsState = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;
|
||||
|
||||
/**
|
||||
* 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 and set of all events,
|
||||
* for the current HBM session.
|
||||
*/
|
||||
private long mRunningStartTimeMillis = -1;
|
||||
|
||||
/**
|
||||
* Queue of previous HBM-events ordered from most recent to least recent.
|
||||
* Meant to store only the events that fall into the most recent
|
||||
* {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}.
|
||||
*/
|
||||
private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>();
|
||||
|
||||
private HighBrightnessModeMetadata mHighBrightnessModeMetadata = null;
|
||||
HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
|
||||
String displayUniqueId, float brightnessMin, float brightnessMax,
|
||||
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
|
||||
Runnable hbmChangeCallback, Context context) {
|
||||
Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
|
||||
this(new Injector(), handler, width, height, displayToken, displayUniqueId, brightnessMin,
|
||||
brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, context);
|
||||
brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, hbmMetadata, context);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
|
||||
IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax,
|
||||
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
|
||||
Runnable hbmChangeCallback, Context context) {
|
||||
Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
|
||||
mInjector = injector;
|
||||
mContext = context;
|
||||
mClock = injector.getClock();
|
||||
@@ -137,6 +130,7 @@ class HighBrightnessModeController {
|
||||
mBrightnessMin = brightnessMin;
|
||||
mBrightnessMax = brightnessMax;
|
||||
mHbmChangeCallback = hbmChangeCallback;
|
||||
mHighBrightnessModeMetadata = hbmMetadata;
|
||||
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
|
||||
mSettingsObserver = new SettingsObserver(mHandler);
|
||||
mRecalcRunnable = this::recalculateTimeAllowance;
|
||||
@@ -222,19 +216,22 @@ class HighBrightnessModeController {
|
||||
|
||||
// If we are starting or ending a high brightness mode session, store the current
|
||||
// session in mRunningStartTimeMillis, or the old one in mEvents.
|
||||
final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1;
|
||||
final long runningStartTime = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
|
||||
final boolean wasHbmDrainingAvailableTime = runningStartTime != -1;
|
||||
final boolean shouldHbmDrainAvailableTime = mBrightness > mHbmData.transitionPoint
|
||||
&& !mIsHdrLayerPresent;
|
||||
if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) {
|
||||
final long currentTime = mClock.uptimeMillis();
|
||||
if (shouldHbmDrainAvailableTime) {
|
||||
mRunningStartTimeMillis = currentTime;
|
||||
mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
|
||||
} else {
|
||||
mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
|
||||
mRunningStartTimeMillis = -1;
|
||||
final HbmEvent hbmEvent = new HbmEvent(runningStartTime, currentTime);
|
||||
mHighBrightnessModeMetadata.addHbmEvent(hbmEvent);
|
||||
mHighBrightnessModeMetadata.setRunningStartTimeMillis(-1);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "New HBM event: " + mEvents.peekFirst());
|
||||
Slog.d(TAG, "New HBM event: "
|
||||
+ mHighBrightnessModeMetadata.getHbmEventQueue().peekFirst());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,6 +257,10 @@ class HighBrightnessModeController {
|
||||
mSettingsObserver.stopObserving();
|
||||
}
|
||||
|
||||
void setHighBrightnessModeMetadata(HighBrightnessModeMetadata hbmInfo) {
|
||||
mHighBrightnessModeMetadata = hbmInfo;
|
||||
}
|
||||
|
||||
void resetHbmData(int width, int height, IBinder displayToken, String displayUniqueId,
|
||||
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg) {
|
||||
mWidth = width;
|
||||
@@ -316,20 +317,22 @@ class HighBrightnessModeController {
|
||||
pw.println(" mBrightnessMax=" + mBrightnessMax);
|
||||
pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis()));
|
||||
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
|
||||
pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
|
||||
pw.println(" mRunningStartTimeMillis="
|
||||
+ TimeUtils.formatUptime(mHighBrightnessModeMetadata.getRunningStartTimeMillis()));
|
||||
pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
|
||||
pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
|
||||
pw.println(" width*height=" + mWidth + "*" + mHeight);
|
||||
pw.println(" mEvents=");
|
||||
final long currentTime = mClock.uptimeMillis();
|
||||
long lastStartTime = currentTime;
|
||||
if (mRunningStartTimeMillis != -1) {
|
||||
lastStartTime = dumpHbmEvent(pw, new HbmEvent(mRunningStartTimeMillis, currentTime));
|
||||
long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
|
||||
if (runningStartTimeMillis != -1) {
|
||||
lastStartTime = dumpHbmEvent(pw, new HbmEvent(runningStartTimeMillis, currentTime));
|
||||
}
|
||||
for (HbmEvent event : mEvents) {
|
||||
if (lastStartTime > event.endTimeMillis) {
|
||||
for (HbmEvent event : mHighBrightnessModeMetadata.getHbmEventQueue()) {
|
||||
if (lastStartTime > event.getEndTimeMillis()) {
|
||||
pw.println(" event: [normal brightness]: "
|
||||
+ TimeUtils.formatDuration(lastStartTime - event.endTimeMillis));
|
||||
+ TimeUtils.formatDuration(lastStartTime - event.getEndTimeMillis()));
|
||||
}
|
||||
lastStartTime = dumpHbmEvent(pw, event);
|
||||
}
|
||||
@@ -338,12 +341,12 @@ class HighBrightnessModeController {
|
||||
}
|
||||
|
||||
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
|
||||
final long duration = event.endTimeMillis - event.startTimeMillis;
|
||||
final long duration = event.getEndTimeMillis() - event.getStartTimeMillis();
|
||||
pw.println(" event: ["
|
||||
+ TimeUtils.formatUptime(event.startTimeMillis) + ", "
|
||||
+ TimeUtils.formatUptime(event.endTimeMillis) + "] ("
|
||||
+ TimeUtils.formatUptime(event.getStartTimeMillis()) + ", "
|
||||
+ TimeUtils.formatUptime(event.getEndTimeMillis()) + "] ("
|
||||
+ TimeUtils.formatDuration(duration) + ")");
|
||||
return event.startTimeMillis;
|
||||
return event.getStartTimeMillis();
|
||||
}
|
||||
|
||||
private boolean isCurrentlyAllowed() {
|
||||
@@ -372,13 +375,15 @@ class HighBrightnessModeController {
|
||||
|
||||
// First, lets see how much time we've taken for any currently running
|
||||
// session of HBM.
|
||||
if (mRunningStartTimeMillis > 0) {
|
||||
if (mRunningStartTimeMillis > currentTime) {
|
||||
long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
|
||||
if (runningStartTimeMillis > 0) {
|
||||
if (runningStartTimeMillis > currentTime) {
|
||||
Slog.e(TAG, "Start time set to the future. curr: " + currentTime
|
||||
+ ", start: " + mRunningStartTimeMillis);
|
||||
mRunningStartTimeMillis = currentTime;
|
||||
+ ", start: " + runningStartTimeMillis);
|
||||
mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
|
||||
runningStartTimeMillis = currentTime;
|
||||
}
|
||||
timeAlreadyUsed = currentTime - mRunningStartTimeMillis;
|
||||
timeAlreadyUsed = currentTime - runningStartTimeMillis;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
@@ -387,18 +392,19 @@ class HighBrightnessModeController {
|
||||
|
||||
// Next, lets iterate through the history of previous sessions and add those times.
|
||||
final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
|
||||
Iterator<HbmEvent> it = mEvents.iterator();
|
||||
Iterator<HbmEvent> it = mHighBrightnessModeMetadata.getHbmEventQueue().iterator();
|
||||
while (it.hasNext()) {
|
||||
final HbmEvent event = it.next();
|
||||
|
||||
// If this event ended before the current Timing window, discard forever and ever.
|
||||
if (event.endTimeMillis < windowstartTimeMillis) {
|
||||
if (event.getEndTimeMillis() < windowstartTimeMillis) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
final long startTimeMillis = Math.max(event.startTimeMillis, windowstartTimeMillis);
|
||||
timeAlreadyUsed += event.endTimeMillis - startTimeMillis;
|
||||
final long startTimeMillis = Math.max(event.getStartTimeMillis(),
|
||||
windowstartTimeMillis);
|
||||
timeAlreadyUsed += event.getEndTimeMillis() - startTimeMillis;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
@@ -425,17 +431,18 @@ class HighBrightnessModeController {
|
||||
// Calculate the time at which we want to recalculate mIsTimeAvailable in case a lux or
|
||||
// brightness change doesn't happen before then.
|
||||
long nextTimeout = -1;
|
||||
final ArrayDeque<HbmEvent> hbmEvents = mHighBrightnessModeMetadata.getHbmEventQueue();
|
||||
if (mBrightness > mHbmData.transitionPoint) {
|
||||
// if we're in high-lux now, timeout when we run out of allowed time.
|
||||
nextTimeout = currentTime + remainingTime;
|
||||
} else if (!mIsTimeAvailable && mEvents.size() > 0) {
|
||||
} else if (!mIsTimeAvailable && hbmEvents.size() > 0) {
|
||||
// If we are not allowed...timeout when the oldest event moved outside of the timing
|
||||
// window by at least minTime. Basically, we're calculating the soonest time we can
|
||||
// get {@code timeMinMillis} back to us.
|
||||
final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
|
||||
final HbmEvent lastEvent = mEvents.peekLast();
|
||||
final HbmEvent lastEvent = hbmEvents.peekLast();
|
||||
final long startTimePlusMinMillis =
|
||||
Math.max(windowstartTimeMillis, lastEvent.startTimeMillis)
|
||||
Math.max(windowstartTimeMillis, lastEvent.getStartTimeMillis())
|
||||
+ mHbmData.timeMinMillis;
|
||||
final long timeWhenMinIsGainedBack =
|
||||
currentTime + (startTimePlusMinMillis - windowstartTimeMillis) - remainingTime;
|
||||
@@ -459,9 +466,10 @@ class HighBrightnessModeController {
|
||||
+ ", mUnthrottledBrightness: " + mUnthrottledBrightness
|
||||
+ ", mThrottlingReason: "
|
||||
+ BrightnessInfo.briMaxReasonToString(mThrottlingReason)
|
||||
+ ", RunningStartTimeMillis: " + mRunningStartTimeMillis
|
||||
+ ", RunningStartTimeMillis: "
|
||||
+ mHighBrightnessModeMetadata.getRunningStartTimeMillis()
|
||||
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
|
||||
+ ", events: " + mEvents);
|
||||
+ ", events: " + hbmEvents);
|
||||
}
|
||||
|
||||
if (nextTimeout != -1) {
|
||||
@@ -588,25 +596,6 @@ class HighBrightnessModeController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an event in which High Brightness Mode was enabled.
|
||||
*/
|
||||
private static class HbmEvent {
|
||||
public long startTimeMillis;
|
||||
public long endTimeMillis;
|
||||
|
||||
HbmEvent(long startTimeMillis, long endTimeMillis) {
|
||||
this.startTimeMillis = startTimeMillis;
|
||||
this.endTimeMillis = endTimeMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Event: {" + startTimeMillis + ", " + endTimeMillis + "}, total: "
|
||||
+ ((endTimeMillis - startTimeMillis) / 1000) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class HdrListener extends SurfaceControlHdrLayerInfoListener {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 java.util.ArrayDeque;
|
||||
|
||||
|
||||
/**
|
||||
* Represents High Brightness Mode metadata associated
|
||||
* with a specific internal physical display.
|
||||
* Required for separately storing data like time information,
|
||||
* and related events when display was in HBM mode per
|
||||
* physical internal display.
|
||||
*/
|
||||
class HighBrightnessModeMetadata {
|
||||
/**
|
||||
* Queue of previous HBM-events ordered from most recent to least recent.
|
||||
* Meant to store only the events that fall into the most recent
|
||||
* {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}.
|
||||
*/
|
||||
private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* If HBM is currently running, this is the start time for the current HBM session.
|
||||
*/
|
||||
private long mRunningStartTimeMillis = -1;
|
||||
|
||||
public long getRunningStartTimeMillis() {
|
||||
return mRunningStartTimeMillis;
|
||||
}
|
||||
|
||||
public void setRunningStartTimeMillis(long setTime) {
|
||||
mRunningStartTimeMillis = setTime;
|
||||
}
|
||||
|
||||
public ArrayDeque<HbmEvent> getHbmEventQueue() {
|
||||
return mEvents;
|
||||
}
|
||||
|
||||
public void addHbmEvent(HbmEvent hbmEvent) {
|
||||
mEvents.addFirst(hbmEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ public final class DisplayPowerController2Test {
|
||||
@Mock
|
||||
private DisplayBlanker mDisplayBlankerMock;
|
||||
@Mock
|
||||
private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
|
||||
@Mock
|
||||
private LogicalDisplay mLogicalDisplayMock;
|
||||
@Mock
|
||||
private DisplayDevice mDisplayDeviceMock;
|
||||
@@ -169,7 +171,7 @@ public final class DisplayPowerController2Test {
|
||||
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
|
||||
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
|
||||
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
|
||||
});
|
||||
}, mHighBrightnessModeMetadataMock);
|
||||
|
||||
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
|
||||
// send a display power request
|
||||
|
||||
@@ -84,6 +84,8 @@ public final class DisplayPowerControllerTest {
|
||||
@Mock
|
||||
private DisplayDevice mDisplayDeviceMock;
|
||||
@Mock
|
||||
private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
|
||||
@Mock
|
||||
private BrightnessTracker mBrightnessTrackerMock;
|
||||
@Mock
|
||||
private BrightnessSetting mBrightnessSettingMock;
|
||||
@@ -151,7 +153,7 @@ public final class DisplayPowerControllerTest {
|
||||
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
|
||||
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
|
||||
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
|
||||
});
|
||||
}, mHighBrightnessModeMetadataMock);
|
||||
|
||||
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
|
||||
// send a display power request
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.assertEquals;
|
||||
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class HbmEventTest {
|
||||
private long mStartTimeMillis;
|
||||
private long mEndTimeMillis;
|
||||
private HbmEvent mHbmEvent;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mStartTimeMillis = 10;
|
||||
mEndTimeMillis = 20;
|
||||
mHbmEvent = new HbmEvent(mStartTimeMillis, mEndTimeMillis);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCorrectValues() {
|
||||
assertEquals(mHbmEvent.getStartTimeMillis(), mStartTimeMillis);
|
||||
assertEquals(mHbmEvent.getEndTimeMillis(), mEndTimeMillis);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringGeneratesExpectedString() {
|
||||
String actualString = mHbmEvent.toString();
|
||||
String expectedString = "HbmEvent: {startTimeMillis:" + mStartTimeMillis
|
||||
+ ", endTimeMillis: " + mEndTimeMillis + "}, total: "
|
||||
+ ((mEndTimeMillis - mStartTimeMillis) / 1000) + "]";
|
||||
assertEquals(actualString, expectedString);
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,7 @@ public class HighBrightnessModeControllerTest {
|
||||
private Binder mDisplayToken;
|
||||
private String mDisplayUniqueId;
|
||||
private Context mContextSpy;
|
||||
private HighBrightnessModeMetadata mHighBrightnessModeMetadata;
|
||||
|
||||
@Rule
|
||||
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||
@@ -118,6 +119,7 @@ public class HighBrightnessModeControllerTest {
|
||||
mTestLooper = new TestLooper(mClock::now);
|
||||
mDisplayToken = null;
|
||||
mDisplayUniqueId = "unique_id";
|
||||
|
||||
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
|
||||
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
|
||||
when(mContextSpy.getContentResolver()).thenReturn(resolver);
|
||||
@@ -134,7 +136,8 @@ public class HighBrightnessModeControllerTest {
|
||||
initHandler(null);
|
||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken,
|
||||
mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {}, mContextSpy);
|
||||
mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {},
|
||||
null, mContextSpy);
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
|
||||
}
|
||||
@@ -144,7 +147,8 @@ public class HighBrightnessModeControllerTest {
|
||||
initHandler(null);
|
||||
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
|
||||
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken,
|
||||
mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {}, mContextSpy);
|
||||
mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {},
|
||||
null, mContextSpy);
|
||||
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
|
||||
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
|
||||
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
|
||||
@@ -699,9 +703,12 @@ public class HighBrightnessModeControllerTest {
|
||||
// Creates instance with standard initialization values.
|
||||
private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) {
|
||||
initHandler(clock);
|
||||
if (mHighBrightnessModeMetadata == null) {
|
||||
mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
|
||||
}
|
||||
return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
|
||||
DISPLAY_HEIGHT, mDisplayToken, mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX,
|
||||
DEFAULT_HBM_DATA, null, () -> {}, mContextSpy);
|
||||
DEFAULT_HBM_DATA, null, () -> {}, mHighBrightnessModeMetadata, mContextSpy);
|
||||
}
|
||||
|
||||
private void initHandler(OffsettableClock clock) {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.assertEquals;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class HighBrightnessModeMetadataTest {
|
||||
private HighBrightnessModeMetadata mHighBrightnessModeMetadata;
|
||||
|
||||
private long mRunningStartTimeMillis = -1;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkDefaultValues() {
|
||||
assertEquals(mHighBrightnessModeMetadata.getRunningStartTimeMillis(),
|
||||
mRunningStartTimeMillis);
|
||||
assertEquals(mHighBrightnessModeMetadata.getHbmEventQueue().size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkSetValues() {
|
||||
mRunningStartTimeMillis = 10;
|
||||
mHighBrightnessModeMetadata.setRunningStartTimeMillis(mRunningStartTimeMillis);
|
||||
assertEquals(mHighBrightnessModeMetadata.getRunningStartTimeMillis(),
|
||||
mRunningStartTimeMillis);
|
||||
HbmEvent expectedHbmEvent = new HbmEvent(10, 20);
|
||||
mHighBrightnessModeMetadata.addHbmEvent(expectedHbmEvent);
|
||||
HbmEvent actualHbmEvent = mHighBrightnessModeMetadata.getHbmEventQueue().peekFirst();
|
||||
assertEquals(expectedHbmEvent.toString(), actualHbmEvent.toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user