From ac24994aaa5bd1f70608cb8c72b93b5ae00d90eb Mon Sep 17 00:00:00 2001 From: Ioana Stefan Date: Thu, 29 Oct 2020 16:49:47 +0000 Subject: [PATCH] IME tracing integration with bugreport IME tracing information is added to bugreport if tracing was previously enabled. IME tracing is reenabled after data is dumped in the bugreport. InputMethodManagerService state information is also dumped in proto format. Bug: 167948910, 154348613 Test: start trace by calling "adb shell ime tracing start" create a bugreport by calling "adb bugreport" check info in the bugreport zip file or upload to Winscope Change-Id: Ie87eb8423e2bb70f28c330983d45b95e2e07062d --- .../android/util/imetracing/ImeTracing.java | 39 +++++++++++++++++++ .../util/imetracing/ImeTracingClientImpl.java | 18 +++++++++ .../util/imetracing/ImeTracingServerImpl.java | 31 ++++++++++++--- .../InputMethodManagerService.java | 36 ++++++++++++++++- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java index 4437191006431..4058eef3e2a37 100644 --- a/core/java/android/util/imetracing/ImeTracing.java +++ b/core/java/android/util/imetracing/ImeTracing.java @@ -16,6 +16,7 @@ package android.util.imetracing; +import android.annotation.Nullable; import android.app.ActivityThread; import android.content.Context; import android.inputmethodservice.AbstractInputMethodService; @@ -29,6 +30,8 @@ import android.view.inputmethod.InputMethodManager; import com.android.internal.view.IInputMethodManager; +import java.io.PrintWriter; + /** * * An abstract class that declares the methods for ime trace related operations - enable trace, @@ -147,7 +150,43 @@ public abstract class ImeTracing { return mService != null; } + /** + * Writes the current tracing data to the specific output proto file. + */ + public abstract void writeTracesToFiles(); + + /** + * Starts a new IME trace if one is not already started. + * + * @param pw Print writer + */ + public abstract void startTrace(@Nullable PrintWriter pw); + + /** + * Stops the IME trace if one was previously started and writes the current buffers to disk. + * + * @param pw Print writer + */ + public abstract void stopTrace(@Nullable PrintWriter pw); + + /** + * Stops the IME trace if one was previously started. + * + * @param pw Print writer + * @param writeToFile If the current buffer should be written to disk or not + */ + public abstract void stopTrace(@Nullable PrintWriter pw, boolean writeToFile); + private static boolean isSystemProcess() { return ActivityThread.isSystem(); } + + protected void logAndPrintln(@Nullable PrintWriter pw, String msg) { + Log.i(TAG, msg); + if (pw != null) { + pw.println(msg); + pw.flush(); + } + } + } diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java index 206006e794869..904b44da97d74 100644 --- a/core/java/android/util/imetracing/ImeTracingClientImpl.java +++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java @@ -25,6 +25,8 @@ import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; +import java.io.PrintWriter; + /** * @hide */ @@ -94,4 +96,20 @@ class ImeTracingClientImpl extends ImeTracing { public void triggerManagerServiceDump(String where) { // Intentionally left empty, this is implemented in ImeTracingServerImpl } + + @Override + public void writeTracesToFiles() { + } + + @Override + public void startTrace(PrintWriter pw) { + } + + @Override + public void stopTrace(PrintWriter pw) { + } + + @Override + public void stopTrace(PrintWriter pw, boolean writeToFile) { + } } diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java index 04452b32d66da..d758d77fb2f26 100644 --- a/core/java/android/util/imetracing/ImeTracingServerImpl.java +++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java @@ -18,6 +18,7 @@ package android.util.imetracing; import static android.os.Build.IS_USER; +import android.annotation.Nullable; import android.inputmethodservice.AbstractInputMethodService; import android.os.RemoteException; import android.os.ServiceManager.ServiceNotFoundException; @@ -163,6 +164,14 @@ class ImeTracingServerImpl extends ImeTracing { } } + @GuardedBy("mEnabledLock") + @Override + public void writeTracesToFiles() { + synchronized (mEnabledLock) { + writeTracesToFilesLocked(); + } + } + private void writeTracesToFilesLocked() { try { ProtoOutputStream clientsProto = new ProtoOutputStream(); @@ -178,13 +187,16 @@ class ImeTracingServerImpl extends ImeTracing { immsProto.write(InputMethodManagerServiceTraceFileProto.MAGIC_NUMBER, MAGIC_NUMBER_IMMS_VALUE); mBufferImms.writeTraceToFile(mTraceFileImms, immsProto); + + resetBuffers(); } catch (IOException e) { Log.e(TAG, "Unable to write buffer to file", e); } } @GuardedBy("mEnabledLock") - private void startTrace(PrintWriter pw) { + @Override + public void startTrace(@Nullable PrintWriter pw) { if (IS_USER) { Log.w(TAG, "Warn: Tracing is not supported on user builds."); return; @@ -196,15 +208,21 @@ class ImeTracingServerImpl extends ImeTracing { return; } - pw.println("Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS + logAndPrintln(pw, "Starting tracing in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS + ", " + TRACE_FILENAME_IMS + ", " + TRACE_FILENAME_IMMS); sEnabled = true; resetBuffers(); } } + @Override + public void stopTrace(@Nullable PrintWriter pw) { + stopTrace(pw, true /* writeToFile */); + } + @GuardedBy("mEnabledLock") - private void stopTrace(PrintWriter pw) { + @Override + public void stopTrace(@Nullable PrintWriter pw, boolean writeToFile) { if (IS_USER) { Log.w(TAG, "Warn: Tracing is not supported on user builds."); return; @@ -216,12 +234,13 @@ class ImeTracingServerImpl extends ImeTracing { return; } - pw.println("Stopping tracing and writing traces in " + TRACE_DIRNAME + ": " + logAndPrintln(pw, "Stopping tracing and writing traces in " + TRACE_DIRNAME + ": " + TRACE_FILENAME_CLIENTS + ", " + TRACE_FILENAME_IMS + ", " + TRACE_FILENAME_IMMS); sEnabled = false; - writeTracesToFilesLocked(); - resetBuffers(); + if (writeToFile) { + writeTracesToFilesLocked(); + } } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 889061b71ee63..2d7f62d90914b 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -15,6 +15,8 @@ package com.android.server.inputmethod; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; +import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD; import static android.server.inputmethod.InputMethodManagerServiceProto.BACK_DISPOSITION; @@ -161,6 +163,7 @@ import com.android.internal.inputmethod.StartInputReason; import com.android.internal.inputmethod.UnbindReason; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.os.BackgroundThread; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; import com.android.internal.os.TransferPipe; @@ -208,6 +211,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub implements ServiceConnection, Handler.Callback { static final boolean DEBUG = false; static final String TAG = "InputMethodManagerService"; + public static final String PROTO_ARG = "--proto"; @Retention(SOURCE) @IntDef({ShellCommandResult.SUCCESS, ShellCommandResult.FAILURE}) @@ -1574,7 +1578,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public void onStart() { LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl(mService)); - publishBinderService(Context.INPUT_METHOD_SERVICE, mService); + publishBinderService(Context.INPUT_METHOD_SERVICE, mService, false /*allowIsolated*/, + DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); } @Override @@ -5094,8 +5099,37 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + boolean asProto = false; + for (int argIndex = 0; argIndex < args.length; argIndex++) { + if (args[argIndex].equals(PROTO_ARG)) { + asProto = true; + break; + } + } + + if (asProto) { + final ImeTracing imeTracing = ImeTracing.getInstance(); + if (imeTracing.isEnabled()) { + imeTracing.stopTrace(null, false /* writeToFile */); + BackgroundThread.getHandler().post(() -> { + imeTracing.writeTracesToFiles(); + imeTracing.startTrace(null); + }); + } + } + doDump(fd, pw, args, asProto); + } + + private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (useProto) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + dumpDebug(proto, InputMethodManagerServiceTraceProto.INPUT_METHOD_MANAGER_SERVICE); + proto.flush(); + return; + } + IInputMethod method; ClientState client; ClientState focusedWindowClient;