Add APIs to notify and restart activity in size compatibility mode

- Notify listeners about whether the resumed activity is using the
  native screen configuration.
- Able to restart foreground activity with saved state.

Bug: 112288258
Test: atest ActivityRecordTests#testRestartProcessIfVisible
Test: atest ActivityDisplayTests#testHandleActivitySizeCompatMode

Change-Id: I0b916b25f187e9406154afced0214a41c02c761a
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d747198..6664b76 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1666,13 +1666,32 @@
 
         final long origId = Binder.clearCallingIdentity();
 
+        String restartingName = null;
+        int restartingUid = 0;
+        final ActivityRecord r;
         synchronized (mGlobalLock) {
-            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
+                if (r.attachedToProcess()
+                        && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) {
+                    // The activity was requested to restart from
+                    // {@link #restartActivityProcessIfVisible}.
+                    restartingName = r.app.mName;
+                    restartingUid = r.app.mUid;
+                }
                 r.activityStoppedLocked(icicle, persistentState, description);
             }
         }
 
+        if (restartingName != null) {
+            // In order to let the foreground activity can be restarted with its saved state from
+            // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed
+            // until the activity reports stopped with the state. And the activity record will be
+            // kept because the record state is restarting, then the activity will be restarted
+            // immediately if it is still the top one.
+            mStackSupervisor.removeRestartTimeouts(r);
+            mAmInternal.killProcess(restartingName, restartingUid, "restartActivityProcess");
+        }
         mAmInternal.trimApplications();
 
         Binder.restoreCallingIdentity(origId);
@@ -2014,6 +2033,23 @@
     }
 
     @Override
+    public void restartActivityProcessIfVisible(IBinder activityToken) {
+        mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "restartActivityProcess()");
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r == null) {
+                    return;
+                }
+                r.restartProcessIfVisible();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
+    @Override
     public boolean removeTask(int taskId) {
         enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
         synchronized (mGlobalLock) {