Loading core/java/android/view/InsetsController.java +10 −2 Original line number Diff line number Diff line Loading @@ -1262,10 +1262,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.getInputMethodManager(), null /* icProto */); } final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_USER, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROL_WINDOW_INSETS_ANIMATION, mHost.isHandlingPointerEvent() /* fromUser */); controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, interpolator, animationType, getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null /* statsToken */); false /* useInsetsAnimationThread */, statsToken); } private void controlAnimationUnchecked(@InsetsType int types, Loading Loading @@ -1567,7 +1570,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return; } final ImeTracker.Token statsToken = runner.getStatsToken(); if (shown) { if (runner.getAnimationType() == ANIMATION_TYPE_USER) { ImeTracker.forLogging().onUserFinished(statsToken, shown); } else if (shown) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW); ImeTracker.forLogging().onShown(statsToken); Loading Loading @@ -1838,6 +1843,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.pendingAnim", 0); mHost.dispatchWindowInsetsAnimationStart(animation, bounds); mStartingAnimation = true; if (runner.getAnimationType() == ANIMATION_TYPE_USER) { ImeTracker.forLogging().onDispatched(runner.getStatsToken()); } runner.setReadyDispatched(true); listener.onReady(runner, types); mStartingAnimation = false; Loading core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java +13 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,19 @@ final class IInputMethodManagerGlobalInvoker { } } /** @see com.android.server.inputmethod.ImeTrackerService#onDispatched */ static void onDispatched(@NonNull ImeTracker.Token statsToken) { final IImeTracker service = getImeTrackerService(); if (service == null) { return; } try { service.onDispatched(statsToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @see com.android.server.inputmethod.ImeTrackerService#hasPendingImeVisibilityRequests */ @AnyThread @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) Loading core/java/android/view/inputmethod/ImeTracker.java +79 −15 Original line number Diff line number Diff line Loading @@ -71,24 +71,40 @@ public interface ImeTracker { /** The type of the IME request. */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_SHOW, TYPE_HIDE TYPE_HIDE, TYPE_USER, }) @Retention(RetentionPolicy.SOURCE) @interface Type {} /** IME show request type. */ /** * IME show request type. * * @see android.view.InsetsController#ANIMATION_TYPE_SHOW */ int TYPE_SHOW = ImeProtoEnums.TYPE_SHOW; /** IME hide request type. */ /** * IME hide request type. * * @see android.view.InsetsController#ANIMATION_TYPE_HIDE */ int TYPE_HIDE = ImeProtoEnums.TYPE_HIDE; /** * IME user-controlled animation request type. * * @see android.view.InsetsController#ANIMATION_TYPE_USER */ int TYPE_USER = ImeProtoEnums.TYPE_USER; /** The status of the IME request. */ @IntDef(prefix = { "STATUS_" }, value = { STATUS_RUN, STATUS_CANCEL, STATUS_FAIL, STATUS_SUCCESS, STATUS_TIMEOUT STATUS_TIMEOUT, }) @Retention(RetentionPolicy.SOURCE) @interface Status {} Loading Loading @@ -117,7 +133,7 @@ public interface ImeTracker { @IntDef(prefix = { "ORIGIN_" }, value = { ORIGIN_CLIENT, ORIGIN_SERVER, ORIGIN_IME ORIGIN_IME, }) @Retention(RetentionPolicy.SOURCE) @interface Origin {} Loading Loading @@ -400,19 +416,35 @@ public interface ImeTracker { void onCancelled(@Nullable Token token, @Phase int phase); /** * Called when the IME show request is successful. * Called when the show IME request is successful. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onShown(@Nullable Token token); /** * Called when the IME hide request is successful. * Called when the hide IME request is successful. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onHidden(@Nullable Token token); /** * Called when the user-controlled IME request was dispatched to the requesting app. The * user animation can take an undetermined amount of time, so it shouldn't be tracked. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onDispatched(@Nullable Token token); /** * Called when the animation of the user-controlled IME request finished. * * @param token the token tracking the current IME request or {@code null} otherwise. * @param shown whether the end state of the animation was shown or hidden. */ void onUserFinished(@Nullable Token token, boolean shown); /** * Returns whether the current IME request was created due to a user interaction. This can * only be {@code true} when running on the view's UI thread. Loading Loading @@ -482,13 +514,6 @@ public interface ImeTracker { /** Whether the stack trace at the request call site should be logged. */ private boolean mLogStackTrace; private void reloadSystemProperties() { mLogProgress = SystemProperties.getBoolean( "persist.debug.imetracker", false); mLogStackTrace = SystemProperties.getBoolean( "persist.debug.imerequest.logstacktrace", false); } @NonNull @Override public Token onStart(@NonNull String component, int uid, @Type int type, @Origin int origin, Loading @@ -497,7 +522,7 @@ public interface ImeTracker { final var token = IInputMethodManagerGlobalInvoker.onStart(tag, uid, type, origin, reason, fromUser); Log.i(TAG, token.mTag + ": onRequest" + (type == TYPE_SHOW ? "Show" : "Hide") Log.i(TAG, token.mTag + ": " + getOnStartPrefix(type) + " at " + Debug.originToString(origin) + " reason " + InputMethodDebug.softInputDisplayReasonToString(reason) + " fromUser " + fromUser, Loading Loading @@ -552,6 +577,45 @@ public interface ImeTracker { Log.i(TAG, token.mTag + ": onHidden"); } @Override public void onDispatched(@Nullable Token token) { if (token == null) return; IInputMethodManagerGlobalInvoker.onDispatched(token); Log.i(TAG, token.mTag + ": onDispatched"); } @Override public void onUserFinished(@Nullable Token token, boolean shown) { if (token == null) return; // This is already sent to ImeTrackerService to mark it finished during onDispatched. Log.i(TAG, token.mTag + ": onUserFinished " + (shown ? "shown" : "hidden")); } /** * Gets the prefix string for {@link #onStart} based on the given request type. * * @param type request type for which to create the prefix string with. */ @NonNull private static String getOnStartPrefix(@Type int type) { return switch (type) { case TYPE_SHOW -> "onRequestShow"; case TYPE_HIDE -> "onRequestHide"; case TYPE_USER -> "onRequestUser"; default -> "onRequestUnknown"; }; } /** Reloads the system properties related to this class. */ private void reloadSystemProperties() { mLogProgress = SystemProperties.getBoolean( "persist.debug.imetracker", false); mLogStackTrace = SystemProperties.getBoolean( "persist.debug.imerequest.logstacktrace", false); } }; /** The singleton IME tracker instance for instrumenting jank metrics. */ Loading core/java/com/android/internal/inputmethod/IImeTracker.aidl +10 −2 Original line number Diff line number Diff line Loading @@ -64,19 +64,27 @@ interface IImeTracker { oneway void onCancelled(in ImeTracker.Token statsToken, int phase); /** * Called when the IME show request is successful. * Called when the show IME request is successful. * * @param statsToken the token tracking the current IME request. */ oneway void onShown(in ImeTracker.Token statsToken); /** * Called when the IME hide request is successful. * Called when the hide IME request is successful. * * @param statsToken the token tracking the current IME request. */ oneway void onHidden(in ImeTracker.Token statsToken); /** * Called when the user-controlled IME request was dispatched to the requesting app. The * user animation can take an undetermined amount of time, so it shouldn't be tracked. * * @param statsToken the token tracking the current IME request. */ oneway void onDispatched(in ImeTracker.Token statsToken); /** * Checks whether there are any pending IME visibility requests. * Loading core/java/com/android/internal/inputmethod/InputMethodDebug.java +2 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,8 @@ public final class InputMethodDebug { return "SHOW_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT"; case SoftInputShowHideReason.SHOW_SOFT_INPUT_IMM_DEPRECATION: return "SHOW_SOFT_INPUT_IMM_DEPRECATION"; case SoftInputShowHideReason.CONTROL_WINDOW_INSETS_ANIMATION: return "CONTROL_WINDOW_INSETS_ANIMATION"; default: return "Unknown=" + reason; } Loading Loading
core/java/android/view/InsetsController.java +10 −2 Original line number Diff line number Diff line Loading @@ -1262,10 +1262,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.getInputMethodManager(), null /* icProto */); } final var statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_USER, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROL_WINDOW_INSETS_ANIMATION, mHost.isHandlingPointerEvent() /* fromUser */); controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, interpolator, animationType, getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null /* statsToken */); false /* useInsetsAnimationThread */, statsToken); } private void controlAnimationUnchecked(@InsetsType int types, Loading Loading @@ -1567,7 +1570,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return; } final ImeTracker.Token statsToken = runner.getStatsToken(); if (shown) { if (runner.getAnimationType() == ANIMATION_TYPE_USER) { ImeTracker.forLogging().onUserFinished(statsToken, shown); } else if (shown) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW); ImeTracker.forLogging().onShown(statsToken); Loading Loading @@ -1838,6 +1843,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.pendingAnim", 0); mHost.dispatchWindowInsetsAnimationStart(animation, bounds); mStartingAnimation = true; if (runner.getAnimationType() == ANIMATION_TYPE_USER) { ImeTracker.forLogging().onDispatched(runner.getStatsToken()); } runner.setReadyDispatched(true); listener.onReady(runner, types); mStartingAnimation = false; Loading
core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java +13 −0 Original line number Diff line number Diff line Loading @@ -754,6 +754,19 @@ final class IInputMethodManagerGlobalInvoker { } } /** @see com.android.server.inputmethod.ImeTrackerService#onDispatched */ static void onDispatched(@NonNull ImeTracker.Token statsToken) { final IImeTracker service = getImeTrackerService(); if (service == null) { return; } try { service.onDispatched(statsToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @see com.android.server.inputmethod.ImeTrackerService#hasPendingImeVisibilityRequests */ @AnyThread @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD) Loading
core/java/android/view/inputmethod/ImeTracker.java +79 −15 Original line number Diff line number Diff line Loading @@ -71,24 +71,40 @@ public interface ImeTracker { /** The type of the IME request. */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_SHOW, TYPE_HIDE TYPE_HIDE, TYPE_USER, }) @Retention(RetentionPolicy.SOURCE) @interface Type {} /** IME show request type. */ /** * IME show request type. * * @see android.view.InsetsController#ANIMATION_TYPE_SHOW */ int TYPE_SHOW = ImeProtoEnums.TYPE_SHOW; /** IME hide request type. */ /** * IME hide request type. * * @see android.view.InsetsController#ANIMATION_TYPE_HIDE */ int TYPE_HIDE = ImeProtoEnums.TYPE_HIDE; /** * IME user-controlled animation request type. * * @see android.view.InsetsController#ANIMATION_TYPE_USER */ int TYPE_USER = ImeProtoEnums.TYPE_USER; /** The status of the IME request. */ @IntDef(prefix = { "STATUS_" }, value = { STATUS_RUN, STATUS_CANCEL, STATUS_FAIL, STATUS_SUCCESS, STATUS_TIMEOUT STATUS_TIMEOUT, }) @Retention(RetentionPolicy.SOURCE) @interface Status {} Loading Loading @@ -117,7 +133,7 @@ public interface ImeTracker { @IntDef(prefix = { "ORIGIN_" }, value = { ORIGIN_CLIENT, ORIGIN_SERVER, ORIGIN_IME ORIGIN_IME, }) @Retention(RetentionPolicy.SOURCE) @interface Origin {} Loading Loading @@ -400,19 +416,35 @@ public interface ImeTracker { void onCancelled(@Nullable Token token, @Phase int phase); /** * Called when the IME show request is successful. * Called when the show IME request is successful. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onShown(@Nullable Token token); /** * Called when the IME hide request is successful. * Called when the hide IME request is successful. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onHidden(@Nullable Token token); /** * Called when the user-controlled IME request was dispatched to the requesting app. The * user animation can take an undetermined amount of time, so it shouldn't be tracked. * * @param token the token tracking the current IME request or {@code null} otherwise. */ void onDispatched(@Nullable Token token); /** * Called when the animation of the user-controlled IME request finished. * * @param token the token tracking the current IME request or {@code null} otherwise. * @param shown whether the end state of the animation was shown or hidden. */ void onUserFinished(@Nullable Token token, boolean shown); /** * Returns whether the current IME request was created due to a user interaction. This can * only be {@code true} when running on the view's UI thread. Loading Loading @@ -482,13 +514,6 @@ public interface ImeTracker { /** Whether the stack trace at the request call site should be logged. */ private boolean mLogStackTrace; private void reloadSystemProperties() { mLogProgress = SystemProperties.getBoolean( "persist.debug.imetracker", false); mLogStackTrace = SystemProperties.getBoolean( "persist.debug.imerequest.logstacktrace", false); } @NonNull @Override public Token onStart(@NonNull String component, int uid, @Type int type, @Origin int origin, Loading @@ -497,7 +522,7 @@ public interface ImeTracker { final var token = IInputMethodManagerGlobalInvoker.onStart(tag, uid, type, origin, reason, fromUser); Log.i(TAG, token.mTag + ": onRequest" + (type == TYPE_SHOW ? "Show" : "Hide") Log.i(TAG, token.mTag + ": " + getOnStartPrefix(type) + " at " + Debug.originToString(origin) + " reason " + InputMethodDebug.softInputDisplayReasonToString(reason) + " fromUser " + fromUser, Loading Loading @@ -552,6 +577,45 @@ public interface ImeTracker { Log.i(TAG, token.mTag + ": onHidden"); } @Override public void onDispatched(@Nullable Token token) { if (token == null) return; IInputMethodManagerGlobalInvoker.onDispatched(token); Log.i(TAG, token.mTag + ": onDispatched"); } @Override public void onUserFinished(@Nullable Token token, boolean shown) { if (token == null) return; // This is already sent to ImeTrackerService to mark it finished during onDispatched. Log.i(TAG, token.mTag + ": onUserFinished " + (shown ? "shown" : "hidden")); } /** * Gets the prefix string for {@link #onStart} based on the given request type. * * @param type request type for which to create the prefix string with. */ @NonNull private static String getOnStartPrefix(@Type int type) { return switch (type) { case TYPE_SHOW -> "onRequestShow"; case TYPE_HIDE -> "onRequestHide"; case TYPE_USER -> "onRequestUser"; default -> "onRequestUnknown"; }; } /** Reloads the system properties related to this class. */ private void reloadSystemProperties() { mLogProgress = SystemProperties.getBoolean( "persist.debug.imetracker", false); mLogStackTrace = SystemProperties.getBoolean( "persist.debug.imerequest.logstacktrace", false); } }; /** The singleton IME tracker instance for instrumenting jank metrics. */ Loading
core/java/com/android/internal/inputmethod/IImeTracker.aidl +10 −2 Original line number Diff line number Diff line Loading @@ -64,19 +64,27 @@ interface IImeTracker { oneway void onCancelled(in ImeTracker.Token statsToken, int phase); /** * Called when the IME show request is successful. * Called when the show IME request is successful. * * @param statsToken the token tracking the current IME request. */ oneway void onShown(in ImeTracker.Token statsToken); /** * Called when the IME hide request is successful. * Called when the hide IME request is successful. * * @param statsToken the token tracking the current IME request. */ oneway void onHidden(in ImeTracker.Token statsToken); /** * Called when the user-controlled IME request was dispatched to the requesting app. The * user animation can take an undetermined amount of time, so it shouldn't be tracked. * * @param statsToken the token tracking the current IME request. */ oneway void onDispatched(in ImeTracker.Token statsToken); /** * Checks whether there are any pending IME visibility requests. * Loading
core/java/com/android/internal/inputmethod/InputMethodDebug.java +2 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,8 @@ public final class InputMethodDebug { return "SHOW_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT"; case SoftInputShowHideReason.SHOW_SOFT_INPUT_IMM_DEPRECATION: return "SHOW_SOFT_INPUT_IMM_DEPRECATION"; case SoftInputShowHideReason.CONTROL_WINDOW_INSETS_ANIMATION: return "CONTROL_WINDOW_INSETS_ANIMATION"; default: return "Unknown=" + reason; } Loading