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

Commit 7cbc9bdf authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Optimize InputConnection tracing logic a bit

This CL is a follow up CL to our previous CL [1], which introduced
InputConnection logging as part of IME tracing project.

The goal of this CL is to consolidate RemoteInputConnectionImpl by
separating core business logic from orthogonal concept such as method
tracing, without sacrificing the runtime performance.

With this CL, both code and string resource duplicates will be
actually reduced.  There is no additional object allocation unless the
IME tracing is explicitly enabled.

 [1]: Iabd6af1b858803030848a0ef5e7dd9ecfc562716
      0653b692

Bug: 154348613
Bug: 192412909
Test: Manually verified that the IC tracing is still working
Change-Id: I329129241bdae231844dc3170faf9e8d11f49f08
parent 89c19701
Loading
Loading
Loading
Loading
+42 −74
Original line number Diff line number Diff line
@@ -16,6 +16,13 @@

package com.android.internal.inputmethod;

import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetCursorCapsModeProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetExtractedTextProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetSelectedTextProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetSurroundingTextProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetTextAfterCursorProto;
import static com.android.internal.inputmethod.InputConnectionProtoDumper.buildGetTextBeforeCursorProto;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -29,20 +36,19 @@ import android.view.View;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.DumpableInputConnection;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionInspector;
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.SurroundingText;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.view.IInputContext;

import java.lang.ref.WeakReference;
import java.util.function.Function;
import java.util.function.Supplier;

/**
@@ -225,21 +231,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
            AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getTextAfterCursor", future, () -> {
            final InputConnection ic = getInputConnection();
            final CharSequence result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
                result = null;
            } else {
                result = ic.getTextAfterCursor(length, flags);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(
                        length, flags, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto);
                return null;
            }
            return result;
        });
            return ic.getTextAfterCursor(length, flags);
        }, useImeTracing() ? result -> buildGetTextAfterCursorProto(length, flags, result) : null);
    }

    @Override
@@ -247,42 +244,24 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
            AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getTextBeforeCursor", future, () -> {
            final InputConnection ic = getInputConnection();
            final CharSequence result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
                result = null;
            } else {
                result = ic.getTextBeforeCursor(length, flags);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(
                        length, flags, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto);
                return null;
            }
            return result;
        });
            return ic.getTextBeforeCursor(length, flags);
        }, useImeTracing() ? result -> buildGetTextBeforeCursorProto(length, flags, result) : null);
    }

    @Override
    public void getSelectedText(int flags, AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getSelectedText", future, () -> {
            final InputConnection ic = getInputConnection();
            final CharSequence result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getSelectedText on inactive InputConnection");
                result = null;
            } else {
                result = ic.getSelectedText(flags);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(
                        flags, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getSelectedText", mParentInputMethodManager, icProto);
                return null;
            }
            return result;
        });
            return ic.getSelectedText(flags);
        }, useImeTracing() ? result -> buildGetSelectedTextProto(flags, result) : null);
    }

    @Override
@@ -290,42 +269,25 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
            AndroidFuture future /* T=SurroundingText */) {
        dispatchWithTracing("getSurroundingText", future, () -> {
            final InputConnection ic = getInputConnection();
            final SurroundingText result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getSurroundingText on inactive InputConnection");
                result = null;
            } else {
                result = ic.getSurroundingText(beforeLength, afterLength, flags);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto(
                        beforeLength, afterLength, flags, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getSurroundingText", mParentInputMethodManager, icProto);
                return null;
            }
            return result;
        });
            return ic.getSurroundingText(beforeLength, afterLength, flags);
        }, useImeTracing() ? result -> buildGetSurroundingTextProto(
                beforeLength, afterLength, flags, result) : null);
    }

    @Override
    public void getCursorCapsMode(int reqModes, AndroidFuture future /* T=Integer */) {
        dispatchWithTracing("getCursorCapsMode", future, () -> {
            final InputConnection ic = getInputConnection();
            final int result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
                result = 0;
            } else {
                result = ic.getCursorCapsMode(reqModes);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(
                        reqModes, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto);
                return 0;
            }
            return result;
        });
            return ic.getCursorCapsMode(reqModes);
        }, useImeTracing() ? result -> buildGetCursorCapsModeProto(reqModes, result) : null);
    }

    @Override
@@ -333,21 +295,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
            AndroidFuture future /* T=ExtractedText */) {
        dispatchWithTracing("getExtractedText", future, () -> {
            final InputConnection ic = getInputConnection();
            final ExtractedText result;
            if (ic == null || !isActive()) {
                Log.w(TAG, "getExtractedText on inactive InputConnection");
                result = null;
            } else {
                result = ic.getExtractedText(request, flags);
            }
            if (ImeTracing.getInstance().isEnabled()) {
                final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(
                        request, flags, result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#getExtractedText", mParentInputMethodManager, icProto);
                return null;
            }
            return result;
        });
            return ic.getExtractedText(request, flags);
        }, useImeTracing() ? result -> buildGetExtractedTextProto(request, flags, result) : null);
    }

    @Override
@@ -643,6 +596,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {

    private <T> void dispatchWithTracing(@NonNull String methodName,
            @NonNull AndroidFuture untypedFuture, @NonNull Supplier<T> supplier) {
        dispatchWithTracing(methodName, untypedFuture, supplier, null /* dumpProtoProvider */);
    }

    private <T> void dispatchWithTracing(@NonNull String methodName,
            @NonNull AndroidFuture untypedFuture, @NonNull Supplier<T> supplier,
            @Nullable Function<T, byte[]> dumpProtoProvider) {
        @SuppressWarnings("unchecked")
        final AndroidFuture<T> future = untypedFuture;
        dispatchWithTracing(methodName, () -> {
@@ -654,6 +613,15 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
                throw throwable;
            }
            future.complete(result);
            if (dumpProtoProvider != null) {
                final byte[] icProto = dumpProtoProvider.apply(result);
                ImeTracing.getInstance().triggerClientDump(
                        TAG + "#" + methodName, mParentInputMethodManager, icProto);
            }
        });
    }

    private static boolean useImeTracing() {
        return ImeTracing.getInstance().isEnabled();
    }
}