Loading services/core/java/com/android/server/display/BrightnessTracker.java +78 −11 Original line number Diff line number Diff line Loading @@ -25,12 +25,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; import android.net.Uri; import android.os.BatteryManager; import android.os.Environment; import android.os.Handler; Loading Loading @@ -110,6 +112,8 @@ public class BrightnessTracker { private static final int MSG_BACKGROUND_START = 0; private static final int MSG_BRIGHTNESS_CHANGED = 1; private static final int MSG_STOP_SENSOR_LISTENER = 2; private static final int MSG_START_SENSOR_LISTENER = 3; // Lock held while accessing mEvents, is held while writing events to flash. private final Object mEventsLock = new Object(); Loading @@ -127,9 +131,14 @@ public class BrightnessTracker { private final Context mContext; private final ContentResolver mContentResolver; private Handler mBgHandler; // mBroadcastReceiver and mSensorListener should only be used on the mBgHandler thread. // mBroadcastReceiver, mSensorListener, mSettingsObserver and mSensorRegistered // should only be used on the mBgHandler thread. private BroadcastReceiver mBroadcastReceiver; private SensorListener mSensorListener; private SettingsObserver mSettingsObserver; private boolean mSensorRegistered; private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL; // Lock held while collecting data related to brightness changes. Loading Loading @@ -178,10 +187,9 @@ public class BrightnessTracker { mSensorListener = new SensorListener(); if (mInjector.isInteractive(mContext)) { mInjector.registerSensorListener(mContext, mSensorListener, mBgHandler); } mSettingsObserver = new SettingsObserver(mBgHandler); mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver); startSensorListener(); final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SHUTDOWN); Loading @@ -205,10 +213,11 @@ public class BrightnessTracker { Slog.d(TAG, "Stop"); } mBgHandler.removeMessages(MSG_BACKGROUND_START); stopSensorListener(); mInjector.unregisterSensorListener(mContext, mSensorListener); mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver); mInjector.unregisterReceiver(mContext, mBroadcastReceiver); mInjector.cancelIdleJob(mContext); mAmbientBrightnessStatsTracker.stop(); synchronized (mDataCollectionLock) { mStarted = false; Loading Loading @@ -366,6 +375,25 @@ public class BrightnessTracker { } } private void startSensorListener() { if (!mSensorRegistered && mInjector.isInteractive(mContext) && mInjector.isBrightnessModeAutomatic(mContentResolver)) { mAmbientBrightnessStatsTracker.start(); mSensorRegistered = true; mInjector.registerSensorListener(mContext, mSensorListener, mInjector.getBackgroundHandler()); } } private void stopSensorListener() { if (mSensorRegistered) { mAmbientBrightnessStatsTracker.stop(); mInjector.unregisterSensorListener(mContext, mSensorListener); mSensorRegistered = false; } } private void scheduleWriteBrightnessTrackerState() { if (!mWriteBrightnessTrackerStateScheduled) { mBgHandler.post(() -> { Loading Loading @@ -724,6 +752,24 @@ public class BrightnessTracker { } } private final class SettingsObserver extends ContentObserver { public SettingsObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { if (DEBUG) { Slog.v(TAG, "settings change " + uri); } if (mInjector.isBrightnessModeAutomatic(mContentResolver)) { mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } else { mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } } } private final class Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Loading @@ -741,12 +787,9 @@ public class BrightnessTracker { batteryLevelChanged(level, scale); } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mAmbientBrightnessStatsTracker.stop(); mInjector.unregisterSensorListener(mContext, mSensorListener); mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { mAmbientBrightnessStatsTracker.start(); mInjector.registerSensorListener(mContext, mSensorListener, mInjector.getBackgroundHandler()); mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } } } Loading @@ -767,6 +810,12 @@ public class BrightnessTracker { values.powerBrightnessFactor, values.isUserSetBrightness, values.isDefaultBrightnessConfig); break; case MSG_START_SENSOR_LISTENER: startSensorListener(); break; case MSG_STOP_SENSOR_LISTENER: stopSensorListener(); break; } } } Loading Loading @@ -801,6 +850,18 @@ public class BrightnessTracker { sensorManager.unregisterListener(sensorListener); } public void registerBrightnessModeObserver(ContentResolver resolver, ContentObserver settingsObserver) { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_BRIGHTNESS_MODE), false, settingsObserver, UserHandle.USER_ALL); } public void unregisterBrightnessModeObserver(Context context, ContentObserver settingsObserver) { context.getContentResolver().unregisterContentObserver(settingsObserver); } public void registerReceiver(Context context, BroadcastReceiver receiver, IntentFilter filter) { context.registerReceiver(receiver, filter); Loading @@ -815,6 +876,12 @@ public class BrightnessTracker { return BackgroundThread.getHandler(); } public boolean isBrightnessModeAutomatic(ContentResolver resolver) { return Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; } public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue, int userId) { return Settings.Secure.getIntForUser(resolver, setting, defaultValue, userId); Loading services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +85 −16 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.display.BrightnessChangeEvent; Loading Loading @@ -101,20 +102,24 @@ public class BrightnessTrackerTest { assertNull(mInjector.mSensorListener); assertNotNull(mInjector.mBroadcastReceiver); assertTrue(mInjector.mIdleScheduled); Intent onIntent = new Intent(); onIntent.setAction(Intent.ACTION_SCREEN_ON); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), onIntent); mInjector.sendScreenChange(/*screen on */ true); assertNotNull(mInjector.mSensorListener); Intent offIntent = new Intent(); offIntent.setAction(Intent.ACTION_SCREEN_OFF); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), offIntent); mInjector.sendScreenChange(/*screen on */ false); assertNull(mInjector.mSensorListener); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), onIntent); // Turn screen on while brightness mode is manual mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false); mInjector.sendScreenChange(/*screen on */ true); assertNull(mInjector.mSensorListener); // Set brightness mode to automatic while screen is off. mInjector.sendScreenChange(/*screen on */ false); mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true); assertNull(mInjector.mSensorListener); // Turn on screen while brightness mode is automatic. mInjector.sendScreenChange(/*screen on */ true); assertNotNull(mInjector.mSensorListener); mTracker.stop(); Loading @@ -123,6 +128,37 @@ public class BrightnessTrackerTest { assertFalse(mInjector.mIdleScheduled); } @Test public void testAdaptiveOnOff() { mInjector.mInteractive = true; mInjector.mIsBrightnessModeAutomatic = false; startTracker(mTracker); assertNull(mInjector.mSensorListener); assertNotNull(mInjector.mBroadcastReceiver); assertNotNull(mInjector.mContentObserver); assertTrue(mInjector.mIdleScheduled); mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true); assertNotNull(mInjector.mSensorListener); SensorEventListener listener = mInjector.mSensorListener; mInjector.mSensorListener = null; // Duplicate notification mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true); // Sensor shouldn't have been registered as it was already registered. assertNull(mInjector.mSensorListener); mInjector.mSensorListener = listener; mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false); assertNull(mInjector.mSensorListener); mTracker.stop(); assertNull(mInjector.mSensorListener); assertNull(mInjector.mBroadcastReceiver); assertNull(mInjector.mContentObserver); assertFalse(mInjector.mIdleScheduled); } @Test public void testBrightnessEvent() { final int brightness = 20; Loading Loading @@ -618,16 +654,39 @@ public class BrightnessTrackerTest { boolean mIdleScheduled; boolean mInteractive = true; int[] mProfiles; ContentObserver mContentObserver; boolean mIsBrightnessModeAutomatic = true; public TestInjector(Handler handler) { mHandler = handler; } public void incrementTime(long timeMillis) { void incrementTime(long timeMillis) { mCurrentTimeMillis += timeMillis; mElapsedRealtimeNanos += TimeUnit.MILLISECONDS.toNanos(timeMillis); } void setBrightnessMode(boolean isBrightnessModeAutomatic) { mIsBrightnessModeAutomatic = isBrightnessModeAutomatic; mContentObserver.dispatchChange(false, null); waitForHandler(); } void sendScreenChange(boolean screenOn) { mInteractive = screenOn; Intent intent = new Intent(); intent.setAction(screenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), intent); waitForHandler(); } void waitForHandler() { Idle idle = new Idle(); mHandler.getLooper().getQueue().addIdleHandler(idle); mHandler.post(() -> {}); idle.waitForIdle(); } @Override public void registerSensorListener(Context context, SensorEventListener sensorListener, Handler handler) { Loading @@ -640,6 +699,18 @@ public class BrightnessTrackerTest { mSensorListener = null; } @Override public void registerBrightnessModeObserver(ContentResolver resolver, ContentObserver settingsObserver) { mContentObserver = settingsObserver; } @Override public void unregisterBrightnessModeObserver(Context context, ContentObserver settingsObserver) { mContentObserver = null; } @Override public void registerReceiver(Context context, BroadcastReceiver shutdownReceiver, IntentFilter shutdownFilter) { Loading @@ -658,11 +729,9 @@ public class BrightnessTrackerTest { return mHandler; } public void waitForHandler() { Idle idle = new Idle(); mHandler.getLooper().getQueue().addIdleHandler(idle); mHandler.post(() -> {}); idle.waitForIdle(); @Override public boolean isBrightnessModeAutomatic(ContentResolver resolver) { return mIsBrightnessModeAutomatic; } @Override Loading Loading
services/core/java/com/android/server/display/BrightnessTracker.java +78 −11 Original line number Diff line number Diff line Loading @@ -25,12 +25,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; import android.net.Uri; import android.os.BatteryManager; import android.os.Environment; import android.os.Handler; Loading Loading @@ -110,6 +112,8 @@ public class BrightnessTracker { private static final int MSG_BACKGROUND_START = 0; private static final int MSG_BRIGHTNESS_CHANGED = 1; private static final int MSG_STOP_SENSOR_LISTENER = 2; private static final int MSG_START_SENSOR_LISTENER = 3; // Lock held while accessing mEvents, is held while writing events to flash. private final Object mEventsLock = new Object(); Loading @@ -127,9 +131,14 @@ public class BrightnessTracker { private final Context mContext; private final ContentResolver mContentResolver; private Handler mBgHandler; // mBroadcastReceiver and mSensorListener should only be used on the mBgHandler thread. // mBroadcastReceiver, mSensorListener, mSettingsObserver and mSensorRegistered // should only be used on the mBgHandler thread. private BroadcastReceiver mBroadcastReceiver; private SensorListener mSensorListener; private SettingsObserver mSettingsObserver; private boolean mSensorRegistered; private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL; // Lock held while collecting data related to brightness changes. Loading Loading @@ -178,10 +187,9 @@ public class BrightnessTracker { mSensorListener = new SensorListener(); if (mInjector.isInteractive(mContext)) { mInjector.registerSensorListener(mContext, mSensorListener, mBgHandler); } mSettingsObserver = new SettingsObserver(mBgHandler); mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver); startSensorListener(); final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SHUTDOWN); Loading @@ -205,10 +213,11 @@ public class BrightnessTracker { Slog.d(TAG, "Stop"); } mBgHandler.removeMessages(MSG_BACKGROUND_START); stopSensorListener(); mInjector.unregisterSensorListener(mContext, mSensorListener); mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver); mInjector.unregisterReceiver(mContext, mBroadcastReceiver); mInjector.cancelIdleJob(mContext); mAmbientBrightnessStatsTracker.stop(); synchronized (mDataCollectionLock) { mStarted = false; Loading Loading @@ -366,6 +375,25 @@ public class BrightnessTracker { } } private void startSensorListener() { if (!mSensorRegistered && mInjector.isInteractive(mContext) && mInjector.isBrightnessModeAutomatic(mContentResolver)) { mAmbientBrightnessStatsTracker.start(); mSensorRegistered = true; mInjector.registerSensorListener(mContext, mSensorListener, mInjector.getBackgroundHandler()); } } private void stopSensorListener() { if (mSensorRegistered) { mAmbientBrightnessStatsTracker.stop(); mInjector.unregisterSensorListener(mContext, mSensorListener); mSensorRegistered = false; } } private void scheduleWriteBrightnessTrackerState() { if (!mWriteBrightnessTrackerStateScheduled) { mBgHandler.post(() -> { Loading Loading @@ -724,6 +752,24 @@ public class BrightnessTracker { } } private final class SettingsObserver extends ContentObserver { public SettingsObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { if (DEBUG) { Slog.v(TAG, "settings change " + uri); } if (mInjector.isBrightnessModeAutomatic(mContentResolver)) { mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } else { mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } } } private final class Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Loading @@ -741,12 +787,9 @@ public class BrightnessTracker { batteryLevelChanged(level, scale); } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mAmbientBrightnessStatsTracker.stop(); mInjector.unregisterSensorListener(mContext, mSensorListener); mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { mAmbientBrightnessStatsTracker.start(); mInjector.registerSensorListener(mContext, mSensorListener, mInjector.getBackgroundHandler()); mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); } } } Loading @@ -767,6 +810,12 @@ public class BrightnessTracker { values.powerBrightnessFactor, values.isUserSetBrightness, values.isDefaultBrightnessConfig); break; case MSG_START_SENSOR_LISTENER: startSensorListener(); break; case MSG_STOP_SENSOR_LISTENER: stopSensorListener(); break; } } } Loading Loading @@ -801,6 +850,18 @@ public class BrightnessTracker { sensorManager.unregisterListener(sensorListener); } public void registerBrightnessModeObserver(ContentResolver resolver, ContentObserver settingsObserver) { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_BRIGHTNESS_MODE), false, settingsObserver, UserHandle.USER_ALL); } public void unregisterBrightnessModeObserver(Context context, ContentObserver settingsObserver) { context.getContentResolver().unregisterContentObserver(settingsObserver); } public void registerReceiver(Context context, BroadcastReceiver receiver, IntentFilter filter) { context.registerReceiver(receiver, filter); Loading @@ -815,6 +876,12 @@ public class BrightnessTracker { return BackgroundThread.getHandler(); } public boolean isBrightnessModeAutomatic(ContentResolver resolver) { return Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; } public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue, int userId) { return Settings.Secure.getIntForUser(resolver, setting, defaultValue, userId); Loading
services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +85 −16 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.display.BrightnessChangeEvent; Loading Loading @@ -101,20 +102,24 @@ public class BrightnessTrackerTest { assertNull(mInjector.mSensorListener); assertNotNull(mInjector.mBroadcastReceiver); assertTrue(mInjector.mIdleScheduled); Intent onIntent = new Intent(); onIntent.setAction(Intent.ACTION_SCREEN_ON); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), onIntent); mInjector.sendScreenChange(/*screen on */ true); assertNotNull(mInjector.mSensorListener); Intent offIntent = new Intent(); offIntent.setAction(Intent.ACTION_SCREEN_OFF); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), offIntent); mInjector.sendScreenChange(/*screen on */ false); assertNull(mInjector.mSensorListener); mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), onIntent); // Turn screen on while brightness mode is manual mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false); mInjector.sendScreenChange(/*screen on */ true); assertNull(mInjector.mSensorListener); // Set brightness mode to automatic while screen is off. mInjector.sendScreenChange(/*screen on */ false); mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true); assertNull(mInjector.mSensorListener); // Turn on screen while brightness mode is automatic. mInjector.sendScreenChange(/*screen on */ true); assertNotNull(mInjector.mSensorListener); mTracker.stop(); Loading @@ -123,6 +128,37 @@ public class BrightnessTrackerTest { assertFalse(mInjector.mIdleScheduled); } @Test public void testAdaptiveOnOff() { mInjector.mInteractive = true; mInjector.mIsBrightnessModeAutomatic = false; startTracker(mTracker); assertNull(mInjector.mSensorListener); assertNotNull(mInjector.mBroadcastReceiver); assertNotNull(mInjector.mContentObserver); assertTrue(mInjector.mIdleScheduled); mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true); assertNotNull(mInjector.mSensorListener); SensorEventListener listener = mInjector.mSensorListener; mInjector.mSensorListener = null; // Duplicate notification mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true); // Sensor shouldn't have been registered as it was already registered. assertNull(mInjector.mSensorListener); mInjector.mSensorListener = listener; mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false); assertNull(mInjector.mSensorListener); mTracker.stop(); assertNull(mInjector.mSensorListener); assertNull(mInjector.mBroadcastReceiver); assertNull(mInjector.mContentObserver); assertFalse(mInjector.mIdleScheduled); } @Test public void testBrightnessEvent() { final int brightness = 20; Loading Loading @@ -618,16 +654,39 @@ public class BrightnessTrackerTest { boolean mIdleScheduled; boolean mInteractive = true; int[] mProfiles; ContentObserver mContentObserver; boolean mIsBrightnessModeAutomatic = true; public TestInjector(Handler handler) { mHandler = handler; } public void incrementTime(long timeMillis) { void incrementTime(long timeMillis) { mCurrentTimeMillis += timeMillis; mElapsedRealtimeNanos += TimeUnit.MILLISECONDS.toNanos(timeMillis); } void setBrightnessMode(boolean isBrightnessModeAutomatic) { mIsBrightnessModeAutomatic = isBrightnessModeAutomatic; mContentObserver.dispatchChange(false, null); waitForHandler(); } void sendScreenChange(boolean screenOn) { mInteractive = screenOn; Intent intent = new Intent(); intent.setAction(screenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF); mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), intent); waitForHandler(); } void waitForHandler() { Idle idle = new Idle(); mHandler.getLooper().getQueue().addIdleHandler(idle); mHandler.post(() -> {}); idle.waitForIdle(); } @Override public void registerSensorListener(Context context, SensorEventListener sensorListener, Handler handler) { Loading @@ -640,6 +699,18 @@ public class BrightnessTrackerTest { mSensorListener = null; } @Override public void registerBrightnessModeObserver(ContentResolver resolver, ContentObserver settingsObserver) { mContentObserver = settingsObserver; } @Override public void unregisterBrightnessModeObserver(Context context, ContentObserver settingsObserver) { mContentObserver = null; } @Override public void registerReceiver(Context context, BroadcastReceiver shutdownReceiver, IntentFilter shutdownFilter) { Loading @@ -658,11 +729,9 @@ public class BrightnessTrackerTest { return mHandler; } public void waitForHandler() { Idle idle = new Idle(); mHandler.getLooper().getQueue().addIdleHandler(idle); mHandler.post(() -> {}); idle.waitForIdle(); @Override public boolean isBrightnessModeAutomatic(ContentResolver resolver) { return mIsBrightnessModeAutomatic; } @Override Loading