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

Commit c47b324d authored by Ioana Stefan's avatar Ioana Stefan
Browse files

Add InputConnection debug information

Add InputConnection information to IME tracing. This change adds
only information about the text associated with an
EditableInputConnection instance: editable text, selected text, text
before and after the cursor (for a preset length) and cursor caps mode.

Test: flash a device
      start IME tracing with `adb shell ime tracing start`
      stop IME tracing with `adb shell ime tracing stop`
      visualise the traces in Winscope and see the inputConnection information
Change-Id: I4dc6147fb7baa2cea413d2c44226e8c84c056c37
parent eb778956
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.view.inputmethod;

import android.annotation.NonNull;
import android.util.proto.ProtoOutputStream;

/** @hide */
public interface DumpableInputConnection {

    /**
     * Method used to dump state of InputConnection implementations of interest.
     *
     * @param proto Stream to write the state to
     * @param fieldId FieldId of DumpableInputConnection as defined in the parent message
     */
    void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId);
}
+19 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.util.imetracing.ImeTracing.PROTO_ARG;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.DISPLAY_ID;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.EDITOR_INFO;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_INSETS_SOURCE_CONSUMER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_CONNECTION;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_METHOD_MANAGER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.VIEW_ROOT_IMPL;
import static android.view.inputmethod.InputMethodManagerProto.ACTIVE;
@@ -998,9 +999,9 @@ public final class InputMethodManager {
        private final InputMethodManager mParentInputMethodManager;
        private final WeakReference<View> mServedView;

        ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn,
        ControlledInputConnectionWrapper(Looper icLooper, InputConnection conn,
                InputMethodManager inputMethodManager, View servedView) {
            super(mainLooper, conn);
            super(icLooper, conn);
            mParentInputMethodManager = inputMethodManager;
            mServedView = new WeakReference<>(servedView);
        }
@@ -1046,6 +1047,18 @@ public final class InputMethodManager {
                    + " mServedView=" + mServedView.get()
                    + "}";
        }

        void dumpDebug(ProtoOutputStream proto, long fieldId) {
            // Check that the call is initiated in the main thread of the current InputConnection
            // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
            // executed on this thread. Otherwise the messages are dispatched to the correct thread
            // in IInputConnectionWrapper, but this is not wanted while dumpng, for performance
            // reasons.
            if (getInputConnection() instanceof DumpableInputConnection && Looper.myLooper()
                    == getLooper()) {
                ((DumpableInputConnection) getInputConnection()).dumpDebug(proto, fieldId);
            }
        }
    }

    private static class ImeThreadFactory implements ThreadFactory {
@@ -2207,6 +2220,7 @@ public final class InputMethodManager {
     * @hide
     */
    public void notifyImeHidden(IBinder windowToken) {
        ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this);
        synchronized (mH) {
            try {
                if (mCurMethod != null && mCurRootView != null
@@ -3312,6 +3326,9 @@ public final class InputMethodManager {
            if (mImeInsetsConsumer != null) {
                mImeInsetsConsumer.dumpDebug(proto, IME_INSETS_SOURCE_CONSUMER);
            }
            if (mServedInputConnectionWrapper != null) {
                mServedInputConnectionWrapper.dumpDebug(proto, INPUT_CONNECTION);
            }
        }
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -111,6 +111,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
        }
    }

    protected Looper getLooper() {
        synchronized (mMainLooper) {
            return mMainLooper;
        }
    }

    protected boolean isFinished() {
        synchronized (mLock) {
            return mFinished;
+40 −1
Original line number Diff line number Diff line
@@ -16,21 +16,36 @@

package com.android.internal.widget;

import static android.view.inputmethod.InputConnectionProto.CURSOR_CAPS_MODE;
import static android.view.inputmethod.InputConnectionProto.EDITABLE_TEXT;
import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT;
import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_END;
import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_START;

import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.text.Editable;
import android.text.Selection;
import android.text.method.KeyListener;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.inputmethod.BaseInputConnection;
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.widget.TextView;

public class EditableInputConnection extends BaseInputConnection {
/**
 * Base class for an editable InputConnection instance. This is created by {@link TextView} or
 * {@link EditText}.
 */
public class EditableInputConnection extends BaseInputConnection
        implements DumpableInputConnection {
    private static final boolean DEBUG = false;
    private static final boolean DUMP_TEXT = false;
    private static final String TAG = "EditableInputConnection";

    private final TextView mTextView;
@@ -222,4 +237,28 @@ public class EditableInputConnection extends BaseInputConnection {
        }
        return true;
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        CharSequence editableText = mTextView.getText();
        CharSequence selectedText = getSelectedText(0 /* flags */);
        if (DUMP_TEXT) {
            if (editableText != null) {
                proto.write(EDITABLE_TEXT, editableText.toString());
            }
            if (selectedText != null) {
                proto.write(SELECTED_TEXT, selectedText.toString());
            }
        }
        final Editable content = getEditable();
        if (content != null) {
            int start = Selection.getSelectionStart(content);
            int end = Selection.getSelectionEnd(content);
            proto.write(SELECTED_TEXT_START, start);
            proto.write(SELECTED_TEXT_END, end);
        }
        proto.write(CURSOR_CAPS_MODE, getCursorCapsMode(0));
        proto.end(token);
    }
}
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.
 */

syntax = "proto2";

import "frameworks/base/core/proto/android/privacy.proto";

package android.view.inputmethod;

option java_multiple_files = true;

/**
 * Represents a {@link android.view.inputmethod.InputConnection} object.
 */
message InputConnectionProto {
  optional string editable_text = 1 [(.android.privacy).dest = DEST_LOCAL];
  optional string selected_text = 2 [(.android.privacy).dest = DEST_LOCAL];
  optional int32 selected_text_start = 3;
  optional int32 selected_text_end = 4;
  optional int32 cursor_caps_mode = 5;
}
 No newline at end of file
Loading