diff options
| author | 2024-10-30 17:36:59 +0000 | |
|---|---|---|
| committer | 2024-11-27 13:31:39 +0000 | |
| commit | 5ac5a9859a6b214e4184e54294c3a657ea9b1cf5 (patch) | |
| tree | 862f8cd948ea352ea755fbbdb10e271848a5f389 | |
| parent | f2779a3f7282febbc2c3724125f6c1053650a953 (diff) | |
Brightness Tracker disable sensor if screen off
Brightness Tracker used to listen to the SCREEN_ON and SCREEN_OFF intent. The SCREEN_OFF intent isn't sent when the screen is off due to proximity, so the sensor wouldn't be disabled. Now we're observing display state changes instead.
The display listener needs to be registered if the following conditions are met:
- there is a light sensor
- the device is interactive
- the brightness mode is automatic
Bug: 362940418
Flag: EXEMPT bugfix
Test: BrightnessTrackerTest
Change-Id: Ie5652aebb26658da7d3d6a006a1e143a08e71998
| -rw-r--r-- | services/core/java/com/android/server/display/BrightnessTracker.java | 73 | ||||
| -rw-r--r-- | services/tests/displayservicetests/src/com/android/server/display/BrightnessTrackerTest.java | 85 |
2 files changed, 127 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index 0f65360e9ee4..c19d2c9091c3 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -130,6 +130,8 @@ public class BrightnessTracker { private static final int MSG_START_SENSOR_LISTENER = 3; private static final int MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED = 4; private static final int MSG_SENSOR_CHANGED = 5; + private static final int MSG_START_DISPLAY_LISTENER = 6; + private static final int MSG_STOP_DISPLAY_LISTENER = 7; private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); @@ -159,7 +161,9 @@ public class BrightnessTracker { private SensorListener mSensorListener; private Sensor mLightSensor; private SettingsObserver mSettingsObserver; - private DisplayListener mDisplayListener; + private final DisplayListener mDisplayListener = new DisplayListener(); + private boolean mDisplayListenerRegistered; + private boolean mIsDisplayActive; private boolean mSensorRegistered; private boolean mColorSamplingEnabled; private int mNoFramesToSample; @@ -231,6 +235,8 @@ public class BrightnessTracker { mSettingsObserver = new SettingsObserver(mBgHandler); mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver); + startDisplayListener(); + mIsDisplayActive = isDisplayActive(); startSensorListener(); final IntentFilter intentFilter = new IntentFilter(); @@ -260,6 +266,7 @@ public class BrightnessTracker { Slog.d(TAG, "Stop"); } mBgHandler.removeMessages(MSG_BACKGROUND_START); + stopDisplayListener(); stopSensorListener(); mInjector.unregisterSensorListener(mContext, mSensorListener); mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver); @@ -443,6 +450,11 @@ public class BrightnessTracker { private void handleSensorChanged(Sensor lightSensor) { if (mLightSensor != lightSensor) { mLightSensor = lightSensor; + if (lightSensor != null) { + mBgHandler.sendEmptyMessage(MSG_START_DISPLAY_LISTENER); + } else { + mBgHandler.sendEmptyMessage(MSG_STOP_DISPLAY_LISTENER); + } stopSensorListener(); // Attempt to restart the sensor listener. It will check to see if it should be running // so there is no need to also check here. @@ -455,6 +467,7 @@ public class BrightnessTracker { && mLightSensor != null && mAmbientBrightnessStatsTracker != null && mInjector.isInteractive(mContext) + && mIsDisplayActive && mInjector.isBrightnessModeAutomatic(mContentResolver)) { mAmbientBrightnessStatsTracker.start(); mSensorRegistered = true; @@ -825,11 +838,14 @@ public class BrightnessTracker { pw.println(" mColorSamplingEnabled=" + mColorSamplingEnabled); pw.println(" mNoFramesToSample=" + mNoFramesToSample); pw.println(" mFrameRate=" + mFrameRate); + pw.println(" mIsDisplayActive=" + mIsDisplayActive); + pw.println(" mDisplayListenerRegistered=" + mDisplayListenerRegistered); } private void enableColorSampling() { if (!mInjector.isBrightnessModeAutomatic(mContentResolver) || !mInjector.isInteractive(mContext) + || !mIsDisplayActive || mColorSamplingEnabled || !mShouldCollectColorSample) { return; @@ -860,10 +876,6 @@ public class BrightnessTracker { + mNoFramesToSample + " frames, success=" + mColorSamplingEnabled); } } - if (mColorSamplingEnabled && mDisplayListener == null) { - mDisplayListener = new DisplayListener(); - mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler); - } } private void disableColorSampling() { @@ -872,10 +884,6 @@ public class BrightnessTracker { } mInjector.enableColorSampling(/* enable= */ false, /* noFrames= */ 0); mColorSamplingEnabled = false; - if (mDisplayListener != null) { - mInjector.unRegisterDisplayListener(mContext, mDisplayListener); - mDisplayListener = null; - } if (DEBUG) { Slog.i(TAG, "turning off color sampling"); } @@ -913,6 +921,25 @@ public class BrightnessTracker { } } + private boolean isDisplayActive() { + return Display.isActiveState(mInjector.getDisplayState(mContext)); + } + + private void startDisplayListener() { + if (!mDisplayListenerRegistered && mLightSensor != null && mInjector.isInteractive(mContext) + && mInjector.isBrightnessModeAutomatic(mContentResolver)) { + mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler); + mDisplayListenerRegistered = true; + } + } + + private void stopDisplayListener() { + if (mDisplayListenerRegistered) { + mInjector.unregisterDisplayListener(mContext, mDisplayListener); + mDisplayListenerRegistered = false; + } + } + private final class SensorListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent event) { @@ -941,6 +968,15 @@ public class BrightnessTracker { public void onDisplayChanged(int displayId) { if (displayId == Display.DEFAULT_DISPLAY) { updateColorSampling(); + boolean isDisplayActive = isDisplayActive(); + if (mIsDisplayActive != isDisplayActive) { + mIsDisplayActive = isDisplayActive; + if (isDisplayActive) { + mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); + } else { + mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); + } + } } } } @@ -956,8 +992,10 @@ public class BrightnessTracker { Slog.v(TAG, "settings change " + uri); } if (mInjector.isBrightnessModeAutomatic(mContentResolver)) { + mBgHandler.sendEmptyMessage(MSG_START_DISPLAY_LISTENER); mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } else { + mBgHandler.sendEmptyMessage(MSG_STOP_DISPLAY_LISTENER); mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } } @@ -980,8 +1018,10 @@ public class BrightnessTracker { batteryLevelChanged(level, scale); } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { + mBgHandler.sendEmptyMessage(MSG_STOP_DISPLAY_LISTENER); mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { + mBgHandler.sendEmptyMessage(MSG_START_DISPLAY_LISTENER); mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } } @@ -1023,7 +1063,12 @@ public class BrightnessTracker { case MSG_SENSOR_CHANGED: handleSensorChanged((Sensor) msg.obj); break; - + case MSG_START_DISPLAY_LISTENER: + startDisplayListener(); + break; + case MSG_STOP_DISPLAY_LISTENER: + stopDisplayListener(); + break; } } } @@ -1151,6 +1196,12 @@ public class BrightnessTracker { return context.getSystemService(PowerManager.class).isInteractive(); } + public int getDisplayState(Context context) { + final DisplayManager displayManager = context.getSystemService(DisplayManager.class); + Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY); + return display.getState(); + } + public int getNightDisplayColorTemperature(Context context) { return context.getSystemService(ColorDisplayManager.class) .getNightDisplayColorTemperature(); @@ -1208,7 +1259,7 @@ public class BrightnessTracker { displayManager.registerDisplayListener(listener, handler); } - public void unRegisterDisplayListener(Context context, + public void unregisterDisplayListener(Context context, DisplayManager.DisplayListener listener) { final DisplayManager displayManager = context.getSystemService(DisplayManager.class); displayManager.unregisterDisplayListener(listener); diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessTrackerTest.java index 44c7dec7633e..cd0bd41d9f05 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessTrackerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessTrackerTest.java @@ -130,34 +130,64 @@ public class BrightnessTrackerTest { } @Test - public void testStartStopTrackerScreenOnOff() { + public void testStartStopTrackerScreenStates() { mInjector.mInteractive = false; + mInjector.mDisplayState = Display.STATE_OFF; startTracker(mTracker); assertNull(mInjector.mSensorListener); assertNotNull(mInjector.mBroadcastReceiver); assertTrue(mInjector.mIdleScheduled); - mInjector.sendScreenChange(/* screenOn= */ true); + mInjector.sendInteractivityChange(true); + mInjector.setDisplayState(Display.STATE_ON); assertNotNull(mInjector.mSensorListener); assertTrue(mInjector.mColorSamplingEnabled); + assertNotNull(mInjector.mDisplayListener); + + mInjector.setDisplayState(Display.STATE_OFF); + assertNull(mInjector.mSensorListener); + assertFalse(mInjector.mColorSamplingEnabled); + + mInjector.setDisplayState(Display.STATE_DOZE); + assertNull(mInjector.mSensorListener); + assertFalse(mInjector.mColorSamplingEnabled); + + mInjector.setDisplayState(Display.STATE_DOZE_SUSPEND); + assertNull(mInjector.mSensorListener); + assertFalse(mInjector.mColorSamplingEnabled); - mInjector.sendScreenChange(/* screenOn= */ false); + mInjector.setDisplayState(Display.STATE_ON_SUSPEND); assertNull(mInjector.mSensorListener); assertFalse(mInjector.mColorSamplingEnabled); - // Turn screen on while brightness mode is manual + // Screen on while device is not interactive + mInjector.setDisplayState(Display.STATE_ON); + mInjector.sendInteractivityChange(false); + assertNull(mInjector.mSensorListener); + assertFalse(mInjector.mColorSamplingEnabled); + assertNull(mInjector.mDisplayListener); + + // Device becomes interactive while brightness mode is manual mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ false); - mInjector.sendScreenChange(/* screenOn= */ true); + mInjector.sendInteractivityChange(true); assertNull(mInjector.mSensorListener); assertFalse(mInjector.mColorSamplingEnabled); + assertNull(mInjector.mDisplayListener); // Set brightness mode to automatic while screen is off. - mInjector.sendScreenChange(/* screenOn= */ false); mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true); + mInjector.setDisplayState(Display.STATE_OFF); + assertNull(mInjector.mSensorListener); + assertFalse(mInjector.mColorSamplingEnabled); + assertNotNull(mInjector.mDisplayListener); + + // Set brightness mode to automatic while screen is in doze. + mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true); + mInjector.setDisplayState(Display.STATE_DOZE); assertNull(mInjector.mSensorListener); assertFalse(mInjector.mColorSamplingEnabled); // Turn on screen while brightness mode is automatic. - mInjector.sendScreenChange(/* screenOn= */ true); + mInjector.setDisplayState(Display.STATE_ON); assertNotNull(mInjector.mSensorListener); assertTrue(mInjector.mColorSamplingEnabled); @@ -166,11 +196,11 @@ public class BrightnessTrackerTest { assertNull(mInjector.mBroadcastReceiver); assertFalse(mInjector.mIdleScheduled); assertFalse(mInjector.mColorSamplingEnabled); + assertNull(mInjector.mDisplayListener); } @Test public void testModifyBrightnessConfiguration() { - mInjector.mInteractive = true; // Start with tracker not listening for color samples. startTracker(mTracker, DEFAULT_INITIAL_BRIGHTNESS, /* collectColorSamples= */ false); assertFalse(mInjector.mColorSamplingEnabled); @@ -186,13 +216,17 @@ public class BrightnessTrackerTest { assertFalse(mInjector.mColorSamplingEnabled); // Pretend screen is off, update config to turn on color sampling. - mInjector.sendScreenChange(/* screenOn= */ false); + mInjector.setDisplayState(Display.STATE_OFF); mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true); mInjector.waitForHandler(); assertFalse(mInjector.mColorSamplingEnabled); + // Pretend screen is in doze + mInjector.setDisplayState(Display.STATE_DOZE); + assertFalse(mInjector.mColorSamplingEnabled); + // Pretend screen is on. - mInjector.sendScreenChange(/* screenOn= */ true); + mInjector.setDisplayState(Display.STATE_ON); assertTrue(mInjector.mColorSamplingEnabled); mTracker.stop(); @@ -208,7 +242,6 @@ public class BrightnessTrackerTest { mInjector.mDefaultSamplingAttributes.getComponentMask()); startTracker(mTracker); assertFalse(mInjector.mColorSamplingEnabled); - assertNull(mInjector.mDisplayListener); } @Test @@ -220,7 +253,6 @@ public class BrightnessTrackerTest { 0x2); startTracker(mTracker); assertFalse(mInjector.mColorSamplingEnabled); - assertNull(mInjector.mDisplayListener); } @Test @@ -228,14 +260,12 @@ public class BrightnessTrackerTest { mInjector.mDefaultSamplingAttributes = null; startTracker(mTracker); assertFalse(mInjector.mColorSamplingEnabled); - assertNull(mInjector.mDisplayListener); } @Test public void testColorSampling_FrameRateChange() { startTracker(mTracker); assertTrue(mInjector.mColorSamplingEnabled); - assertNotNull(mInjector.mDisplayListener); int noFramesSampled = mInjector.mNoColorSamplingFrames; mInjector.mFrameRate = 120.0f; // Wrong display @@ -248,7 +278,6 @@ public class BrightnessTrackerTest { @Test public void testAdaptiveOnOff() { - mInjector.mInteractive = true; mInjector.mIsBrightnessModeAutomatic = false; startTracker(mTracker); assertNull(mInjector.mSensorListener); @@ -256,7 +285,6 @@ public class BrightnessTrackerTest { assertNotNull(mInjector.mContentObserver); assertTrue(mInjector.mIdleScheduled); assertFalse(mInjector.mColorSamplingEnabled); - assertNull(mInjector.mDisplayListener); mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true); assertNotNull(mInjector.mSensorListener); @@ -835,12 +863,14 @@ public class BrightnessTrackerTest { mInjector.waitForHandler(); assertNull(mInjector.mSensorListener); assertNull(mInjector.mLightSensor); + assertNull(mInjector.mDisplayListener); // Resetting sensor should start listener again mTracker.setLightSensor(mLightSensorFake); mInjector.waitForHandler(); assertNotNull(mInjector.mSensorListener); assertEquals(mInjector.mLightSensor, mLightSensorFake); + assertNotNull(mInjector.mDisplayListener); Sensor secondSensor = new Sensor(mInputSensorInfoMock); // Setting a different listener should keep things working @@ -848,6 +878,7 @@ public class BrightnessTrackerTest { mInjector.waitForHandler(); assertNotNull(mInjector.mSensorListener); assertEquals(mInjector.mLightSensor, secondSensor); + assertNotNull(mInjector.mDisplayListener); } @Test @@ -862,6 +893,7 @@ public class BrightnessTrackerTest { startTracker(mTracker); assertNull(mInjector.mSensorListener); assertNull(mInjector.mLightSensor); + assertNull(mInjector.mDisplayListener); } @Test @@ -895,6 +927,7 @@ public class BrightnessTrackerTest { assertNull(mInjector.mContentObserver); assertNull(mInjector.mBroadcastReceiver); assertFalse(mInjector.mIdleScheduled); + assertNull(mInjector.mDisplayListener); // mInjector asserts that we aren't removing a null receiver mTracker.stop(); @@ -1017,6 +1050,7 @@ public class BrightnessTrackerTest { Handler mHandler; boolean mIdleScheduled; boolean mInteractive = true; + int mDisplayState = Display.STATE_ON; int[] mProfiles; ContentObserver mContentObserver; boolean mIsBrightnessModeAutomatic = true; @@ -1042,14 +1076,20 @@ public class BrightnessTrackerTest { waitForHandler(); } - void sendScreenChange(boolean screenOn) { - mInteractive = screenOn; + void sendInteractivityChange(boolean interactive) { + mInteractive = interactive; Intent intent = new Intent(); - intent.setAction(screenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); + intent.setAction(interactive ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), intent); waitForHandler(); } + void setDisplayState(int state) { + mDisplayState = state; + mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY); + waitForHandler(); + } + void waitForHandler() { Idle idle = new Idle(); mHandler.getLooper().getQueue().addIdleHandler(idle); @@ -1183,6 +1223,11 @@ public class BrightnessTrackerTest { } @Override + public int getDisplayState(Context context) { + return mDisplayState; + } + + @Override public int getNightDisplayColorTemperature(Context context) { return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, mDefaultNightModeColorTemperature); @@ -1239,7 +1284,7 @@ public class BrightnessTrackerTest { } @Override - public void unRegisterDisplayListener(Context context, + public void unregisterDisplayListener(Context context, DisplayManager.DisplayListener listener) { mDisplayListener = null; } |