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

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

Optimized workflow for IME tracing on clients side

Optimized the tracing logic for the IME clients information. The
clients trigger a tracing dump through the new method triggerClientDump
exposed by the ImeTracing interface. This change was done
to be able to support custom dump for clients information and
custom dump from IMS.

This change only covers the clients information. The IMS and IMMS
information will be dumped in next changes.

Bug: 154348613
Test: start IME tracing by calling "adb shell ime tracing start"
      end IME tracing by calling "adb shell ime tracing stop"
      pull trace using "adb pull /data/misc/wmtrace/ime_trace_clients.pb ime_trace_clients.pb"
Change-Id: I499cb5f45a3e78912b09b9c6cedf1ce5443e797a
parent b8b238ee
Loading
Loading
Loading
Loading
+41 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.util.imetracing;

import android.app.ActivityThread;
import android.content.Context;
import android.inputmethodservice.InputMethodService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -40,10 +41,18 @@ public abstract class ImeTracing {
    static final String TAG = "imeTracing";
    public static final String PROTO_ARG = "--proto-com-android-imetracing";

    /* Constants describing the component type that triggered a dump. */
    public static final int IME_TRACING_FROM_CLIENT = 0;
    public static final int IME_TRACING_FROM_IMS = 1;
    public static final int IME_TRACING_FROM_IMMS = 2;

    private static ImeTracing sInstance;
    static boolean sEnabled = false;
    IInputMethodManager mService;

    protected boolean mDumpInProgress;
    protected final Object mDumpInProgressLock = new Object();

    ImeTracing() throws ServiceNotFoundException {
        mService = IInputMethodManager.Stub.asInterface(
                ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
@@ -69,15 +78,22 @@ public abstract class ImeTracing {
    }

    /**
     * Sends request to start proto dump to {@link ImeTracingServerImpl} when called from a
     * server process and to {@link ImeTracingClientImpl} when called from a client process.
     * Transmits the information from client or InputMethodService side to the server, in order to
     * be stored persistently to the current IME tracing dump.
     *
     * @param protoDump client or service side information to be stored by the server
     * @param source where the information is coming from, refer to {@see #IME_TRACING_FROM_CLIENT}
     * and {@see #IME_TRACING_FROM_IMS}
     * @param where
     */
    public abstract void triggerDump();
    public void sendToService(byte[] protoDump, int source, String where) throws RemoteException {
        mService.startProtoDump(protoDump, source, where);
    }

    /**
     * @param proto dump to be added to the buffer
     */
    public abstract void addToBuffer(ProtoOutputStream proto);
    public abstract void addToBuffer(ProtoOutputStream proto, int source);

    /**
     * @param shell The shell command to process
@@ -85,6 +101,27 @@ public abstract class ImeTracing {
     */
    public abstract int onShellCommand(ShellCommand shell);

    /**
     * Starts a proto dump of the client side information.
     *
     * @param where Place where the trace was triggered.
     */
    public abstract void triggerClientDump(String where);

    /**
     * Starts a proto dump of the currently connected InputMethodService information.
     *
     * @param where Place where the trace was triggered.
     */
    public abstract void triggerServiceDump(String where, InputMethodService service);

    /**
     * Starts a proto dump of the InputMethodManagerService information.
     *
     * @param where Place where the trace was triggered.
     */
    public abstract void triggerManagerServiceDump(String where);

    /**
     * Sets whether ime tracing is enabled.
     *
+30 −24
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.util.imetracing;

import android.inputmethodservice.InputMethodService;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.ShellCommand;
@@ -27,16 +28,12 @@ import android.view.inputmethod.InputMethodManager;
 * @hide
 */
class ImeTracingClientImpl extends ImeTracing {

    private boolean mDumpInProgress;
    private final Object mDumpInProgressLock = new Object();

    ImeTracingClientImpl() throws ServiceNotFoundException, RemoteException {
        sEnabled = mService.isImeTraceEnabled();
    }

    @Override
    public void addToBuffer(ProtoOutputStream proto) {
    public void addToBuffer(ProtoOutputStream proto, int source) {
    }

    @Override
@@ -45,27 +42,36 @@ class ImeTracingClientImpl extends ImeTracing {
    }

    @Override
    public void triggerDump() {
        if (isAvailable() && isEnabled()) {
            boolean doDump = false;
    public void triggerClientDump(String where) {
        if (!isEnabled() || !isAvailable()) {
            return;
        }

        synchronized (mDumpInProgressLock) {
                if (!mDumpInProgress) {
                    mDumpInProgress = true;
                    doDump = true;
            if (mDumpInProgress) {
                return;
            }
            mDumpInProgress = true;
        }

            if (doDump) {
        try {
            ProtoOutputStream proto = new ProtoOutputStream();
            InputMethodManager.dumpProto(proto);
                    mService.startProtoDump(proto.getBytes());
            sendToService(proto.getBytes(), IME_TRACING_FROM_CLIENT, where);
        } catch (RemoteException e) {
            Log.e(TAG, "Exception while sending ime-related client dump to server", e);
        } finally {
            mDumpInProgress = false;
        }
    }

    @Override
    public void triggerServiceDump(String where, InputMethodService service) {
        // TODO (b/154348613)
    }

    @Override
    public void triggerManagerServiceDump(String where) {
        // Intentionally left empty, this is implemented in ImeTracingServerImpl
    }
}
+47 −29
Original line number Diff line number Diff line
@@ -17,11 +17,11 @@
package android.util.imetracing;

import static android.os.Build.IS_USER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorTraceFileProto.MAGIC_NUMBER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorTraceFileProto.MAGIC_NUMBER_H;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorTraceFileProto.MAGIC_NUMBER_L;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto.MAGIC_NUMBER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto.MAGIC_NUMBER_H;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto.MAGIC_NUMBER_L;

import android.os.RemoteException;
import android.inputmethodservice.InputMethodService;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.ShellCommand;
import android.util.Log;
@@ -38,20 +38,23 @@ import java.io.PrintWriter;
 * @hide
 */
class ImeTracingServerImpl extends ImeTracing {
    private static final String TRACE_FILENAME = "/data/misc/wmtrace/ime_trace.pb";
    private static final String TRACE_DIRNAME = "/data/misc/wmtrace/";
    private static final String TRACE_FILENAME_CLIENTS = "ime_trace_clients.pb";
    private static final int BUFFER_CAPACITY = 4096 * 1024;

    // Needed for winscope to auto-detect the dump type. Explained further in
    // core.proto.android.view.inputmethod.inputmethodeditortrace.proto
    private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
    // core.proto.android.view.inputmethod.inputmethodeditortrace.proto. This magic number
    // corresponds to InputMethodClientsTraceFileProto.
    private static final long MAGIC_NUMBER_CLIENTS_VALUE =
            ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;

    private final TraceBuffer mBuffer;
    private final File mTraceFile;
    private final TraceBuffer mBufferClients;
    private final File mTraceFileClients;
    private final Object mEnabledLock = new Object();

    ImeTracingServerImpl() throws ServiceNotFoundException {
        mBuffer = new TraceBuffer<>(BUFFER_CAPACITY);
        mTraceFile = new File(TRACE_FILENAME);
        mBufferClients = new TraceBuffer<>(BUFFER_CAPACITY);
        mTraceFileClients = new File(TRACE_DIRNAME + TRACE_FILENAME_CLIENTS);
    }

    /**
@@ -60,9 +63,19 @@ class ImeTracingServerImpl extends ImeTracing {
     * @param proto dump to be added to the buffer
     */
    @Override
    public void addToBuffer(ProtoOutputStream proto) {
    public void addToBuffer(ProtoOutputStream proto, int source) {
        if (isAvailable() && isEnabled()) {
            mBuffer.add(proto);
            switch (source) {
                case IME_TRACING_FROM_CLIENT:
                    mBufferClients.add(proto);
                    return;
                case IME_TRACING_FROM_IMS:
                    // TODO (b/154348613)
                case IME_TRACING_FROM_IMMS:
                    // TODO (b/154348613)
                default:
                    // Source not recognised.
            }
        }
    }

@@ -93,21 +106,25 @@ class ImeTracingServerImpl extends ImeTracing {
    }

    @Override
    public void triggerDump() {
        if (isAvailable() && isEnabled()) {
            try {
                mService.startProtoDump(null);
            } catch (RemoteException e) {
                Log.e(TAG, "Exception while triggering proto dump", e);
    public void triggerClientDump(String where) {
        // Intentionally left empty, this is implemented in ImeTracingClientImpl
    }

    @Override
    public void triggerServiceDump(String where, InputMethodService service) {
        // Intentionally left empty, this is implemented in ImeTracingClientImpl
    }

    @Override
    public void triggerManagerServiceDump(String where) {
        // TODO (b/154348613)
    }

    private void writeTraceToFileLocked() {
    private void writeTracesToFilesLocked() {
        try {
            ProtoOutputStream proto = new ProtoOutputStream();
            proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
            mBuffer.writeTraceToFile(mTraceFile, proto);
            proto.write(MAGIC_NUMBER, MAGIC_NUMBER_CLIENTS_VALUE);
            mBufferClients.writeTraceToFile(mTraceFileClients, proto);
        } catch (IOException e) {
            Log.e(TAG, "Unable to write buffer to file", e);
        }
@@ -126,9 +143,9 @@ class ImeTracingServerImpl extends ImeTracing {
                return;
            }

            pw.println("Starting tracing to " + mTraceFile + ".");
            pw.println("Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS);
            sEnabled = true;
            mBuffer.resetBuffer();
            mBufferClients.resetBuffer();
        }
    }

@@ -145,10 +162,11 @@ class ImeTracingServerImpl extends ImeTracing {
                return;
            }

            pw.println("Stopping tracing and writing traces to " + mTraceFile + ".");
            pw.println("Stopping tracing and writing traces in " + TRACE_DIRNAME + ": "
                    + TRACE_FILENAME_CLIENTS);
            sEnabled = false;
            writeTraceToFileLocked();
            mBuffer.resetBuffer();
            writeTracesToFilesLocked();
            mBufferClients.resetBuffer();
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
                new Bounds(mHiddenInsets, mShownInsets));

        if ((mTypes & WindowInsets.Type.ime()) != 0) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl");
        }
    }

+8 −6
Original line number Diff line number Diff line
@@ -313,7 +313,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        @Override
        public void onReady(WindowInsetsAnimationController controller, int types) {
            if ((types & ime()) != 0) {
                ImeTracing.getInstance().triggerDump();
                ImeTracing.getInstance().triggerClientDump(
                        "InsetsController.InternalAnimationControlListener#onReady");
            }

            mController = controller;
@@ -832,7 +833,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            Log.d(TAG, "show(ime(), fromIme=" + fromIme + ")");
        }
        if (fromIme) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump("InsetsController#show");
            Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
            Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0);
        } else {
@@ -888,7 +889,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    void hide(@InsetsType int types, boolean fromIme) {
        if (fromIme) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump("InsetsController#hide");
            Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0);
        } else {
            Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
@@ -928,7 +929,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            return;
        }
        if (fromIme) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump(
                    "InsetsController#controlWindowInsetsAnimation");
        }

        controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs,
@@ -1335,7 +1337,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            @InsetsType int types, boolean animationFinished, @AnimationType int animationType,
            boolean fromIme) {
        if ((types & ime()) != 0) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly");
        }
        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
@@ -1350,7 +1352,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    private void showDirectly(@InsetsType int types, boolean fromIme) {
        if ((types & ime()) != 0) {
            ImeTracing.getInstance().triggerDump();
            ImeTracing.getInstance().triggerClientDump("InsetsController#showDirectly");
        }
        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
Loading