Loading core/java/android/service/dreams/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -110,3 +110,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "disallow_dream_on_auto_projection" namespace: "systemui" description: "Disallows dreaming when Android Auto projected display is active" bug: "413508543" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file services/core/java/com/android/server/dreams/DreamManagerService.java +13 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.os.BatteryManager.EXTRA_CHARGING_STATUS; import static android.service.dreams.Flags.allowDreamWhenPostured; import static android.service.dreams.Flags.allowDreamWithChargeLimit; import static android.service.dreams.Flags.cleanupDreamSettingsOnUninstall; import static android.service.dreams.Flags.disallowDreamOnAutoProjection; import static android.service.dreams.Flags.dreamHandlesBeingObscured; import static android.service.dreams.Flags.dreamsV2; Loading @@ -35,6 +36,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.IAppTask; import android.app.TaskInfo; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading Loading @@ -136,6 +138,7 @@ public final class DreamManagerService extends SystemService { private final Handler mHandler; private final DreamController mController; private final PowerManager mPowerManager; private final UiModeManager mUiModeManager; private final PowerManagerInternal mPowerManagerInternal; private final BatteryManagerInternal mBatteryManagerInternal; private final PowerManager.WakeLock mDozeWakeLock; Loading Loading @@ -276,6 +279,7 @@ public final class DreamManagerService extends SystemService { mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPowerManagerInternal = getLocalService(PowerManagerInternal.class); mUiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE); mAtmInternal = getLocalService(ActivityTaskManagerInternal.class); mPmInternal = getLocalService(PackageManagerInternal.class); mUserManager = context.getSystemService(UserManager.class); Loading Loading @@ -597,7 +601,8 @@ public final class DreamManagerService extends SystemService { } /** Whether dreaming can start given user settings and the current dock/charge state. */ private boolean canStartDreamingInternal(boolean isScreenOn) { @VisibleForTesting boolean canStartDreamingInternal(boolean isScreenOn) { synchronized (mLock) { // Can't start dreaming if we are already dreaming and the dream has focus. If we are // dreaming but the dream does not have focus, then the dream can be brought to the Loading @@ -606,6 +611,13 @@ public final class DreamManagerService extends SystemService { return false; } if (disallowDreamOnAutoProjection() && (mUiModeManager.getActiveProjectionTypes() & UiModeManager.PROJECTION_TYPE_AUTOMOTIVE) != 0) { // Don't dream when connected to Android Auto unit as dreams can't start anyways. return false; } if (!mDreamsEnabledSetting) { return false; } Loading services/tests/dreamservicetests/src/com/android/server/dreams/DreamManagerServiceTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ package com.android.server.dreams; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.BatteryManager.EXTRA_CHARGING_STATUS; import static android.service.dreams.Flags.FLAG_DREAMS_V2; import static android.service.dreams.Flags.FLAG_ALLOW_DREAM_WITH_CHARGE_LIMIT; import static android.service.dreams.Flags.FLAG_DISALLOW_DREAM_ON_AUTO_PROJECTION; import static android.service.dreams.Flags.FLAG_DREAMS_V2; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; Loading @@ -32,8 +34,11 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.Manifest; import android.app.ActivityManagerInternal; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.hardware.health.BatteryChargingState; Loading Loading @@ -84,6 +89,8 @@ public class DreamManagerServiceTest { @Mock private PowerManagerInternal mPowerManagerInternalMock; @Mock private UiModeManager mUiModeManagerMock; @Mock private UserManager mUserManagerMock; @Rule Loading @@ -98,6 +105,10 @@ public class DreamManagerServiceTest { public void setUp() throws Exception { mTestHandler = new TestHandler(/* callback= */ null); MockitoAnnotations.initMocks(this); mContext.getTestablePermissions().setPermission( Manifest.permission.READ_PROJECTION_STATE, PERMISSION_GRANTED); mContextSpy = spy(mContext); mLocalServiceKeeperRule.overrideLocalService(ActivityManagerInternal.class, Loading @@ -117,6 +128,7 @@ public class DreamManagerServiceTest { Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING, 0); when(mContextSpy.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); when(mContextSpy.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManagerMock); } private DreamManagerService createService() { Loading Loading @@ -145,6 +157,66 @@ public class DreamManagerServiceTest { assertThat(service.dreamsEnabled()).isFalse(); } @Test public void testCanStartDreaming_charging() { // Enable dreaming while charging only. Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1, UserHandle.USER_CURRENT); Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT); // Set up preconditions. when(mUserManagerMock.isUserUnlocked()).thenReturn(true); // Device is charging. when(mBatteryManagerInternal.isPowered(anyInt())).thenReturn(true); // Initialize service so settings are read. final DreamManagerService service = createService(); service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // Battery changed event is received. ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mContextSpy).registerReceiver(receiverCaptor.capture(), argThat((arg) -> arg.hasAction(Intent.ACTION_BATTERY_CHANGED))); receiverCaptor.getValue().onReceive(mContext, new Intent()); // Can start dreaming is true. assertThat(service.canStartDreamingInternal(/*isScreenOn=*/ true)).isTrue(); } @EnableFlags(FLAG_DISALLOW_DREAM_ON_AUTO_PROJECTION) @Test public void testCanStartDreaming_falseWithProjectedDisplay() { // Enable dreaming while charging only. Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1, UserHandle.USER_CURRENT); Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT); // Device is charging. when(mBatteryManagerInternal.isPowered(anyInt())).thenReturn(true); // Connected to Android Auto. when(mUiModeManagerMock.getActiveProjectionTypes()) .thenReturn(UiModeManager.PROJECTION_TYPE_NONE); // Initialize service so settings are read. final DreamManagerService service = createService(); service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // Battery changed event is received. ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mContextSpy).registerReceiver(receiverCaptor.capture(), argThat((arg) -> arg.hasAction(Intent.ACTION_BATTERY_CHANGED))); receiverCaptor.getValue().onReceive(mContext, new Intent()); // Can start dreaming is true. assertThat(service.canStartDreamingInternal(/*isScreenOn=*/ true)).isFalse(); } @Test public void testDreamConditionActive_onDock() { // Enable dreaming on dock. Loading Loading
core/java/android/service/dreams/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -110,3 +110,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "disallow_dream_on_auto_projection" namespace: "systemui" description: "Disallows dreaming when Android Auto projected display is active" bug: "413508543" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file
services/core/java/com/android/server/dreams/DreamManagerService.java +13 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.os.BatteryManager.EXTRA_CHARGING_STATUS; import static android.service.dreams.Flags.allowDreamWhenPostured; import static android.service.dreams.Flags.allowDreamWithChargeLimit; import static android.service.dreams.Flags.cleanupDreamSettingsOnUninstall; import static android.service.dreams.Flags.disallowDreamOnAutoProjection; import static android.service.dreams.Flags.dreamHandlesBeingObscured; import static android.service.dreams.Flags.dreamsV2; Loading @@ -35,6 +36,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.IAppTask; import android.app.TaskInfo; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading Loading @@ -136,6 +138,7 @@ public final class DreamManagerService extends SystemService { private final Handler mHandler; private final DreamController mController; private final PowerManager mPowerManager; private final UiModeManager mUiModeManager; private final PowerManagerInternal mPowerManagerInternal; private final BatteryManagerInternal mBatteryManagerInternal; private final PowerManager.WakeLock mDozeWakeLock; Loading Loading @@ -276,6 +279,7 @@ public final class DreamManagerService extends SystemService { mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPowerManagerInternal = getLocalService(PowerManagerInternal.class); mUiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE); mAtmInternal = getLocalService(ActivityTaskManagerInternal.class); mPmInternal = getLocalService(PackageManagerInternal.class); mUserManager = context.getSystemService(UserManager.class); Loading Loading @@ -597,7 +601,8 @@ public final class DreamManagerService extends SystemService { } /** Whether dreaming can start given user settings and the current dock/charge state. */ private boolean canStartDreamingInternal(boolean isScreenOn) { @VisibleForTesting boolean canStartDreamingInternal(boolean isScreenOn) { synchronized (mLock) { // Can't start dreaming if we are already dreaming and the dream has focus. If we are // dreaming but the dream does not have focus, then the dream can be brought to the Loading @@ -606,6 +611,13 @@ public final class DreamManagerService extends SystemService { return false; } if (disallowDreamOnAutoProjection() && (mUiModeManager.getActiveProjectionTypes() & UiModeManager.PROJECTION_TYPE_AUTOMOTIVE) != 0) { // Don't dream when connected to Android Auto unit as dreams can't start anyways. return false; } if (!mDreamsEnabledSetting) { return false; } Loading
services/tests/dreamservicetests/src/com/android/server/dreams/DreamManagerServiceTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -16,9 +16,11 @@ package com.android.server.dreams; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.BatteryManager.EXTRA_CHARGING_STATUS; import static android.service.dreams.Flags.FLAG_DREAMS_V2; import static android.service.dreams.Flags.FLAG_ALLOW_DREAM_WITH_CHARGE_LIMIT; import static android.service.dreams.Flags.FLAG_DISALLOW_DREAM_ON_AUTO_PROJECTION; import static android.service.dreams.Flags.FLAG_DREAMS_V2; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; Loading @@ -32,8 +34,11 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.Manifest; import android.app.ActivityManagerInternal; import android.app.UiModeManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.hardware.health.BatteryChargingState; Loading Loading @@ -84,6 +89,8 @@ public class DreamManagerServiceTest { @Mock private PowerManagerInternal mPowerManagerInternalMock; @Mock private UiModeManager mUiModeManagerMock; @Mock private UserManager mUserManagerMock; @Rule Loading @@ -98,6 +105,10 @@ public class DreamManagerServiceTest { public void setUp() throws Exception { mTestHandler = new TestHandler(/* callback= */ null); MockitoAnnotations.initMocks(this); mContext.getTestablePermissions().setPermission( Manifest.permission.READ_PROJECTION_STATE, PERMISSION_GRANTED); mContextSpy = spy(mContext); mLocalServiceKeeperRule.overrideLocalService(ActivityManagerInternal.class, Loading @@ -117,6 +128,7 @@ public class DreamManagerServiceTest { Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING, 0); when(mContextSpy.getSystemService(UserManager.class)).thenReturn(mUserManagerMock); when(mContextSpy.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManagerMock); } private DreamManagerService createService() { Loading Loading @@ -145,6 +157,66 @@ public class DreamManagerServiceTest { assertThat(service.dreamsEnabled()).isFalse(); } @Test public void testCanStartDreaming_charging() { // Enable dreaming while charging only. Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1, UserHandle.USER_CURRENT); Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT); // Set up preconditions. when(mUserManagerMock.isUserUnlocked()).thenReturn(true); // Device is charging. when(mBatteryManagerInternal.isPowered(anyInt())).thenReturn(true); // Initialize service so settings are read. final DreamManagerService service = createService(); service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // Battery changed event is received. ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mContextSpy).registerReceiver(receiverCaptor.capture(), argThat((arg) -> arg.hasAction(Intent.ACTION_BATTERY_CHANGED))); receiverCaptor.getValue().onReceive(mContext, new Intent()); // Can start dreaming is true. assertThat(service.canStartDreamingInternal(/*isScreenOn=*/ true)).isTrue(); } @EnableFlags(FLAG_DISALLOW_DREAM_ON_AUTO_PROJECTION) @Test public void testCanStartDreaming_falseWithProjectedDisplay() { // Enable dreaming while charging only. Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1, UserHandle.USER_CURRENT); Settings.Secure.putIntForUser(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1, UserHandle.USER_CURRENT); // Device is charging. when(mBatteryManagerInternal.isPowered(anyInt())).thenReturn(true); // Connected to Android Auto. when(mUiModeManagerMock.getActiveProjectionTypes()) .thenReturn(UiModeManager.PROJECTION_TYPE_NONE); // Initialize service so settings are read. final DreamManagerService service = createService(); service.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // Battery changed event is received. ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mContextSpy).registerReceiver(receiverCaptor.capture(), argThat((arg) -> arg.hasAction(Intent.ACTION_BATTERY_CHANGED))); receiverCaptor.getValue().onReceive(mContext, new Intent()); // Can start dreaming is true. assertThat(service.canStartDreamingInternal(/*isScreenOn=*/ true)).isFalse(); } @Test public void testDreamConditionActive_onDock() { // Enable dreaming on dock. Loading