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

Commit 68b1703e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Support WRAP_CONTENT in InlineSuggestion#inflate" into rvc-dev am:...

Merge "Support WRAP_CONTENT in InlineSuggestion#inflate" into rvc-dev am: 5e9aed81 am: 820cf907 am: 46c7679a

Change-Id: I1d9448942e391ba2565ca72f40acf90e6b10d03e
parents 974298a4 46c7679a
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ import android.view.SurfaceControlViewHost;
oneway interface IInlineSuggestionUiCallback {
oneway interface IInlineSuggestionUiCallback {
    void onClick();
    void onClick();
    void onLongClick();
    void onLongClick();
    void onContent(in SurfaceControlViewHost.SurfacePackage surface);
    void onContent(in SurfaceControlViewHost.SurfacePackage surface, int width, int height);
    void onError();
    void onError();
    void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId);
    void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId);
    void onStartIntentSender(in IntentSender intentSender);
    void onStartIntentSender(in IntentSender intentSender);
+66 −21
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.TestApi;
import android.app.Service;
import android.app.Service;
import android.app.slice.Slice;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender;
import android.graphics.PixelFormat;
import android.graphics.PixelFormat;
@@ -34,14 +33,15 @@ import android.os.Looper;
import android.os.RemoteCallback;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;
import android.util.Size;
import android.view.Display;
import android.view.Display;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager;


/**
/**
 * A service that renders an inline presentation given the {@link InlinePresentation} containing
 * A service that renders an inline presentation view given the {@link InlinePresentation}.
 * a {@link Slice} built using the {@link androidx.autofill.AutofillSliceBuilder}.
 *
 *
 * {@hide}
 * {@hide}
 */
 */
@@ -55,8 +55,8 @@ public abstract class InlineSuggestionRenderService extends Service {
     * The {@link Intent} that must be declared as handled by the service.
     * The {@link Intent} that must be declared as handled by the service.
     *
     *
     * <p>To be supported, the service must also require the
     * <p>To be supported, the service must also require the
     * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so
     * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so that
     * that other applications can not abuse it.
     * other applications can not abuse it.
     */
     */
    public static final String SERVICE_INTERFACE =
    public static final String SERVICE_INTERFACE =
            "android.service.autofill.InlineSuggestionRenderService";
            "android.service.autofill.InlineSuggestionRenderService";
@@ -65,6 +65,45 @@ public abstract class InlineSuggestionRenderService extends Service {


    private IInlineSuggestionUiCallback mCallback;
    private IInlineSuggestionUiCallback mCallback;


    /**
     * If the specified {@code width}/{@code height} is an exact value, then it will be returned as
     * is, otherwise the method tries to measure a size that is just large enough to fit the view
     * content, within constraints posed by {@code minSize} and {@code maxSize}.
     *
     * @param view    the view for which we measure the size
     * @param width   the expected width of the view, either an exact value or {@link
     *                ViewGroup.LayoutParams#WRAP_CONTENT}
     * @param height  the expected width of the view, either an exact value or {@link
     *                ViewGroup.LayoutParams#WRAP_CONTENT}
     * @param minSize the lower bound of the size to be returned
     * @param maxSize the upper bound of the size to be returned
     * @return the measured size of the view based on the given size constraints.
     */
    private Size measuredSize(@NonNull View view, int width, int height, @NonNull Size minSize,
            @NonNull Size maxSize) {
        if (width != ViewGroup.LayoutParams.WRAP_CONTENT
                && height != ViewGroup.LayoutParams.WRAP_CONTENT) {
            return new Size(width, height);
        }
        int widthMeasureSpec;
        if (width == ViewGroup.LayoutParams.WRAP_CONTENT) {
            widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getWidth(),
                    View.MeasureSpec.AT_MOST);
        } else {
            widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
        }
        int heightMeasureSpec;
        if (height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getHeight(),
                    View.MeasureSpec.AT_MOST);
        } else {
            heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
        }
        view.measure(widthMeasureSpec, heightMeasureSpec);
        return new Size(Math.max(view.getMeasuredWidth(), minSize.getWidth()),
                Math.max(view.getMeasuredHeight(), minSize.getHeight()));
    }

    private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
    private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
            InlinePresentation presentation, int width, int height, IBinder hostInputToken,
            InlinePresentation presentation, int width, int height, IBinder hostInputToken,
            int displayId) {
            int displayId) {
@@ -82,6 +121,7 @@ public abstract class InlineSuggestionRenderService extends Service {
        try {
        try {
            final View suggestionView = onRenderSuggestion(presentation, width, height);
            final View suggestionView = onRenderSuggestion(presentation, width, height);
            if (suggestionView == null) {
            if (suggestionView == null) {
                Log.w(TAG, "ExtServices failed to render the inline suggestion view.");
                try {
                try {
                    callback.onError();
                    callback.onError();
                } catch (RemoteException e) {
                } catch (RemoteException e) {
@@ -90,12 +130,15 @@ public abstract class InlineSuggestionRenderService extends Service {
                return;
                return;
            }
            }
            mCallback = callback;
            mCallback = callback;
            final Size measuredSize = measuredSize(suggestionView, width, height,
                    presentation.getInlinePresentationSpec().getMinSize(),
                    presentation.getInlinePresentationSpec().getMaxSize());
            Log.v(TAG, "width=" + width + ", height=" + height + ", measuredSize=" + measuredSize);


            final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback);
            final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback);
            suggestionRoot.addView(suggestionView);
            suggestionRoot.addView(suggestionView);
            WindowManager.LayoutParams lp =
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(measuredSize.getWidth(),
                    new WindowManager.LayoutParams(width, height,
                    measuredSize.getHeight(), WindowManager.LayoutParams.TYPE_APPLICATION, 0,
                            WindowManager.LayoutParams.TYPE_APPLICATION, 0,
                    PixelFormat.TRANSPARENT);
                    PixelFormat.TRANSPARENT);


            final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(),
            final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(),
@@ -124,7 +167,8 @@ public abstract class InlineSuggestionRenderService extends Service {
                return true;
                return true;
            });
            });


            sendResult(callback, host.getSurfacePackage());
            sendResult(callback, host.getSurfacePackage(), measuredSize.getWidth(),
                    measuredSize.getHeight());
        } finally {
        } finally {
            updateDisplay(Display.DEFAULT_DISPLAY);
            updateDisplay(Display.DEFAULT_DISPLAY);
        }
        }
@@ -136,9 +180,9 @@ public abstract class InlineSuggestionRenderService extends Service {
    }
    }


    private void sendResult(@NonNull IInlineSuggestionUiCallback callback,
    private void sendResult(@NonNull IInlineSuggestionUiCallback callback,
            @Nullable SurfaceControlViewHost.SurfacePackage surface) {
            @Nullable SurfaceControlViewHost.SurfacePackage surface, int width, int height) {
        try {
        try {
            callback.onContent(surface);
            callback.onContent(surface, width, height);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Log.w(TAG, "RemoteException calling onContent(" + surface + ")");
            Log.w(TAG, "RemoteException calling onContent(" + surface + ")");
        }
        }
@@ -154,8 +198,8 @@ public abstract class InlineSuggestionRenderService extends Service {
                public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
                public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
                        @NonNull InlinePresentation presentation, int width, int height,
                        @NonNull InlinePresentation presentation, int width, int height,
                        @Nullable IBinder hostInputToken, int displayId) {
                        @Nullable IBinder hostInputToken, int displayId) {
                    mHandler.sendMessage(obtainMessage(
                    mHandler.sendMessage(
                            InlineSuggestionRenderService::handleRenderSuggestion,
                            obtainMessage(InlineSuggestionRenderService::handleRenderSuggestion,
                                    InlineSuggestionRenderService.this, callback, presentation,
                                    InlineSuggestionRenderService.this, callback, presentation,
                                    width, height, hostInputToken, displayId));
                                    width, height, hostInputToken, displayId));
                }
                }
@@ -176,7 +220,8 @@ public abstract class InlineSuggestionRenderService extends Service {
    /**
    /**
     * Starts the {@link IntentSender} from the client app.
     * Starts the {@link IntentSender} from the client app.
     *
     *
     * @param intentSender the {@link IntentSender} to start the attribution UI from the client app.
     * @param intentSender the {@link IntentSender} to start the attribution UI from the client
     *                     app.
     */
     */
    public final void startIntentSender(@NonNull IntentSender intentSender) {
    public final void startIntentSender(@NonNull IntentSender intentSender) {
        if (mCallback == null) return;
        if (mCallback == null) return;
@@ -200,8 +245,8 @@ public abstract class InlineSuggestionRenderService extends Service {
     * Renders the slice into a view.
     * Renders the slice into a view.
     */
     */
    @Nullable
    @Nullable
    public View onRenderSuggestion(@NonNull InlinePresentation presentation,
    public View onRenderSuggestion(@NonNull InlinePresentation presentation, int width,
            int width, int height) {
            int height) {
        Log.e(TAG, "service implementation (" + getClass() + " does not implement "
        Log.e(TAG, "service implementation (" + getClass() + " does not implement "
                + "onRenderSuggestion()");
                + "onRenderSuggestion()");
        return null;
        return null;
+38 −15
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.os.RemoteException;
import android.util.Size;
import android.util.Size;
import android.util.Slog;
import android.util.Slog;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceControlViewHost;
import android.view.ViewGroup;
import android.widget.inline.InlineContentView;
import android.widget.inline.InlineContentView;


import com.android.internal.util.DataClass;
import com.android.internal.util.DataClass;
@@ -94,19 +95,26 @@ public final class InlineSuggestion implements Parcelable {


    /**
    /**
     * Inflates a view with the content of this suggestion at a specific size.
     * Inflates a view with the content of this suggestion at a specific size.
     * The size must be between the
     *
     * <p> The size must be either 1) between the
     * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the
     * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the
     * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the
     * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the
     * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}.
     * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()},
     * or 2) {@link ViewGroup.LayoutParams#WRAP_CONTENT}. If the size is set to
     * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, then the size of the inflated view will be just
     * large enough to fit the content, while still conforming to the min / max size specified by
     * the {@link android.widget.inline.InlinePresentationSpec}.
     *
     *
     * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an
     * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an
     * {@link android.view.View.OnLongClickListener} to the view in the
     * {@link android.view.View.OnLongClickListener} to the view in the
     * {@code callback} to receive click and
     * {@code callback} to receive click and long click events on the view.
     * long click events on the view.
     *
     *
     * @param context  Context in which to inflate the view.
     * @param context  Context in which to inflate the view.
     * @param size     The size at which to inflate the suggestion.
     * @param size     The size at which to inflate the suggestion. For each dimension, it maybe
     * @param callback Callback for receiving the inflated view.
     *                 an exact value or {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
     * @param callback Callback for receiving the inflated view, where the
     *                 {@link ViewGroup.LayoutParams} of the view is set as the actual size of
     *                 the underlying remote view.
     * @throws IllegalArgumentException If an invalid argument is passed.
     * @throws IllegalArgumentException If an invalid argument is passed.
     * @throws IllegalStateException    If this method is already called.
     * @throws IllegalStateException    If this method is already called.
     */
     */
@@ -115,10 +123,11 @@ public final class InlineSuggestion implements Parcelable {
            @NonNull Consumer<InlineContentView> callback) {
            @NonNull Consumer<InlineContentView> callback) {
        final Size minSize = mInfo.getInlinePresentationSpec().getMinSize();
        final Size minSize = mInfo.getInlinePresentationSpec().getMinSize();
        final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize();
        final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize();
        if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight()
        if (!isValid(size.getWidth(), minSize.getWidth(), maxSize.getWidth())
                || size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) {
                || !isValid(size.getHeight(), minSize.getHeight(), maxSize.getHeight())) {
            throw new IllegalArgumentException("size not between min:"
            throw new IllegalArgumentException(
                    + minSize + " and max:" + maxSize);
                    "size is neither between min:" + minSize + " and max:" + maxSize
                            + ", nor wrap_content");
        }
        }
        mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback);
        mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback);
        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
@@ -136,6 +145,17 @@ public final class InlineSuggestion implements Parcelable {
        });
        });
    }
    }


    /**
     * Returns true if the {@code actual} length is within [min, max] or is {@link
     * ViewGroup.LayoutParams#WRAP_CONTENT}.
     */
    private static boolean isValid(int actual, int min, int max) {
        if (actual == ViewGroup.LayoutParams.WRAP_CONTENT) {
            return true;
        }
        return actual >= min && actual <= max;
    }

    private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context,
    private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context,
            Executor callbackExecutor, Consumer<InlineContentView> callback) {
            Executor callbackExecutor, Consumer<InlineContentView> callback) {
        if (mInlineContentCallback != null) {
        if (mInlineContentCallback != null) {
@@ -154,10 +174,11 @@ public final class InlineSuggestion implements Parcelable {


        @Override
        @Override
        @BinderThread
        @BinderThread
        public void onContent(SurfaceControlViewHost.SurfacePackage content) {
        public void onContent(SurfaceControlViewHost.SurfacePackage content, int width,
                int height) {
            final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
            final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
            if (callbackImpl != null) {
            if (callbackImpl != null) {
                callbackImpl.onContent(content);
                callbackImpl.onContent(content, width, height);
            }
            }
        }
        }


@@ -196,11 +217,13 @@ public final class InlineSuggestion implements Parcelable {
        }
        }


        @BinderThread
        @BinderThread
        public void onContent(SurfaceControlViewHost.SurfacePackage content) {
        public void onContent(SurfaceControlViewHost.SurfacePackage content, int width,
                int height) {
            if (content == null) {
            if (content == null) {
                mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
                mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
            } else {
            } else {
                mView = new InlineContentView(mContext);
                mView = new InlineContentView(mContext);
                mView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
                mView.setChildSurfacePackage(content);
                mView.setChildSurfacePackage(content);
                mCallbackExecutor.execute(() -> mCallback.accept(mView));
                mCallbackExecutor.execute(() -> mCallback.accept(mView));
            }
            }
@@ -398,10 +421,10 @@ public final class InlineSuggestion implements Parcelable {
    };
    };


    @DataClass.Generated(
    @DataClass.Generated(
            time = 1585180783541L,
            time = 1587771173367L,
            codegenVersion = "1.0.15",
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
            sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
            inputSignatures = "private static final  java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic  void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate synchronized  android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
            inputSignatures = "private static final  java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic  void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static  boolean isValid(int,int,int)\nprivate synchronized  android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
    @Deprecated
    @Deprecated
    private void __metadata() {}
    private void __metadata() {}


+1 −1
Original line number Original line Diff line number Diff line
@@ -23,7 +23,7 @@ import android.view.SurfaceControlViewHost;
 * {@hide}
 * {@hide}
 */
 */
oneway interface IInlineContentCallback {
oneway interface IInlineContentCallback {
    void onContent(in SurfaceControlViewHost.SurfacePackage content);
    void onContent(in SurfaceControlViewHost.SurfacePackage content, int width, int height);
    void onClick();
    void onClick();
    void onLongClick();
    void onLongClick();
}
}
+3 −2
Original line number Original line Diff line number Diff line
@@ -319,9 +319,10 @@ public final class InlineSuggestionFactory {
            }
            }


            @Override
            @Override
            public void onContent(SurfaceControlViewHost.SurfacePackage surface)
            public void onContent(SurfaceControlViewHost.SurfacePackage surface, int width,
                    int height)
                    throws RemoteException {
                    throws RemoteException {
                callback.onContent(surface);
                callback.onContent(surface, width, height);
                surface.release();
                surface.release();
            }
            }