From 6d728c2b0f531c05ba977a386aa8f661f685234d Mon Sep 17 00:00:00 2001 From: raylinhsu Date: Wed, 6 Jan 2021 15:58:05 +0800 Subject: [PATCH] Fix the ambient lux which did not update for blocking zone When the display enters doze mode, it should unregister the light sensor. It should register light sensor again when the display state change from doze to on otherwise we will lost lux information and then the refresh rate could not be locked. Bug: 175655244 Test: atest DisplayModeDirectorTest Test: no fps transition in the blocking zone when the display state change Test: check if the lux will update when the display state change Change-Id: Ibf2e7cb2e336c88a583f00f59abcbc9d06ec3d62 --- .../server/display/DisplayModeDirector.java | 35 ++++++++++++---- .../display/DisplayModeDirectorTest.java | 42 ++++++++++++++++++- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 95918945eecd5..006f87571f829 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -52,9 +52,12 @@ import com.android.server.display.utils.AmbientFilterFactory; import com.android.server.utils.DeviceConfigInterface; import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Objects; @@ -1299,7 +1302,8 @@ public class DisplayModeDirector { // mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate // changeable and low power mode off. After initialization, these states will // be updated from the same handler thread. - private boolean mDefaultDisplayOn = false; + private int mDefaultDisplayState = Display.STATE_UNKNOWN; + private boolean mIsDeviceActive = false; private boolean mRefreshRateChangeable = false; private boolean mLowPowerModeEnabled = false; @@ -1480,7 +1484,8 @@ public class DisplayModeDirector { pw.println(" BrightnessObserver"); pw.println(" mAmbientLux: " + mAmbientLux); pw.println(" mBrightness: " + mBrightness); - pw.println(" mDefaultDisplayOn: " + mDefaultDisplayOn); + pw.println(" mDefaultDisplayState: " + mDefaultDisplayState); + pw.println(" mIsDeviceActive: " + mIsDeviceActive); pw.println(" mLowPowerModeEnabled: " + mLowPowerModeEnabled); pw.println(" mRefreshRateChangeable: " + mRefreshRateChangeable); pw.println(" mShouldObserveDisplayLowChange: " + mShouldObserveDisplayLowChange); @@ -1706,14 +1711,17 @@ public class DisplayModeDirector { private void updateDefaultDisplayState() { Display display = mContext.getSystemService(DisplayManager.class) .getDisplay(Display.DEFAULT_DISPLAY); - boolean defaultDisplayOn = display != null && display.getState() != Display.STATE_OFF; - setDefaultDisplayState(defaultDisplayOn); + if (display == null) { + return; + } + + setDefaultDisplayState(display.getState()); } @VisibleForTesting - public void setDefaultDisplayState(boolean on) { - if (mDefaultDisplayOn != on) { - mDefaultDisplayOn = on; + public void setDefaultDisplayState(int state) { + if (mDefaultDisplayState != state) { + mDefaultDisplayState = state; updateSensorStatus(); } } @@ -1734,15 +1742,19 @@ public class DisplayModeDirector { } private boolean isDeviceActive() { - return mDefaultDisplayOn && mInjector.isDeviceInteractive(mContext); + mIsDeviceActive = mInjector.isDeviceInteractive(mContext); + return (mDefaultDisplayState == Display.STATE_ON) + && mIsDeviceActive; } private final class LightSensorEventListener implements SensorEventListener { final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS; private float mLastSensorData; + private long mTimestamp; public void dumpLocked(PrintWriter pw) { pw.println(" mLastSensorData: " + mLastSensorData); + pw.println(" mTimestamp: " + formatTimestamp(mTimestamp)); } @Override @@ -1766,6 +1778,7 @@ public class DisplayModeDirector { } long now = SystemClock.uptimeMillis(); + mTimestamp = System.currentTimeMillis(); if (mAmbientFilter != null) { mAmbientFilter.addValue(now, mLastSensorData); } @@ -1792,6 +1805,12 @@ public class DisplayModeDirector { mHandler.removeCallbacks(mInjectSensorEventRunnable); } + private String formatTimestamp(long time) { + SimpleDateFormat dateFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); + return dateFormat.format(new Date(time)); + } + private void processSensorData(long now) { if (mAmbientFilter != null) { mAmbientLux = mAmbientFilter.getEstimate(now); 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 603608b231723..26c304f763d62 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -34,6 +34,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.internal.verification.VerificationModeFactory.times; import android.annotation.NonNull; import android.content.ContentResolver; @@ -505,7 +506,7 @@ public class DisplayModeDirectorTest { createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); setPeakRefreshRate(90); director.getSettingsObserver().setDefaultRefreshRate(90); - director.getBrightnessObserver().setDefaultDisplayState(true); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); final FakeDeviceConfig config = mInjector.getDeviceConfig(); config.setRefreshRateInLowZone(90); @@ -548,7 +549,7 @@ public class DisplayModeDirectorTest { createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); setPeakRefreshRate(90 /*fps*/); director.getSettingsObserver().setDefaultRefreshRate(90); - director.getBrightnessObserver().setDefaultDisplayState(true); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); final FakeDeviceConfig config = mInjector.getDeviceConfig(); config.setRefreshRateInHighZone(60); @@ -585,6 +586,43 @@ public class DisplayModeDirectorTest { assertVoteForRefreshRateLocked(vote, 60 /*fps*/); } + @Test + public void testSensorRegistration() { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); + setPeakRefreshRate(90 /*fps*/); + director.getSettingsObserver().setDefaultRefreshRate(90); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + + director.start(sensorManager); + ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(SensorEventListener.class); + Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) + .registerListener( + listenerCaptor.capture(), + eq(lightSensor), + anyInt(), + any(Handler.class)); + + // Dispaly state changed from On to Doze + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_DOZE); + Mockito.verify(sensorManager) + .unregisterListener(listenerCaptor.capture()); + + // Dispaly state changed from Doze to On + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + Mockito.verify(sensorManager, times(2)) + .registerListener( + listenerCaptor.capture(), + eq(lightSensor), + anyInt(), + any(Handler.class)); + + } + private void assertVoteForRefreshRateLocked(Vote vote, float refreshRate) { assertThat(vote).isNotNull(); final DisplayModeDirector.RefreshRateRange expectedRange =