/* * 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.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.view.KeyEvent; import android.view.inputmethod.SurroundingText; import android.view.inputmethod.TextAttribute; import com.android.internal.infra.AndroidFuture; import java.util.Objects; final class IRemoteAccessibilityInputConnectionInvoker { @NonNull private final IRemoteAccessibilityInputConnection mConnection; private final int mSessionId; private IRemoteAccessibilityInputConnectionInvoker( @NonNull IRemoteAccessibilityInputConnection inputContext, int sessionId) { mConnection = inputContext; mSessionId = sessionId; } /** * Creates a new instance of {@link IRemoteAccessibilityInputConnectionInvoker} for the given * {@link IRemoteAccessibilityInputConnection}. * * @param connection {@link IRemoteAccessibilityInputConnection} to be wrapped. * @return A new instance of {@link IRemoteAccessibilityInputConnectionInvoker}. */ public static IRemoteAccessibilityInputConnectionInvoker create( @NonNull IRemoteAccessibilityInputConnection connection) { Objects.requireNonNull(connection); return new IRemoteAccessibilityInputConnectionInvoker(connection, 0); } /** * Creates a new instance of {@link IRemoteAccessibilityInputConnectionInvoker} with the given * {@code sessionId}. * * @param sessionId the new session ID to be used. * @return A new instance of {@link IRemoteAccessibilityInputConnectionInvoker}. */ @NonNull public IRemoteAccessibilityInputConnectionInvoker cloneWithSessionId(int sessionId) { return new IRemoteAccessibilityInputConnectionInvoker(mConnection, sessionId); } /** * @param connection {@code IRemoteAccessibilityInputConnection} to be compared with * @return {@code true} if the underlying {@code IRemoteAccessibilityInputConnection} is the * same. {@code false} if {@code connection} is {@code null}. */ @AnyThread public boolean isSameConnection(@NonNull IRemoteAccessibilityInputConnection connection) { if (connection == null) { return false; } return mConnection.asBinder() == connection.asBinder(); } @NonNull InputConnectionCommandHeader createHeader() { return new InputConnectionCommandHeader(mSessionId); } /** * Invokes {@link IRemoteAccessibilityInputConnection#commitText(InputConnectionCommandHeader, * int, CharSequence)}. * * @param text {@code text} parameter to be passed. * @param newCursorPosition {@code newCursorPosition} parameter to be passed. * @param textAttribute The extra information about the text. */ @AnyThread public void commitText(CharSequence text, int newCursorPosition, @Nullable TextAttribute textAttribute) { try { mConnection.commitText(createHeader(), text, newCursorPosition, textAttribute); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#setSelection(InputConnectionCommandHeader, * int, int)}. * * @param start {@code start} parameter to be passed. * @param end {@code start} parameter to be passed. */ @AnyThread public void setSelection(int start, int end) { try { mConnection.setSelection(createHeader(), start, end); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#getSurroundingText( * InputConnectionCommandHeader, int, int, int, AndroidFuture)}. * * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. * @param flags {@code flags} parameter to be passed. * @return {@link AndroidFuture< SurroundingText >} that can be used to retrieve the * invocation result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull public AndroidFuture getSurroundingText(int beforeLength, int afterLength, int flags) { final AndroidFuture future = new AndroidFuture<>(); try { mConnection.getSurroundingText(createHeader(), beforeLength, afterLength, flags, future); } catch (RemoteException e) { future.completeExceptionally(e); } return future; } /** * Invokes {@link IRemoteAccessibilityInputConnection#deleteSurroundingText( * InputConnectionCommandHeader, int, int)}. * * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. */ @AnyThread public void deleteSurroundingText(int beforeLength, int afterLength) { try { mConnection.deleteSurroundingText(createHeader(), beforeLength, afterLength); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#sendKeyEvent( * InputConnectionCommandHeader, KeyEvent)}. * * @param event {@code event} parameter to be passed. */ @AnyThread public void sendKeyEvent(KeyEvent event) { try { mConnection.sendKeyEvent(createHeader(), event); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#performEditorAction( * InputConnectionCommandHeader, int)}. * * @param actionCode {@code start} parameter to be passed. */ @AnyThread public void performEditorAction(int actionCode) { try { mConnection.performEditorAction(createHeader(), actionCode); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#performContextMenuAction( * InputConnectionCommandHeader, int)}. * * @param id {@code id} parameter to be passed. */ @AnyThread public void performContextMenuAction(int id) { try { mConnection.performContextMenuAction(createHeader(), id); } catch (RemoteException e) { } } /** * Invokes {@link IRemoteAccessibilityInputConnection#getCursorCapsMode( * InputConnectionCommandHeader, int, AndroidFuture)}. * * @param reqModes {@code reqModes} parameter to be passed. * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull public AndroidFuture getCursorCapsMode(int reqModes) { final AndroidFuture future = new AndroidFuture<>(); try { mConnection.getCursorCapsMode(createHeader(), reqModes, future); } catch (RemoteException e) { future.completeExceptionally(e); } return future; } /** * Invokes {@link IRemoteAccessibilityInputConnection#clearMetaKeyStates( * InputConnectionCommandHeader, int)}. * * @param states {@code states} parameter to be passed. */ @AnyThread public void clearMetaKeyStates(int states) { try { mConnection.clearMetaKeyStates(createHeader(), states); } catch (RemoteException e) { } } }