From ab1008480bcc2e400ab90745dee067c5c0b0f050 Mon Sep 17 00:00:00 2001 From: Ioana Stefan Date: Mon, 26 Oct 2020 17:09:41 +0000 Subject: [PATCH 1/4] 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 --- .../android/util/imetracing/ImeTracing.java | 45 +++++++++- .../util/imetracing/ImeTracingClientImpl.java | 54 ++++++----- .../util/imetracing/ImeTracingServerImpl.java | 76 ++++++++++------ .../view/InsetsAnimationControlImpl.java | 2 +- core/java/android/view/InsetsController.java | 14 +-- .../android/view/InsetsSourceConsumer.java | 3 +- core/java/android/view/ViewRootImpl.java | 8 +- .../view/inputmethod/InputMethodManager.java | 19 ++-- .../internal/view/IInputMethodManager.aidl | 2 +- .../inputmethod/inputmethodeditortrace.proto | 89 +++++++++++++++--- .../InputMethodManagerService.java | 90 ++++++------------- .../MultiClientInputMethodManagerService.java | 4 +- 12 files changed, 252 insertions(+), 154 deletions(-) diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java index 865d5608a40a1..5c155e20d0878 100644 --- a/core/java/android/util/imetracing/ImeTracing.java +++ b/core/java/android/util/imetracing/ImeTracing.java @@ -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. * diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java index e5d7d3380d021..8330572e60ff8 100644 --- a/core/java/android/util/imetracing/ImeTracingClientImpl.java +++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java @@ -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; - synchronized (mDumpInProgressLock) { - if (!mDumpInProgress) { - mDumpInProgress = true; - doDump = true; - } - } + public void triggerClientDump(String where) { + if (!isEnabled() || !isAvailable()) { + return; + } - if (doDump) { - try { - ProtoOutputStream proto = new ProtoOutputStream(); - InputMethodManager.dumpProto(proto); - mService.startProtoDump(proto.getBytes()); - } catch (RemoteException e) { - Log.e(TAG, "Exception while sending ime-related client dump to server", e); - } finally { - mDumpInProgress = false; - } + synchronized (mDumpInProgressLock) { + if (mDumpInProgress) { + return; } + mDumpInProgress = true; + } + + try { + ProtoOutputStream proto = new ProtoOutputStream(); + InputMethodManager.dumpProto(proto); + 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 + } } diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java index 350cf5721148a..a8c0f66f15f0b 100644 --- a/core/java/android/util/imetracing/ImeTracingServerImpl.java +++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java @@ -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 } - private void writeTraceToFileLocked() { + @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 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(); } } } diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 06ddf3c69f8e0..afe02f24d114e 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -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"); } } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index bcb3a36ebe2c6..ce970cea28548 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -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 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 internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index e4a24ebfe9e42..ed7aa83e33def 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -329,7 +329,8 @@ public class InsetsSourceConsumer { @VisibleForTesting(visibility = PACKAGE) public boolean notifyAnimationFinished() { if (mType == ITYPE_IME) { - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump( + "InsetsSourceConsumer#notifyAnimationFinished"); } if (mPendingFrame != null) { InsetsSource source = mState.getSource(mType); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index c0770063beea0..2493059c98294 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -79,8 +79,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.IME_FOCUS_CONTROLLER; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.INSETS_CONTROLLER; +import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER; +import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; import android.Manifest; import android.animation.LayoutTransition; @@ -9222,7 +9222,7 @@ public final class ViewRootImpl implements ViewParent, @Override public void showInsets(@InsetsType int types, boolean fromIme) { if (fromIme) { - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#showInsets"); } final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { @@ -9233,7 +9233,7 @@ public final class ViewRootImpl implements ViewParent, @Override public void hideInsets(@InsetsType int types, boolean fromIme) { if (fromIme) { - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#hideInsets"); } final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index f1cbd2533a5a3..4ba45779c8746 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -19,12 +19,12 @@ package android.view.inputmethod; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static android.util.imetracing.ImeTracing.PROTO_ARG; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.DISPLAY_ID; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.EDITOR_INFO; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.IME_INSETS_SOURCE_CONSUMER; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.INPUT_METHOD_MANAGER; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.VIEW_ROOT_IMPL; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientsProto.CLIENT; +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_METHOD_MANAGER; +import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.VIEW_ROOT_IMPL; +import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientsProto.CLIENT; import static android.view.inputmethod.InputMethodManagerProto.ACTIVE; import static android.view.inputmethod.InputMethodManagerProto.CUR_ID; import static android.view.inputmethod.InputMethodManagerProto.FULLSCREEN_MODE; @@ -576,7 +576,8 @@ public final class InputMethodManager { @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags) { final View servedView; - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump( + "InputMethodManager.DelegateImpl#startInput"); synchronized (mH) { mCurrentTextBoxAttribute = null; mCompletions = null; @@ -1662,7 +1663,7 @@ public final class InputMethodManager { * {@link #RESULT_HIDDEN}. */ public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) { - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput"); // Re-dispatch if there is a context mismatch. final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view); if (fallbackImm != null) { @@ -1770,7 +1771,7 @@ public final class InputMethodManager { */ public boolean hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver) { - ImeTracing.getInstance().triggerDump(); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow"); checkFocus(); synchronized (mH) { final View servedView = getServedViewLocked(); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 5a06273bb1739..844c56bd3529f 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -77,6 +77,6 @@ interface IInputMethodManager { void removeImeSurface(); /** Remove the IME surface. Requires passing the currently focused window. */ void removeImeSurfaceFromWindow(in IBinder windowToken); - void startProtoDump(in byte[] clientProtoDump); + void startProtoDump(in byte[] protoDump, int source, String where); boolean isImeTraceEnabled(); } diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto index 856d8da1a1ea8..11af832d62052 100644 --- a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto +++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto @@ -30,35 +30,36 @@ import "frameworks/base/core/proto/android/server/inputmethod/inputmethodmanager import "frameworks/base/core/proto/android/inputmethodservice/inputmethodservice.proto"; /** - * Represents a file full of input method editor trace entries. - * Encoded, it should start with 0x9 0x49 0x4d 0x45 0x54 0x52 0x41 0x43 0x45 (.IMETRACE), such + * Represents a file full of trace entries for clients that use InputMethod. + * Encoded, it should start with 0x9 0x49 0x4d 0x43 0x54 0x52 0x41 0x43 0x45 (.IMCTRACE), such * that they can be easily identified. */ -message InputMethodEditorTraceFileProto { +message InputMethodClientsTraceFileProto { /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L (this is needed because enums have to be 32 bits and there's no nice way to put 64bit constants into .proto files.) */ enum MagicNumber { INVALID = 0; - MAGIC_NUMBER_L = 0x54454d49; /* IMET (little-endian ASCII) */ + MAGIC_NUMBER_L = 0x54434d49; /* IMCT (little-endian ASCII) */ MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ } /* Must be the first field to allow winscope to auto-detect the dump type. Set to value in MagicNumber */ optional fixed64 magic_number = 1; - repeated InputMethodEditorProto entry = 2; + repeated InputMethodClientsTraceProto entry = 2; } -/* one input method editor dump entry. */ -message InputMethodEditorProto { - +/* One dump entry for clients that use InputMethod. */ +message InputMethodClientsTraceProto { /* required: elapsed realtime in nanos since boot of when this entry was logged */ optional fixed64 elapsed_realtime_nanos = 1; - optional ClientsProto clients = 2; - optional .android.inputmethodservice.InputMethodServiceProto input_method_service = 3; - optional .android.server.inputmethod.InputMethodManagerServiceProto input_method_manager_service = 4; + + /* where the trace originated */ + optional string where = 2; + + optional ClientsProto clients = 3; // this wrapper helps to simplify the dumping logic message ClientsProto { @@ -75,4 +76,70 @@ message InputMethodEditorProto { optional EditorInfoProto editor_info = 6; optional ImeFocusControllerProto ime_focus_controller = 7; } +} + +/** + * Represents a file full of InputMethodService trace entries. + * Encoded, it should start with 0x9 0x49 0x4d 0x53 0x54 0x52 0x41 0x43 0x45 (.IMSTRACE), such + * that they can be easily identified. + */ +message InputMethodServiceTraceFileProto { + + /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L + (this is needed because enums have to be 32 bits and there's no nice way to put 64bit + constants into .proto files.) */ + enum MagicNumber { + INVALID = 0; + MAGIC_NUMBER_L = 0x54534d49; /* IMST (little-endian ASCII) */ + MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ + } + + /* Must be the first field to allow winscope to auto-detect the dump type. Set to value + in MagicNumber */ + optional fixed64 magic_number = 1; + repeated InputMethodServiceTraceProto entry = 2; +} + +/* One dump entry for InputMethodService. */ +message InputMethodServiceTraceProto { + /* required: elapsed realtime in nanos since boot of when this entry was logged */ + optional fixed64 elapsed_realtime_nanos = 1; + + /* where the trace originated */ + optional string where = 2; + + optional .android.inputmethodservice.InputMethodServiceProto input_method_service = 3; +} + +/** + * Represents a file full of InputMethodManagerService trace entries. + * Encoded, it should start with 0x9 0x49 0x4d 0x4d 0x54 0x52 0x41 0x43 0x45 (.IMMTRACE), such + * that they can be easily identified. + */ +message InputMethodManagerServiceTraceFileProto { + + /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L + (this is needed because enums have to be 32 bits and there's no nice way to put 64bit + constants into .proto files.) */ + enum MagicNumber { + INVALID = 0; + MAGIC_NUMBER_L = 0x544d4d49; /* IMMT (little-endian ASCII) */ + MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ + } + + /* Must be the first field to allow winscope to auto-detect the dump type. Set to value + in MagicNumber */ + optional fixed64 magic_number = 1; + repeated InputMethodManagerServiceTraceProto entry = 2; +} + +/* One dump entry for InputMethodManagerService. */ +message InputMethodManagerServiceTraceProto { + /* required: elapsed realtime in nanos since boot of when this entry was logged */ + optional fixed64 elapsed_realtime_nanos = 1; + + /* where the trace originated */ + optional string where = 2; + + optional .android.server.inputmethod.InputMethodManagerServiceProto input_method_manager_service = 3; } \ No newline at end of file diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 6dd91e533a87a..ba6e673711878 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -42,11 +42,6 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_REQ import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_READY; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.CLIENTS; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ELAPSED_REALTIME_NANOS; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.INPUT_METHOD_MANAGER_SERVICE; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.INPUT_METHOD_SERVICE; -import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorTraceFileProto.ENTRY; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -97,7 +92,6 @@ import android.os.Binder; import android.os.Bundle; import android.os.Debug; import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.IInterface; import android.os.LocaleList; @@ -145,6 +139,8 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionInspector; import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags; import android.view.inputmethod.InputMethod; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; @@ -734,8 +730,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final IPackageManager mIPackageManager; private final String mSlotIme; - private HandlerThread mTracingThread; - /** * Registered {@link InputMethodListListener}. * This variable can be accessed from both of MainThread and BinderThread. @@ -1707,9 +1701,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSettings, context); mMenuController = new InputMethodMenuController(this); - - mTracingThread = new HandlerThread("android.tracing", Process.THREAD_PRIORITY_FOREGROUND); - mTracingThread.start(); } private void resetDefaultImeLocked(Context context) { @@ -4019,58 +4010,33 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override @GuardedBy("mMethodMap") - public void startProtoDump(byte[] clientProtoDump) { - mTracingThread.getThreadHandler().post(() -> { - if (!ImeTracing.getInstance().isAvailable() || !ImeTracing.getInstance().isEnabled()) { + public void startProtoDump(byte[] protoDump, int source, String where) { + if (protoDump == null) { + // Dump not triggered from IMMS, but no proto information provided. + return; + } + ImeTracing tracingInstance = ImeTracing.getInstance(); + if (!tracingInstance.isAvailable() || !tracingInstance.isEnabled()) { + return; + } + + ProtoOutputStream proto = new ProtoOutputStream(); + switch (source) { + case ImeTracing.IME_TRACING_FROM_CLIENT: + final long client_token = proto.start(InputMethodClientsTraceFileProto.ENTRY); + proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodClientsTraceProto.WHERE, where); + proto.write(InputMethodClientsTraceProto.CLIENTS, protoDump); + proto.end(client_token); + break; + case ImeTracing.IME_TRACING_FROM_IMS: + // TODO (b/154348613) + default: + // Dump triggered by a source not recognised. return; - } - if (clientProtoDump == null && mCurClient == null) { - return; - } - - ProtoOutputStream proto = new ProtoOutputStream(); - final long token = proto.start(ENTRY); - proto.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos()); - dumpDebug(proto, INPUT_METHOD_MANAGER_SERVICE); - - IBinder service = null; - synchronized (mMethodMap) { - if (mCurMethod != null) { - service = mCurMethod.asBinder(); - } - } - - if (service != null) { - try { - proto.write(INPUT_METHOD_SERVICE, - TransferPipe.dumpAsync(service, ImeTracing.PROTO_ARG)); - } catch (IOException | RemoteException e) { - Log.e(TAG, "Exception while collecting ime process dump", e); - } - } - - if (clientProtoDump != null) { - proto.write(CLIENTS, clientProtoDump); - } else { - IBinder client = null; - synchronized (mMethodMap) { - if (mCurClient != null && mCurClient.client != null) { - client = mCurClient.client.asBinder(); - } - } - - if (client != null) { - try { - proto.write(CLIENTS, - TransferPipe.dumpAsync(client, ImeTracing.PROTO_ARG)); - } catch (IOException | RemoteException e) { - Log.e(TAG, "Exception while collecting client side ime dump", e); - } - } - } - proto.end(token); - ImeTracing.getInstance().addToBuffer(proto); - }); + } + tracingInstance.addToBuffer(proto, source); } @BinderThread diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index a6ca25b0e6c12..7af27ca46f687 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -1808,12 +1808,12 @@ public final class MultiClientInputMethodManagerService { @BinderThread @Override - public void startProtoDump(byte[] clientProtoDump) throws RemoteException { + public void startProtoDump(byte[] clientProtoDump, int source, String where) { } @BinderThread @Override - public boolean isImeTraceEnabled() throws RemoteException { + public boolean isImeTraceEnabled() { return false; } } From 8418bef70abf31d3cbfcfa500b2e694988735557 Mon Sep 17 00:00:00 2001 From: Ioana Stefan Date: Tue, 27 Oct 2020 11:30:38 +0000 Subject: [PATCH 2/4] Optimized workflow for IME tracing on InputMethodService side Optimized the tracing logic for the IMS information. The InputMethodService triggers a tracing dump through the new method triggerServiceDump, exposed by the meTracing interface. This change was done to be able to support custom dumps from clients and custom dumps from InputMethodService. This change only covers the IMS information. The 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_service.pb ime_trace_service.pb" Change-Id: Icda0f82d76fb7db5b2bd8d021069b1ff15a4e15b --- .../AbstractInputMethodService.java | 9 ++-- .../IInputMethodWrapper.java | 17 +------ .../InputMethodService.java | 21 ++++++-- .../android/util/imetracing/ImeTracing.java | 4 +- .../util/imetracing/ImeTracingClientImpl.java | 25 ++++++++-- .../util/imetracing/ImeTracingServerImpl.java | 50 +++++++++++++------ .../InputMethodManagerService.java | 10 +++- 7 files changed, 92 insertions(+), 44 deletions(-) diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java index cd436374b489b..7cf0b10031acc 100644 --- a/core/java/android/inputmethodservice/AbstractInputMethodService.java +++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.app.Service; import android.content.Intent; import android.os.IBinder; +import android.util.proto.ProtoOutputStream; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.inputmethod.InputConnection; @@ -195,15 +196,13 @@ 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}. + * Dumps the internal state of IME to a protocol buffer output stream. * - * @param fd The file descriptor to which proto dump should be written. - * @param args The arguments passed to the dump method. + * @param proto ProtoOutputStream to dump data to. * @hide */ @SuppressWarnings("HiddenAbstractMethod") - abstract void dumpProtoInternal(FileDescriptor fd, String[] args); + public abstract void dumpProtoInternal(ProtoOutputStream proto); /** * Implement this to handle {@link android.os.Binder#dump Binder.dump()} diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 3d1755e9b0176..5cfcd667632b0 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -16,8 +16,6 @@ package android.inputmethodservice; -import static android.util.imetracing.ImeTracing.PROTO_ARG; - import android.annotation.BinderThread; import android.annotation.MainThread; import android.annotation.Nullable; @@ -157,20 +155,9 @@ 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 { - if (protoDumpRequested) { - target.dumpProtoInternal((FileDescriptor) args.arg1, dumpArgs); - } else { - target.dump((FileDescriptor) args.arg1, (PrintWriter) args.arg2, dumpArgs); - } + target.dump((FileDescriptor) args.arg1, + (PrintWriter) args.arg2, (String[]) args.arg3); } catch (RuntimeException e) { ((PrintWriter)args.arg2).println("Exception: " + e); } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 44640c44332ee..fe8f3d7edae0b 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -90,6 +90,7 @@ import android.text.method.MovementMethod; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.imetracing.ImeTracing; import android.util.proto.ProtoOutputStream; import android.view.Gravity; import android.view.KeyCharacterMap; @@ -116,6 +117,7 @@ import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.InputMethod; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceProto; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.FrameLayout; @@ -708,6 +710,8 @@ public class InputMethodService extends AbstractInputMethodService { + " Use requestHideSelf(int) itself"); return; } + ImeTracing.getInstance().triggerServiceDump( + "InputMethodService.InputMethodImpl#hideSoftInput", InputMethodService.this); final boolean wasVisible = isInputViewShown(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.hideSoftInput"); @@ -762,6 +766,8 @@ public class InputMethodService extends AbstractInputMethodService { Binder.disableTracing(); } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showSoftInput"); + ImeTracing.getInstance().triggerServiceDump( + "InputMethodService.InputMethodImpl#showSoftInput", InputMethodService.this); final boolean wasVisible = isInputViewShown(); if (dispatchOnShowInputRequested(flags, false)) { @@ -2138,6 +2144,8 @@ public class InputMethodService extends AbstractInputMethodService { return; } + ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", this); + mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; final int previousImeWindowStatus = @@ -2212,6 +2220,8 @@ public class InputMethodService extends AbstractInputMethodService { * @param setVisible {@code true} to make it visible, false to hide it. */ private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) { + ImeTracing.getInstance().triggerServiceDump( + "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", this); mPrivOps.applyImeVisibility(setVisible ? mCurShowInputToken : mCurHideInputToken, setVisible); } @@ -2236,6 +2246,7 @@ public class InputMethodService extends AbstractInputMethodService { public void hideWindow() { if (DEBUG) Log.v(TAG, "CALL: hideWindow"); + ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", this); mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { @@ -2306,6 +2317,7 @@ public class InputMethodService extends AbstractInputMethodService { void doFinishInput() { if (DEBUG) Log.v(TAG, "CALL: doFinishInput"); + ImeTracing.getInstance().triggerServiceDump("InputMethodService#doFinishInput", this); finishViews(true /* finishingInput */); if (mInputStarted) { mInlineSuggestionSessionController.notifyOnFinishInput(); @@ -2321,6 +2333,7 @@ public class InputMethodService extends AbstractInputMethodService { if (!restarting) { doFinishInput(); } + ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", this); mInputStarted = true; mStartedInputConnection = ic; mInputEditorInfo = attribute; @@ -2479,6 +2492,7 @@ public class InputMethodService extends AbstractInputMethodService { * @param flags Provides additional operating flags. */ public void requestHideSelf(int flags) { + ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", this); mPrivOps.hideMySoftInput(flags); } @@ -2491,6 +2505,7 @@ public class InputMethodService extends AbstractInputMethodService { * @param flags Provides additional operating flags. */ public final void requestShowSelf(int flags) { + ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestShowSelf", this); mPrivOps.showMySoftInput(flags); } @@ -3310,8 +3325,8 @@ public class InputMethodService extends AbstractInputMethodService { * @hide */ @Override - final void dumpProtoInternal(FileDescriptor fd, String[] args) { - final ProtoOutputStream proto = new ProtoOutputStream(fd); + public final void dumpProtoInternal(ProtoOutputStream proto) { + final long token = proto.start(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE); mWindow.dumpDebug(proto, SOFT_INPUT_WINDOW); proto.write(VIEWS_CREATED, mViewsCreated); proto.write(DECOR_VIEW_VISIBLE, mDecorViewVisible); @@ -3339,6 +3354,6 @@ public class InputMethodService extends AbstractInputMethodService { proto.write(STATUS_ICON, mStatusIcon); mTmpInsets.dumpDebug(proto, LAST_COMPUTED_INSETS); proto.write(SETTINGS_OBSERVER, Objects.toString(mSettingsObserver)); - proto.flush(); + proto.end(token); } } diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java index 5c155e20d0878..a43c87203e032 100644 --- a/core/java/android/util/imetracing/ImeTracing.java +++ b/core/java/android/util/imetracing/ImeTracing.java @@ -18,7 +18,7 @@ package android.util.imetracing; import android.app.ActivityThread; import android.content.Context; -import android.inputmethodservice.InputMethodService; +import android.inputmethodservice.AbstractInputMethodService; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; @@ -113,7 +113,7 @@ public abstract class ImeTracing { * * @param where Place where the trace was triggered. */ - public abstract void triggerServiceDump(String where, InputMethodService service); + public abstract void triggerServiceDump(String where, AbstractInputMethodService service); /** * Starts a proto dump of the InputMethodManagerService information. diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java index 8330572e60ff8..9c21f4dd39dfd 100644 --- a/core/java/android/util/imetracing/ImeTracingClientImpl.java +++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java @@ -16,7 +16,7 @@ package android.util.imetracing; -import android.inputmethodservice.InputMethodService; +import android.inputmethodservice.AbstractInputMethodService; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.os.ShellCommand; @@ -66,8 +66,27 @@ class ImeTracingClientImpl extends ImeTracing { } @Override - public void triggerServiceDump(String where, InputMethodService service) { - // TODO (b/154348613) + public void triggerServiceDump(String where, AbstractInputMethodService service) { + if (!isEnabled() || !isAvailable()) { + return; + } + + synchronized (mDumpInProgressLock) { + if (mDumpInProgress) { + return; + } + mDumpInProgress = true; + } + + try { + ProtoOutputStream proto = new ProtoOutputStream(); + service.dumpProtoInternal(proto); + sendToService(proto.getBytes(), IME_TRACING_FROM_IMS, where); + } catch (RemoteException e) { + Log.e(TAG, "Exception while sending ime-related service dump to server", e); + } finally { + mDumpInProgress = false; + } } @Override diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java index a8c0f66f15f0b..d2147f8e89f31 100644 --- a/core/java/android/util/imetracing/ImeTracingServerImpl.java +++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java @@ -17,15 +17,14 @@ package android.util.imetracing; import static android.os.Build.IS_USER; -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.inputmethodservice.InputMethodService; +import android.inputmethodservice.AbstractInputMethodService; import android.os.ServiceManager.ServiceNotFoundException; import android.os.ShellCommand; import android.util.Log; import android.util.proto.ProtoOutputStream; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceFileProto; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.TraceBuffer; @@ -40,25 +39,37 @@ import java.io.PrintWriter; class ImeTracingServerImpl extends ImeTracing { private static final String TRACE_DIRNAME = "/data/misc/wmtrace/"; private static final String TRACE_FILENAME_CLIENTS = "ime_trace_clients.pb"; + private static final String TRACE_FILENAME_IMS = "ime_trace_service.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. This magic number - // corresponds to InputMethodClientsTraceFileProto. + // 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; + ((long) InputMethodClientsTraceFileProto.MAGIC_NUMBER_H << 32) + | InputMethodClientsTraceFileProto.MAGIC_NUMBER_L; + // This magic number corresponds to InputMethodServiceTraceFileProto. + private static final long MAGIC_NUMBER_IMS_VALUE = + ((long) InputMethodServiceTraceFileProto.MAGIC_NUMBER_H << 32) + | InputMethodServiceTraceFileProto.MAGIC_NUMBER_L; private final TraceBuffer mBufferClients; private final File mTraceFileClients; + private final TraceBuffer mBufferIms; + private final File mTraceFileIms; + private final Object mEnabledLock = new Object(); ImeTracingServerImpl() throws ServiceNotFoundException { mBufferClients = new TraceBuffer<>(BUFFER_CAPACITY); mTraceFileClients = new File(TRACE_DIRNAME + TRACE_FILENAME_CLIENTS); + mBufferIms = new TraceBuffer<>(BUFFER_CAPACITY); + mTraceFileIms = new File(TRACE_DIRNAME + TRACE_FILENAME_IMS); } /** - * The provided dump is added to the current dump buffer {@link ImeTracingServerImpl#mBuffer}. + * The provided dump is added to the corresponding dump buffer: + * {@link ImeTracingServerImpl#mBufferClients} or {@link ImeTracingServerImpl#mBufferIms}. * * @param proto dump to be added to the buffer */ @@ -70,7 +81,8 @@ class ImeTracingServerImpl extends ImeTracing { mBufferClients.add(proto); return; case IME_TRACING_FROM_IMS: - // TODO (b/154348613) + mBufferIms.add(proto); + return; case IME_TRACING_FROM_IMMS: // TODO (b/154348613) default: @@ -111,7 +123,7 @@ class ImeTracingServerImpl extends ImeTracing { } @Override - public void triggerServiceDump(String where, InputMethodService service) { + public void triggerServiceDump(String where, AbstractInputMethodService service) { // Intentionally left empty, this is implemented in ImeTracingClientImpl } @@ -122,9 +134,14 @@ class ImeTracingServerImpl extends ImeTracing { private void writeTracesToFilesLocked() { try { - ProtoOutputStream proto = new ProtoOutputStream(); - proto.write(MAGIC_NUMBER, MAGIC_NUMBER_CLIENTS_VALUE); - mBufferClients.writeTraceToFile(mTraceFileClients, proto); + ProtoOutputStream clientsProto = new ProtoOutputStream(); + clientsProto.write(InputMethodClientsTraceFileProto.MAGIC_NUMBER, + MAGIC_NUMBER_CLIENTS_VALUE); + mBufferClients.writeTraceToFile(mTraceFileClients, clientsProto); + + ProtoOutputStream imsProto = new ProtoOutputStream(); + imsProto.write(InputMethodServiceTraceFileProto.MAGIC_NUMBER, MAGIC_NUMBER_IMS_VALUE); + mBufferIms.writeTraceToFile(mTraceFileIms, imsProto); } catch (IOException e) { Log.e(TAG, "Unable to write buffer to file", e); } @@ -143,9 +160,11 @@ class ImeTracingServerImpl extends ImeTracing { return; } - pw.println("Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS); + pw.println("Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS + + ", " + TRACE_FILENAME_IMS); sEnabled = true; mBufferClients.resetBuffer(); + mBufferIms.resetBuffer(); } } @@ -163,10 +182,11 @@ class ImeTracingServerImpl extends ImeTracing { } pw.println("Stopping tracing and writing traces in " + TRACE_DIRNAME + ": " - + TRACE_FILENAME_CLIENTS); + + TRACE_FILENAME_CLIENTS + ", " + TRACE_FILENAME_IMS); sEnabled = false; writeTracesToFilesLocked(); mBufferClients.resetBuffer(); + mBufferIms.resetBuffer(); } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index ba6e673711878..c08e6a9cd8abb 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -141,6 +141,8 @@ import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceFileProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceProto; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; @@ -4031,7 +4033,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub proto.end(client_token); break; case ImeTracing.IME_TRACING_FROM_IMS: - // TODO (b/154348613) + final long service_token = proto.start(InputMethodServiceTraceFileProto.ENTRY); + proto.write(InputMethodServiceTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodServiceTraceProto.WHERE, where); + proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump); + proto.end(service_token); + break; default: // Dump triggered by a source not recognised. return; From d7daa0bd6729039850123bd32b360d5d7ce17492 Mon Sep 17 00:00:00 2001 From: Ioana Stefan Date: Tue, 27 Oct 2020 14:55:36 +0000 Subject: [PATCH 3/4] Optimized workflow for IME tracing on InputMethodManagerService side Optimized the tracing logic for the IMMS information. The InputMethodManagerService triggers a tracing dump through the new method triggerManagerServiceDump, exposed by the ImeTracing interface. This change only covers the IMMS information. The clients and IMS information were added on previous 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_managerservice.pb ime_trace_managerservice.pb" Change-Id: Ia5fb8f47769ec8c6a1a24c18cd19952c0c550274 --- .../util/imetracing/ImeTracingServerImpl.java | 56 ++++++++++++++++--- .../InputMethodManagerService.java | 20 ++++++- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java index d2147f8e89f31..4d4fc231f86b2 100644 --- a/core/java/android/util/imetracing/ImeTracingServerImpl.java +++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java @@ -19,11 +19,13 @@ package android.util.imetracing; import static android.os.Build.IS_USER; import android.inputmethodservice.AbstractInputMethodService; +import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; import android.os.ShellCommand; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodManagerServiceTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceFileProto; import com.android.internal.annotations.GuardedBy; @@ -40,6 +42,7 @@ class ImeTracingServerImpl extends ImeTracing { private static final String TRACE_DIRNAME = "/data/misc/wmtrace/"; private static final String TRACE_FILENAME_CLIENTS = "ime_trace_clients.pb"; private static final String TRACE_FILENAME_IMS = "ime_trace_service.pb"; + private static final String TRACE_FILENAME_IMMS = "ime_trace_managerservice.pb"; private static final int BUFFER_CAPACITY = 4096 * 1024; // Needed for winscope to auto-detect the dump type. Explained further in @@ -52,11 +55,17 @@ class ImeTracingServerImpl extends ImeTracing { private static final long MAGIC_NUMBER_IMS_VALUE = ((long) InputMethodServiceTraceFileProto.MAGIC_NUMBER_H << 32) | InputMethodServiceTraceFileProto.MAGIC_NUMBER_L; + // This magic number corresponds to InputMethodManagerServiceTraceFileProto. + private static final long MAGIC_NUMBER_IMMS_VALUE = + ((long) InputMethodManagerServiceTraceFileProto.MAGIC_NUMBER_H << 32) + | InputMethodManagerServiceTraceFileProto.MAGIC_NUMBER_L; private final TraceBuffer mBufferClients; private final File mTraceFileClients; private final TraceBuffer mBufferIms; private final File mTraceFileIms; + private final TraceBuffer mBufferImms; + private final File mTraceFileImms; private final Object mEnabledLock = new Object(); @@ -65,6 +74,8 @@ class ImeTracingServerImpl extends ImeTracing { mTraceFileClients = new File(TRACE_DIRNAME + TRACE_FILENAME_CLIENTS); mBufferIms = new TraceBuffer<>(BUFFER_CAPACITY); mTraceFileIms = new File(TRACE_DIRNAME + TRACE_FILENAME_IMS); + mBufferImms = new TraceBuffer<>(BUFFER_CAPACITY); + mTraceFileImms = new File(TRACE_DIRNAME + TRACE_FILENAME_IMMS); } /** @@ -84,9 +95,11 @@ class ImeTracingServerImpl extends ImeTracing { mBufferIms.add(proto); return; case IME_TRACING_FROM_IMMS: - // TODO (b/154348613) + mBufferImms.add(proto); + return; default: // Source not recognised. + Log.w(TAG, "Request to add to buffer, but source not recognised."); } } } @@ -129,7 +142,24 @@ class ImeTracingServerImpl extends ImeTracing { @Override public void triggerManagerServiceDump(String where) { - // TODO (b/154348613) + if (!isEnabled() || !isAvailable()) { + return; + } + + synchronized (mDumpInProgressLock) { + if (mDumpInProgress) { + return; + } + mDumpInProgress = true; + } + + try { + sendToService(null, IME_TRACING_FROM_IMMS, where); + } catch (RemoteException e) { + Log.e(TAG, "Exception while sending ime-related manager service dump to server", e); + } finally { + mDumpInProgress = false; + } } private void writeTracesToFilesLocked() { @@ -142,6 +172,11 @@ class ImeTracingServerImpl extends ImeTracing { ProtoOutputStream imsProto = new ProtoOutputStream(); imsProto.write(InputMethodServiceTraceFileProto.MAGIC_NUMBER, MAGIC_NUMBER_IMS_VALUE); mBufferIms.writeTraceToFile(mTraceFileIms, imsProto); + + ProtoOutputStream immsProto = new ProtoOutputStream(); + immsProto.write(InputMethodManagerServiceTraceFileProto.MAGIC_NUMBER, + MAGIC_NUMBER_IMMS_VALUE); + mBufferImms.writeTraceToFile(mTraceFileImms, immsProto); } catch (IOException e) { Log.e(TAG, "Unable to write buffer to file", e); } @@ -161,10 +196,9 @@ class ImeTracingServerImpl extends ImeTracing { } pw.println("Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS - + ", " + TRACE_FILENAME_IMS); + + ", " + TRACE_FILENAME_IMS + ", " + TRACE_FILENAME_IMMS); sEnabled = true; - mBufferClients.resetBuffer(); - mBufferIms.resetBuffer(); + resetBuffers(); } } @@ -182,11 +216,17 @@ class ImeTracingServerImpl extends ImeTracing { } pw.println("Stopping tracing and writing traces in " + TRACE_DIRNAME + ": " - + TRACE_FILENAME_CLIENTS + ", " + TRACE_FILENAME_IMS); + + TRACE_FILENAME_CLIENTS + ", " + TRACE_FILENAME_IMS + ", " + + TRACE_FILENAME_IMMS); sEnabled = false; writeTracesToFilesLocked(); - mBufferClients.resetBuffer(); - mBufferIms.resetBuffer(); + resetBuffers(); } } + + private void resetBuffers() { + mBufferClients.resetBuffer(); + mBufferIms.resetBuffer(); + mBufferImms.resetBuffer(); + } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index c08e6a9cd8abb..30937208745a5 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -40,6 +40,7 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_FOR import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_IME_WITH_HARD_KEYBOARD; import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_REQUESTED; import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_READY; +import static android.util.imetracing.ImeTracing.IME_TRACING_FROM_IMMS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; @@ -141,6 +142,8 @@ import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodManagerServiceTraceFileProto; +import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodManagerServiceTraceProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceProto; import android.view.inputmethod.InputMethodInfo; @@ -3103,6 +3106,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub ResultReceiver resultReceiver) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput"); int uid = Binder.getCallingUid(); + ImeTracing.getInstance().triggerManagerServiceDump( + "InputMethodManagerService#showSoftInput"); synchronized (mMethodMap) { if (!calledFromValidUserLocked()) { return false; @@ -3216,6 +3221,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags, ResultReceiver resultReceiver) { int uid = Binder.getCallingUid(); + ImeTracing.getInstance().triggerManagerServiceDump( + "InputMethodManagerService#hideSoftInput"); synchronized (mMethodMap) { if (!calledFromValidUserLocked()) { return false; @@ -3312,6 +3319,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.startInputOrWindowGainedFocus"); + ImeTracing.getInstance().triggerManagerServiceDump( + "InputMethodManagerService#startInputOrWindowGainedFocus"); final int callingUserId = UserHandle.getCallingUserId(); final int userId; if (attribute != null && attribute.targetInputMethodUser != null @@ -4013,7 +4022,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override @GuardedBy("mMethodMap") public void startProtoDump(byte[] protoDump, int source, String where) { - if (protoDump == null) { + if (protoDump == null && source != IME_TRACING_FROM_IMMS) { // Dump not triggered from IMMS, but no proto information provided. return; } @@ -4040,6 +4049,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub proto.write(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE, protoDump); proto.end(service_token); break; + case IME_TRACING_FROM_IMMS: + final long managerservice_token = + proto.start(InputMethodManagerServiceTraceFileProto.ENTRY); + proto.write(InputMethodManagerServiceTraceProto.ELAPSED_REALTIME_NANOS, + SystemClock.elapsedRealtimeNanos()); + proto.write(InputMethodManagerServiceTraceProto.WHERE, where); + dumpDebug(proto, InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE); + proto.end(managerservice_token); + break; default: // Dump triggered by a source not recognised. return; From 45296595a3c1c969e4ee801303349cf9e8f03d36 Mon Sep 17 00:00:00 2001 From: Ioana Stefan Date: Thu, 12 Nov 2020 13:33:23 +0000 Subject: [PATCH 4/4] Log only current client data in IME tracing This change moves from dumping information of all Input Method client instances to dumping only the current client, which is the one in which the triggering event happened. Bug: 154348613 Test: flash a device start IME tracing by calling "adb shell ime tracing start" end IME tracing by calling "adb shell ime tracing stop" pull generated trace files and visualize in Winscope or start tracing directly through ADB Connect and visualize traces Change-Id: I46460d3d08947c7d37a8969a2fed6539f35aaf91 --- .../android/util/imetracing/ImeTracing.java | 4 ++- .../util/imetracing/ImeTracingClientImpl.java | 7 +++-- .../util/imetracing/ImeTracingServerImpl.java | 3 +- .../view/InsetsAnimationControlImpl.java | 5 ---- core/java/android/view/InsetsController.java | 29 ++++++++++++------- .../android/view/InsetsSourceConsumer.java | 6 ---- core/java/android/view/ViewRootImpl.java | 15 ++++++---- .../view/inputmethod/InputMethodManager.java | 25 ++++------------ .../inputmethod/inputmethodeditortrace.proto | 7 +---- .../InputMethodManagerService.java | 2 +- 10 files changed, 44 insertions(+), 59 deletions(-) diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java index a43c87203e032..4437191006431 100644 --- a/core/java/android/util/imetracing/ImeTracing.java +++ b/core/java/android/util/imetracing/ImeTracing.java @@ -25,6 +25,7 @@ import android.os.ServiceManager.ServiceNotFoundException; import android.os.ShellCommand; import android.util.Log; import android.util.proto.ProtoOutputStream; +import android.view.inputmethod.InputMethodManager; import com.android.internal.view.IInputMethodManager; @@ -105,8 +106,9 @@ public abstract class ImeTracing { * Starts a proto dump of the client side information. * * @param where Place where the trace was triggered. + * @param immInstance The {@link InputMethodManager} instance to dump. */ - public abstract void triggerClientDump(String where); + public abstract void triggerClientDump(String where, InputMethodManager immInstance); /** * Starts a proto dump of the currently connected InputMethodService information. diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java index 9c21f4dd39dfd..206006e794869 100644 --- a/core/java/android/util/imetracing/ImeTracingClientImpl.java +++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java @@ -16,6 +16,7 @@ package android.util.imetracing; +import android.annotation.NonNull; import android.inputmethodservice.AbstractInputMethodService; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; @@ -42,7 +43,7 @@ class ImeTracingClientImpl extends ImeTracing { } @Override - public void triggerClientDump(String where) { + public void triggerClientDump(String where, @NonNull InputMethodManager immInstance) { if (!isEnabled() || !isAvailable()) { return; } @@ -56,7 +57,7 @@ class ImeTracingClientImpl extends ImeTracing { try { ProtoOutputStream proto = new ProtoOutputStream(); - InputMethodManager.dumpProto(proto); + immInstance.dumpDebug(proto); sendToService(proto.getBytes(), IME_TRACING_FROM_CLIENT, where); } catch (RemoteException e) { Log.e(TAG, "Exception while sending ime-related client dump to server", e); @@ -66,7 +67,7 @@ class ImeTracingClientImpl extends ImeTracing { } @Override - public void triggerServiceDump(String where, AbstractInputMethodService service) { + public void triggerServiceDump(String where, @NonNull AbstractInputMethodService service) { if (!isEnabled() || !isAvailable()) { return; } diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java index 4d4fc231f86b2..04452b32d66da 100644 --- a/core/java/android/util/imetracing/ImeTracingServerImpl.java +++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java @@ -27,6 +27,7 @@ import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodManagerServiceTraceFileProto; import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceFileProto; +import android.view.inputmethod.InputMethodManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.TraceBuffer; @@ -131,7 +132,7 @@ class ImeTracingServerImpl extends ImeTracing { } @Override - public void triggerClientDump(String where) { + public void triggerClientDump(String where, InputMethodManager immInstance) { // Intentionally left empty, this is implemented in ImeTracingClientImpl } diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index afe02f24d114e..75dc0c43085d3 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -47,7 +47,6 @@ import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseSetArray; -import android.util.imetracing.ImeTracing; import android.util.proto.ProtoOutputStream; import android.view.InsetsState.InternalInsetsSide; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; @@ -136,10 +135,6 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mTranslator = translator; mController.startAnimation(this, listener, types, mAnimation, new Bounds(mHiddenInsets, mShownInsets)); - - if ((mTypes & WindowInsets.Type.ime()) != 0) { - ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl"); - } } private boolean calculatePerceptible(Insets currentInsets, float currentAlpha) { diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index ce970cea28548..1c82619a61ade 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -312,11 +312,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void onReady(WindowInsetsAnimationController controller, int types) { - if ((types & ime()) != 0) { - ImeTracing.getInstance().triggerClientDump( - "InsetsController.InternalAnimationControlListener#onReady"); - } - mController = controller; if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); @@ -833,7 +828,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation Log.d(TAG, "show(ime(), fromIme=" + fromIme + ")"); } if (fromIme) { - ImeTracing.getInstance().triggerClientDump("InsetsController#show"); + ImeTracing.getInstance().triggerClientDump("InsetsController#show", + mHost.getInputMethodManager()); Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0); Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0); } else { @@ -889,7 +885,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation void hide(@InsetsType int types, boolean fromIme) { if (fromIme) { - ImeTracing.getInstance().triggerClientDump("InsetsController#hide"); + ImeTracing.getInstance().triggerClientDump("InsetsController#hide", + mHost.getInputMethodManager()); Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0); } else { Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); @@ -930,7 +927,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (fromIme) { ImeTracing.getInstance().triggerClientDump( - "InsetsController#controlWindowInsetsAnimation"); + "InsetsController#controlWindowInsetsAnimation", + mHost.getInputMethodManager()); } controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, @@ -1022,6 +1020,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation : new InsetsAnimationControlImpl(controls, frame, mState, listener, typesReady, this, durationMs, interpolator, animationType, mHost.getTranslator()); + if ((typesReady & WindowInsets.Type.ime()) != 0) { + ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl", + mHost.getInputMethodManager()); + } mRunningAnimations.add(new RunningAnimation(runner, animationType)); if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: " + useInsetsAnimationThread); @@ -1195,6 +1197,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mRunningAnimations.remove(i); ArraySet types = toInternalType(control.getTypes()); for (int j = types.size() - 1; j >= 0; j--) { + if (types.valueAt(j) == ITYPE_IME) { + ImeTracing.getInstance().triggerClientDump( + "InsetsSourceConsumer#notifyAnimationFinished", + mHost.getInputMethodManager()); + } stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished(); } if (invokeCallback && runningAnimation.startDispatched) { @@ -1337,7 +1344,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @InsetsType int types, boolean animationFinished, @AnimationType int animationType, boolean fromIme) { if ((types & ime()) != 0) { - ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly"); + ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly", + mHost.getInputMethodManager()); } final ArraySet internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { @@ -1352,7 +1360,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private void showDirectly(@InsetsType int types, boolean fromIme) { if ((types & ime()) != 0) { - ImeTracing.getInstance().triggerClientDump("InsetsController#showDirectly"); + ImeTracing.getInstance().triggerClientDump("InsetsController#showDirectly", + mHost.getInputMethodManager()); } final ArraySet internalTypes = InsetsState.toInternalType(types); for (int i = internalTypes.size() - 1; i >= 0; i--) { diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index ed7aa83e33def..537fd42d71358 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -25,7 +25,6 @@ import static android.view.InsetsSourceConsumerProto.IS_REQUESTED_VISIBLE; import static android.view.InsetsSourceConsumerProto.PENDING_FRAME; import static android.view.InsetsSourceConsumerProto.PENDING_VISIBLE_FRAME; import static android.view.InsetsSourceConsumerProto.SOURCE_CONTROL; -import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.getDefaultVisibility; import static android.view.InsetsState.toPublicType; @@ -35,7 +34,6 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; import android.util.Log; -import android.util.imetracing.ImeTracing; import android.util.proto.ProtoOutputStream; import android.view.InsetsState.InternalInsetsType; import android.view.SurfaceControl.Transaction; @@ -328,10 +326,6 @@ public class InsetsSourceConsumer { @VisibleForTesting(visibility = PACKAGE) public boolean notifyAnimationFinished() { - if (mType == ITYPE_IME) { - ImeTracing.getInstance().triggerClientDump( - "InsetsSourceConsumer#notifyAnimationFinished"); - } if (mPendingFrame != null) { InsetsSource source = mState.getSource(mType); source.setFrame(mPendingFrame); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2493059c98294..33a1f228e2ad2 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -9221,10 +9221,11 @@ public final class ViewRootImpl implements ViewParent, @Override public void showInsets(@InsetsType int types, boolean fromIme) { - if (fromIme) { - ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#showInsets"); - } final ViewRootImpl viewAncestor = mViewAncestor.get(); + if (fromIme) { + ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#showInsets", + viewAncestor.getInsetsController().getHost().getInputMethodManager()); + } if (viewAncestor != null) { viewAncestor.showInsets(types, fromIme); } @@ -9232,10 +9233,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void hideInsets(@InsetsType int types, boolean fromIme) { - if (fromIme) { - ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#hideInsets"); - } + final ViewRootImpl viewAncestor = mViewAncestor.get(); + if (fromIme) { + ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#hideInsets", + viewAncestor.getInsetsController().getHost().getInputMethodManager()); + } if (viewAncestor != null) { viewAncestor.hideInsets(types, fromIme); } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 4ba45779c8746..3c89a4bfad59f 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -24,7 +24,6 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_INSETS_SOURCE_CONSUMER; 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.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientsProto.CLIENT; import static android.view.inputmethod.InputMethodManagerProto.ACTIVE; import static android.view.inputmethod.InputMethodManagerProto.CUR_ID; import static android.view.inputmethod.InputMethodManagerProto.FULLSCREEN_MODE; @@ -577,7 +576,7 @@ public final class InputMethodManager { int windowFlags) { final View servedView; ImeTracing.getInstance().triggerClientDump( - "InputMethodManager.DelegateImpl#startInput"); + "InputMethodManager.DelegateImpl#startInput", InputMethodManager.this); synchronized (mH) { mCurrentTextBoxAttribute = null; mCompletions = null; @@ -1663,7 +1662,7 @@ public final class InputMethodManager { * {@link #RESULT_HIDDEN}. */ public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) { - ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput"); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this); // Re-dispatch if there is a context mismatch. final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view); if (fallbackImm != null) { @@ -1771,7 +1770,8 @@ public final class InputMethodManager { */ public boolean hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver) { - ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow"); + ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow", + this); checkFocus(); synchronized (mH) { final View servedView = getServedViewLocked(); @@ -3241,7 +3241,7 @@ public final class InputMethodManager { for (String arg : args) { if (arg.equals(PROTO_ARG)) { final ProtoOutputStream proto = new ProtoOutputStream(fd); - dumpProto(proto); + dumpDebug(proto); proto.flush(); return true; } @@ -3249,19 +3249,6 @@ public final class InputMethodManager { return false; } - /** - * Write the proto dump for all displays associated with this client. - * - * @param proto The proto stream to which the dumps are written. - * @hide - */ - public static void dumpProto(ProtoOutputStream proto) { - for (int i = sInstanceMap.size() - 1; i >= 0; i--) { - InputMethodManager imm = sInstanceMap.valueAt(i); - imm.dumpDebug(proto); - } - } - /** * Write the proto dump of various client side components to the provided * {@link ProtoOutputStream}. @@ -3275,7 +3262,6 @@ public final class InputMethodManager { return; } - final long clientDumpToken = proto.start(CLIENT); proto.write(DISPLAY_ID, mDisplayId); final long token = proto.start(INPUT_METHOD_MANAGER); synchronized (mH) { @@ -3294,6 +3280,5 @@ public final class InputMethodManager { mImeInsetsConsumer.dumpDebug(proto, IME_INSETS_SOURCE_CONSUMER); } } - proto.end(clientDumpToken); } } diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto index 11af832d62052..5c0f341cb9e46 100644 --- a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto +++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto @@ -59,12 +59,7 @@ message InputMethodClientsTraceProto { /* where the trace originated */ optional string where = 2; - optional ClientsProto clients = 3; - - // this wrapper helps to simplify the dumping logic - message ClientsProto { - repeated ClientSideProto client = 1; - } + optional ClientSideProto client = 3; /* groups together the dump from ime related client side classes */ message ClientSideProto { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 30937208745a5..889061b71ee63 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4038,7 +4038,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub proto.write(InputMethodClientsTraceProto.ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos()); proto.write(InputMethodClientsTraceProto.WHERE, where); - proto.write(InputMethodClientsTraceProto.CLIENTS, protoDump); + proto.write(InputMethodClientsTraceProto.CLIENT, protoDump); proto.end(client_token); break; case ImeTracing.IME_TRACING_FROM_IMS: