Introducing PendingIntentController (17/n)

Added PendingIntentController and centralize pending intent handling
in that class. Pending intents are used by activities and other components
like services and broadcasts. Since, activity handling is going to be moving
to the wm package, we need a way to access pending intents from both am and
wm packages. The PendingIntentController allows this to by not holding any
service level locks.

Bug: 80414790
Test: Existing tests pass.
Change-Id: I52f6f233b24e62839a85067556f3560dec27f0c7
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 4dc2851..add9f2a 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -239,7 +239,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 
@@ -276,6 +278,7 @@
     UriGrantsManagerInternal mUgmInternal;
     private PackageManagerInternal mPmInternal;
     private ActivityTaskManagerInternal mInternal;
+    PendingIntentController mPendingIntentController;
     /* Global service lock used by the package the owns this service. */
     Object mGlobalLock;
     ActivityStackSupervisor mStackSupervisor;
@@ -628,6 +631,7 @@
         final File systemDir = SystemServiceManager.ensureSystemDir();
         mAppWarnings = new AppWarnings(this, mUiContext, mH, mUiHandler, systemDir);
         mCompatModePackages = new CompatModePackages(this, systemDir, mH);
+        mPendingIntentController = mAm.mPendingIntentController;
 
         mTempConfig.setToDefaults();
         mTempConfig.setLocales(LocaleList.getDefault());
@@ -5019,6 +5023,39 @@
 
     }
 
+    IIntentSender getIntentSenderLocked(int type, String packageName, int callingUid, int userId,
+            IBinder token, String resultWho, int requestCode, Intent[] intents,
+            String[] resolvedTypes, int flags, Bundle bOptions) {
+
+        ActivityRecord activity = null;
+        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+            activity = ActivityRecord.isInStackLocked(token);
+            if (activity == null) {
+                Slog.w(TAG, "Failed createPendingResult: activity " + token + " not in any stack");
+                return null;
+            }
+            if (activity.finishing) {
+                Slog.w(TAG, "Failed createPendingResult: activity " + activity + " is finishing");
+                return null;
+            }
+        }
+
+        final PendingIntentRecord rec = mPendingIntentController.getIntentSender(type, packageName,
+                callingUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
+                bOptions);
+        final boolean noCreate = (flags & PendingIntent.FLAG_NO_CREATE) != 0;
+        if (noCreate) {
+            return rec;
+        }
+        if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+            if (activity.pendingResults == null) {
+                activity.pendingResults = new HashSet<>();
+            }
+            activity.pendingResults.add(rec.ref);
+        }
+        return rec;
+    }
+
     // TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities
     private void startTimeTrackingFocusedActivityLocked() {
         final ActivityRecord resumedActivity = mStackSupervisor.getTopResumedActivity();
@@ -5310,6 +5347,31 @@
         }
 
         @Override
+        public int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
+                String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
+                boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent) {
+            synchronized (mGlobalLock) {
+                return getActivityStartController().startActivitiesInPackage(uid, callingPackage,
+                        intents, resolvedTypes, resultTo, options, userId, validateIncomingUser,
+                        originatingPendingIntent);
+            }
+        }
+
+        @Override
+        public int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
+                String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
+                String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
+                int userId, TaskRecord inTask, String reason, boolean validateIncomingUser,
+                PendingIntentRecord originatingPendingIntent) {
+            synchronized (mGlobalLock) {
+                return getActivityStartController().startActivityInPackage(uid, realCallingPid,
+                        realCallingUid, callingPackage, intent, resolvedType, resultTo, resultWho,
+                        requestCode, startFlags, options, userId, inTask, reason,
+                        validateIncomingUser, originatingPendingIntent);
+            }
+        }
+
+        @Override
         public int startActivityAsUser(IApplicationThread caller, String callerPacakge,
                 Intent intent, Bundle options, int userId) {
             return ActivityTaskManagerService.this.startActivityAsUser(
@@ -5684,5 +5746,39 @@
                 }
             });
         }
+
+        @Override
+        public void sendActivityResult(int callingUid, IBinder activityToken, String resultWho,
+                int requestCode, int resultCode, Intent data) {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r != null && r.getStack() != null) {
+                    r.getStack().sendActivityResultLocked(callingUid, r, resultWho, requestCode,
+                            resultCode, data);
+                }
+            }
+        }
+
+        @Override
+        public void clearPendingResultForActivity(IBinder activityToken,
+                WeakReference<PendingIntentRecord> pir) {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r != null && r.pendingResults != null) {
+                    r.pendingResults.remove(pir);
+                }
+            }
+        }
+
+        @Override
+        public IIntentSender getIntentSender(int type, String packageName,
+                int callingUid, int userId, IBinder token, String resultWho,
+                int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
+                Bundle bOptions) {
+            synchronized (mGlobalLock) {
+                return getIntentSenderLocked(type, packageName, callingUid, userId, token,
+                        resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
+            }
+        }
     }
 }