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

Commit 4b5d6969 authored by Taran Singh's avatar Taran Singh
Browse files

Add consumer callback in performHandwritingGesture()

performHandwritingGesture should take an optional IntConsumer
& executor to provide result of Gesture operation back to IME.

Bug: 210039666
Bug: 239783077
Test: atest InputConnectionEndToEndTests

Change-Id: I2ca7eaa182159b7ffef0812d970512ffcf817ce2
parent f135f895
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -53220,6 +53220,12 @@ package android.view.inputmethod {
    field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
    field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
    field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
    field public static final int HANDWRITING_GESTURE_RESULT_CANCELLED = 4; // 0x4
    field public static final int HANDWRITING_GESTURE_RESULT_FAILED = 3; // 0x3
    field public static final int HANDWRITING_GESTURE_RESULT_FALLBACK = 5; // 0x5
    field public static final int HANDWRITING_GESTURE_RESULT_SUCCESS = 1; // 0x1
    field public static final int HANDWRITING_GESTURE_RESULT_UNKNOWN = 0; // 0x0
    field public static final int HANDWRITING_GESTURE_RESULT_UNSUPPORTED = 2; // 0x2
    field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
  }
+62 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -29,6 +30,7 @@ import android.view.inputmethod.DeleteGesture;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.HandwritingGesture;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InsertGesture;
import android.view.inputmethod.SelectGesture;
@@ -59,6 +61,38 @@ final class IRemoteInputConnectionInvoker {
        mSessionId = sessionId;
    }

    /**
     * Subclass of {@link ResultReceiver} used by
     * {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} for providing
     * callback.
     */
    private static final class IntResultReceiver extends ResultReceiver {
        @NonNull
        private IntConsumer mConsumer;
        @NonNull
        private Executor mExecutor;

        IntResultReceiver(@NonNull Executor executor, @NonNull IntConsumer consumer) {
            super(null);
            mExecutor = executor;
            mConsumer = consumer;
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            if (mExecutor != null && mConsumer != null) {
                mExecutor.execute(() -> mConsumer.accept(resultCode));
                // provide callback only once.
                clear();
            }
        }

        private void clear() {
            mExecutor = null;
            mConsumer = null;
        }
    };

    /**
     * Creates a new instance of {@link IRemoteInputConnectionInvoker} for the given
     * {@link IRemoteInputConnection}.
@@ -598,24 +632,47 @@ final class IRemoteInputConnectionInvoker {
        }
    }

    /**
     * Invokes one of {@link IRemoteInputConnection#performHandwritingSelectGesture(
     * InputConnectionCommandHeader, SelectGesture, AndroidFuture)},
     * {@link IRemoteInputConnection#performHandwritingDeleteGesture(InputConnectionCommandHeader,
     * DeleteGesture, AndroidFuture)},
     * {@link IRemoteInputConnection#performHandwritingInsertGesture(InputConnectionCommandHeader,
     * InsertGesture, AndroidFuture)}
     *
     * @param {@code gesture} parameter {@link HandwritingGesture}.
     * @return {@link AndroidFuture<Integer>} that can be used to retrieve the invocation
     *         result. {@link RemoteException} will be treated as an error.
     */
    @AnyThread
    public void performHandwritingGesture(
            @NonNull HandwritingGesture gesture, @Nullable @CallbackExecutor Executor executor,
            @Nullable IntConsumer consumer) {
        // TODO(b/210039666): implement resultReceiver

        ResultReceiver resultReceiver = null;
        if (consumer != null) {
            Objects.requireNonNull(executor);
            resultReceiver = new IntResultReceiver(executor, consumer);
        }
        try {
            if (gesture instanceof SelectGesture) {
                mConnection.performHandwritingSelectGesture(
                        createHeader(), (SelectGesture) gesture, null);
                        createHeader(), (SelectGesture) gesture, resultReceiver);
            } else if (gesture instanceof InsertGesture) {
                mConnection.performHandwritingInsertGesture(
                        createHeader(), (InsertGesture) gesture, null);
                        createHeader(), (InsertGesture) gesture, resultReceiver);
            } else if (gesture instanceof DeleteGesture) {
                mConnection.performHandwritingDeleteGesture(
                        createHeader(), (DeleteGesture) gesture, null);
                        createHeader(), (DeleteGesture) gesture, resultReceiver);
            } else if (consumer != null && executor != null) {
                executor.execute(()
                        -> consumer.accept(InputConnection.HANDWRITING_GESTURE_RESULT_UNSUPPORTED));
            }
        } catch (RemoteException e) {
            // TODO(b/210039666): return result
            if (consumer != null && executor != null) {
                executor.execute(() -> consumer.accept(
                        InputConnection.HANDWRITING_GESTURE_RESULT_CANCELLED));
            }
        }
    }

+67 −3
Original line number Diff line number Diff line
@@ -156,6 +156,59 @@ public interface InputConnection {
     */
    int GET_EXTRACTED_TEXT_MONITOR = 0x0001;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * editor didn't provide any result.
     */
    int HANDWRITING_GESTURE_RESULT_UNKNOWN = 0;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * {@link HandwritingGesture} is successfully executed on text.
     */
    int HANDWRITING_GESTURE_RESULT_SUCCESS = 1;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * {@link HandwritingGesture} is unsupported by the current editor.
     */
    int HANDWRITING_GESTURE_RESULT_UNSUPPORTED = 2;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * {@link HandwritingGesture} failed and there was no applicable
     * {@link HandwritingGesture#getFallbackText()} or it couldn't
     * be applied for any other reason.
     */
    int HANDWRITING_GESTURE_RESULT_FAILED = 3;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * {@link HandwritingGesture} was cancelled. This happens when the {@link InputConnection} is
     * or becomes invalidated while performing the gesture, for example because a new
     * {@code InputConnection} was started, or due to {@link InputMethodManager#invalidateInput}.
     */
    int HANDWRITING_GESTURE_RESULT_CANCELLED = 4;

    /**
     * Result for {@link #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)} when
     * {@link HandwritingGesture} failed but {@link HandwritingGesture#getFallbackText()} was
     * committed.
     */
    int HANDWRITING_GESTURE_RESULT_FALLBACK = 5;

    /** @hide */
    @IntDef(prefix = { "HANDWRITING_GESTURE_RESULT_" }, value = {
            HANDWRITING_GESTURE_RESULT_UNKNOWN,
            HANDWRITING_GESTURE_RESULT_SUCCESS,
            HANDWRITING_GESTURE_RESULT_UNSUPPORTED,
            HANDWRITING_GESTURE_RESULT_FAILED,
            HANDWRITING_GESTURE_RESULT_CANCELLED,
            HANDWRITING_GESTURE_RESULT_FALLBACK
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface HandwritingGestureResult {}

    /**
     * Get <var>n</var> characters of text before the current cursor
     * position.
@@ -974,12 +1027,23 @@ public interface InputConnection {
     * Perform a handwriting gesture on text.
     *
     * @param gesture the gesture to perform
     * @param executor if the caller passes a non-null consumer  TODO(b/210039666): complete doc
     * @param consumer if the caller passes a non-null receiver, the editor must invoke this
     * @param executor The executor to run the callback on.
     * @param consumer if the caller passes a non-null consumer, the editor must invoke this
     * with one of {@link #HANDWRITING_GESTURE_RESULT_UNKNOWN},
     * {@link #HANDWRITING_GESTURE_RESULT_SUCCESS}, {@link #HANDWRITING_GESTURE_RESULT_FAILED},
     * {@link #HANDWRITING_GESTURE_RESULT_CANCELLED}, {@link #HANDWRITING_GESTURE_RESULT_FALLBACK},
     * {@link #HANDWRITING_GESTURE_RESULT_UNSUPPORTED} after applying the {@code gesture} has
     * completed. Will be invoked on the given {@link Executor}.
     * Default implementation provides a callback to {@link IntConsumer} with
     * {@link #HANDWRITING_GESTURE_RESULT_UNSUPPORTED}.
     */
    default void performHandwritingGesture(
            @NonNull HandwritingGesture gesture, @Nullable @CallbackExecutor Executor executor,
            @Nullable IntConsumer consumer) {}
            @Nullable IntConsumer consumer) {
        if (executor != null && consumer != null) {
            executor.execute(() -> consumer.accept(HANDWRITING_GESTURE_RESULT_UNSUPPORTED));
        }
    }

    /**
     * The editor is requested to call
+17 −2
Original line number Diff line number Diff line
@@ -1001,15 +1001,30 @@ public final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub
            InputConnectionCommandHeader header,  T gesture, ResultReceiver resultReceiver) {
        dispatchWithTracing("performHandwritingGesture", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                if (resultReceiver != null) {
                    resultReceiver.send(
                            InputConnection.HANDWRITING_GESTURE_RESULT_CANCELLED, null);
                }
                return;  // cancelled
            }
            InputConnection ic = getInputConnection();
            if (ic == null || !isActive()) {
                Log.w(TAG, "performHandwritingGesture on inactive InputConnection");
                if (resultReceiver != null) {
                    resultReceiver.send(
                            InputConnection.HANDWRITING_GESTURE_RESULT_CANCELLED, null);
                }
                return;
            }
            // TODO(b/210039666): implement resultReceiver
            ic.performHandwritingGesture(gesture, null, null);

            // TODO(210039666): implement Cleaner to return HANDWRITING_GESTURE_RESULT_UNKNOWN if
            //  editor doesn't return any type.
            ic.performHandwritingGesture(
                    gesture,
                    resultReceiver != null ? Runnable::run : null,
                    resultReceiver != null
                            ? (resultCode) -> resultReceiver.send(resultCode, null /* resultData */)
                            : null);
        });
    }