/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.inputmethod; import android.annotation.AnyThread; import android.annotation.DurationMillisLong; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.view.KeyEvent; import android.view.inputmethod.SurroundingText; import android.view.inputmethod.TextAttribute; import com.android.internal.infra.AndroidFuture; import java.util.concurrent.CompletableFuture; /** * A wrapper object for A11y IME. * *
This needs to be public to be referenced from {@link android.app.UiAutomation}.
*/ public final class RemoteAccessibilityInputConnection { private static final String TAG = "RemoteA11yInputConnection"; @DurationMillisLong private static final int MAX_WAIT_TIME_MILLIS = 2000; @NonNull IRemoteAccessibilityInputConnectionInvoker mInvoker; /** * Signaled when the system decided to take away IME focus from the target app. * *This is expected to be signaled immediately when the IME process receives * {@link com.android.internal.inputmethod.IInputMethod#unbindInput()}.
*/ @NonNull private final CancellationGroup mCancellationGroup; public RemoteAccessibilityInputConnection( @NonNull IRemoteAccessibilityInputConnection connection, @NonNull CancellationGroup cancellationGroup) { mInvoker = IRemoteAccessibilityInputConnectionInvoker.create(connection); mCancellationGroup = cancellationGroup; } public RemoteAccessibilityInputConnection(@NonNull RemoteAccessibilityInputConnection original, int sessionId) { mInvoker = original.mInvoker.cloneWithSessionId(sessionId); mCancellationGroup = original.mCancellationGroup; } /** * Test if this object holds the given {@link IRemoteAccessibilityInputConnection} or not. * * @param connection {@link IRemoteAccessibilityInputConnection} to be tested. * @return {@code true} if this object holds the same object. */ @AnyThread public boolean isSameConnection(@NonNull IRemoteAccessibilityInputConnection connection) { return mInvoker.isSameConnection(connection); } /** * Invokes {@link IRemoteAccessibilityInputConnection#commitText(InputConnectionCommandHeader, * CharSequence, int, TextAttribute)}. * * @param text The {@code "text"} parameter to be passed. * @param newCursorPosition The {@code "newCursorPosition"} parameter to be passed. * @param textAttribute The {@code "textAttribute"} parameter to be passed. */ @AnyThread public void commitText(@NonNull CharSequence text, int newCursorPosition, @Nullable TextAttribute textAttribute) { mInvoker.commitText(text, newCursorPosition, textAttribute); } /** * Invokes {@link IRemoteAccessibilityInputConnection#setSelection(InputConnectionCommandHeader, * int, int)}. * * @param start The {@code "start"} parameter to be passed. * @param end The {@code "end"} parameter to be passed. */ @AnyThread public void setSelection(int start, int end) { mInvoker.setSelection(start, end); } /** * Invokes {@link IRemoteAccessibilityInputConnection#getSurroundingText( * InputConnectionCommandHeader, int, int, int, AndroidFuture)}. * * @param beforeLength The {@code "beforeLength"} parameter to be passed. * @param afterLength The {@code "afterLength"} parameter to be passed. * @param flags The {@code "flags"} parameter to be passed. * @return The {@link SurroundingText} object returned from the target application. */ @AnyThread public SurroundingText getSurroundingText( @IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength, int flags) { if (mCancellationGroup.isCanceled()) { return null; } final CompletableFuture