summaryrefslogtreecommitdiff
path: root/core/java/android/inputmethodservice
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2021-09-13 16:48:09 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-09-13 16:48:09 +0000
commit23c4146d0132d4727b4e36a9ae28282ea8c238f5 (patch)
tree33cfb90a983317fbbd7e8a07a243d8f1ec03b045 /core/java/android/inputmethodservice
parent5b32677ed7bbc5df35774e17fb5c6e09bd6dc8d7 (diff)
parent95d4f0dc175f5579e765f49e3b6fa35338b807dc (diff)
Merge "Log errors if RemoteInputConnection is used after IMS#onDestroy()"
Diffstat (limited to 'core/java/android/inputmethodservice')
-rw-r--r--core/java/android/inputmethodservice/RemoteInputConnection.java76
1 files changed, 48 insertions, 28 deletions
diff --git a/core/java/android/inputmethodservice/RemoteInputConnection.java b/core/java/android/inputmethodservice/RemoteInputConnection.java
index 464b421d970d..1065d041713f 100644
--- a/core/java/android/inputmethodservice/RemoteInputConnection.java
+++ b/core/java/android/inputmethodservice/RemoteInputConnection.java
@@ -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;
@@ -62,8 +63,29 @@ final class RemoteInputConnection implements InputConnection {
@NonNull
private final IInputContextInvoker mInvoker;
+ private static final class InputMethodServiceInternalHolder {
+ @NonNull
+ 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 WeakReference<InputMethodServiceInternal> mInputMethodService;
+ private final InputMethodServiceInternalHolder mImsInternal;
@MissingMethodFlags
private final int mMissingMethods;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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
@@ -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 =