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

Commit 5e68eeac authored by Anmol Gupta's avatar Anmol Gupta Committed by Ioana Stefan
Browse files

Add proto-based InputMethodService and server side dumping for IME

This CL implements a mechanism to dump InputMethodService and IME
related server states into a proto file which can later be imported
to Winscope to allow easy debugging.

The Design Doc for the IME tracing project is: go/ime-tracing

Bug: 154348613
Test: start trace by calling "adb shell ime tracing start"
      end trace by calling "adb shell ime tracing stop"
      pull trace using "adb pull /data/misc/wmtrace/ime_trace.pb ime_trace.pb"
Change-Id: Icbfb8c11e882f29eb45dea9d4c23315c48e9d619
parent 48acf101
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -194,6 +194,16 @@ public abstract class AbstractInputMethodService extends Service
     */
    public abstract AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();

    /**
     * Dumps the internal state of IME to a protocol buffer output stream initialized using the
     * given {@link FileDescriptor}.
     *
     * @param fd The file descriptor to which proto dump should be written.
     * @param args The arguments passed to the dump method.
     * @hide
     */
    abstract void dumpProtoInternal(FileDescriptor fd, String[] args);

    /**
     * Implement this to handle {@link android.os.Binder#dump Binder.dump()}
     * calls on your input method.
+16 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.inputmethodservice;

import static android.util.imetracing.ImeTracing.PROTO_ARG;

import android.annotation.BinderThread;
import android.annotation.MainThread;
import android.annotation.Nullable;
@@ -37,8 +39,8 @@ import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.InputMethodSubtype;

import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.CancellationGroup;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInlineSuggestionsRequestCallback;
@@ -155,9 +157,20 @@ class IInputMethodWrapper extends IInputMethod.Stub
                    return;
                }
                SomeArgs args = (SomeArgs)msg.obj;
                String[] dumpArgs = (String[]) args.arg3;
                boolean protoDumpRequested = false;
                for (String arg : dumpArgs) {
                    if (arg.equals(PROTO_ARG)) {
                        protoDumpRequested = true;
                        break;
                    }
                }
                try {
                    target.dump((FileDescriptor)args.arg1,
                            (PrintWriter)args.arg2, (String[])args.arg3);
                    if (protoDumpRequested) {
                        target.dumpProtoInternal((FileDescriptor) args.arg1, dumpArgs);
                    } else {
                        target.dump((FileDescriptor) args.arg1, (PrintWriter) args.arg2, dumpArgs);
                    }
                } catch (RuntimeException e) {
                    ((PrintWriter)args.arg2).println("Exception: " + e);
                }
+83 −3
Original line number Diff line number Diff line
@@ -17,6 +17,37 @@
package android.inputmethodservice;

import static android.graphics.Color.TRANSPARENT;
import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VIEW_STARTED;
import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VISIBILITY;
import static android.inputmethodservice.InputMethodServiceProto.CAN_PRE_RENDER;
import static android.inputmethodservice.InputMethodServiceProto.CONFIGURATION;
import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_VISIBLE;
import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_WAS_VISIBLE;
import static android.inputmethodservice.InputMethodServiceProto.EXTRACTED_TOKEN;
import static android.inputmethodservice.InputMethodServiceProto.EXTRACT_VIEW_HIDDEN;
import static android.inputmethodservice.InputMethodServiceProto.FULLSCREEN_APPLIED;
import static android.inputmethodservice.InputMethodServiceProto.INPUT_BINDING;
import static android.inputmethodservice.InputMethodServiceProto.INPUT_EDITOR_INFO;
import static android.inputmethodservice.InputMethodServiceProto.INPUT_STARTED;
import static android.inputmethodservice.InputMethodServiceProto.INPUT_VIEW_STARTED;
import static android.inputmethodservice.InputMethodServiceProto.IN_SHOW_WINDOW;
import static android.inputmethodservice.InputMethodServiceProto.IS_FULLSCREEN;
import static android.inputmethodservice.InputMethodServiceProto.IS_INPUT_VIEW_SHOWN;
import static android.inputmethodservice.InputMethodServiceProto.IS_PRE_RENDERED;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.CONTENT_TOP_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_REGION;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.VISIBLE_TOP_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.LAST_COMPUTED_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.LAST_SHOW_INPUT_REQUESTED;
import static android.inputmethodservice.InputMethodServiceProto.SETTINGS_OBSERVER;
import static android.inputmethodservice.InputMethodServiceProto.SHOW_INPUT_FLAGS;
import static android.inputmethodservice.InputMethodServiceProto.SHOW_INPUT_REQUESTED;
import static android.inputmethodservice.InputMethodServiceProto.SOFT_INPUT_WINDOW;
import static android.inputmethodservice.InputMethodServiceProto.STATUS_ICON;
import static android.inputmethodservice.InputMethodServiceProto.TOKEN;
import static android.inputmethodservice.InputMethodServiceProto.VIEWS_CREATED;
import static android.inputmethodservice.InputMethodServiceProto.WINDOW_VISIBLE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowInsets.Type.navigationBars;
@@ -59,6 +90,7 @@ import android.text.method.MovementMethod;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -104,6 +136,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.Objects;

/**
 * InputMethodService provides a standard implementation of an InputMethod,
@@ -1041,6 +1074,15 @@ public class InputMethodService extends AbstractInputMethodService {
         * or {@link #TOUCHABLE_INSETS_REGION}.
         */
        public int touchableInsets;

        private void dumpDebug(ProtoOutputStream proto, long fieldId) {
            final long token = proto.start(fieldId);
            proto.write(CONTENT_TOP_INSETS, contentTopInsets);
            proto.write(VISIBLE_TOP_INSETS, visibleTopInsets);
            proto.write(TOUCHABLE_INSETS, touchableInsets);
            proto.write(TOUCHABLE_REGION, touchableRegion.toString());
            proto.end(token);
        }
    }

    /**
@@ -3325,4 +3367,42 @@ public class InputMethodService extends AbstractInputMethodService {
                + " touchableRegion=" + mTmpInsets.touchableRegion);
        p.println(" mSettingsObserver=" + mSettingsObserver);
    }

    /**
     * @hide
     */
    @Override
    final void dumpProtoInternal(FileDescriptor fd, String[] args) {
        final ProtoOutputStream proto = new ProtoOutputStream(fd);
        mWindow.dumpDebug(proto, SOFT_INPUT_WINDOW);
        proto.write(VIEWS_CREATED, mViewsCreated);
        proto.write(DECOR_VIEW_VISIBLE, mDecorViewVisible);
        proto.write(DECOR_VIEW_WAS_VISIBLE, mDecorViewWasVisible);
        proto.write(WINDOW_VISIBLE, mWindowVisible);
        proto.write(IN_SHOW_WINDOW, mInShowWindow);
        proto.write(CONFIGURATION, getResources().getConfiguration().toString());
        proto.write(TOKEN, Objects.toString(mToken));
        proto.write(INPUT_BINDING, Objects.toString(mInputBinding));
        proto.write(INPUT_STARTED, mInputStarted);
        proto.write(INPUT_VIEW_STARTED, mInputViewStarted);
        proto.write(CANDIDATES_VIEW_STARTED, mCandidatesViewStarted);
        if (mInputEditorInfo != null) {
            mInputEditorInfo.dumpDebug(proto, INPUT_EDITOR_INFO);
        }
        proto.write(SHOW_INPUT_REQUESTED, mShowInputRequested);
        proto.write(LAST_SHOW_INPUT_REQUESTED, mLastShowInputRequested);
        proto.write(CAN_PRE_RENDER, mCanPreRender);
        proto.write(IS_PRE_RENDERED, mIsPreRendered);
        proto.write(SHOW_INPUT_FLAGS, mShowInputFlags);
        proto.write(CANDIDATES_VISIBILITY, mCandidatesVisibility);
        proto.write(FULLSCREEN_APPLIED, mFullscreenApplied);
        proto.write(IS_FULLSCREEN, mIsFullscreen);
        proto.write(EXTRACT_VIEW_HIDDEN, mExtractViewHidden);
        proto.write(EXTRACTED_TOKEN, mExtractedToken);
        proto.write(IS_INPUT_VIEW_SHOWN, mIsInputViewShown);
        proto.write(STATUS_ICON, mStatusIcon);
        mTmpInsets.dumpDebug(proto, LAST_COMPUTED_INSETS);
        proto.write(SETTINGS_OBSERVER, Objects.toString(mSettingsObserver));
        proto.flush();
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -16,6 +16,13 @@

package android.inputmethodservice;

import static android.inputmethodservice.SoftInputWindowProto.BOUNDS;
import static android.inputmethodservice.SoftInputWindowProto.GRAVITY;
import static android.inputmethodservice.SoftInputWindowProto.NAME;
import static android.inputmethodservice.SoftInputWindowProto.TAKES_FOCUS;
import static android.inputmethodservice.SoftInputWindowProto.WINDOW_STATE;
import static android.inputmethodservice.SoftInputWindowProto.WINDOW_TYPE;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.IntDef;
@@ -25,6 +32,7 @@ import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -362,4 +370,15 @@ public class SoftInputWindow extends Dialog {
                throw new IllegalStateException("Unknown state=" + state);
        }
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(NAME, mName);
        proto.write(WINDOW_TYPE, mWindowType);
        proto.write(GRAVITY, mGravity);
        proto.write(TAKES_FOCUS, mTakesFocus);
        mBounds.dumpDebug(proto, BOUNDS);
        proto.write(WINDOW_STATE, mWindowState);
        proto.end(token);
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -188,7 +188,13 @@ public class InsetsSource implements Parcelable {
        return false;
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId) {
    /**
     * Export the state of {@link InsetsSource} into a protocol buffer output stream.
     *
     * @param proto   Stream to write the state to
     * @param fieldId FieldId of InsetsSource as defined in the parent message
     */
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(TYPE, InsetsState.typeToString(mType));
        mFrame.dumpDebug(proto, FRAME);
Loading