Add task organizer based task embedder

- Split TaskEmbedder into its current VirtualDisplay implementation
  and an implementation that uses task org to create and manage
  the task
- Use the task org embedder implementation in separate bubble task view
- Skip task org tasks from triggering task resizing
- Add task org callback for back press on task root if requested

Bug: 148977538
Test: atest CtsWindowManagerDeviceTestCases:ActivityViewTest
Test: atest WmTests:TaskOrganizerTests
Change-Id: Id422bb2547197c617f914ed7cf5085e02a1c3fb5
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7e999c6..bda6da5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2420,7 +2420,12 @@
                 return;
             }
             ActivityStack stack = r.getRootTask();
-            if (stack != null && stack.isSingleTaskInstance()) {
+            final TaskOrganizerController taskOrgController =
+                    mWindowOrganizerController.mTaskOrganizerController;
+            if (taskOrgController.handleInterceptBackPressedOnTaskRoot(stack)) {
+                // This task is handled by a task organizer that has requested the back pressed
+                // callback
+            } else if (stack != null && (stack.isSingleTaskInstance())) {
                 // Single-task stacks are used for activities which are presented in floating
                 // windows above full screen activities. Instead of directly finishing the
                 // task, a task change listener is used to notify SystemUI so the action can be
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4a7edee..459a8d6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4131,6 +4131,10 @@
                 return true;
             }
 
+            if (task.isOrganized()) {
+                return true;
+            }
+
             // We need to use the task's dim bounds (which is derived from the visible bounds of
             // its apps windows) for any touch-related tests. Can't use the task's original
             // bounds because it might be adjusted to fit the content frame. One example is when
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 8edcd2f..7c47e50 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -32,7 +32,6 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.window.ITaskOrganizer;
@@ -46,7 +45,6 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
 import java.util.WeakHashMap;
 
 /**
@@ -88,6 +86,7 @@
         private final DeathRecipient mDeathRecipient;
         private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
         private final int mUid;
+        private boolean mInterceptBackPressedOnTaskRoot;
 
         TaskOrganizerState(ITaskOrganizer organizer, int uid) {
             mOrganizer = organizer;
@@ -100,6 +99,10 @@
             mUid = uid;
         }
 
+        void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
+            mInterceptBackPressedOnTaskRoot = interceptBackPressed;
+        }
+
         void addTask(Task t) {
             mOrganizedTasks.add(t);
             try {
@@ -473,6 +476,41 @@
         }
     }
 
+    @Override
+    public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
+            boolean interceptBackPressed) {
+        enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
+                if (state != null) {
+                    state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
+        if (task == null || !task.isOrganized()) {
+            return false;
+        }
+
+        final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
+        if (!state.mInterceptBackPressedOnTaskRoot) {
+            return false;
+        }
+
+        try {
+            state.mOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
+        } catch (Exception e) {
+            Slog.e(TAG, "Exception sending interceptBackPressedOnTaskRoot callback" + e);
+        }
+        return true;
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.print(prefix); pw.println("TaskOrganizerController:");