diff --git a/core/api/current.txt b/core/api/current.txt index a40e0f65e0e1f..c808524d51c4a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -48466,6 +48466,7 @@ package android.view { method public boolean checkInputConnectionProxy(android.view.View); method public void clearAnimation(); method public void clearFocus(); + method public void clearViewTranslationCallback(); method public static int combineMeasuredStates(int, int); method protected int computeHorizontalScrollExtent(); method protected int computeHorizontalScrollOffset(); @@ -48502,7 +48503,7 @@ package android.view { method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); method public void dispatchProvideAutofillStructure(@NonNull android.view.ViewStructure, int); method public void dispatchProvideStructure(android.view.ViewStructure); - method public void dispatchRequestTranslation(@NonNull java.util.Map, @NonNull int[], @Nullable android.view.translation.TranslationCapability, @NonNull java.util.List); + method public void dispatchRequestTranslation(@NonNull java.util.Map, @NonNull int[], @NonNull android.view.translation.TranslationCapability, @NonNull java.util.List); method protected void dispatchRestoreInstanceState(android.util.SparseArray); method protected void dispatchSaveInstanceState(android.util.SparseArray); method public void dispatchScrollCaptureSearch(@NonNull android.graphics.Rect, @NonNull android.graphics.Point, @NonNull java.util.function.Consumer); @@ -48699,7 +48700,7 @@ package android.view { method @Nullable public android.graphics.drawable.Drawable getVerticalScrollbarTrackDrawable(); method public int getVerticalScrollbarWidth(); method @Nullable public android.view.ViewRoot getViewRoot(); - method @Nullable public android.view.translation.ViewTranslationCallback getViewTranslationCallback(); + method @Nullable public android.view.translation.ViewTranslationResponse getViewTranslationResponse(); method public android.view.ViewTreeObserver getViewTreeObserver(); method public int getVisibility(); method public final int getWidth(); @@ -48799,8 +48800,8 @@ package android.view { method protected void onCreateContextMenu(android.view.ContextMenu); method protected int[] onCreateDrawableState(int); method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo); - method @Nullable public android.view.translation.ViewTranslationRequest onCreateTranslationRequest(@NonNull int[]); - method public void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer); + method public void onCreateViewTranslationRequest(@NonNull int[], @NonNull java.util.function.Consumer); + method public void onCreateVirtualViewTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer); method @CallSuper protected void onDetachedFromWindow(); method protected void onDisplayHint(int); method public boolean onDragEvent(android.view.DragEvent); @@ -48845,8 +48846,8 @@ package android.view { method public void onStartTemporaryDetach(); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); - method public void onTranslationResponse(@NonNull android.view.translation.ViewTranslationResponse); - method public void onTranslationResponse(@NonNull android.util.LongSparseArray); + method public void onViewTranslationResponse(@NonNull android.view.translation.ViewTranslationResponse); + method public void onVirtualViewTranslationResponses(@NonNull android.util.LongSparseArray); method @CallSuper public void onVisibilityAggregated(boolean); method protected void onVisibilityChanged(@NonNull android.view.View, int); method public void onWindowFocusChanged(boolean); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3f463f9f35092..d2836e0657221 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -14825,7 +14825,7 @@ package android.webkit { method public default boolean onCheckIsTextEditor(); method public void onConfigurationChanged(android.content.res.Configuration); method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo); - method public default void onCreateTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer); + method public default void onCreateVirtualViewTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer); method public void onDetachedFromWindow(); method public boolean onDragEvent(android.view.DragEvent); method public void onDraw(android.graphics.Canvas); @@ -14850,7 +14850,7 @@ package android.webkit { method public void onStartTemporaryDetach(); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); - method public default void onTranslationResponse(@NonNull android.util.LongSparseArray); + method public default void onVirtualViewTranslationResponses(@NonNull android.util.LongSparseArray); method public void onVisibilityChanged(android.view.View, int); method public void onWindowFocusChanged(boolean); method public void onWindowVisibilityChanged(int); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bed5eea2d199b..b82afca2f6944 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5260,6 +5260,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @Nullable private ViewTranslationCallback mViewTranslationCallback; + @Nullable + + private ViewTranslationResponse mViewTranslationResponse; + /** * Simple constructor to use when creating a view from code. * @@ -30770,57 +30774,50 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Returns a {@link ViewTranslationRequest} which represents the content to be translated. - * - *

The default implementation does nothing and returns null.

- * - * @param supportedFormats the supported translation formats. For now, the only possible value - * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}. - * @return the {@link ViewTranslationRequest} which contains the information to be translated or - * {@code null} if this View doesn't support translation. - * The {@link AutofillId} must be set on the returned value. - */ - @Nullable - public ViewTranslationRequest onCreateTranslationRequest( - @NonNull @DataFormat int[] supportedFormats) { - return null; - } - - /** - * Returns a {@link ViewTranslationRequest} list which represents the content to be translated - * in the virtual view. This is called if this view returned a virtual view structure - * from {@link #onProvideContentCaptureStructure} and the system determined that those virtual - * views were relevant for translation. + * Collects a {@link ViewTranslationRequest} which represents the content to be translated in + * the view. * *

The default implementation does nothing.

* - * @param virtualChildIds the virtual child ids which represents the child views in the virtual + * @param supportedFormats the supported translation formats. For now, the only possible value + * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}. + * @param requestsCollector a {@link ViewTranslationRequest} collector that can be used to + * collect the information to be translated in the view. The {@code requestsCollector} only + * accepts one request; an IllegalStateException is thrown if more than one + * {@link ViewTranslationRequest} is submitted to it. The {@link AutofillId} must be set on the + * {@link ViewTranslationRequest}. + */ + public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats, + @NonNull Consumer requestsCollector) { + } + + /** + * Collects {@link ViewTranslationRequest}s which represents the content to be translated + * for the virtual views in the host view. This is called if this view returned a virtual + * view structure from {@link #onProvideContentCaptureStructure} and the system determined that + * those virtual views were relevant for translation. + * + *

The default implementation does nothing.

+ * + * @param virtualIds the virtual view ids which represents the virtual views in the host * view. * @param supportedFormats the supported translation formats. For now, the only possible value * is the {@link android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}. * @param requestsCollector a {@link ViewTranslationRequest} collector that can be called - * multiple times to collect the information to be translated in the virtual view. One + * multiple times to collect the information to be translated in the host view. One * {@link ViewTranslationRequest} per virtual child. The {@link ViewTranslationRequest} must * contains the {@link AutofillId} corresponding to the virtualChildIds. Do not keep this * Consumer after the method returns. */ @SuppressLint("NullableCollection") - public void onCreateTranslationRequests(@NonNull long[] virtualChildIds, + public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer requestsCollector) { // no-op } /** - * Returns a {@link ViewTranslationCallback} that is used to display/hide the translated - * information. If the View supports displaying translated content, it should implement - * {@link ViewTranslationCallback}. - * - *

The default implementation returns null if developers don't set the customized - * {@link ViewTranslationCallback} by {@link #setViewTranslationCallback}

- * - * @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 public ViewTranslationCallback getViewTranslationCallback() { @@ -30840,30 +30837,52 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Called when the content from {@link View#onCreateTranslationRequest} had been translated by - * the TranslationService. + * Clear the {@link ViewTranslationCallback} from this view. + */ + public void clearViewTranslationCallback() { + mViewTranslationCallback = null; + } + + /** + * Returns the {@link ViewTranslationResponse} associated with this view. The response will be + * set when the translation is done then {@link #onViewTranslationResponse} is called. The + * {@link ViewTranslationCallback} can use to get {@link ViewTranslationResponse} to display the + * translated information. * - *

The default implementation does nothing.

+ * @return a {@link ViewTranslationResponse} that contains the translated information associated + * with this view or {@code null} if this View doesn't have the translation. + */ + @Nullable + public ViewTranslationResponse getViewTranslationResponse() { + return mViewTranslationResponse; + } + + /** + * Called when the content from {@link View#onCreateViewTranslationRequest} had been translated + * by the TranslationService. + * + *

The default implementation will set the ViewTranslationResponse that can be get from + * {@link View#getViewTranslationResponse}.

* * @param response a {@link ViewTranslationResponse} that contains the translated information * which can be shown in the view. */ - public void onTranslationResponse(@NonNull ViewTranslationResponse response) { - // no-op + public void onViewTranslationResponse(@NonNull ViewTranslationResponse response) { + mViewTranslationResponse = response; } /** - * Called when the content from {@link View#onCreateTranslationRequest} had been translated by - * the TranslationService. + * Called when the content from {@link View#onCreateVirtualViewTranslationRequests} had been + * translated by the TranslationService. * *

The default implementation does nothing.

* * @param response a {@link ViewTranslationResponse} SparseArray for the request that send by - * {@link View#onCreateTranslationRequests} that contains the translated information which can - * be shown in the view. The key of SparseArray is - * the virtual child ids. + * {@link View#onCreateVirtualViewTranslationRequests} that contains the translated information + * which can be shown in the view. The key of SparseArray is the virtual child ids. */ - public void onTranslationResponse(@NonNull LongSparseArray response) { + public void onVirtualViewTranslationResponses( + @NonNull LongSparseArray response) { // no-op } @@ -30871,16 +30890,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Dispatch to collect the {@link ViewTranslationRequest}s for translation purpose by traversing * the hierarchy when the app requests ui translation. Typically, this method should only be * overridden by subclasses that provide a view hierarchy (such as {@link ViewGroup}). Other - * classes should override {@link View#onCreateTranslationRequest}. When requested to start the - * ui translation, the system will call this method to traverse the view hierarchy to call - * {@link View#onCreateTranslationRequest} to build {@link ViewTranslationRequest}s and create a + * classes should override {@link View#onCreateViewTranslationRequest} for normal view or + * override {@link View#onVirtualViewTranslationResponses} for view contains virtual children. + * When requested to start the ui translation, the system will call this method to traverse the + * view hierarchy to collect {@link ViewTranslationRequest}s and create a * {@link android.view.translation.Translator} to translate the requests. All the * {@link ViewTranslationRequest}s must be added when the traversal is done. * - *

The default implementation calls {@link View#onCreateTranslationRequest} 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.

+ *

The default implementation calls {@link View#onCreateViewTranslationRequest} for normal + * 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.

* * @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 @@ -30893,27 +30914,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public void dispatchRequestTranslation(@NonNull Map viewIds, @NonNull @DataFormat int[] supportedFormats, - @Nullable TranslationCapability capability, + @NonNull TranslationCapability capability, @NonNull List requests) { AutofillId autofillId = getAutofillId(); if (viewIds.containsKey(autofillId)) { if (viewIds.get(autofillId) == null) { - ViewTranslationRequest request = onCreateTranslationRequest(supportedFormats); - if (request != null && request.getKeys().size() > 0) { - requests.add(request); - if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { - Log.v(CONTENT_CAPTURE_LOG_TAG, "Calling setHasTransientState(true) for " - + autofillId); - } - // TODO: Add a default ViewTranslationCallback for View that resets this in - // onClearTranslation(). Also update the javadoc for this method to mention - // that. - setHasTransientState(true); - } + // TODO: avoiding the allocation per view + onCreateViewTranslationRequest(supportedFormats, + new ViewTranslationRequestConsumer(requests)); } else { - onCreateTranslationRequests(viewIds.get(autofillId), supportedFormats, request -> { - requests.add(request); - }); + onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats, + request -> { + requests.add(request); + }); + } + } + } + + private class ViewTranslationRequestConsumer implements Consumer { + private final List mRequests; + private boolean mCalled; + + ViewTranslationRequestConsumer(List requests) { + mRequests = requests; + } + + @Override + public void accept(ViewTranslationRequest request) { + if (mCalled) { + throw new IllegalStateException("The translation Consumer is not reusable."); + } + mCalled = true; + if (request != null && request.getKeys().size() > 0) { + mRequests.add(request); + if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { + 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); } } } diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java index b6d3d0953d71c..0425572a6f768 100644 --- a/core/java/android/view/translation/UiTranslationController.java +++ b/core/java/android/view/translation/UiTranslationController.java @@ -315,7 +315,7 @@ public class UiTranslationController { } return; } - view.onTranslationResponse(virtualChildResponse); + view.onVirtualViewTranslationResponses(virtualChildResponse); if (view.getViewTranslationCallback() != null) { view.getViewTranslationCallback().onShowTranslation(view); } @@ -373,8 +373,7 @@ public class UiTranslationController { // TODO: Do this for specific views on request only. callback.enableContentPadding(); - - view.onTranslationResponse(response); + view.onViewTranslationResponse(response); callback.onShowTranslation(view); }); } diff --git a/core/java/android/view/translation/ViewTranslationCallback.java b/core/java/android/view/translation/ViewTranslationCallback.java index 78b4855bc7cf2..1f0723b0bd054 100644 --- a/core/java/android/view/translation/ViewTranslationCallback.java +++ b/core/java/android/view/translation/ViewTranslationCallback.java @@ -21,23 +21,27 @@ import android.annotation.UiThread; import android.view.View; /** - * Callback for handling the translated information show or hide in the {@link View}. See {@link - * View#onTranslationResponse} for how to get the translated information. + * Callback for handling the translated information show or hide in the {@link View}. */ @UiThread public interface ViewTranslationCallback { /** * Called when the translated text is ready to show or if the user has requested to reshow the - * translated content after hiding it. This may be called before the translation results are - * returned through the {@link View#onTranslationResponse}. + * translated content after hiding it. + *

+ * The translated content can be obtained from {@link View#getViewTranslationResponse}. This + * method will not be called before {@link View#onViewTranslationResponse} or + * {@link View#onVirtualViewTranslationResponses}. + * + * See {@link View#onViewTranslationResponse} for how to get the translated information. * * @return {@code true} if the View handles showing the translation. */ boolean onShowTranslation(@NonNull View view); /** * Called when the user wants to show the original text instead of the translated text. This - * may be called before the translation results are returned through the - * {@link View#onTranslationResponse}. + * method will not be called before {@link View#onViewTranslationResponse} or + * {@link View#onViewTranslationResponse}. * * @return {@code true} if the View handles hiding the translation. */ diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 6d4fa658b3e9c..a1d482264f4c0 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2861,16 +2861,17 @@ public class WebView extends AbsoluteLayout @Override @Nullable - public void onCreateTranslationRequests(@NonNull long[] virtualChildIds, + public void onCreateVirtualViewTranslationRequests(@NonNull long[] virtualIds, @NonNull @DataFormat int[] supportedFormats, @NonNull Consumer requestsCollector) { - mProvider.getViewDelegate().onCreateTranslationRequests(virtualChildIds, supportedFormats, - requestsCollector); + mProvider.getViewDelegate().onCreateVirtualViewTranslationRequests(virtualIds, + supportedFormats, requestsCollector); } @Override - public void onTranslationResponse(@NonNull LongSparseArray response) { - mProvider.getViewDelegate().onTranslationResponse(response); + public void onVirtualViewTranslationResponses( + @NonNull LongSparseArray response) { + mProvider.getViewDelegate().onVirtualViewTranslationResponses(response); } /** @hide */ diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index 770a1568241cc..8d996ee9f50a9 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -365,14 +365,14 @@ public interface WebViewProvider { } @SuppressLint("NullableCollection") - default void onCreateTranslationRequests( - @NonNull @SuppressWarnings("unused") long[] virtualChildIds, + default void onCreateVirtualViewTranslationRequests( + @NonNull @SuppressWarnings("unused") long[] virtualIds, @NonNull @SuppressWarnings("unused") @DataFormat int[] supportedFormats, @NonNull @SuppressWarnings("unused") Consumer requestsCollector) { } - default void onTranslationResponse( + default void onVirtualViewTranslationResponses( @NonNull @SuppressWarnings("unused") LongSparseArray response) { } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 1953a7687cb9e..07a9a5fad6e2c 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -13870,7 +13870,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Returns a {@link ViewTranslationRequest} which represents the content to be translated. + * Collects a {@link ViewTranslationRequest} which represents the content to be translated in + * the view. * *

NOTE: When overriding the method, it should not translate the password. If the subclass * uses {@link TransformationMethod} to display the translated result, it's also not recommend @@ -13880,15 +13881,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * android.view.translation.TranslationSpec#DATA_FORMAT_TEXT}. * @return the {@link ViewTranslationRequest} which contains the information to be translated. */ - @Nullable @Override - public ViewTranslationRequest onCreateTranslationRequest(@NonNull int[] supportedFormats) { + public void onCreateViewTranslationRequest(@NonNull int[] supportedFormats, + @NonNull Consumer requestsCollector) { if (supportedFormats == null || supportedFormats.length == 0) { // TODO(b/182433547): remove before S release if (UiTranslationController.DEBUG) { Log.w(LOG_TAG, "Do not provide the support translation formats."); } - return null; + return; } ViewTranslationRequest.Builder requestBuilder = new ViewTranslationRequest.Builder(getAutofillId()); @@ -13899,7 +13900,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (UiTranslationController.DEBUG) { Log.w(LOG_TAG, "Cannot create translation request for the empty text."); } - return null; + return; } boolean isPassword = isAnyPasswordInputType() || hasPasswordTransformationMethod(); // TODO(b/177214256): support selectable text translation. @@ -13914,14 +13915,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Log.w(LOG_TAG, "Cannot create translation request. editable = " + isTextEditable() + ", isPassword = " + isPassword + ", selectable = " + isTextSelectable()); + return; } - return null; } // TODO(b/176488462): apply the view's important for translation requestBuilder.setValue(ViewTranslationRequest.ID_TEXT, TranslationRequestValue.forText(mText)); } - return requestBuilder.build(); + requestsCollector.accept(requestBuilder.build()); } /** @@ -13932,6 +13933,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @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 @@ -13948,15 +13951,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * - * Called when the content from {@link #onCreateTranslationRequest} had been translated by the - * TranslationService. The default implementation will replace the current + * Called when the content from {@link #onCreateViewTranslationRequest} had been translated by + * the TranslationService. The default implementation will replace the current * {@link TransformationMethod} to transform the original text to the translated text display. * * @param response a {@link ViewTranslationResponse} that contains the translated information * which can be shown in the view. */ @Override - public void onTranslationResponse(@NonNull ViewTranslationResponse response) { + 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 = diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java index 73f19a7a48c0f..0376061155216 100644 --- a/core/java/android/widget/TextViewTranslationCallback.java +++ b/core/java/android/widget/TextViewTranslationCallback.java @@ -79,6 +79,11 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { @Override public boolean onShowTranslation(@NonNull View view) { mIsShowingTranslation = true; + if (view.getViewTranslationResponse() == null) { + Log.wtf(TAG, "onShowTranslation() shouldn't be called before " + + "onViewTranslationResponse()."); + return false; + } if (mTranslationTransformation != null) { ((TextView) view).setTransformationMethod(mTranslationTransformation); } else { @@ -86,6 +91,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { // TODO(b/182433547): remove before S release Log.w(TAG, "onShowTranslation(): no translated text."); } + return false; } return true; } @@ -96,6 +102,11 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { @Override public boolean onHideTranslation(@NonNull View view) { mIsShowingTranslation = false; + if (view.getViewTranslationResponse() == null) { + Log.wtf(TAG, "onHideTranslation() shouldn't be called before " + + "onViewTranslationResponse()."); + return false; + } // Restore to original text content. if (mTranslationTransformation != null) { ((TextView) view).setTransformationMethod( @@ -105,6 +116,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { // TODO(b/182433547): remove before S release Log.w(TAG, "onHideTranslation(): no translated text."); } + return false; } return true; } @@ -124,6 +136,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { // TODO(b/182433547): remove before S release Log.w(TAG, "onClearTranslation(): no translated text."); } + return false; } return true; }