From 3c94bacacd58807fe77fe3c6cb9c7d0a21de3023 Mon Sep 17 00:00:00 2001 From: Darrell Shi Date: Thu, 18 Aug 2022 16:32:29 +0000 Subject: [PATCH] Add hidden system dream API in DreamManagerService. This change - adds a new private API in dream manager that allows a client with write dream permission to set a system dream component, which takes precedence over user configured dream - fixes startDream() API in DreamManager which shouldn't take in a component name Test: atest SystemDreamTest Bug: 222529147 Change-Id: Iee9a0af1071e5ed57fa5bd4b0d06d8178118116e --- core/api/test-current.txt | 3 +- core/java/android/app/DreamManager.java | 31 ++++++++++++-- .../android/service/dreams/IDreamManager.aidl | 1 + .../server/dreams/DreamManagerService.java | 41 +++++++++++++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) 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);