From 7cf2634f919231b8f853722857e190d22c64b737 Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Mon, 3 Oct 2022 14:50:48 -0400 Subject: [PATCH] Fix PowerManager#dream API by partially rolling back ag/19763724 ag/19763724 modified Sandman.java to use LocalServices, but it turns out that Sandman.java is exposed to clients via PowerManager - where LocalServices isn't available. This caused PowerManager#dream to break Fixes: 249916607 Test: atest UiModeManagerServiceTest Test: "OKG go to ambient" voice command Change-Id: I3e031593568fdb7b92a1209823463832feeb1601 --- core/java/android/service/dreams/Sandman.java | 48 ++++++------ .../android/server/UiModeManagerService.java | 6 +- .../server/UiModeManagerServiceTest.java | 78 +++++-------------- 3 files changed, 50 insertions(+), 82 deletions(-) diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java index fae72a2e91a89..ced2a01cb1d0d 100644 --- a/core/java/android/service/dreams/Sandman.java +++ b/core/java/android/service/dreams/Sandman.java @@ -20,13 +20,13 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; -import com.android.server.LocalServices; - /** * Internal helper for launching dreams to ensure consistency between the * UiModeManagerService system service and the Somnambulator activity. @@ -75,28 +75,32 @@ public final class Sandman { } private static void startDream(Context context, boolean docked) { - DreamManagerInternal dreamManagerService = - LocalServices.getService(DreamManagerInternal.class); - if (dreamManagerService != null && !dreamManagerService.isDreaming()) { - if (docked) { - Slog.i(TAG, "Activating dream while docked."); + try { + IDreamManager dreamManagerService = IDreamManager.Stub.asInterface( + ServiceManager.getService(DreamService.DREAM_SERVICE)); + if (dreamManagerService != null && !dreamManagerService.isDreaming()) { + if (docked) { + Slog.i(TAG, "Activating dream while docked."); - // Wake up. - // The power manager will wake up the system automatically when it starts - // receiving power from a dock but there is a race between that happening - // and the UI mode manager starting a dream. We want the system to already - // be awake by the time this happens. Otherwise the dream may not start. - PowerManager powerManager = - context.getSystemService(PowerManager.class); - powerManager.wakeUp(SystemClock.uptimeMillis(), - PowerManager.WAKE_REASON_PLUGGED_IN, - "android.service.dreams:DREAM"); - } else { - Slog.i(TAG, "Activating dream by user request."); + // Wake up. + // The power manager will wake up the system automatically when it starts + // receiving power from a dock but there is a race between that happening + // and the UI mode manager starting a dream. We want the system to already + // be awake by the time this happens. Otherwise the dream may not start. + PowerManager powerManager = + context.getSystemService(PowerManager.class); + powerManager.wakeUp(SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_PLUGGED_IN, + "android.service.dreams:DREAM"); + } else { + Slog.i(TAG, "Activating dream by user request."); + } + + // Dream. + dreamManagerService.dream(); } - - // Dream. - dreamManagerService.requestDream(); + } catch (RemoteException ex) { + Slog.e(TAG, "Could not start dream when docked.", ex); } } diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index e9dd836e527af..8d878af4b788d 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -1831,7 +1831,7 @@ final class UiModeManagerService extends SystemService { if (category != null && !dockAppStarted && (mStartDreamImmediatelyOnDock || mWindowManager.isKeyguardShowingAndNotOccluded() || !mPowerManager.isInteractive())) { - Sandman.startDreamWhenDockedIfAppropriate(getContext()); + mInjector.startDreamWhenDockedIfAppropriate(getContext()); } } @@ -2145,5 +2145,9 @@ final class UiModeManagerService extends SystemService { public int getCallingUid() { return Binder.getCallingUid(); } + + public void startDreamWhenDockedIfAppropriate(Context context) { + Sandman.startDreamWhenDockedIfAppropriate(context); + } } } diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java index 617a34f44bff4..91c2fe0eb262c 100644 --- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java @@ -54,6 +54,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -83,7 +84,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; -import android.service.dreams.DreamManagerInternal; import android.test.mock.MockContentResolver; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -101,6 +101,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Spy; import java.time.LocalDateTime; import java.time.LocalTime; @@ -137,8 +138,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { private PackageManager mPackageManager; @Mock private IBinder mBinder; - @Mock - private DreamManagerInternal mDreamManager; + @Spy + private TestInjector mInjector; @Captor private ArgumentCaptor mOrderedBroadcastIntent; @Captor @@ -207,10 +208,10 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { addLocalService(WindowManagerInternal.class, mWindowManager); addLocalService(PowerManagerInternal.class, mLocalPowerManager); addLocalService(TwilightManager.class, mTwilightManager); - addLocalService(DreamManagerInternal.class, mDreamManager); - + + mInjector = spy(new TestInjector()); mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true, - mTwilightManager, new TestInjector()); + mTwilightManager, mInjector); try { mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); } catch (SecurityException e) {/* ignore for permission denial */} @@ -1321,84 +1322,53 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { @Test public void dreamWhenDocked() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(true); - triggerDockIntent(); verifyAndSendResultBroadcast(); - verify(mDreamManager).requestDream(); - } - - @Test - public void noDreamWhenDocked_dreamsDisabled() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(false); - - triggerDockIntent(); - verifyAndSendResultBroadcast(); - verify(mDreamManager, never()).requestDream(); - } - - @Test - public void noDreamWhenDocked_dreamsWhenDockedDisabled() { - setScreensaverActivateOnDock(false); - setScreensaverEnabled(true); - - triggerDockIntent(); - verifyAndSendResultBroadcast(); - verify(mDreamManager, never()).requestDream(); + verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); } @Test public void noDreamWhenDocked_keyguardNotShowing_interactive() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(true); mUiManagerService.setStartDreamImmediatelyOnDock(false); when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false); when(mPowerManager.isInteractive()).thenReturn(true); triggerDockIntent(); verifyAndSendResultBroadcast(); - verify(mDreamManager, never()).requestDream(); + verify(mInjector, never()).startDreamWhenDockedIfAppropriate(mContext); } @Test public void dreamWhenDocked_keyguardShowing_interactive() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(true); mUiManagerService.setStartDreamImmediatelyOnDock(false); when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true); when(mPowerManager.isInteractive()).thenReturn(false); triggerDockIntent(); verifyAndSendResultBroadcast(); - verify(mDreamManager).requestDream(); + verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); } @Test public void dreamWhenDocked_keyguardNotShowing_notInteractive() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(true); mUiManagerService.setStartDreamImmediatelyOnDock(false); when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(false); when(mPowerManager.isInteractive()).thenReturn(false); triggerDockIntent(); verifyAndSendResultBroadcast(); - verify(mDreamManager).requestDream(); + verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); } @Test public void dreamWhenDocked_keyguardShowing_notInteractive() { - setScreensaverActivateOnDock(true); - setScreensaverEnabled(true); mUiManagerService.setStartDreamImmediatelyOnDock(false); when(mWindowManager.isKeyguardShowingAndNotOccluded()).thenReturn(true); when(mPowerManager.isInteractive()).thenReturn(false); triggerDockIntent(); verifyAndSendResultBroadcast(); - verify(mDreamManager).requestDream(); + verify(mInjector).startDreamWhenDockedIfAppropriate(mContext); } private void triggerDockIntent() { @@ -1435,22 +1405,6 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { mOrderedBroadcastIntent.getValue()); } - private void setScreensaverEnabled(boolean enable) { - Settings.Secure.putIntForUser( - mContentResolver, - Settings.Secure.SCREENSAVER_ENABLED, - enable ? 1 : 0, - UserHandle.USER_CURRENT); - } - - private void setScreensaverActivateOnDock(boolean enable) { - Settings.Secure.putIntForUser( - mContentResolver, - Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, - enable ? 1 : 0, - UserHandle.USER_CURRENT); - } - private void requestAllPossibleProjectionTypes() throws RemoteException { for (int i = 0; i < Integer.SIZE; ++i) { mService.requestProjection(mBinder, 1 << i, PACKAGE_NAME); @@ -1467,11 +1421,17 @@ public class UiModeManagerServiceTest extends UiServiceTestCase { } public TestInjector(int callingUid) { - this.callingUid = callingUid; + this.callingUid = callingUid; } + @Override public int getCallingUid() { return callingUid; } + + @Override + public void startDreamWhenDockedIfAppropriate(Context context) { + // do nothing + } } }