Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be20ca46 authored by Joanne Chung's avatar Joanne Chung Committed by Android (Google) Code Review
Browse files

Merge "API feedback: Translation View API refinement." into sc-dev

parents 1c3372f3 f6a52811
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -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<android.view.autofill.AutofillId,long[]>, @NonNull int[], @Nullable android.view.translation.TranslationCapability, @NonNull java.util.List<android.view.translation.ViewTranslationRequest>);
    method public void dispatchRequestTranslation(@NonNull java.util.Map<android.view.autofill.AutofillId,long[]>, @NonNull int[], @NonNull android.view.translation.TranslationCapability, @NonNull java.util.List<android.view.translation.ViewTranslationRequest>);
    method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
    method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
    method public void dispatchScrollCaptureSearch(@NonNull android.graphics.Rect, @NonNull android.graphics.Point, @NonNull java.util.function.Consumer<android.view.ScrollCaptureTarget>);
@@ -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<android.view.translation.ViewTranslationRequest>);
    method public void onCreateViewTranslationRequest(@NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
    method public void onCreateVirtualViewTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
    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<android.view.translation.ViewTranslationResponse>);
    method public void onViewTranslationResponse(@NonNull android.view.translation.ViewTranslationResponse);
    method public void onVirtualViewTranslationResponses(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
    method @CallSuper public void onVisibilityAggregated(boolean);
    method protected void onVisibilityChanged(@NonNull android.view.View, int);
    method public void onWindowFocusChanged(boolean);
+2 −2
Original line number Diff line number Diff line
@@ -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<android.view.translation.ViewTranslationRequest>);
    method public default void onCreateVirtualViewTranslationRequests(@NonNull long[], @NonNull int[], @NonNull java.util.function.Consumer<android.view.translation.ViewTranslationRequest>);
    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<android.view.translation.ViewTranslationResponse>);
    method public default void onVirtualViewTranslationResponses(@NonNull android.util.LongSparseArray<android.view.translation.ViewTranslationResponse>);
    method public void onVisibilityChanged(android.view.View, int);
    method public void onWindowFocusChanged(boolean);
    method public void onWindowVisibilityChanged(int);
+100 −59
Original line number Diff line number Diff line
@@ -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.
     * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
     * the view.
     *
     * <p>The default implementation does nothing and returns null.</p>
     * <p>The default implementation does nothing.</p>
     *
     * @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.
     * @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}.
     */
    @Nullable
    public ViewTranslationRequest onCreateTranslationRequest(
            @NonNull @DataFormat int[] supportedFormats) {
        return null;
    public void onCreateViewTranslationRequest(@NonNull @DataFormat int[] supportedFormats,
            @NonNull Consumer<ViewTranslationRequest> requestsCollector) {
    }
    /**
     * 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 {@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.
     *
     * <p>The default implementation does nothing.</p>
     *
     * @param virtualChildIds the virtual child ids which represents the child views in the virtual
     * @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<ViewTranslationRequest> 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}.
     *
     * <p>The default implementation returns null if developers don't set the customized
     * {@link ViewTranslationCallback} by {@link #setViewTranslationCallback} </p>
     *
     * @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.
     *
     * <p> The default implementation does nothing.</p>
     * @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.
     *
     * <p> The default implementation will set the ViewTranslationResponse that can be get from
     * {@link View#getViewTranslationResponse}. </p>
     *
     * @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.
     *
     * <p> The default implementation does nothing.</p>
     *
     * @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<ViewTranslationResponse> response) {
    public void onVirtualViewTranslationResponses(
            @NonNull LongSparseArray<ViewTranslationResponse> 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.
     *
     * <p> 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.</p>
     * <p> 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.</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
@@ -30893,28 +30914,48 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public void dispatchRequestTranslation(@NonNull Map<AutofillId, long[]> viewIds,
            @NonNull @DataFormat int[] supportedFormats,
            @Nullable TranslationCapability capability,
            @NonNull TranslationCapability capability,
            @NonNull List<ViewTranslationRequest> requests) {
        AutofillId autofillId = getAutofillId();
        if (viewIds.containsKey(autofillId)) {
            if (viewIds.get(autofillId) == null) {
                ViewTranslationRequest request = onCreateTranslationRequest(supportedFormats);
                if (request != null && request.getKeys().size() > 0) {
                // TODO: avoiding the allocation per view
                onCreateViewTranslationRequest(supportedFormats,
                        new ViewTranslationRequestConsumer(requests));
            } else {
                onCreateVirtualViewTranslationRequests(viewIds.get(autofillId), supportedFormats,
                        request -> {
                            requests.add(request);
                        });
            }
        }
    }
    private class ViewTranslationRequestConsumer implements Consumer<ViewTranslationRequest> {
        private final List<ViewTranslationRequest> mRequests;
        private boolean mCalled;
        ViewTranslationRequestConsumer(List<ViewTranslationRequest> 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 "
                                + autofillId);
                            + 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);
            }
            } else {
                onCreateTranslationRequests(viewIds.get(autofillId), supportedFormats, request -> {
                    requests.add(request);
                });
            }
        }
    }
+2 −3
Original line number Diff line number Diff line
@@ -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);
                });
            }
+10 −6
Original line number Diff line number Diff line
@@ -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.
     * <p>
     * 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.
     */
Loading