From 5c61eefbafeec60522b1e3d51d0fa13361099159 Mon Sep 17 00:00:00 2001 From: Taran Singh Date: Tue, 3 Nov 2020 11:48:03 -0800 Subject: [PATCH] Measure baseline IMF latency (2/n) Add methods to trace. Refer to design doc in bug. Bug: 167947940 Test: atest ImePerfTests and also refer to README.md Change-Id: I423e4f3f9253707d9b6d3d5a2dee260f872b879f --- .../InputMethodService.java | 15 ++++ .../android/view/ImeInsetsSourceConsumer.java | 3 + core/java/android/view/InsetsController.java | 39 ++++++-- .../InputMethodManagerService.java | 89 ++++++++++++------- .../server/wm/ImeInsetsSourceProvider.java | 4 + .../server/wm/InsetsStateController.java | 4 + .../server/wm/WindowManagerService.java | 4 +- 7 files changed, 114 insertions(+), 44 deletions(-) diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 32a8c0af0c014..44640c44332ee 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -46,6 +46,7 @@ import static android.inputmethodservice.InputMethodServiceProto.STATUS_ICON; import static android.inputmethodservice.InputMethodServiceProto.TOKEN; import static android.inputmethodservice.InputMethodServiceProto.VIEWS_CREATED; import static android.inputmethodservice.InputMethodServiceProto.WINDOW_VISIBLE; +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsets.Type.navigationBars; @@ -80,6 +81,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.ResultReceiver; import android.os.SystemClock; +import android.os.Trace; import android.provider.Settings; import android.text.InputType; import android.text.Layout; @@ -645,7 +647,9 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void startInput(InputConnection ic, EditorInfo attribute) { if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.startInput"); doStartInput(ic, attribute, false); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } /** @@ -705,6 +709,8 @@ public class InputMethodService extends AbstractInputMethodService { return; } final boolean wasVisible = isInputViewShown(); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.hideSoftInput"); + applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */); mShowInputFlags = 0; mShowInputRequested = false; @@ -717,6 +723,7 @@ public class InputMethodService extends AbstractInputMethodService { : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } /** @@ -748,6 +755,13 @@ public class InputMethodService extends AbstractInputMethodService { + " Use requestShowSelf(int) itself"); return; } + + if (Trace.isEnabled()) { + Binder.enableTracing(); + } else { + Binder.disableTracing(); + } + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showSoftInput"); final boolean wasVisible = isInputViewShown(); if (dispatchOnShowInputRequested(flags, false)) { @@ -764,6 +778,7 @@ public class InputMethodService extends AbstractInputMethodService { : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } /** diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 5780d4f69f9eb..f4d5a7b695eba 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -16,6 +16,7 @@ package android.view; +import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER; import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL; import static android.view.InsetsController.AnimationType; @@ -24,6 +25,7 @@ import static android.view.InsetsState.ITYPE_IME; import android.annotation.Nullable; import android.inputmethodservice.InputMethodService; import android.os.IBinder; +import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl.Transaction; import android.view.inputmethod.InputMethodManager; @@ -105,6 +107,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override void notifyHidden() { getImm().notifyImeHidden(mController.getHost().getWindowToken()); + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } @Override diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index b5bf08443a6ce..fbee83389d8a2 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -16,6 +16,7 @@ package android.view; +import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.InsetsControllerProto.CONTROL; import static android.view.InsetsControllerProto.STATE; import static android.view.InsetsState.ITYPE_CAPTION_BAR; @@ -829,6 +830,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void show(@InsetsType int types, boolean fromIme) { if (fromIme) { ImeTracing.getInstance().triggerDump(); + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0); + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0); + } else { + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0); + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0); } // Handle pending request ready in case there was one set. if (fromIme && mPendingImeControlRequest != null) { @@ -880,6 +886,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation void hide(@InsetsType int types, boolean fromIme) { if (fromIme) { ImeTracing.getInstance().triggerDump(); + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0); + } else { + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } int typesReady = 0; final ArraySet internalTypes = InsetsState.toInternalType(types); @@ -989,6 +998,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation }); } updateRequestedVisibility(); + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0); return; } @@ -1014,11 +1024,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation cancellationSignal.setOnCancelListener(() -> { cancelAnimation(runner, true /* invokeCallback */); }); + } else { + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.pendingAnim", 0); } if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) { - showDirectly(types); + showDirectly(types, fromIme); } else { - hideDirectly(types, false /* animationFinished */, animationType); + hideDirectly(types, false /* animationFinished */, animationType, fromIme); } updateRequestedVisibility(); } @@ -1141,10 +1153,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation cancelAnimation(runner, false /* invokeCallback */); if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown); if (shown) { - showDirectly(runner.getTypes()); + showDirectly(runner.getTypes(), true /* fromIme */); } else { hideDirectly(runner.getTypes(), true /* animationFinished */, - runner.getAnimationType()); + runner.getAnimationType(), true /* fromIme */); } } @@ -1314,11 +1326,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */); - } private void hideDirectly( - @InsetsType int types, boolean animationFinished, @AnimationType int animationType) { + @InsetsType int types, boolean animationFinished, @AnimationType int animationType, + boolean fromIme) { if ((types & ime()) != 0) { ImeTracing.getInstance().triggerDump(); } @@ -1327,9 +1339,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType); } updateRequestedVisibility(); + + if (fromIme) { + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0); + } } - private void showDirectly(@InsetsType int types) { + private void showDirectly(@InsetsType int types, boolean fromIme) { if ((types & ime()) != 0) { ImeTracing.getInstance().triggerDump(); } @@ -1338,6 +1354,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */); } updateRequestedVisibility(); + + if (fromIme) { + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0); + } } /** @@ -1374,7 +1394,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (WARN) Log.w(TAG, "startAnimation canceled before preDraw"); return; } - Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, + Trace.asyncTraceBegin(TRACE_TAG_VIEW, "InsetsAnimation: " + WindowInsets.Type.toString(types), types); for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { RunningAnimation runningAnimation = mRunningAnimations.get(i); @@ -1382,6 +1402,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation runningAnimation.startDispatched = true; } } + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.pendingAnim", 0); mHost.dispatchWindowInsetsAnimationStart(animation, bounds); mStartingAnimation = true; controller.mReadyDispatched = true; @@ -1392,7 +1413,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void dispatchAnimationEnd(WindowInsetsAnimation animation) { - Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "InsetsAnimation: " + WindowInsets.Type.toString(animation.getTypeMask()), animation.getTypeMask()); mHost.dispatchWindowInsetsAnimationEnd(animation); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 9a60afb7be683..683a4b67cc635 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -15,6 +15,7 @@ package com.android.server.inputmethod; +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; import static android.server.inputmethod.InputMethodManagerServiceProto.BOUND_TO_METHOD; @@ -110,6 +111,7 @@ import android.os.ShellCallback; import android.os.ShellCommand; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; @@ -3106,6 +3108,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Override public boolean showSoftInput(IInputMethodClient client, IBinder windowToken, int flags, ResultReceiver resultReceiver) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput"); int uid = Binder.getCallingUid(); synchronized (mMethodMap) { if (!calledFromValidUserLocked()) { @@ -3133,6 +3136,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub SoftInputShowHideReason.SHOW_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } } } @@ -3225,6 +3229,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } final long ident = Binder.clearCallingIdentity(); try { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput"); if (mCurClient == null || client == null || mCurClient.client.asBinder() != client.asBinder()) { // We need to check if this is the current client with @@ -3248,6 +3253,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub SoftInputShowHideReason.HIDE_SOFT_INPUT); } finally { Binder.restoreCallingIdentity(ident); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } } } @@ -3310,43 +3316,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.e(TAG, "windowToken cannot be null."); return InputBindResult.NULL; } - final int callingUserId = UserHandle.getCallingUserId(); - final int userId; - if (attribute != null && attribute.targetInputMethodUser != null - && attribute.targetInputMethodUser.getIdentifier() != callingUserId) { - mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, - "Using EditorInfo.targetInputMethodUser requires INTERACT_ACROSS_USERS_FULL."); - userId = attribute.targetInputMethodUser.getIdentifier(); - if (!mUserManagerInternal.isUserRunning(userId)) { - // There is a chance that we hit here because of race condition. Let's just return - // an error code instead of crashing the caller process, which at least has - // INTERACT_ACROSS_USERS_FULL permission thus is likely to be an important process. - Slog.e(TAG, "User #" + userId + " is not running."); - return InputBindResult.INVALID_USER; + try { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, + "IMMS.startInputOrWindowGainedFocus"); + final int callingUserId = UserHandle.getCallingUserId(); + final int userId; + if (attribute != null && attribute.targetInputMethodUser != null + && attribute.targetInputMethodUser.getIdentifier() != callingUserId) { + mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "Using EditorInfo.targetInputMethodUser requires" + + " INTERACT_ACROSS_USERS_FULL."); + userId = attribute.targetInputMethodUser.getIdentifier(); + if (!mUserManagerInternal.isUserRunning(userId)) { + // There is a chance that we hit here because of race condition. Let's just + // return an error code instead of crashing the caller process, which at least + // has INTERACT_ACROSS_USERS_FULL permission thus is likely to be an important + // process. + Slog.e(TAG, "User #" + userId + " is not running."); + return InputBindResult.INVALID_USER; + } + } else { + userId = callingUserId; } - } else { - userId = callingUserId; - } - final InputBindResult result; - synchronized (mMethodMap) { - final long ident = Binder.clearCallingIdentity(); - try { - result = startInputOrWindowGainedFocusInternalLocked(startInputReason, client, - windowToken, startInputFlags, softInputMode, windowFlags, attribute, - inputContext, missingMethods, unverifiedTargetSdkVersion, userId); - } finally { - Binder.restoreCallingIdentity(ident); + final InputBindResult result; + synchronized (mMethodMap) { + final long ident = Binder.clearCallingIdentity(); + try { + result = startInputOrWindowGainedFocusInternalLocked(startInputReason, client, + windowToken, startInputFlags, softInputMode, windowFlags, attribute, + inputContext, missingMethods, unverifiedTargetSdkVersion, userId); + } finally { + Binder.restoreCallingIdentity(ident); + } } + if (result == null) { + // This must never happen, but just in case. + Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason=" + + InputMethodDebug.startInputReasonToString(startInputReason) + + " windowFlags=#" + Integer.toHexString(windowFlags) + + " editorInfo=" + attribute); + return InputBindResult.NULL; + } + + return result; + } finally { + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } - if (result == null) { - // This must never happen, but just in case. - Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason=" - + InputMethodDebug.startInputReasonToString(startInputReason) - + " windowFlags=#" + Integer.toHexString(windowFlags) - + " editorInfo=" + attribute); - return InputBindResult.NULL; - } - return result; } @NonNull @@ -4124,6 +4139,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility"); synchronized (mMethodMap) { if (!calledWithValidTokenLocked(token)) { return; @@ -4145,6 +4161,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mWindowManagerInternal.showImePostLayout(mShowRequestWindowMap.get(windowToken)); } } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) { @@ -4172,6 +4189,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread private void hideMySoftInput(@NonNull IBinder token, int flags) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput"); synchronized (mMethodMap) { if (!calledWithValidTokenLocked(token)) { return; @@ -4186,10 +4204,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Binder.restoreCallingIdentity(ident); } } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @BinderThread private void showMySoftInput(@NonNull IBinder token, int flags) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput"); synchronized (mMethodMap) { if (!calledWithValidTokenLocked(token)) { return; @@ -4202,6 +4222,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Binder.restoreCallingIdentity(ident); } } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } void setEnabledSessionInMainThread(SessionState session) { diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 0813b4f9efe0f..818d96ceb5a6a 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -16,11 +16,14 @@ package com.android.server.wm; +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; + import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import static com.android.server.wm.ImeInsetsSourceProviderProto.IME_TARGET_FROM_IME; import static com.android.server.wm.ImeInsetsSourceProviderProto.INSETS_SOURCE_PROVIDER; import static com.android.server.wm.ImeInsetsSourceProviderProto.IS_IME_LAYOUT_DRAWN; +import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; import android.view.WindowInsets; @@ -79,6 +82,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s", target.getWindow() != null ? target.getWindow().getName() : ""); target.showInsets(WindowInsets.Type.ime(), true /* fromIme */); + Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0); if (target != mImeTargetFromIme && mImeTargetFromIme != null) { ProtoLog.w(WM_DEBUG_IME, "showInsets(ime) was requested by different window: %s ", diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index e7f140f989ccb..773bf542e212e 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_CLIMATE_BAR; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; @@ -35,6 +36,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; +import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseArray; @@ -281,6 +283,7 @@ class InsetsStateController { * Called when a layout pass has occurred. */ void onPostLayout() { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ISC.onPostLayout"); for (int i = mProviders.size() - 1; i >= 0; i--) { mProviders.valueAt(i).onPostLayout(); } @@ -297,6 +300,7 @@ class InsetsStateController { } } winInsetsChanged.clear(); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } void onInsetsModified(InsetsControlTarget caller) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c806c94358cbe..7e2d0addadb35 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -197,7 +197,6 @@ import android.os.SystemService; import android.os.Trace; import android.os.UserHandle; import android.os.WorkSource; -import android.provider.DeviceConfig; import android.provider.Settings; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; @@ -7669,6 +7668,7 @@ public class WindowManagerService extends IWindowManager.Stub if (imeTarget == null) { return; } + Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0); final InsetsControlTarget controlTarget = imeTarget.getImeControlTarget(); imeTarget = controlTarget.getWindow(); // If InsetsControlTarget doesn't have a window, its using remoteControlTarget which @@ -7682,6 +7682,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void hideIme(IBinder imeTargetWindowToken, int displayId) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.hideIme"); synchronized (mGlobalLock) { WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); ProtoLog.d(WM_DEBUG_IME, "hideIme target: %s ", imeTarget); @@ -7702,6 +7703,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowInsets.Type.ime(), true /* fromIme */); } } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @Override