diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 521793b0ec436..00de2c781760d 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -286,7 +286,8 @@ package android.app { method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setActiveDream(@Nullable android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setDreamOverlay(@Nullable android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setScreensaverEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream(@NonNull android.content.ComponentName); + method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setSystemDreamComponent(@Nullable android.content.ComponentName); + method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream(); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream(); } diff --git a/core/java/android/app/DreamManager.java b/core/java/android/app/DreamManager.java index 00af1c02d92dd..7c8b0fd499e36 100644 --- a/core/java/android/app/DreamManager.java +++ b/core/java/android/app/DreamManager.java @@ -18,7 +18,6 @@ package android.app; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; @@ -86,16 +85,23 @@ public class DreamManager { } /** - * Starts dream service with name "name". + * Starts dreaming. + * + * The system dream component, if set by {@link DreamManager#setSystemDreamComponent}, will be + * started. + * Otherwise, starts the active dream set by {@link DreamManager#setActiveDream}. * *
This is only used for testing the dream service APIs. * + * @see DreamManager#setActiveDream(ComponentName) + * @see DreamManager#setSystemDreamComponent(ComponentName) + * * @hide */ @TestApi @UserHandleAware @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) - public void startDream(@NonNull ComponentName name) { + public void startDream() { try { mService.dream(); } catch (RemoteException e) { @@ -141,6 +147,25 @@ public class DreamManager { } } + /** + * Sets or clears the system dream component. + * + * The system dream component, when set, will be shown instead of the user configured dream + * when the system starts dreaming (not dozing). If the system is dreaming at the time the + * system dream is set or cleared, it immediately switches dream. + * + * @hide + */ + @TestApi + @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) + public void setSystemDreamComponent(@Nullable ComponentName dreamComponent) { + try { + mService.setSystemDreamComponent(dreamComponent); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Sets the active dream on the device to be "dreamComponent". * diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl index 53ae6576ef95f..609425c95b0d4 100644 --- a/core/java/android/service/dreams/IDreamManager.aidl +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -43,5 +43,6 @@ interface IDreamManager { void forceAmbientDisplayEnabled(boolean enabled); ComponentName[] getDreamComponentsForUser(int userId); void setDreamComponentsForUser(int userId, in ComponentName[] componentNames); + void setSystemDreamComponent(in ComponentName componentName); void registerDreamOverlayService(in ComponentName componentName); } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 4e0489a5c4bc3..8a4b6e31c78ab 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -110,6 +110,10 @@ public final class DreamManagerService extends SystemService { private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; + // A temporary dream component that, when present, takes precedence over user configured dream + // component. + private ComponentName mSystemDreamComponent; + private ComponentName mDreamOverlayServiceName; private AmbientDisplayConfiguration mDozeConfig; @@ -352,11 +356,21 @@ public final class DreamManagerService extends SystemService { return chooseDreamForUser(doze, ActivityManager.getCurrentUser()); } + /** + * If doze is true, returns the doze component for the user. + * Otherwise, returns the system dream component, if present. + * Otherwise, returns the first valid user configured dream component. + */ private ComponentName chooseDreamForUser(boolean doze, int userId) { if (doze) { ComponentName dozeComponent = getDozeComponent(userId); return validateDream(dozeComponent) ? dozeComponent : null; } + + if (mSystemDreamComponent != null) { + return mSystemDreamComponent; + } + ComponentName[] dreams = getDreamComponentsForUser(userId); return dreams != null && dreams.length != 0 ? dreams[0] : null; } @@ -416,6 +430,21 @@ public final class DreamManagerService extends SystemService { userId); } + private void setSystemDreamComponentInternal(ComponentName componentName) { + synchronized (mLock) { + if (Objects.equals(mSystemDreamComponent, componentName)) { + return; + } + + mSystemDreamComponent = componentName; + + // Switch dream if currently dreaming and not dozing. + if (isDreamingInternal() && !mCurrentDreamIsDozing) { + startDreamInternal(false); + } + } + } + private ComponentName getDefaultDreamComponentForUser(int userId) { String name = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, @@ -667,6 +696,18 @@ public final class DreamManagerService extends SystemService { } } + @Override // Binder call + public void setSystemDreamComponent(ComponentName componentName) { + checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); + + final long ident = Binder.clearCallingIdentity(); + try { + DreamManagerService.this.setSystemDreamComponentInternal(componentName); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + @Override // Binder call public void registerDreamOverlayService(ComponentName overlayComponent) { checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);