Pass InlineSuggestionsRequest via autofill auth intent extras

Bug: 159616829
Test: atest android.autofillservice.cts.inline.InlineAuthenticationTest

Change-Id: Ifb4b60afe2c241011138d1c5fa8195585d53b82b
diff --git a/core/api/current.txt b/core/api/current.txt
index 3efb789..81f5143 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -50589,6 +50589,7 @@
     field public static final String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE";
+    field public static final String EXTRA_INLINE_SUGGESTIONS_REQUEST = "android.view.autofill.extra.INLINE_SUGGESTIONS_REQUEST";
   }
 
   public abstract static class AutofillManager.AutofillCallback {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 794181e..ef36db6 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -221,6 +221,18 @@
     public static final String EXTRA_CLIENT_STATE =
             "android.view.autofill.extra.CLIENT_STATE";
 
+    /**
+     * Intent extra: the {@link android.view.inputmethod.InlineSuggestionsRequest} in the
+     * autofill request.
+     *
+     * <p>This is filled in the authentication intent so the
+     * {@link android.service.autofill.AutofillService} can use it to create the inline
+     * suggestion {@link android.service.autofill.Dataset} in the response, if the original autofill
+     * request contains the {@link android.view.inputmethod.InlineSuggestionsRequest}.
+     */
+    public static final String EXTRA_INLINE_SUGGESTIONS_REQUEST =
+            "android.view.autofill.extra.INLINE_SUGGESTIONS_REQUEST";
+
     /** @hide */
     public static final String EXTRA_RESTORE_SESSION_TOKEN =
             "android.view.autofill.extra.RESTORE_SESSION_TOKEN";
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 67f654e..9805a2e8 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -91,6 +91,7 @@
 import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -222,6 +223,13 @@
     private final ArrayMap<AutofillId, ViewState> mViewStates = new ArrayMap<>();
 
     /**
+     * Tracks the most recent IME inline request and the corresponding request id, for regular
+     * autofill.
+     */
+    @GuardedBy("mLock")
+    @Nullable private Pair<Integer, InlineSuggestionsRequest> mLastInlineSuggestionsRequest;
+
+    /**
      * Id of the View currently being displayed.
      */
     @GuardedBy("mLock")
@@ -330,7 +338,7 @@
     @GuardedBy("mLock")
     private ArrayList<AutofillId> mAugmentedAutofillableIds;
 
-    @Nullable
+    @NonNull
     private final AutofillInlineSessionController mInlineSessionController;
 
     /**
@@ -821,11 +829,14 @@
                             /* isInlineRequest= */ true);
             if (inlineSuggestionsRequestConsumer != null) {
                 final AutofillId focusedId = mCurrentViewId;
+                final int requestIdCopy = requestId;
                 remoteRenderService.getInlineSuggestionsRendererInfo(
                         new RemoteCallback((extras) -> {
                             synchronized (mLock) {
                                 mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
-                                        focusedId, inlineSuggestionsRequestConsumer, extras);
+                                        focusedId, inlineSuggestionsRequestCacheDecorator(
+                                                inlineSuggestionsRequestConsumer, requestIdCopy),
+                                        extras);
                             }
                         }, mHandler)
                 );
@@ -3653,11 +3664,27 @@
                     requestId, mContexts);
             return null;
         }
+        if (mLastInlineSuggestionsRequest != null
+                && mLastInlineSuggestionsRequest.first == requestId) {
+            fillInIntent.putExtra(AutofillManager.EXTRA_INLINE_SUGGESTIONS_REQUEST,
+                    mLastInlineSuggestionsRequest.second);
+        }
         fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, context.getStructure());
         fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE, extras);
         return fillInIntent;
     }
 
+    @NonNull
+    private Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestCacheDecorator(
+            @NonNull Consumer<InlineSuggestionsRequest> consumer, int requestId) {
+        return inlineSuggestionsRequest -> {
+            consumer.accept(inlineSuggestionsRequest);
+            synchronized (mLock) {
+                mLastInlineSuggestionsRequest = Pair.create(requestId, inlineSuggestionsRequest);
+            }
+        };
+    }
+
     private void startAuthentication(int authenticationId, IntentSender intent,
             Intent fillInIntent, boolean authenticateInline) {
         try {