Snap for 7796451 from 250448c0bc to sc-qpr1-release

Change-Id: I5e48f86ac700b2c10feb07688fb410cf91b58e8e
This commit is contained in:
Android Build Coastguard Worker
2021-10-06 01:06:59 +00:00
22 changed files with 401 additions and 186 deletions

View File

@@ -60,12 +60,18 @@ public final class BrightnessInfo implements Parcelable {
/** Brightness */
public final float brightness;
/** Brightness after {@link DisplayPowerController} adjustments */
public final float adjustedBrightness;
/** Current minimum supported brightness. */
public final float brightnessMinimum;
/** Current maximum supported brightness. */
public final float brightnessMaximum;
/** Brightness values greater than this point are only used in High Brightness Mode. */
public final float highBrightnessTransitionPoint;
/**
* Current state of high brightness mode.
* Can be any of HIGH_BRIGHTNESS_MODE_* values.
@@ -73,11 +79,20 @@ public final class BrightnessInfo implements Parcelable {
public final int highBrightnessMode;
public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum,
@HighBrightnessMode int highBrightnessMode) {
@HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint) {
this(brightness, brightness, brightnessMinimum, brightnessMaximum, highBrightnessMode,
highBrightnessTransitionPoint);
}
public BrightnessInfo(float brightness, float adjustedBrightness, float brightnessMinimum,
float brightnessMaximum, @HighBrightnessMode int highBrightnessMode,
float highBrightnessTransitionPoint) {
this.brightness = brightness;
this.adjustedBrightness = adjustedBrightness;
this.brightnessMinimum = brightnessMinimum;
this.brightnessMaximum = brightnessMaximum;
this.highBrightnessMode = highBrightnessMode;
this.highBrightnessTransitionPoint = highBrightnessTransitionPoint;
}
/**
@@ -103,9 +118,11 @@ public final class BrightnessInfo implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloat(brightness);
dest.writeFloat(adjustedBrightness);
dest.writeFloat(brightnessMinimum);
dest.writeFloat(brightnessMaximum);
dest.writeInt(highBrightnessMode);
dest.writeFloat(highBrightnessTransitionPoint);
}
public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR =
@@ -123,9 +140,11 @@ public final class BrightnessInfo implements Parcelable {
private BrightnessInfo(Parcel source) {
brightness = source.readFloat();
adjustedBrightness = source.readFloat();
brightnessMinimum = source.readFloat();
brightnessMaximum = source.readFloat();
highBrightnessMode = source.readInt();
highBrightnessTransitionPoint = source.readFloat();
}
}

View File

@@ -782,7 +782,7 @@ public class TextLine {
int spanStart = runStart;
int spanLimit;
if (mSpanned == null) {
if (mSpanned == null || runStart == runLimit) {
spanLimit = runLimit;
} else {
int target = after ? offset + 1 : offset;

View File

@@ -248,6 +248,8 @@
android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
<protected-broadcast
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />

View File

@@ -28,9 +28,4 @@
android:startOffset="0"
android:duration="500"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:duration="600"/>
</set>
</set>

View File

@@ -28,9 +28,4 @@
android:startOffset="0"
android:duration="500"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:duration="600"/>
</set>
</set>

View File

@@ -30,9 +30,4 @@
android:startOffset="0"
android:duration="500"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:duration="600"/>
</set>
</set>

View File

@@ -30,9 +30,4 @@
android:startOffset="0"
android:duration="500"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"
android:duration="600"/>
</set>
</set>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ বিফল হৈছে -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"সেৱাটো ছাবস্ক্ৰাইব কৰা নাই -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"এটা APNৰ বাবে একাধিক PDN সংযোগৰ অনুমতি নাই -55-"</string>
</resources>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"যাচাই করা যায়নি -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"পরিষেবা সাবস্ক্রাইব করা হয়নি -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"নির্দিষ্ট কোনও APN-এর জন্য একাধিক PDN কানেকশন অনুমোদিত নয় -55-"</string>
</resources>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ÉCHEC DE L\'AUTHENTIFICATION -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NON ABONNÉ AU SERVICE -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Connexions PDN multiples interdites pour un APN donné -55-"</string>
</resources>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"પ્રમાણીકરણ નિષ્ફળ થયું -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"સેવા સબ્સ્ક્રાઇબ કરી નથી -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"આપેલા APN માટે એક કરતાં વધારે PDN કનેક્શનની મંજૂરી નથી -55-"</string>
</resources>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"توثیق کی ناکامی -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"سروس کو سبسکرائب نہیں کیا -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"‏ایک دیئے گئے APN کے لیے متعدد PDN کنکشنز کی اجازت نہیں ہے -55-"</string>
</resources>

View File

@@ -20,10 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
<!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) -->
<skip />
<!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) -->
<skip />
<!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) -->
<skip />
<string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"身份验证失败 -29-"</string>
<string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未订阅服务 -33-"</string>
<string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不能有多个 PDN 连接 -55-"</string>
</resources>

View File

@@ -260,6 +260,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private boolean mExpandedInThisMotion;
private boolean mShouldShowShelfOnly;
protected boolean mScrollingEnabled;
private boolean mIsCurrentUserSetup;
protected FooterView mFooterView;
protected EmptyShadeView mEmptyShadeView;
private boolean mDismissAllInProgress;
@@ -687,6 +688,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mController.hasActiveClearableNotifications(ROWS_ALL);
RemoteInputController remoteInputController = mRemoteInputManager.getController();
boolean showFooterView = (showDismissView || getVisibleNotificationCount() > 0)
&& mIsCurrentUserSetup // see: b/193149550
&& mStatusBarState != StatusBarState.KEYGUARD
&& !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
&& (remoteInputController == null || !remoteInputController.isRemoteInputActive());
@@ -5598,6 +5600,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mAnimateNextTopPaddingChange = true;
}
/**
* Sets whether the current user is set up, which is required to show the footer (b/193149550)
*/
public void setCurrentUserSetup(boolean isCurrentUserSetup) {
if (mIsCurrentUserSetup != isCurrentUserSetup) {
mIsCurrentUserSetup = isCurrentUserSetup;
updateFooter();
}
}
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/

View File

@@ -117,6 +117,8 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
@@ -144,6 +146,7 @@ public class NotificationStackScrollLayoutController {
private final HeadsUpManagerPhone mHeadsUpManager;
private final NotificationRoundnessManager mNotificationRoundnessManager;
private final TunerService mTunerService;
private final DeviceProvisionedController mDeviceProvisionedController;
private final DynamicPrivacyController mDynamicPrivacyController;
private final ConfigurationController mConfigurationController;
private final ZenModeController mZenModeController;
@@ -219,6 +222,28 @@ public class NotificationStackScrollLayoutController {
}
};
private final DeviceProvisionedListener mDeviceProvisionedListener =
new DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
updateCurrentUserIsSetup();
}
@Override
public void onUserSwitched() {
updateCurrentUserIsSetup();
}
@Override
public void onUserSetupChanged() {
updateCurrentUserIsSetup();
}
private void updateCurrentUserIsSetup() {
mView.setCurrentUserSetup(mDeviceProvisionedController.isCurrentUserSetup());
}
};
private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> {
if (mView.isExpanded()) {
// The bottom might change because we're using the final actual height of the view
@@ -588,6 +613,7 @@ public class NotificationStackScrollLayoutController {
HeadsUpManagerPhone headsUpManager,
NotificationRoundnessManager notificationRoundnessManager,
TunerService tunerService,
DeviceProvisionedController deviceProvisionedController,
DynamicPrivacyController dynamicPrivacyController,
ConfigurationController configurationController,
SysuiStatusBarStateController statusBarStateController,
@@ -624,6 +650,7 @@ public class NotificationStackScrollLayoutController {
mHeadsUpManager = headsUpManager;
mNotificationRoundnessManager = notificationRoundnessManager;
mTunerService = tunerService;
mDeviceProvisionedController = deviceProvisionedController;
mDynamicPrivacyController = dynamicPrivacyController;
mConfigurationController = configurationController;
mStatusBarStateController = statusBarStateController;
@@ -762,6 +789,9 @@ public class NotificationStackScrollLayoutController {
return Unit.INSTANCE;
});
// callback is invoked synchronously, updating mView immediately
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
if (mView.isAttachedToWindow()) {
mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
}

View File

@@ -290,6 +290,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
public void testUpdateFooter_noNotifications() {
setBarStateForTest(StatusBarState.SHADE);
mStackScroller.setCurrentUserSetup(true);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
mStackScroller.updateFooter();
@@ -299,6 +301,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
public void testUpdateFooter_remoteInput() {
setBarStateForTest(StatusBarState.SHADE);
mStackScroller.setCurrentUserSetup(true);
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
when(row.canViewBeDismissed()).thenReturn(true);
@@ -318,6 +321,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
public void testUpdateFooter_oneClearableNotification() {
setBarStateForTest(StatusBarState.SHADE);
mStackScroller.setCurrentUserSetup(true);
when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
@@ -330,9 +334,26 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
verify(mStackScroller).updateFooterView(true, true, true);
}
@Test
public void testUpdateFooter_oneClearableNotification_beforeUserSetup() {
setBarStateForTest(StatusBarState.SHADE);
mStackScroller.setCurrentUserSetup(false);
when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
.thenReturn(true);
when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
mStackScroller.updateFooter();
verify(mStackScroller).updateFooterView(false, true, true);
}
@Test
public void testUpdateFooter_oneNonClearableNotification() {
setBarStateForTest(StatusBarState.SHADE);
mStackScroller.setCurrentUserSetup(true);
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
when(row.canViewBeDismissed()).thenReturn(false);
@@ -351,6 +372,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
public void testUpdateFooter_atEnd() {
mStackScroller.setCurrentUserSetup(true);
// add footer
mStackScroller.inflateFooterView();

View File

@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
@@ -98,6 +99,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@Mock private TunerService mTunerService;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private ConfigurationController mConfigurationController;
@Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
@@ -153,6 +155,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
mHeadsUpManager,
mNotificationRoundnessManager,
mTunerService,
mDeviceProvisionedController,
mDynamicPrivacyController,
mConfigurationController,
mSysuiStatusBarStateController,

View File

@@ -17,6 +17,7 @@
package com.android.server.display;
import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
import static android.os.PowerManager.BRIGHTNESS_INVALID;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,6 +41,7 @@ import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -60,6 +62,7 @@ import android.view.DisplayInfo;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.display.utils.AmbientFilter;
@@ -155,7 +158,7 @@ public class DisplayModeDirector {
mAppRequestObserver = new AppRequestObserver();
mSettingsObserver = new SettingsObserver(context, handler);
mDisplayObserver = new DisplayObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler, injector);
mUdfpsObserver = new UdfpsObserver();
final BallotBox ballotBox = (displayId, priority, vote) -> {
synchronized (mLock) {
@@ -1427,8 +1430,6 @@ public class DisplayModeDirector {
@Override
public void onDisplayChanged(int displayId) {
updateDisplayModes(displayId);
// TODO: Break the coupling between DisplayObserver and BrightnessObserver.
mBrightnessObserver.onDisplayChanged(displayId);
}
private void updateDisplayModes(int displayId) {
@@ -1465,7 +1466,7 @@ public class DisplayModeDirector {
* {@link R.array#config_ambientThresholdsOfPeakRefreshRate}.
*/
@VisibleForTesting
public class BrightnessObserver extends ContentObserver {
public class BrightnessObserver implements DisplayManager.DisplayListener {
private final static int LIGHT_SENSOR_RATE_MS = 250;
private int[] mLowDisplayBrightnessThresholds;
private int[] mLowAmbientBrightnessThresholds;
@@ -1488,6 +1489,8 @@ public class DisplayModeDirector {
private int mBrightness = -1;
private final Context mContext;
private final Injector mInjector;
private final Handler mHandler;
// Enable light sensor only when mShouldObserveAmbientLowChange is true or
// mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate
@@ -1500,9 +1503,11 @@ public class DisplayModeDirector {
private int mRefreshRateInLowZone;
private int mRefreshRateInHighZone;
BrightnessObserver(Context context, Handler handler) {
super(handler);
BrightnessObserver(Context context, Handler handler, Injector injector) {
mContext = context;
mHandler = handler;
mInjector = injector;
mLowDisplayBrightnessThresholds = context.getResources().getIntArray(
R.array.config_brightnessThresholdsOfPeakRefreshRate);
mLowAmbientBrightnessThresholds = context.getResources().getIntArray(
@@ -1569,8 +1574,7 @@ public class DisplayModeDirector {
public void observe(SensorManager sensorManager) {
mSensorManager = sensorManager;
final ContentResolver cr = mContext.getContentResolver();
mBrightness = Settings.System.getIntForUser(cr,
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
// DeviceConfig is accessible after system ready.
int[] lowDisplayBrightnessThresholds =
@@ -1603,6 +1607,10 @@ public class DisplayModeDirector {
restartObserver();
mDeviceConfigDisplaySettings.startListening();
mInjector.registerDisplayListener(this, mHandler,
DisplayManager.EVENT_FLAG_DISPLAY_CHANGED |
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
public void setLoggingEnabled(boolean loggingEnabled) {
@@ -1718,28 +1726,30 @@ public class DisplayModeDirector {
}
}
@Override
public void onDisplayAdded(int displayId) {}
@Override
public void onDisplayRemoved(int displayId) {}
@Override
public void onDisplayChanged(int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
updateDefaultDisplayState();
}
}
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
synchronized (mLock) {
final ContentResolver cr = mContext.getContentResolver();
int brightness = Settings.System.getIntForUser(cr,
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
if (brightness != mBrightness) {
mBrightness = brightness;
onBrightnessChangedLocked();
// We don't support multiple display blocking zones yet, so only handle
// brightness changes for the default display for now.
int brightness = getBrightness(displayId);
synchronized (mLock) {
if (brightness != mBrightness) {
mBrightness = brightness;
onBrightnessChangedLocked();
}
}
}
}
private void restartObserver() {
final ContentResolver cr = mContext.getContentResolver();
if (mRefreshRateInLowZone > 0) {
mShouldObserveDisplayLowChange = hasValidThreshold(
mLowDisplayBrightnessThresholds);
@@ -1760,15 +1770,6 @@ public class DisplayModeDirector {
mShouldObserveAmbientHighChange = false;
}
if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) {
// Content Service does not check if an listener has already been registered.
// To ensure only one listener is registered, force an unregistration first.
mInjector.unregisterBrightnessObserver(cr, this);
mInjector.registerBrightnessObserver(cr, this);
} else {
mInjector.unregisterBrightnessObserver(cr, this);
}
if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
Resources resources = mContext.getResources();
String lightSensorType = resources.getString(
@@ -1968,6 +1969,15 @@ public class DisplayModeDirector {
return mDefaultDisplayState == Display.STATE_ON;
}
private int getBrightness(int displayId) {
final BrightnessInfo info = mInjector.getBrightnessInfo(displayId);
if (info != null) {
return BrightnessSynchronizer.brightnessFloatToInt(info.adjustedBrightness);
}
return BRIGHTNESS_INVALID;
}
private final class LightSensorEventListener implements SensorEventListener {
final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
private float mLastSensorData;
@@ -2283,6 +2293,7 @@ public class DisplayModeDirector {
private final BallotBox mBallotBox;
private final Handler mHandler;
private final SparseIntArray mHbmMode = new SparseIntArray();
private final SparseBooleanArray mHbmActive = new SparseBooleanArray();
private final Injector mInjector;
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
private int mRefreshRateInHbmSunlight;
@@ -2351,6 +2362,7 @@ public class DisplayModeDirector {
public void onDisplayRemoved(int displayId) {
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
mHbmMode.delete(displayId);
mHbmActive.delete(displayId);
}
@Override
@@ -2360,12 +2372,17 @@ public class DisplayModeDirector {
// Display no longer there. Assume we'll get an onDisplayRemoved very soon.
return;
}
final int hbmMode = info.highBrightnessMode;
if (hbmMode == mHbmMode.get(displayId)) {
final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF &&
info.adjustedBrightness > info.highBrightnessTransitionPoint;
if (hbmMode == mHbmMode.get(displayId) &&
isHbmActive == mHbmActive.get(displayId)) {
// no change, ignore.
return;
}
mHbmMode.put(displayId, hbmMode);
mHbmActive.put(displayId, isHbmActive);
recalculateVotesForDisplay(displayId);
}
@@ -2379,28 +2396,36 @@ public class DisplayModeDirector {
}
private void recalculateVotesForDisplay(int displayId) {
final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
Vote vote = null;
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
break;
if (mHbmActive.get(displayId, false)) {
final int hbmMode =
mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
vote = Vote.forRefreshRates(limitation.range.min,
limitation.range.max);
break;
}
}
}
} else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR &&
mRefreshRateInHbmHdr > 0) {
// HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
// a vote from Device properties
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
} else {
Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId);
}
}
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
&& mRefreshRateInHbmHdr > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
}
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
}
@@ -2408,6 +2433,7 @@ public class DisplayModeDirector {
void dumpLocked(PrintWriter pw) {
pw.println(" HbmObserver");
pw.println(" mHbmMode: " + mHbmMode);
pw.println(" mHbmActive: " + mHbmActive);
pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight);
pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr);
}
@@ -2630,19 +2656,11 @@ public class DisplayModeDirector {
}
interface Injector {
// TODO: brightnessfloat: change this to the float setting
Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
@NonNull
DeviceConfigInterface getDeviceConfig();
void registerBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
void unregisterBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
@@ -2671,19 +2689,6 @@ public class DisplayModeDirector {
return DeviceConfigInterface.REAL;
}
@Override
public void registerBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/,
observer, UserHandle.USER_SYSTEM);
}
@Override
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.unregisterContentObserver(observer);
}
@Override
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {

View File

@@ -1259,10 +1259,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true);
}
// We save the brightness info *after* the brightness setting has been changed so that
// the brightness info reflects the latest value.
saveBrightnessInfo(getScreenBrightnessSetting());
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1393,6 +1389,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
hadUserBrightnessPoint);
}
// We save the brightness info *after* the brightness setting has been changed and
// adjustments made so that the brightness info reflects the latest value.
saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
} else {
saveBrightnessInfo(getScreenBrightnessSetting());
}
// Log any changes to what is currently driving the brightness setting.
@@ -1509,18 +1510,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
synchronized (mCachedBrightnessInfo) {
return new BrightnessInfo(
mCachedBrightnessInfo.brightness,
mCachedBrightnessInfo.adjustedBrightness,
mCachedBrightnessInfo.brightnessMin,
mCachedBrightnessInfo.brightnessMax,
mCachedBrightnessInfo.hbmMode);
mCachedBrightnessInfo.hbmMode,
mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
}
private void saveBrightnessInfo(float brightness) {
saveBrightnessInfo(brightness, brightness);
}
private void saveBrightnessInfo(float brightness, float adjustedBrightness) {
synchronized (mCachedBrightnessInfo) {
mCachedBrightnessInfo.brightness = brightness;
mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness;
mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin();
mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax();
mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode();
mCachedBrightnessInfo.highBrightnessTransitionPoint =
mHbmController.getTransitionPoint();
}
}
@@ -2195,6 +2205,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
pw.println(" mColorFadeEnabled=" + mColorFadeEnabled);
synchronized (mCachedBrightnessInfo) {
pw.println(" mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness);
pw.println(" mCachedBrightnessInfo.adjustedBrightness=" +
mCachedBrightnessInfo.adjustedBrightness);
pw.println(" mCachedBrightnessInfo.brightnessMin=" +
mCachedBrightnessInfo.brightnessMin);
pw.println(" mCachedBrightnessInfo.brightnessMax=" +
mCachedBrightnessInfo.brightnessMax);
pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode);
pw.println(" mCachedBrightnessInfo.highBrightnessTransitionPoint=" +
mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -2606,8 +2628,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
static class CachedBrightnessInfo {
public float brightness;
public float adjustedBrightness;
public float brightnessMin;
public float brightnessMax;
public int hbmMode;
public float highBrightnessTransitionPoint;
}
}

View File

@@ -59,6 +59,9 @@ class HighBrightnessModeController {
private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f;
@VisibleForTesting
static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
private final float mBrightnessMin;
private final float mBrightnessMax;
private final Handler mHandler;
@@ -214,6 +217,14 @@ class HighBrightnessModeController {
return mHbmMode;
}
float getTransitionPoint() {
if (deviceSupportsHbm()) {
return mHbmData.transitionPoint;
} else {
return HBM_TRANSITION_POINT_INVALID;
}
}
void stop() {
registerHdrListener(null /*displayToken*/);
mSkinThermalStatusObserver.stopObserving();

View File

@@ -26,6 +26,7 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_R
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE;
import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
import static com.google.common.truth.Truth.assertThat;
@@ -74,6 +75,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
@@ -110,6 +112,7 @@ public class DisplayModeDirectorTest {
private static final boolean DEBUG = false;
private static final float FLOAT_TOLERANCE = 0.01f;
private static final int DISPLAY_ID = 0;
private static final float TRANSITION_POINT = 0.763f;
private Context mContext;
private FakesInjector mInjector;
@@ -751,19 +754,27 @@ public class DisplayModeDirectorTest {
director.start(sensorManager);
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor<DisplayListener> displayListenerCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
.registerListener(
listenerCaptor.capture(),
sensorListenerCaptor.capture(),
eq(lightSensor),
anyInt(),
any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
SensorEventListener sensorListener = sensorListenerCaptor.getValue();
setBrightness(10);
setBrightness(10, 10, displayListener);
// Sensor reads 20 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 90 /*fps*/);
@@ -771,9 +782,11 @@ public class DisplayModeDirectorTest {
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
setBrightness(125);
// We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this
// parameter to the necessary threshold
setBrightness(10, 125, displayListener);
// Sensor reads 1000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
@@ -799,6 +812,14 @@ public class DisplayModeDirectorTest {
director.start(sensorManager);
ArgumentCaptor<DisplayListener> displayListenerCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
@@ -807,20 +828,22 @@ public class DisplayModeDirectorTest {
eq(lightSensor),
anyInt(),
any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
SensorEventListener sensorListener = listenerCaptor.getValue();
setBrightness(100);
setBrightness(100, 100, displayListener);
// Sensor reads 2000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNull();
setBrightness(255);
// We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this
// parameter to the necessary threshold
setBrightness(100, 255, displayListener);
// Sensor reads 9000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 60 /*fps*/);
@@ -1435,16 +1458,58 @@ public class DisplayModeDirectorTest {
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HBM
// Turn on HBM, with brightness in the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR));
new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, hbmRefreshRate);
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, hbmRefreshRate);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1514,7 +1579,8 @@ 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));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, initialRefreshRate);
@@ -1531,14 +1597,16 @@ 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));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// 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));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, updatedRefreshRate);
@@ -1553,7 +1621,8 @@ 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));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1584,14 +1653,82 @@ 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));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
}
@Test
public void testHbmVoting_HbmUnsupported() {
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
director.start(createMockSensorManager());
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
DisplayListener listener = captor.getValue();
// Specify Limitation
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn(
List.of(new RefreshRateLimitation(
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE,
60.0f, 60.0f)));
// Verify that there is no HBM vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, 60.0f);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on Sunlight HBM when HBM is unsupported; expect an invalid transition point and
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HDR HBM when HBM is unsupported; expect an invalid transition point and
// 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));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1600,7 +1737,7 @@ 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));
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
@@ -1679,7 +1816,8 @@ 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));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, 60.f);
@@ -1834,11 +1972,14 @@ public class DisplayModeDirectorTest {
}
}
private void setBrightness(int brightness) {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,
brightness);
mInjector.notifyBrightnessChanged();
waitForIdleSync();
private void setBrightness(int brightness, int adjustedBrightness, DisplayListener listener) {
float floatBri = BrightnessSynchronizer.brightnessIntToFloat(brightness);
float floatAdjBri = BrightnessSynchronizer.brightnessIntToFloat(adjustedBrightness);
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
}
private void setPeakRefreshRate(float fps) {
@@ -1901,27 +2042,6 @@ public class DisplayModeDirectorTest {
return mDeviceConfig;
}
@Override
public void registerBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
if (mBrightnessObserver != null) {
throw new IllegalStateException("Tried to register a second brightness observer");
}
mBrightnessObserver = observer;
}
@Override
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
mBrightnessObserver = null;
}
void notifyBrightnessChanged() {
if (mBrightnessObserver != null) {
mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI);
}
}
@Override
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {

View File

@@ -20,6 +20,8 @@ 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;
import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
@@ -124,6 +126,7 @@ public class HighBrightnessModeControllerTest {
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
DEFAULT_MAX, null, () -> {}, mContextSpy);
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
}
@Test
@@ -135,6 +138,7 @@ public class HighBrightnessModeControllerTest {
hbmc.setAutoBrightnessEnabled(true);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
}
@Test