Add startDreamActivity request verification

The ActivityTaskManagerTestService has a special method to start a
DreamActivity. This CL adds a verification check before the activity is
started to check that the caller is the currently active dream
component.

Bug: 133216167

Test: atest DreamManagerServiceTest

Merged-In: Id71b4cbc57c6569f58b6d906cc8361c104a507dc
Change-Id: Id71b4cbc57c6569f58b6d906cc8361c104a507dc
(cherry picked from commit 20dc51820ae813788819a916277268fe571bbbf3)
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index ff7cef9..41fdd0b 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.service.dreams;
 
+import android.content.ComponentName;
+
 /**
  * Dream manager local system service interface.
  *
@@ -42,4 +44,13 @@
      * Called by the power manager to determine whether a dream is running.
      */
     public abstract boolean isDreaming();
+
+    /**
+     * Called by the ActivityTaskManagerService to verify that the startDreamActivity
+     * request comes from the current active dream component.
+     *
+     * @param doze If true returns the current active doze component. Otherwise, returns the
+     *             active dream component.
+     */
+    public abstract ComponentName getActiveDreamComponent(boolean doze);
 }
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index b31238c..28f4929 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -608,6 +608,8 @@
      * Marks this dream as windowless.  Only available to doze dreams.
      *
      * @hide
+     *
+     * TODO: Remove @UnsupportedAppUsage.
      */
     @UnsupportedAppUsage
     public void setWindowless(boolean windowless) {
@@ -904,12 +906,9 @@
 
         if (mActivity == null) {
             Slog.w(TAG, "Finish was called before the dream was attached.");
-            return;
-        }
-
-        // In case the activity is not finished yet, do it now. This can happen if someone calls
-        // finish() directly, without going through wakeUp().
-        if (!mActivity.isFinishing()) {
+        } else if (!mActivity.isFinishing()) {
+            // In case the activity is not finished yet, do it now. This can happen if someone calls
+            // finish() directly, without going through wakeUp().
             mActivity.finishAndRemoveTask();
             return;
         }
@@ -924,7 +923,6 @@
             } catch (RemoteException ex) {
                 // system server died
             }
-
         }
     }
 
@@ -995,6 +993,8 @@
 
         if (mActivity != null && !mActivity.isFinishing()) {
             mActivity.finishAndRemoveTask();
+        } else {
+            finish();
         }
 
         mDreamToken = null;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 3052e3c..a74be13 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -268,6 +268,10 @@
         }
     }
 
+    private ComponentName getActiveDreamComponentInternal(boolean doze) {
+        return chooseDreamForUser(doze, ActivityManager.getCurrentUser());
+    }
+
     private ComponentName chooseDreamForUser(boolean doze, int userId) {
         if (doze) {
             ComponentName dozeComponent = getDozeComponent(userId);
@@ -671,6 +675,11 @@
         public boolean isDreaming() {
             return isDreamingInternal();
         }
+
+        @Override
+        public ComponentName getActiveDreamComponent(boolean doze) {
+            return getActiveDreamComponentInternal(doze);
+        }
     }
 
     private final Runnable mSystemPropertiesChanged = new Runnable() {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index dfc9aa8..1f2a9c7 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -213,6 +213,7 @@
 import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.service.dreams.DreamActivity;
+import android.service.dreams.DreamManagerInternal;
 import android.service.voice.IVoiceInteractionSession;
 import android.service.voice.VoiceInteractionManagerInternal;
 import android.sysprop.DisplayProperties;
@@ -1233,12 +1234,25 @@
 
     @Override
     public boolean startDreamActivity(Intent intent) {
+        final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
+        final long origId = Binder.clearCallingIdentity();
+
+        // The dream activity is only called for non-doze dreams.
+        final ComponentName currentDream = LocalServices.getService(DreamManagerInternal.class)
+                .getActiveDreamComponent(/* doze= */ false);
+
+        if (currentDream == null || currentDream.getPackageName() == null
+                || !currentDream.getPackageName().equals(process.mInfo.packageName)) {
+            Slog.e(TAG, "Calling package is not the current dream package. "
+                    + "Aborting startDreamActivity...");
+            return false;
+        }
+
         final ActivityInfo a = new ActivityInfo();
         a.theme = com.android.internal.R.style.Theme_Dream;
         a.exported = true;
         a.name = DreamActivity.class.getName();
 
-        final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
 
         a.packageName = process.mInfo.packageName;
         a.applicationInfo = process.mInfo;
@@ -1253,7 +1267,6 @@
         a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
         a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
 
-        final long origId = Binder.clearCallingIdentity();
         try {
             getActivityStartController().obtainStarter(intent, "dream")
                     .setActivityInfo(a)