diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 198fa651695c4..295943da12622 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -136,6 +136,7 @@ import android.view.contentcapture.ContentCaptureManager; 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 @@ public class Activity extends ContextThemeWrapper * @hide */ public void updateUiTranslationState(int state, TranslationSpec sourceSpec, - TranslationSpec targetSpec, List viewIds) { + TranslationSpec targetSpec, List 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 { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a6677674a679a..3ebf545248c7c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -178,6 +178,7 @@ import android.view.autofill.AutofillId; 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 @@ public final class ActivityThread extends ClientTransactionHandler @Override public void updateUiTranslationState(IBinder activityToken, int state, - TranslationSpec sourceSpec, TranslationSpec targetSpec, List viewIds) { + TranslationSpec sourceSpec, TranslationSpec targetSpec, List 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 @@ public final class ActivityThread extends ClientTransactionHandler final SomeArgs args = (SomeArgs) msg.obj; updateUiTranslationState((IBinder) args.arg1, (int) args.arg2, (TranslationSpec) args.arg3, (TranslationSpec) args.arg4, - (List) args.arg5); + (List) args.arg5, (UiTranslationSpec) args.arg6); break; case SET_CONTENT_CAPTURE_OPTIONS_CALLBACK: handleSetContentCaptureOptionsCallback((String) msg.obj); @@ -4194,13 +4197,15 @@ public final class ActivityThread extends ClientTransactionHandler } private void updateUiTranslationState(IBinder activityToken, int state, - TranslationSpec sourceSpec, TranslationSpec targetSpec, List viewIds) { + TranslationSpec sourceSpec, TranslationSpec targetSpec, List 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 sCurrentBroadcastIntent = new ThreadLocal(); diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 918309e8e735c..4555c1725a569 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -46,6 +46,7 @@ import android.os.RemoteCallback; 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 @@ oneway interface IApplicationThread { IUiAutomationConnection instrumentationUiConnection, in ApplicationInfo targetInfo); void updateUiTranslationState(IBinder activityToken, int state, in TranslationSpec sourceSpec, - in TranslationSpec targetSpec, in List viewIds); + in TranslationSpec targetSpec, in List viewIds, + in UiTranslationSpec uiTranslationSpec); } diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java index e0526f87340a5..9e350d9aa328e 100644 --- a/core/java/android/view/translation/UiTranslationController.java +++ b/core/java/android/view/translation/UiTranslationController.java @@ -30,6 +30,7 @@ import android.os.Handler; 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 @@ public class UiTranslationController { private final ArrayMap, Translator> mTranslators; @NonNull private final ArrayMap> mViews; + /** + * Views for which {@link UiTranslationSpec#shouldPadContentForCompat()} is true. + */ + @NonNull + private final ArraySet mViewsToPadContent; @NonNull private final HandlerThread mWorkerThread; @NonNull @@ -88,6 +94,7 @@ public class UiTranslationController { mContext = context; mViews = new ArrayMap<>(); mTranslators = new ArrayMap<>(); + mViewsToPadContent = new ArraySet<>(); mWorkerThread = new HandlerThread("UiTranslationController_" + mActivity.getComponentName(), @@ -100,19 +107,27 @@ public class UiTranslationController { * Update the Ui translation state. */ public void updateUiTranslationState(@UiTranslationState int state, TranslationSpec sourceSpec, - TranslationSpec targetSpec, List views) { + TranslationSpec targetSpec, List 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 specs = new Pair<>(sourceSpec, targetSpec); if (!mTranslators.containsKey(specs)) { @@ -177,6 +192,7 @@ public class UiTranslationController { 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 @@ public class UiTranslationController { 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 281ce2bd3ab68..df0c64c810c66 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.DisplayCutout; 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 @@ public class TransactionParcelTests { @Override public void updateUiTranslationState(IBinder activityToken, int state, - TranslationSpec sourceSpec, TranslationSpec targetSpec, List viewIds) { - + TranslationSpec sourceSpec, TranslationSpec targetSpec, List 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 4198d3b86500d..2b01cdfdc27ff 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 @@ final class TranslationManagerServiceImpl extends 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); }