Adds OnBackPressedOnTaskRoot

This allows Bubbles to be collapsed instead of finished
when there is only one activity in the stack.

Bug: 126852149
Test: launch activity, press back
Change-Id: Iad8db0549853e3f385d54fc6b6cea5e502d37139
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 4a6aa33..b234bc6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -141,6 +141,7 @@
 import android.app.IApplicationThread;
 import android.app.IAssistDataReceiver;
 import android.app.INotificationManager;
+import android.app.IRequestFinishCallback;
 import android.app.ITaskStackListener;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -2288,6 +2289,32 @@
         }
     }
 
+    @Override
+    public void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
+        synchronized (mGlobalLock) {
+            ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            if (r == null) {
+                return;
+            }
+            ActivityStack stack = r.getActivityStack();
+            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
+                // handled specially.
+                final TaskRecord task = r.getTaskRecord();
+                mTaskChangeNotificationController
+                        .notifyBackPressedOnTaskRoot(task.getTaskInfo());
+            } else {
+                try {
+                    callback.requestFinish();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to invoke request finish callback", e);
+                }
+            }
+        }
+    }
+
     /**
      * TODO: Add mController hook
      */
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 3d57219..66200e3 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -53,6 +53,7 @@
     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
     private static final int NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG = 20;
+    private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -92,6 +93,10 @@
         l.onTaskDescriptionChanged((RunningTaskInfo) m.obj);
     };
 
+    private final TaskStackConsumer mNotifyBackPressedOnTaskRoot = (l, m) -> {
+        l.onBackPressedOnTaskRoot((RunningTaskInfo) m.obj);
+    };
+
     private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
         l.onActivityRequestedOrientationChanged(m.arg1, m.arg2);
     };
@@ -225,6 +230,9 @@
                 case NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG:
                     forAllRemoteListeners(mOnSizeCompatModeActivityChanged, msg);
                     break;
+                case NOTIFY_BACK_PRESSED_ON_TASK_ROOT:
+                    forAllRemoteListeners(mNotifyBackPressedOnTaskRoot, msg);
+                    break;
             }
         }
     }
@@ -458,4 +466,15 @@
         forAllLocalListeners(mOnSizeCompatModeActivityChanged, msg);
         msg.sendToTarget();
     }
+
+    /**
+     * Notify listeners that an activity received a back press when there are no other activities
+     * in the back stack.
+     */
+    void notifyBackPressedOnTaskRoot(TaskInfo taskInfo) {
+        final Message msg = mHandler.obtainMessage(NOTIFY_BACK_PRESSED_ON_TASK_ROOT,
+                taskInfo);
+        forAllLocalListeners(mNotifyBackPressedOnTaskRoot, msg);
+        msg.sendToTarget();
+    }
 }