Allow AssistDataRequester to fetch AssistContent without AssistStructure

This provides a new request type for AssistDataRequester, ASSIST_CONTEXT_CONTENT. Using this prevents ActivityTaskManagerService from sending the potentially large AssistStructure when it isn't necessary.

Bug: 189164641
Test: Manual (confirmed the new call worked as expected on Pixel 3A)
Change-Id: I5cec15c88c52f8319808aee474cc2351f2fa931a
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6d2d023..91e2d88 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -779,6 +779,9 @@
     /** @hide requestType for assist context: generate full AssistStructure for autofill. */
     public static final int ASSIST_CONTEXT_AUTOFILL = 2;
 
+    /** @hide requestType for assist context: generate AssistContent but not AssistStructure. */
+    public static final int ASSIST_CONTEXT_CONTENT = 3;
+
     /** @hide Flag for registerUidObserver: report changes in process state. */
     public static final int UID_OBSERVER_PROCSTATE = 1<<0;
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index eb0a7b4..d8b2a72 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3830,6 +3830,8 @@
         // - it does not call onProvideAssistData()
         // - it needs an IAutoFillCallback
         boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL;
+        // When only the AssistContent is requested, omit the AsssistStructure
+        boolean requestedOnlyContent = cmd.requestType == ActivityManager.ASSIST_CONTEXT_CONTENT;
 
         // TODO: decide if lastSessionId logic applies to autofill sessions
         if (mLastSessionId != cmd.sessionId) {
@@ -3856,8 +3858,11 @@
                 r.activity.onProvideAssistData(data);
                 referrer = r.activity.onProvideReferrer();
             }
-            if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) {
-                structure = new AssistStructure(r.activity, forAutofill, cmd.flags);
+            if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill
+                    || requestedOnlyContent) {
+                if (!requestedOnlyContent) {
+                    structure = new AssistStructure(r.activity, forAutofill, cmd.flags);
+                }
                 Intent activityIntent = r.activity.getIntent();
                 boolean notSecure = r.window == null ||
                         (r.window.getAttributes().flags
@@ -3879,18 +3884,21 @@
                     r.activity.onProvideAssistContent(content);
                 }
             }
-
-        }
-        if (structure == null) {
-            structure = new AssistStructure();
         }
 
-        // TODO: decide if lastSessionId logic applies to autofill sessions
+        if (!requestedOnlyContent) {
+            if (structure == null) {
+                structure = new AssistStructure();
+            }
 
-        structure.setAcquisitionStartTime(startTime);
-        structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
+            // TODO: decide if lastSessionId logic applies to autofill sessions
 
-        mLastAssistStructures.add(new WeakReference<>(structure));
+            structure.setAcquisitionStartTime(startTime);
+            structure.setAcquisitionEndTime(SystemClock.uptimeMillis());
+
+            mLastAssistStructures.add(new WeakReference<>(structure));
+        }
+
         IActivityTaskManager mgr = ActivityTaskManager.getService();
         try {
             mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
diff --git a/services/core/java/com/android/server/am/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index 70a54cf..98ad81d 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.ASSIST_CONTEXT_CONTENT;
 import static android.app.ActivityManager.ASSIST_CONTEXT_FULL;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_NONE;
@@ -143,45 +144,47 @@
      * Request that autofill data be loaded asynchronously. The resulting data will be provided
      * through the {@link AssistDataRequesterCallbacks}.
      *
-     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
-     * boolean)}.
+     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+     * String, boolean)}.
      */
     public void requestAutofillData(List<IBinder> activityTokens, int callingUid,
             String callingPackage) {
         requestData(activityTokens, true /* requestAutofillData */,
                 true /* fetchData */, false /* fetchScreenshot */,
-                true /* allowFetchData */, false /* allowFetchScreenshot */,
-                false /* ignoreTopActivityCheck */, callingUid, callingPackage);
+                true /* fetchStructure */, true /* allowFetchData */,
+                false /* allowFetchScreenshot */, false /* ignoreTopActivityCheck */, callingUid,
+                callingPackage);
     }
 
     /**
      * Request that assist data be loaded asynchronously. The resulting data will be provided
      * through the {@link AssistDataRequesterCallbacks}.
      *
-     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
-     * boolean)}.
+     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+     * String, boolean)}.
      */
     public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
             final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot,
             int callingUid, String callingPackage) {
-        requestAssistData(activityTokens, fetchData, fetchScreenshot, allowFetchData,
-                allowFetchScreenshot, false /* ignoreTopActivityCheck */, callingUid,
-                callingPackage);
+        requestAssistData(activityTokens, fetchData, fetchScreenshot, true /* fetchStructure */,
+                allowFetchData, allowFetchScreenshot, false /* ignoreTopActivityCheck */,
+                callingUid, callingPackage);
     }
 
     /**
      * Request that assist data be loaded asynchronously. The resulting data will be provided
      * through the {@link AssistDataRequesterCallbacks}.
      *
-     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, int, String,
-     * boolean)}.
+     * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
+     * String, boolean)}.
      */
     public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
-            final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot,
-            boolean ignoreTopActivityCheck, int callingUid, String callingPackage) {
+            final boolean fetchScreenshot, final boolean fetchStructure, boolean allowFetchData,
+            boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
+            String callingPackage) {
         requestData(activityTokens, false /* requestAutofillData */, fetchData, fetchScreenshot,
-                allowFetchData, allowFetchScreenshot, ignoreTopActivityCheck, callingUid,
-                callingPackage);
+                fetchStructure, allowFetchData, allowFetchScreenshot, ignoreTopActivityCheck,
+                callingUid, callingPackage);
     }
 
     /**
@@ -197,6 +200,8 @@
      * @param fetchScreenshot whether or not to fetch the screenshot, only applies if fetchData is
      *     true, the caller is allowed to fetch the assist data, and the current activity allows
      *     assist data to be fetched from it
+     * @param fetchStructure whether or not to fetch the AssistStructure along with the
+     *     AssistContent
      * @param allowFetchData to be joined with other checks, determines whether or not the requester
      *     is allowed to fetch the assist data
      * @param allowFetchScreenshot to be joined with other checks, determines whether or not the
@@ -205,9 +210,9 @@
      *     making the request. Used when passing an activity from Recents.
      */
     private void requestData(List<IBinder> activityTokens, final boolean requestAutofillData,
-            final boolean fetchData, final boolean fetchScreenshot, boolean allowFetchData,
-            boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
-            String callingPackage) {
+            final boolean fetchData, final boolean fetchScreenshot, final boolean fetchStructure,
+            boolean allowFetchData, boolean allowFetchScreenshot, boolean ignoreTopActivityCheck,
+            int callingUid, String callingPackage) {
         // TODO(b/34090158): Known issue, if the assist data is not allowed on the current activity,
         //                   then no assist data is requested for any of the other activities
 
@@ -246,13 +251,18 @@
                         Bundle receiverExtras = new Bundle();
                         receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
                         receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, numActivities);
-                        boolean result = requestAutofillData
-                                ? mActivityTaskManager.requestAutofillData(this,
-                                        receiverExtras, topActivity, 0 /* flags */)
-                                : mActivityTaskManager.requestAssistContextExtras(
-                                        ASSIST_CONTEXT_FULL, this, receiverExtras, topActivity,
+                        boolean result;
+                        if (requestAutofillData) {
+                            result = mActivityTaskManager.requestAutofillData(this, receiverExtras,
+                                    topActivity, 0 /* flags */);
+                        } else {
+                            int requestType = fetchStructure ? ASSIST_CONTEXT_FULL :
+                                    ASSIST_CONTEXT_CONTENT;
+                            result = mActivityTaskManager.requestAssistContextExtras(
+                                        requestType, this, receiverExtras, topActivity,
                                         /* checkActivityIsTop= */ (i == 0)
                                         && !ignoreTopActivityCheck, /* newSessionId= */ i == 0);
+                        }
                         if (result) {
                             mPendingDataCount++;
                         } else if (i == 0) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c7e4abb..45e6c66 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2834,7 +2834,7 @@
         List<IBinder> topActivityToken = new ArrayList<>();
         topActivityToken.add(tokens.getActivityToken());
         requester.requestAssistData(topActivityToken, true /* fetchData */,
-                false /* fetchScreenshot */, true /* allowFetchData */,
+                false /* fetchScreenshot */, false /* fetchStructure */, true /* allowFetchData */,
                 false /* allowFetchScreenshot*/, true /* ignoreFocusCheck */,
                 Binder.getCallingUid(), callingPackageName);