Loading core/java/android/view/View.java +36 −4 Original line number Diff line number Diff line Loading @@ -3514,6 +3514,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 11 PFLAG4_SCROLL_CAPTURE_HINT_MASK * 1 PFLAG4_ALLOW_CLICK_WHEN_DISABLED * 1 PFLAG4_DETACHED * 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE * |-------|-------|-------|-------| */ Loading Loading @@ -3580,6 +3581,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private static final int PFLAG4_DETACHED = 0x000002000; /** * Indicates that the view has transient state because the system is translating it. */ private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -12270,6 +12276,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } /** * Set the view is tracking translation transient state. This flag is used to check if the view * need to call setHasTransientState(false) to reset transient state that set when starting * translation. * * @param hasTranslationTransientState true if this view has translation transient state * @hide */ public void setHasTranslationTransientState(boolean hasTranslationTransientState) { if (hasTranslationTransientState) { mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } else { mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } } /** * @hide */ public boolean hasTranslationTransientState() { return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE) == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } /** * Returns true if this view is currently attached to a window. */ Loading Loading @@ -30839,6 +30869,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** * Returns a {@link ViewTranslationCallback} that is used to display the translated information * or {@code null} if this View doesn't support translation. * * @hide */ @Nullable Loading Loading @@ -30925,7 +30958,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual * children to build {@link ViewTranslationRequest} if the view should be translated. * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that * recycling of views doesn't prevent the system from attaching the response to it.</p> * recycling of views doesn't prevent the system from attaching the response to it. Therefore, * if overriding this method, you should set or reset the transient state. </p> * * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or * {@code null} if the view doesn't have virtual child that should be translated. The virtual Loading Loading @@ -30975,10 +31009,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for " + getAutofillId()); } // TODO: Add a default ViewTranslationCallback for View that resets this in // onClearTranslation(). Also update the javadoc for this method to mention // that. setHasTransientState(true); setHasTranslationTransientState(true); } } } core/java/android/view/translation/UiTranslationController.java +24 −10 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.translation.UiTranslationManager.UiTranslationState; import android.widget.TextView; import android.widget.TextViewTranslationCallback; import com.android.internal.util.function.pooled.PooledLambda; Loading Loading @@ -146,7 +148,13 @@ public class UiTranslationController { break; case STATE_UI_TRANSLATION_FINISHED: destroyTranslators(); runForEachView((view, callback) -> callback.onClearTranslation(view)); runForEachView((view, callback) -> { callback.onClearTranslation(view); if (view.hasTranslationTransientState()) { view.setHasTransientState(false); view.setHasTranslationTransientState(false); } }); synchronized (mLock) { mViews.clear(); } Loading Loading @@ -381,17 +389,23 @@ public class UiTranslationController { continue; } mActivity.runOnUiThread(() -> { final ViewTranslationCallback callback = view.getViewTranslationCallback(); ViewTranslationCallback callback = view.getViewTranslationCallback(); if (callback == null) { if (view instanceof TextView) { // developer doesn't provide their override, we set the default TextView // implememtation. callback = new TextViewTranslationCallback(); view.setViewTranslationCallback(callback); if (mViewsToPadContent.contains(autofillId)) { callback.enableContentPadding(); } } else { if (DEBUG) { Log.d(TAG, view + " doesn't support showing translation because of " + "null ViewTranslationCallback."); } return; } if (mViewsToPadContent.contains(autofillId)) { callback.enableContentPadding(); } view.onViewTranslationResponse(response); callback.onShowTranslation(view); Loading core/java/android/widget/TextView.java +24 −42 Original line number Diff line number Diff line Loading @@ -740,7 +740,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private MovementMethod mMovement; private TransformationMethod mTransformation; private TextViewTranslationCallback mDefaultTranslationCallback; @UnsupportedAppUsage private boolean mAllowTransformationLengthChange; @UnsupportedAppUsage Loading Loading @@ -2376,11 +2375,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @ViewDebug.CapturedViewProperty @InspectableProperty public CharSequence getText() { if (mUseTextPaddingForUiTranslation && mDefaultTranslationCallback != null && mDefaultTranslationCallback.isTextPaddingEnabled() && mDefaultTranslationCallback.isShowingTranslation()) { return mDefaultTranslationCallback.getPaddedText(mText, mTransformed); if (mUseTextPaddingForUiTranslation) { ViewTranslationCallback callback = getViewTranslationCallback(); if (callback != null && callback instanceof TextViewTranslationCallback) { TextViewTranslationCallback defaultCallback = (TextViewTranslationCallback) callback; if (defaultCallback.isTextPaddingEnabled() && defaultCallback.isShowingTranslation()) { return defaultCallback.getPaddedText(mText, mTransformed); } } } return mText; } Loading Loading @@ -13932,30 +13936,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener requestsCollector.accept(requestBuilder.build()); } /** * Returns a {@link ViewTranslationCallback} that is used to display the translated information. * The default implementation will use a {@link TransformationMethod} that allow to replace the * current {@link TransformationMethod} to transform the original text to the translated text * display. * * @return a {@link ViewTranslationCallback} that is used to control how to display the * translated information or {@code null} if this View doesn't support translation. * * @hide */ @Nullable @Override public ViewTranslationCallback getViewTranslationCallback() { return getDefaultViewTranslationCallback(); } private ViewTranslationCallback getDefaultViewTranslationCallback() { if (mDefaultTranslationCallback == null) { mDefaultTranslationCallback = new TextViewTranslationCallback(); } return mDefaultTranslationCallback; } /** * * Called when the content from {@link #onCreateViewTranslationRequest} had been translated by Loading @@ -13969,17 +13949,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) { // set ViewTranslationResponse super.onViewTranslationResponse(response); // TODO(b/183467275): Use the overridden ViewTranslationCallback instead of our default // implementation if the view has overridden getViewTranslationCallback. TextViewTranslationCallback callback = (TextViewTranslationCallback) getDefaultViewTranslationCallback(); // TODO(b/178353965): move to ViewTranslationCallback.onShow() ViewTranslationCallback callback = getViewTranslationCallback(); if (callback instanceof TextViewTranslationCallback) { TextViewTranslationCallback textViewDefaultCallback = (TextViewTranslationCallback) callback; TranslationTransformationMethod oldTranslationMethod = callback.getTranslationTransformation(); textViewDefaultCallback.getTranslationTransformation(); TransformationMethod originalTranslationMethod = oldTranslationMethod != null ? oldTranslationMethod.getOriginalTransformationMethod() : mTransformation; TranslationTransformationMethod newTranslationMethod = new TranslationTransformationMethod(response, originalTranslationMethod); // TODO(b/178353965): well-handle setTransformationMethod. callback.setTranslationTransformation(newTranslationMethod); textViewDefaultCallback.setTranslationTransformation(newTranslationMethod); } } } Loading
core/java/android/view/View.java +36 −4 Original line number Diff line number Diff line Loading @@ -3514,6 +3514,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 11 PFLAG4_SCROLL_CAPTURE_HINT_MASK * 1 PFLAG4_ALLOW_CLICK_WHEN_DISABLED * 1 PFLAG4_DETACHED * 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE * |-------|-------|-------|-------| */ Loading Loading @@ -3580,6 +3581,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private static final int PFLAG4_DETACHED = 0x000002000; /** * Indicates that the view has transient state because the system is translating it. */ private static final int PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE = 0x000004000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -12270,6 +12276,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } /** * Set the view is tracking translation transient state. This flag is used to check if the view * need to call setHasTransientState(false) to reset transient state that set when starting * translation. * * @param hasTranslationTransientState true if this view has translation transient state * @hide */ public void setHasTranslationTransientState(boolean hasTranslationTransientState) { if (hasTranslationTransientState) { mPrivateFlags4 |= PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } else { mPrivateFlags4 &= ~PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } } /** * @hide */ public boolean hasTranslationTransientState() { return (mPrivateFlags4 & PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE) == PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE; } /** * Returns true if this view is currently attached to a window. */ Loading Loading @@ -30839,6 +30869,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** * Returns a {@link ViewTranslationCallback} that is used to display the translated information * or {@code null} if this View doesn't support translation. * * @hide */ @Nullable Loading Loading @@ -30925,7 +30958,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * view or calls {@link View#onVirtualViewTranslationResponses} for view contains virtual * children to build {@link ViewTranslationRequest} if the view should be translated. * The view is marked as having {@link #setHasTransientState(boolean) transient state} so that * recycling of views doesn't prevent the system from attaching the response to it.</p> * recycling of views doesn't prevent the system from attaching the response to it. Therefore, * if overriding this method, you should set or reset the transient state. </p> * * @param viewIds a map for the view's {@link AutofillId} and its virtual child ids or * {@code null} if the view doesn't have virtual child that should be translated. The virtual Loading Loading @@ -30975,10 +31009,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for " + getAutofillId()); } // TODO: Add a default ViewTranslationCallback for View that resets this in // onClearTranslation(). Also update the javadoc for this method to mention // that. setHasTransientState(true); setHasTranslationTransientState(true); } } }
core/java/android/view/translation/UiTranslationController.java +24 −10 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.translation.UiTranslationManager.UiTranslationState; import android.widget.TextView; import android.widget.TextViewTranslationCallback; import com.android.internal.util.function.pooled.PooledLambda; Loading Loading @@ -146,7 +148,13 @@ public class UiTranslationController { break; case STATE_UI_TRANSLATION_FINISHED: destroyTranslators(); runForEachView((view, callback) -> callback.onClearTranslation(view)); runForEachView((view, callback) -> { callback.onClearTranslation(view); if (view.hasTranslationTransientState()) { view.setHasTransientState(false); view.setHasTranslationTransientState(false); } }); synchronized (mLock) { mViews.clear(); } Loading Loading @@ -381,17 +389,23 @@ public class UiTranslationController { continue; } mActivity.runOnUiThread(() -> { final ViewTranslationCallback callback = view.getViewTranslationCallback(); ViewTranslationCallback callback = view.getViewTranslationCallback(); if (callback == null) { if (view instanceof TextView) { // developer doesn't provide their override, we set the default TextView // implememtation. callback = new TextViewTranslationCallback(); view.setViewTranslationCallback(callback); if (mViewsToPadContent.contains(autofillId)) { callback.enableContentPadding(); } } else { if (DEBUG) { Log.d(TAG, view + " doesn't support showing translation because of " + "null ViewTranslationCallback."); } return; } if (mViewsToPadContent.contains(autofillId)) { callback.enableContentPadding(); } view.onViewTranslationResponse(response); callback.onShowTranslation(view); Loading
core/java/android/widget/TextView.java +24 −42 Original line number Diff line number Diff line Loading @@ -740,7 +740,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private MovementMethod mMovement; private TransformationMethod mTransformation; private TextViewTranslationCallback mDefaultTranslationCallback; @UnsupportedAppUsage private boolean mAllowTransformationLengthChange; @UnsupportedAppUsage Loading Loading @@ -2376,11 +2375,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @ViewDebug.CapturedViewProperty @InspectableProperty public CharSequence getText() { if (mUseTextPaddingForUiTranslation && mDefaultTranslationCallback != null && mDefaultTranslationCallback.isTextPaddingEnabled() && mDefaultTranslationCallback.isShowingTranslation()) { return mDefaultTranslationCallback.getPaddedText(mText, mTransformed); if (mUseTextPaddingForUiTranslation) { ViewTranslationCallback callback = getViewTranslationCallback(); if (callback != null && callback instanceof TextViewTranslationCallback) { TextViewTranslationCallback defaultCallback = (TextViewTranslationCallback) callback; if (defaultCallback.isTextPaddingEnabled() && defaultCallback.isShowingTranslation()) { return defaultCallback.getPaddedText(mText, mTransformed); } } } return mText; } Loading Loading @@ -13932,30 +13936,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener requestsCollector.accept(requestBuilder.build()); } /** * Returns a {@link ViewTranslationCallback} that is used to display the translated information. * The default implementation will use a {@link TransformationMethod} that allow to replace the * current {@link TransformationMethod} to transform the original text to the translated text * display. * * @return a {@link ViewTranslationCallback} that is used to control how to display the * translated information or {@code null} if this View doesn't support translation. * * @hide */ @Nullable @Override public ViewTranslationCallback getViewTranslationCallback() { return getDefaultViewTranslationCallback(); } private ViewTranslationCallback getDefaultViewTranslationCallback() { if (mDefaultTranslationCallback == null) { mDefaultTranslationCallback = new TextViewTranslationCallback(); } return mDefaultTranslationCallback; } /** * * Called when the content from {@link #onCreateViewTranslationRequest} had been translated by Loading @@ -13969,17 +13949,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) { // set ViewTranslationResponse super.onViewTranslationResponse(response); // TODO(b/183467275): Use the overridden ViewTranslationCallback instead of our default // implementation if the view has overridden getViewTranslationCallback. TextViewTranslationCallback callback = (TextViewTranslationCallback) getDefaultViewTranslationCallback(); // TODO(b/178353965): move to ViewTranslationCallback.onShow() ViewTranslationCallback callback = getViewTranslationCallback(); if (callback instanceof TextViewTranslationCallback) { TextViewTranslationCallback textViewDefaultCallback = (TextViewTranslationCallback) callback; TranslationTransformationMethod oldTranslationMethod = callback.getTranslationTransformation(); textViewDefaultCallback.getTranslationTransformation(); TransformationMethod originalTranslationMethod = oldTranslationMethod != null ? oldTranslationMethod.getOriginalTransformationMethod() : mTransformation; TranslationTransformationMethod newTranslationMethod = new TranslationTransformationMethod(response, originalTranslationMethod); // TODO(b/178353965): well-handle setTransformationMethod. callback.setTranslationTransformation(newTranslationMethod); textViewDefaultCallback.setTranslationTransformation(newTranslationMethod); } } }