Loading core/java/android/inputmethodservice/RemoteInputConnection.java +48 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; Loading Loading @@ -62,8 +63,29 @@ final class RemoteInputConnection implements InputConnection { @NonNull private final IInputContextInvoker mInvoker; private static final class InputMethodServiceInternalHolder { @NonNull private final WeakReference<InputMethodServiceInternal> mInputMethodService; private final WeakReference<InputMethodServiceInternal> mServiceRef; private InputMethodServiceInternalHolder( @NonNull WeakReference<InputMethodServiceInternal> ims) { mServiceRef = ims; } @AnyThread @Nullable public InputMethodServiceInternal getAndWarnIfNull() { final InputMethodServiceInternal ims = mServiceRef.get(); if (ims == null) { Log.e(TAG, "InputMethodService is already destroyed. InputConnection instances" + " cannot be used beyond InputMethodService lifetime.", new Throwable()); } return ims; } } @NonNull private final InputMethodServiceInternalHolder mImsInternal; @MissingMethodFlags private final int mMissingMethods; Loading @@ -81,7 +103,7 @@ final class RemoteInputConnection implements InputConnection { @NonNull WeakReference<InputMethodServiceInternal> inputMethodService, IInputContext inputContext, @MissingMethodFlags int missingMethods, @NonNull CancellationGroup cancellationGroup) { mInputMethodService = inputMethodService; mImsInternal = new InputMethodServiceInternalHolder(inputMethodService); mInvoker = IInputContextInvoker.create(inputContext); mMissingMethods = missingMethods; mCancellationGroup = cancellationGroup; Loading @@ -101,11 +123,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getTextAfterCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(length, flags, result); inputMethodService.triggerServiceDump(TAG + "#getTextAfterCursor", icProto); imsInternal.triggerServiceDump(TAG + "#getTextAfterCursor", icProto); } return result; Loading @@ -125,11 +147,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getTextBeforeCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(length, flags, result); inputMethodService.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto); imsInternal.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto); } return result; Loading @@ -149,11 +171,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(flags, result); inputMethodService.triggerServiceDump(TAG + "#getSelectedText", icProto); imsInternal.triggerServiceDump(TAG + "#getSelectedText", icProto); } return result; Loading Loading @@ -187,11 +209,11 @@ final class RemoteInputConnection implements InputConnection { final SurroundingText result = CompletableFutureUtil.getResultOrNull( value, TAG, "getSurroundingText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto( beforeLength, afterLength, flags, result); inputMethodService.triggerServiceDump(TAG + "#getSurroundingText", icProto); imsInternal.triggerServiceDump(TAG + "#getSurroundingText", icProto); } return result; Loading @@ -207,11 +229,11 @@ final class RemoteInputConnection implements InputConnection { final int result = CompletableFutureUtil.getResultOrZero( value, TAG, "getCursorCapsMode()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto( reqModes, result); inputMethodService.triggerServiceDump(TAG + "#getCursorCapsMode", icProto); imsInternal.triggerServiceDump(TAG + "#getCursorCapsMode", icProto); } return result; Loading @@ -227,11 +249,11 @@ final class RemoteInputConnection implements InputConnection { final ExtractedText result = CompletableFutureUtil.getResultOrNull( value, TAG, "getExtractedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto( request, flags, result); inputMethodService.triggerServiceDump(TAG + "#getExtractedText", icProto); imsInternal.triggerServiceDump(TAG + "#getExtractedText", icProto); } return result; Loading @@ -248,12 +270,11 @@ final class RemoteInputConnection implements InputConnection { @AnyThread private void notifyUserActionIfNecessary() { final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService == null) { // This basically should not happen, because it's the the caller of this method. final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal == null) { return; } inputMethodService.notifyUserActionIfNecessary(); imsInternal.notifyUserActionIfNecessary(); } @AnyThread Loading Loading @@ -400,12 +421,11 @@ final class RemoteInputConnection implements InputConnection { } if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService == null) { // This basically should not happen, because it's the caller of this method. final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal == null) { return false; } inputMethodService.exposeContent(inputContentInfo, this); imsInternal.exposeContent(inputContentInfo, this); } final CompletableFuture<Boolean> value = Loading Loading
core/java/android/inputmethodservice/RemoteInputConnection.java +48 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; Loading Loading @@ -62,8 +63,29 @@ final class RemoteInputConnection implements InputConnection { @NonNull private final IInputContextInvoker mInvoker; private static final class InputMethodServiceInternalHolder { @NonNull private final WeakReference<InputMethodServiceInternal> mInputMethodService; private final WeakReference<InputMethodServiceInternal> mServiceRef; private InputMethodServiceInternalHolder( @NonNull WeakReference<InputMethodServiceInternal> ims) { mServiceRef = ims; } @AnyThread @Nullable public InputMethodServiceInternal getAndWarnIfNull() { final InputMethodServiceInternal ims = mServiceRef.get(); if (ims == null) { Log.e(TAG, "InputMethodService is already destroyed. InputConnection instances" + " cannot be used beyond InputMethodService lifetime.", new Throwable()); } return ims; } } @NonNull private final InputMethodServiceInternalHolder mImsInternal; @MissingMethodFlags private final int mMissingMethods; Loading @@ -81,7 +103,7 @@ final class RemoteInputConnection implements InputConnection { @NonNull WeakReference<InputMethodServiceInternal> inputMethodService, IInputContext inputContext, @MissingMethodFlags int missingMethods, @NonNull CancellationGroup cancellationGroup) { mInputMethodService = inputMethodService; mImsInternal = new InputMethodServiceInternalHolder(inputMethodService); mInvoker = IInputContextInvoker.create(inputContext); mMissingMethods = missingMethods; mCancellationGroup = cancellationGroup; Loading @@ -101,11 +123,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getTextAfterCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(length, flags, result); inputMethodService.triggerServiceDump(TAG + "#getTextAfterCursor", icProto); imsInternal.triggerServiceDump(TAG + "#getTextAfterCursor", icProto); } return result; Loading @@ -125,11 +147,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getTextBeforeCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(length, flags, result); inputMethodService.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto); imsInternal.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto); } return result; Loading @@ -149,11 +171,11 @@ final class RemoteInputConnection implements InputConnection { final CharSequence result = CompletableFutureUtil.getResultOrNull( value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(flags, result); inputMethodService.triggerServiceDump(TAG + "#getSelectedText", icProto); imsInternal.triggerServiceDump(TAG + "#getSelectedText", icProto); } return result; Loading Loading @@ -187,11 +209,11 @@ final class RemoteInputConnection implements InputConnection { final SurroundingText result = CompletableFutureUtil.getResultOrNull( value, TAG, "getSurroundingText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto( beforeLength, afterLength, flags, result); inputMethodService.triggerServiceDump(TAG + "#getSurroundingText", icProto); imsInternal.triggerServiceDump(TAG + "#getSurroundingText", icProto); } return result; Loading @@ -207,11 +229,11 @@ final class RemoteInputConnection implements InputConnection { final int result = CompletableFutureUtil.getResultOrZero( value, TAG, "getCursorCapsMode()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto( reqModes, result); inputMethodService.triggerServiceDump(TAG + "#getCursorCapsMode", icProto); imsInternal.triggerServiceDump(TAG + "#getCursorCapsMode", icProto); } return result; Loading @@ -227,11 +249,11 @@ final class RemoteInputConnection implements InputConnection { final ExtractedText result = CompletableFutureUtil.getResultOrNull( value, TAG, "getExtractedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS); final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) { final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal != null && ImeTracing.getInstance().isEnabled()) { final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto( request, flags, result); inputMethodService.triggerServiceDump(TAG + "#getExtractedText", icProto); imsInternal.triggerServiceDump(TAG + "#getExtractedText", icProto); } return result; Loading @@ -248,12 +270,11 @@ final class RemoteInputConnection implements InputConnection { @AnyThread private void notifyUserActionIfNecessary() { final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService == null) { // This basically should not happen, because it's the the caller of this method. final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal == null) { return; } inputMethodService.notifyUserActionIfNecessary(); imsInternal.notifyUserActionIfNecessary(); } @AnyThread Loading Loading @@ -400,12 +421,11 @@ final class RemoteInputConnection implements InputConnection { } if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { final InputMethodServiceInternal inputMethodService = mInputMethodService.get(); if (inputMethodService == null) { // This basically should not happen, because it's the caller of this method. final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull(); if (imsInternal == null) { return false; } inputMethodService.exposeContent(inputContentInfo, this); imsInternal.exposeContent(inputContentInfo, this); } final CompletableFuture<Boolean> value = Loading