Pipe UiTranslationSpec through to the UiTranslationController.

And use it to conditionally enable content padding for requested views.

Fix: 179693024
Test: atest android.translation.cts.UiTranslationManagerTest
Test: adb shell dumpsys activity <ACTIVITY> --translation
Change-Id: I23fb29a60525d736f2dcf9d11b548c62332c412c
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 198fa65..295943d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -136,6 +136,7 @@
 import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
 import android.view.translation.TranslationSpec;
 import android.view.translation.UiTranslationController;
+import android.view.translation.UiTranslationSpec;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -8815,11 +8816,13 @@
      * @hide
      */
     public void updateUiTranslationState(int state, TranslationSpec sourceSpec,
-            TranslationSpec targetSpec, List<AutofillId> viewIds) {
+            TranslationSpec targetSpec, List<AutofillId> viewIds,
+            UiTranslationSpec uiTranslationSpec) {
         if (mUiTranslationController == null) {
             mUiTranslationController = new UiTranslationController(this, getApplicationContext());
         }
-        mUiTranslationController.updateUiTranslationState(state, sourceSpec, targetSpec, viewIds);
+        mUiTranslationController.updateUiTranslationState(
+                state, sourceSpec, targetSpec, viewIds, uiTranslationSpec);
     }
 
     class HostCallbacks extends FragmentHostCallback<Activity> {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ff210e1..3713b7c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -178,6 +178,7 @@
 import android.view.contentcapture.IContentCaptureManager;
 import android.view.contentcapture.IContentCaptureOptionsCallback;
 import android.view.translation.TranslationSpec;
+import android.view.translation.UiTranslationSpec;
 import android.webkit.WebView;
 import android.window.SizeConfigurationBuckets;
 import android.window.SplashScreen;
@@ -1843,13 +1844,15 @@
 
         @Override
         public void updateUiTranslationState(IBinder activityToken, int state,
-                TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds) {
+                TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds,
+                UiTranslationSpec uiTranslationSpec) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = activityToken;
             args.arg2 = state;
             args.arg3 = sourceSpec;
             args.arg4 = targetSpec;
             args.arg5 = viewIds;
+            args.arg6 = uiTranslationSpec;
             sendMessage(H.UPDATE_UI_TRANSLATION_STATE, args);
         }
     }
@@ -2212,7 +2215,7 @@
                     final SomeArgs args = (SomeArgs) msg.obj;
                     updateUiTranslationState((IBinder) args.arg1, (int) args.arg2,
                             (TranslationSpec) args.arg3, (TranslationSpec) args.arg4,
-                            (List<AutofillId>) args.arg5);
+                            (List<AutofillId>) args.arg5, (UiTranslationSpec) args.arg6);
                     break;
                 case SET_CONTENT_CAPTURE_OPTIONS_CALLBACK:
                     handleSetContentCaptureOptionsCallback((String) msg.obj);
@@ -4194,13 +4197,15 @@
     }
 
     private void updateUiTranslationState(IBinder activityToken, int state,
-            TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds) {
+            TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds,
+            UiTranslationSpec uiTranslationSpec) {
         final ActivityClientRecord r = mActivities.get(activityToken);
         if (r == null) {
             Log.w(TAG, "updateUiTranslationState(): no activity for " + activityToken);
             return;
         }
-        r.activity.updateUiTranslationState(state, sourceSpec, targetSpec, viewIds);
+        r.activity.updateUiTranslationState(
+                state, sourceSpec, targetSpec, viewIds, uiTranslationSpec);
     }
 
     private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 918309e..4555c172 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -46,6 +46,7 @@
 import android.os.SharedMemory;
 import android.view.autofill.AutofillId;
 import android.view.translation.TranslationSpec;
+import android.view.translation.UiTranslationSpec;
 
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
@@ -160,5 +161,6 @@
             IUiAutomationConnection instrumentationUiConnection,
             in ApplicationInfo targetInfo);
     void updateUiTranslationState(IBinder activityToken, int state, in TranslationSpec sourceSpec,
-            in TranslationSpec targetSpec, in List<AutofillId> viewIds);
+            in TranslationSpec targetSpec, in List<AutofillId> viewIds,
+            in UiTranslationSpec uiTranslationSpec);
 }
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index e0526f8..9e350d9 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -30,6 +30,7 @@
 import android.os.HandlerThread;
 import android.os.Process;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.LongSparseArray;
@@ -77,6 +78,11 @@
     private final ArrayMap<Pair<TranslationSpec, TranslationSpec>, Translator> mTranslators;
     @NonNull
     private final ArrayMap<AutofillId, WeakReference<View>> mViews;
+    /**
+     * Views for which {@link UiTranslationSpec#shouldPadContentForCompat()} is true.
+     */
+    @NonNull
+    private final ArraySet<AutofillId> mViewsToPadContent;
     @NonNull
     private final HandlerThread mWorkerThread;
     @NonNull
@@ -88,6 +94,7 @@
         mContext = context;
         mViews = new ArrayMap<>();
         mTranslators = new ArrayMap<>();
+        mViewsToPadContent = new ArraySet<>();
 
         mWorkerThread =
                 new HandlerThread("UiTranslationController_" + mActivity.getComponentName(),
@@ -100,19 +107,27 @@
      * Update the Ui translation state.
      */
     public void updateUiTranslationState(@UiTranslationState int state, TranslationSpec sourceSpec,
-            TranslationSpec targetSpec, List<AutofillId> views) {
+            TranslationSpec targetSpec, List<AutofillId> views,
+            UiTranslationSpec uiTranslationSpec) {
         if (!mActivity.isResumed() && (state == STATE_UI_TRANSLATION_STARTED
                 || state == STATE_UI_TRANSLATION_RESUMED)) {
             return;
         }
 
         Log.i(TAG, "updateUiTranslationState state: " + stateToString(state)
-                + (DEBUG ? ", views: " + views : ""));
+                + (DEBUG ? (", views: " + views + ", spec: " + uiTranslationSpec) : ""));
         synchronized (mLock) {
             mCurrentState = state;
         }
         switch (state) {
             case STATE_UI_TRANSLATION_STARTED:
+                if (uiTranslationSpec != null && uiTranslationSpec.shouldPadContentForCompat()) {
+                    synchronized (mLock) {
+                        mViewsToPadContent.addAll(views);
+                        // TODO: Cleanup disappeared views from mViews and mViewsToPadContent at
+                        //  some appropriate place.
+                    }
+                }
                 final Pair<TranslationSpec, TranslationSpec> specs =
                         new Pair<>(sourceSpec, targetSpec);
                 if (!mTranslators.containsKey(specs)) {
@@ -177,6 +192,7 @@
                 pw.print(pfx); pw.print("autofillId: "); pw.println(autofillId);
                 pw.print(pfx); pw.print("view:"); pw.println(view);
             }
+            pw.print(outerPrefix); pw.print("padded views: "); pw.println(mViewsToPadContent);
         }
         // TODO(b/182433547): we will remove debug rom condition before S release then we change
         //  change this back to "DEBUG"
@@ -374,8 +390,9 @@
                         return;
                     }
 
-                    // TODO: Do this for specific views on request only.
-                    callback.enableContentPadding();
+                    if (mViewsToPadContent.contains(autofillId)) {
+                        callback.enableContentPadding();
+                    }
                     view.onViewTranslationResponse(response);
                     callback.onShowTranslation(view);
                 });
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 281ce2b..df0c64c 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -61,6 +61,7 @@
 import android.view.Surface;
 import android.view.autofill.AutofillId;
 import android.view.translation.TranslationSpec;
+import android.view.translation.UiTranslationSpec;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -693,8 +694,8 @@
 
         @Override
         public void updateUiTranslationState(IBinder activityToken, int state,
-                TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds) {
-
+                TranslationSpec sourceSpec, TranslationSpec targetSpec, List<AutofillId> viewIds,
+                UiTranslationSpec uiTranslationSpec) {
         }
     }
 }
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
index 4198d3b..2b01cdf 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -175,10 +175,9 @@
             return;
         }
         try {
-            // TODO: Pipe uiTranslationSpec through to the UiTranslationController.
             taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
                     taskTopActivityTokens.getActivityToken(), state, sourceSpec, targetSpec,
-                    viewIds);
+                    viewIds, uiTranslationSpec);
         } catch (RemoteException e) {
             Slog.w(TAG, "Update UiTranslationState fail: " + e);
         }