diff --git a/api/test-current.txt b/api/test-current.txt
index d32c77f4cd254..1bcd2e1e9c6cb 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -412,6 +412,12 @@ package android.app {
field public static final String COLUMN_MEDIASTORE_URI = "mediastore_uri";
}
+ public class DreamManager {
+ method @RequiresPermission("android.permission.WRITE_DREAM_STATE") public void setActiveDream(@NonNull android.content.ComponentName);
+ method @RequiresPermission("android.permission.WRITE_DREAM_STATE") public void startDream(@NonNull android.content.ComponentName);
+ method @RequiresPermission("android.permission.WRITE_DREAM_STATE") public void stopDream();
+ }
+
public final class NotificationChannel implements android.os.Parcelable {
method public int getOriginalImportance();
method public boolean isBlockableSystem();
@@ -791,6 +797,7 @@ package android.content {
field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
+ field public static final String DREAM_SERVICE = "dream";
field public static final String ETHERNET_SERVICE = "ethernet";
field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String PERMISSION_SERVICE = "permission";
diff --git a/core/java/android/app/DreamManager.java b/core/java/android/app/DreamManager.java
new file mode 100644
index 0000000000000..fe13b8f26d789
--- /dev/null
+++ b/core/java/android/app/DreamManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.annotation.UserHandleAware;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+
+/**
+ * @hide
+ */
+@SystemService(Context.DREAM_SERVICE)
+@TestApi
+public class DreamManager {
+ private final IDreamManager mService;
+ private final Context mContext;
+
+ /**
+ * @hide
+ */
+ public DreamManager(Context context) throws ServiceManager.ServiceNotFoundException {
+ mService = IDreamManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(DreamService.DREAM_SERVICE));
+ mContext = context;
+ }
+
+ /**
+ * Starts dream service with name "name".
+ *
+ *
This is only used for testing the dream service APIs.
+ *
+ * @hide
+ */
+ @TestApi
+ @UserHandleAware
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void startDream(@NonNull ComponentName name) {
+ try {
+ mService.testDream(mContext.getUserId(), name);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Stops the dream service on the device if one is started.
+ *
+ *
This is only used for testing the dream service APIs.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void stopDream() {
+ try {
+ mService.awaken();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets the active dream on the device to be "dreamComponent".
+ *
+ *
This is only used for testing the dream service APIs.
+ *
+ * @hide
+ */
+ @TestApi
+ @UserHandleAware
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void setActiveDream(@NonNull ComponentName dreamComponent) {
+ ComponentName[] dreams = {dreamComponent};
+ try {
+ mService.setDreamComponentsForUser(mContext.getUserId(), dreams);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4369680e77819..ab73abbd75c0d 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1334,6 +1334,13 @@ public final class SystemServiceRegistry {
IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
}});
+ registerService(Context.DREAM_SERVICE, DreamManager.class,
+ new CachedServiceFetcher() {
+ @Override
+ public DreamManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return new DreamManager(ctx);
+ }});
sInitializing = true;
try {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c6e84b7e46b05..536b6c33b1426 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5156,6 +5156,17 @@ public abstract class Context {
*/
public static final String LIGHTS_SERVICE = "lights";
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.app.DreamManager} for controlling Dream states.
+ *
+ * @see #getSystemService(String)
+
+ * @hide
+ */
+ @TestApi
+ public static final String DREAM_SERVICE = "dream";
+
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index d254ffdb69863..6496de3e15a03 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -31,12 +31,14 @@ interface IDreamManager {
void setDreamComponents(in ComponentName[] componentNames);
@UnsupportedAppUsage
ComponentName[] getDreamComponents();
- ComponentName getDefaultDreamComponent();
- void testDream(in ComponentName componentName);
+ ComponentName getDefaultDreamComponentForUser(int userId);
+ void testDream(int userId, in ComponentName componentName);
@UnsupportedAppUsage
boolean isDreaming();
void finishSelf(in IBinder token, boolean immediate);
void startDozing(in IBinder token, int screenState, int screenBrightness);
void stopDozing(in IBinder token);
void forceAmbientDisplayEnabled(boolean enabled);
+ ComponentName[] getDreamComponentsForUser(int userId);
+ void setDreamComponentsForUser(int userId, in ComponentName[] componentNames);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 3c0f6fe8ccbb3..57e680849fec3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -136,7 +136,7 @@ public class DreamBackend {
if (mDreamManager == null)
return null;
try {
- return mDreamManager.getDefaultDreamComponent();
+ return mDreamManager.getDefaultDreamComponentForUser(mContext.getUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed to get default dream", e);
return null;
@@ -269,7 +269,7 @@ public class DreamBackend {
if (mDreamManager == null || dreamInfo == null || dreamInfo.componentName == null)
return;
try {
- mDreamManager.testDream(dreamInfo.componentName);
+ mDreamManager.testDream(mContext.getUserId(), dreamInfo.componentName);
} catch (RemoteException e) {
Log.w(TAG, "Failed to preview " + dreamInfo, e);
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index a74be1357e302..eb0257e95b6c3 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -505,12 +505,18 @@ public final class DreamManagerService extends SystemService {
@Override // Binder call
public ComponentName[] getDreamComponents() {
- checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+ return getDreamComponentsForUser(UserHandle.getCallingUserId());
+ }
+
+ @Override // Binder call
+ public ComponentName[] getDreamComponentsForUser(int userId) {
+ checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "getDreamComponents", null);
- final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
- return getDreamComponentsForUser(userId);
+ return DreamManagerService.this.getDreamComponentsForUser(userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -530,13 +536,28 @@ public final class DreamManagerService extends SystemService {
}
@Override // Binder call
- public ComponentName getDefaultDreamComponent() {
- checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+ public void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
+ checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "setDreamComponents", null);
- final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
- return getDefaultDreamComponentForUser(userId);
+ DreamManagerService.this.setDreamComponentsForUser(userId, componentNames);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public ComponentName getDefaultDreamComponentForUser(int userId) {
+ checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "getDefaultDreamComponent", null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return DreamManagerService.this.getDefaultDreamComponentForUser(userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -567,24 +588,25 @@ public final class DreamManagerService extends SystemService {
}
@Override // Binder call
- public void testDream(ComponentName dream) {
+ public void testDream(int userId, ComponentName dream) {
if (dream == null) {
throw new IllegalArgumentException("dream must not be null");
}
checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "testDream", null);
- final int callingUserId = UserHandle.getCallingUserId();
final int currentUserId = ActivityManager.getCurrentUser();
- if (callingUserId != currentUserId) {
+ if (userId != currentUserId) {
// This check is inherently prone to races but at least it's something.
Slog.w(TAG, "Aborted attempt to start a test dream while a different "
- + " user is active: callingUserId=" + callingUserId
+ + " user is active: userId=" + userId
+ ", currentUserId=" + currentUserId);
return;
}
final long ident = Binder.clearCallingIdentity();
try {
- testDreamInternal(dream, callingUserId);
+ testDreamInternal(dream, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}