From b6104ac4c7feb93ef5eb4611b76f12ad728c1822 Mon Sep 17 00:00:00 2001 From: Oleg Petsjonkin Date: Thu, 19 Jan 2023 16:37:17 +0000 Subject: [PATCH] RESTRICT AUTOMERGE adding new refresh rate priority new priority for auth screen. this allow to request higher refresh rate for screens where auth possible, and avoid swithcing rate when LHBM mode is activated Test: atest DisplayModeDirectorTest Bug: b/263908377 Change-Id: I2c19941dd9507d7e9171e30f6f433384ef620a92 --- .../fingerprint/IUdfpsHbmListener.aidl | 10 +++ .../server/display/DisplayModeDirector.java | 65 +++++++++++++----- .../display/DisplayModeDirectorTest.java | 68 +++++++++++++++++++ 3 files changed, 125 insertions(+), 18 deletions(-) diff --git a/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl b/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl index 9c2aa66993347..a36ccf6150bae 100644 --- a/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl +++ b/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl @@ -39,5 +39,15 @@ oneway interface IUdfpsHbmListener { * {@link android.view.Display#getDisplayId()}. */ void onHbmDisabled(int displayId); + + /** + * To avoid delay in switching refresh rate when activating LHBM, allow screens to request + * higher refersh rate if auth is possible on particular screen + * + * @param displayId The displayId for which the refresh rate should be unset. See + * {@link android.view.Display#getDisplayId()}. + * @param isPossible If authentication is possible on particualr screen + */ + void onAuthenticationPossible(int displayId, boolean isPossible); } diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 045be763bc351..7c6b667f585fe 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -561,7 +561,7 @@ public class DisplayModeDirector { /** * Sets the display mode switching type. - * @param newType + * @param newType new mode switching type */ public void setModeSwitchingType(@DisplayManager.SwitchingType int newType) { synchronized (mLock) { @@ -678,6 +678,18 @@ public class DisplayModeDirector { notifyDesiredDisplayModeSpecsChangedLocked(); } + @GuardedBy("mLock") + private float getMaxRefreshRateLocked(int displayId) { + Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); + float maxRefreshRate = 0f; + for (Display.Mode mode : modes) { + if (mode.getRefreshRate() > maxRefreshRate) { + maxRefreshRate = mode.getRefreshRate(); + } + } + return maxRefreshRate; + } + private void notifyDesiredDisplayModeSpecsChangedLocked() { if (mDesiredDisplayModeSpecsListener != null && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) { @@ -996,25 +1008,29 @@ public class DisplayModeDirector { // of low priority voters. It votes [0, max(PEAK, MIN)] public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 7; + // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh + // rate to max value (same as for PRIORITY_UDFPS) on lock screen + public static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 8; + // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on. - public static final int PRIORITY_LOW_POWER_MODE = 8; + public static final int PRIORITY_LOW_POWER_MODE = 9; // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the // higher priority voters' result is a range, it will fix the rate to a single choice. // It's used to avoid refresh rate switches in certain conditions which may result in the // user seeing the display flickering when the switches occur. - public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9; + public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 10; // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. - public static final int PRIORITY_SKIN_TEMPERATURE = 10; + public static final int PRIORITY_SKIN_TEMPERATURE = 11; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. - public static final int PRIORITY_PROXIMITY = 11; + public static final int PRIORITY_PROXIMITY = 12; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. - public static final int PRIORITY_UDFPS = 12; + public static final int PRIORITY_UDFPS = 13; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. @@ -1117,6 +1133,8 @@ public class DisplayModeDirector { return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE"; case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE: return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE"; + case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE: + return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE"; default: return Integer.toString(priority); } @@ -2329,6 +2347,7 @@ public class DisplayModeDirector { private class UdfpsObserver extends IUdfpsHbmListener.Stub { private final SparseBooleanArray mLocalHbmEnabled = new SparseBooleanArray(); + private final SparseBooleanArray mAuthenticationPossible = new SparseBooleanArray(); public void observe() { StatusBarManagerInternal statusBar = @@ -2354,25 +2373,28 @@ public class DisplayModeDirector { private void updateHbmStateLocked(int displayId, boolean enabled) { mLocalHbmEnabled.put(displayId, enabled); - updateVoteLocked(displayId); + updateVoteLocked(displayId, enabled, Vote.PRIORITY_UDFPS); } - private void updateVoteLocked(int displayId) { + @Override + public void onAuthenticationPossible(int displayId, boolean isPossible) { + synchronized (mLock) { + mAuthenticationPossible.put(displayId, isPossible); + updateVoteLocked(displayId, isPossible, + Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + } + } + + @GuardedBy("mLock") + private void updateVoteLocked(int displayId, boolean enabled, int votePriority) { final Vote vote; - if (mLocalHbmEnabled.get(displayId)) { - Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); - float maxRefreshRate = 0f; - for (Display.Mode mode : modes) { - if (mode.getRefreshRate() > maxRefreshRate) { - maxRefreshRate = mode.getRefreshRate(); - } - } + if (enabled) { + float maxRefreshRate = DisplayModeDirector.this.getMaxRefreshRateLocked(displayId); vote = Vote.forRefreshRates(maxRefreshRate, maxRefreshRate); } else { vote = null; } - - DisplayModeDirector.this.updateVoteLocked(displayId, Vote.PRIORITY_UDFPS, vote); + DisplayModeDirector.this.updateVoteLocked(displayId, votePriority, vote); } void dumpLocked(PrintWriter pw) { @@ -2383,6 +2405,13 @@ public class DisplayModeDirector { final String enabled = mLocalHbmEnabled.valueAt(i) ? "enabled" : "disabled"; pw.println(" Display " + displayId + ": " + enabled); } + pw.println(" mAuthenticationPossible: "); + for (int i = 0; i < mAuthenticationPossible.size(); i++) { + final int displayId = mAuthenticationPossible.keyAt(i); + final String isPossible = mAuthenticationPossible.valueAt(i) ? "possible" + : "impossible"; + pw.println(" Display " + displayId + ": " + isPossible); + } } } diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index af39dd44065e5..2cc6bd557aeae 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -2011,6 +2011,74 @@ public class DisplayModeDirectorTest { eq(lightSensorTwo), anyInt(), any(Handler.class)); } + @Test + public void testAuthenticationPossibleSetsPhysicalRateRangesToMax() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + // don't call director.start(createMockSensorManager()); + // DisplayObserver will reset mSupportedModesByDisplay + director.onBootCompleted(); + ArgumentCaptor captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + + captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + assertThat(vote.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(vote.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + } + + @Test + public void testAuthenticationPossibleUnsetsVote() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + director.onBootCompleted(); + ArgumentCaptor captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); + captor.getValue().onAuthenticationPossible(DISPLAY_ID, false); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + assertNull(vote); + } + + @Test + public void testUdfpsRequestSetsPhysicalRateRangesToMax() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + // don't call director.start(createMockSensorManager()); + // DisplayObserver will reset mSupportedModesByDisplay + director.onBootCompleted(); + ArgumentCaptor captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + + captor.getValue().onHbmEnabled(DISPLAY_ID); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); + assertThat(vote.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(vote.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + } + + @Test + public void testUdfpsRequestUnsetsUnsetsVote() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + director.onBootCompleted(); + ArgumentCaptor captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + captor.getValue().onHbmEnabled(DISPLAY_ID); + captor.getValue().onHbmEnabled(DISPLAY_ID); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); + assertNull(vote); + } + private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) { return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); }