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

Commit 23c4146d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Log errors if RemoteInputConnection is used after IMS#onDestroy()"

parents 5b32677e 95d4f0dc
Loading
Loading
Loading
Loading
+48 −28
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.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> 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;
@@ -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 =