From 6c8bd65c605831b691cfedeeccaaed1f19725bf8 Mon Sep 17 00:00:00 2001 From: Pascal Muetschard <pmuetschard@google.com> Date: Tue, 21 Nov 2023 17:25:56 +0100 Subject: [PATCH] Some code cleanup of InteractionJankMonitor. - Move the CUJ constant related stuff to its own class - Remove the Session class - Separation of IJM and FT via event listener, breaking the dep loop - Fix (unlikely) race problems in begin/cancel/end - Trim out some unused stuff - Remove some duplicated stuff (like config validation) - Remove checks ensured by tests - Fix a bunch of warnings - Fix missing locks in debug overlay - Remove the outdated DEBUG mechanism Test: atest com.android.internal.jank Flag: NA Change-Id: I29b9da107313d4c07777ce50ce907c7516258807 --- .../android/view/inputmethod/ImeTracker.java | 6 +- core/java/com/android/internal/jank/Cuj.java | 503 ++++++++ .../android/internal/jank/FrameTracker.java | 151 +-- .../internal/jank/InteractionJankMonitor.java | 1112 ++++------------- .../jank/InteractionMonitorDebugOverlay.java | 87 +- .../com/android/internal/jank/CujTest.java | 156 +++ .../internal/jank/FrameTrackerTest.java | 128 +- .../jank/InteractionJankMonitorTest.java | 230 +--- .../wm/shell/back/BackAnimationRunner.java | 6 +- .../common/InteractionJankMonitorUtils.java | 17 +- .../OneHandedDisplayAreaOrganizer.java | 11 +- .../SettingsJankMonitorTest.java | 4 +- .../animation/DialogLaunchAnimator.kt | 2 +- .../GhostedViewLaunchAnimatorController.kt | 3 +- .../system/InteractionJankMonitorWrapper.java | 58 +- 15 files changed, 1171 insertions(+), 1303 deletions(-) create mode 100644 core/java/com/android/internal/jank/Cuj.java create mode 100644 core/tests/coretests/src/com/android/internal/jank/CujTest.java diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java index d4cfd63492fc..661815853470 100644 --- a/core/java/android/view/inputmethod/ImeTracker.java +++ b/core/java/android/view/inputmethod/ImeTracker.java @@ -20,8 +20,8 @@ import static android.view.InsetsController.ANIMATION_TYPE_HIDE; import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static com.android.internal.inputmethod.InputMethodDebug.softInputDisplayReasonToString; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_HIDE_ANIMATION; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_SHOW_ANIMATION; +import static com.android.internal.jank.Cuj.CUJ_IME_INSETS_HIDE_ANIMATION; +import static com.android.internal.jank.Cuj.CUJ_IME_INSETS_SHOW_ANIMATION; import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_HIDDEN; import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_SHOWN; @@ -758,7 +758,7 @@ public interface ImeTracker { * A helper method to translate animation type to CUJ type for IME animations. * * @param animType the animation type. - * @return the integer in {@link com.android.internal.jank.InteractionJankMonitor.CujType}, + * @return the integer in {@link com.android.internal.jank.Cuj.CujType}, * or {@code -1} if the animation type is not supported for tracking yet. */ private static int getImeInsetsCujFromAnimation(@AnimationType int animType) { diff --git a/core/java/com/android/internal/jank/Cuj.java b/core/java/com/android/internal/jank/Cuj.java new file mode 100644 index 000000000000..f460233f0edd --- /dev/null +++ b/core/java/com/android/internal/jank/Cuj.java @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.jank; + +import android.annotation.IntDef; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FrameworkStatsLog; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; + +/** @hide */ +public class Cuj { + @VisibleForTesting + public static final int MAX_LENGTH_OF_CUJ_NAME = 80; + + // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE. + public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0; + public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 2; + public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 3; + public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 4; + public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 5; + public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 6; + public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 7; + public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 8; + public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 9; + public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 10; + public static final int CUJ_LAUNCHER_QUICK_SWITCH = 11; + public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = 12; + public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = 13; + public static final int CUJ_NOTIFICATION_ADD = 14; + public static final int CUJ_NOTIFICATION_REMOVE = 15; + public static final int CUJ_NOTIFICATION_APP_START = 16; + public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = 17; + public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = 18; + public static final int CUJ_LOCKSCREEN_PIN_APPEAR = 19; + public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = 20; + public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = 21; + public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = 22; + public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = 23; + public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = 24; + public static final int CUJ_LAUNCHER_OPEN_ALL_APPS = 25; + public static final int CUJ_LAUNCHER_ALL_APPS_SCROLL = 26; + public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27; + public static final int CUJ_SETTINGS_PAGE_SCROLL = 28; + public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = 29; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = 30; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = 31; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = 32; + public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = 33; + public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = 34; + public static final int CUJ_PIP_TRANSITION = 35; + public static final int CUJ_WALLPAPER_TRANSITION = 36; + public static final int CUJ_USER_SWITCH = 37; + public static final int CUJ_SPLASHSCREEN_AVD = 38; + public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = 39; + public static final int CUJ_SCREEN_OFF = 40; + public static final int CUJ_SCREEN_OFF_SHOW_AOD = 41; + public static final int CUJ_ONE_HANDED_ENTER_TRANSITION = 42; + public static final int CUJ_ONE_HANDED_EXIT_TRANSITION = 43; + public static final int CUJ_UNFOLD_ANIM = 44; + public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = 45; + public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = 46; + public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = 47; + public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = 48; + public static final int CUJ_SPLIT_SCREEN_ENTER = 49; + public static final int CUJ_SPLIT_SCREEN_EXIT = 50; + public static final int CUJ_LOCKSCREEN_LAUNCH_CAMERA = 51; // reserved. + public static final int CUJ_SPLIT_SCREEN_RESIZE = 52; + public static final int CUJ_SETTINGS_SLIDER = 53; + public static final int CUJ_TAKE_SCREENSHOT = 54; + public static final int CUJ_VOLUME_CONTROL = 55; + public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = 56; + public static final int CUJ_SETTINGS_TOGGLE = 57; + public static final int CUJ_SHADE_DIALOG_OPEN = 58; + public static final int CUJ_USER_DIALOG_OPEN = 59; + public static final int CUJ_TASKBAR_EXPAND = 60; + public static final int CUJ_TASKBAR_COLLAPSE = 61; + public static final int CUJ_SHADE_CLEAR_ALL = 62; + public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION = 63; + public static final int CUJ_LOCKSCREEN_OCCLUSION = 64; + public static final int CUJ_RECENTS_SCROLLING = 65; + public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66; + public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67; + public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68; + public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70; + public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71; + // 72 - 77 are reserved for b/281564325. + + /** + * In some cases when we do not have any end-target, we play a simple slide-down animation. + * eg: Open an app from Overview/Task switcher such that there is no home-screen icon. + * eg: Exit the app using back gesture. + */ + public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78; + public static final int CUJ_IME_INSETS_SHOW_ANIMATION = 80; + public static final int CUJ_IME_INSETS_HIDE_ANIMATION = 81; + + public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82; + + public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83; + + public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = 84; + public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = 85; + public static final int CUJ_PREDICTIVE_BACK_HOME = 86; + + // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE. + @VisibleForTesting + static final int LAST_CUJ = CUJ_PREDICTIVE_BACK_HOME; + + /** @hide */ + @IntDef({ + CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, + CUJ_NOTIFICATION_SHADE_SCROLL_FLING, + CUJ_NOTIFICATION_SHADE_ROW_EXPAND, + CUJ_NOTIFICATION_SHADE_ROW_SWIPE, + CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, + CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, + CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS, + CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON, + CUJ_LAUNCHER_APP_CLOSE_TO_HOME, + CUJ_LAUNCHER_APP_CLOSE_TO_PIP, + CUJ_LAUNCHER_QUICK_SWITCH, + CUJ_NOTIFICATION_HEADS_UP_APPEAR, + CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, + CUJ_NOTIFICATION_ADD, + CUJ_NOTIFICATION_REMOVE, + CUJ_NOTIFICATION_APP_START, + CUJ_LOCKSCREEN_PASSWORD_APPEAR, + CUJ_LOCKSCREEN_PATTERN_APPEAR, + CUJ_LOCKSCREEN_PIN_APPEAR, + CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR, + CUJ_LOCKSCREEN_PATTERN_DISAPPEAR, + CUJ_LOCKSCREEN_PIN_DISAPPEAR, + CUJ_LOCKSCREEN_TRANSITION_FROM_AOD, + CUJ_LOCKSCREEN_TRANSITION_TO_AOD, + CUJ_LAUNCHER_OPEN_ALL_APPS, + CUJ_LAUNCHER_ALL_APPS_SCROLL, + CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET, + CUJ_SETTINGS_PAGE_SCROLL, + CUJ_LOCKSCREEN_UNLOCK_ANIMATION, + CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON, + CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER, + CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE, + CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON, + CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP, + CUJ_PIP_TRANSITION, + CUJ_WALLPAPER_TRANSITION, + CUJ_USER_SWITCH, + CUJ_SPLASHSCREEN_AVD, + CUJ_SPLASHSCREEN_EXIT_ANIM, + CUJ_SCREEN_OFF, + CUJ_SCREEN_OFF_SHOW_AOD, + CUJ_ONE_HANDED_ENTER_TRANSITION, + CUJ_ONE_HANDED_EXIT_TRANSITION, + CUJ_UNFOLD_ANIM, + CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS, + CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS, + CUJ_SUW_LOADING_TO_NEXT_FLOW, + CUJ_SUW_LOADING_SCREEN_FOR_STATUS, + CUJ_SPLIT_SCREEN_ENTER, + CUJ_SPLIT_SCREEN_EXIT, + CUJ_LOCKSCREEN_LAUNCH_CAMERA, + CUJ_SPLIT_SCREEN_RESIZE, + CUJ_SETTINGS_SLIDER, + CUJ_TAKE_SCREENSHOT, + CUJ_VOLUME_CONTROL, + CUJ_BIOMETRIC_PROMPT_TRANSITION, + CUJ_SETTINGS_TOGGLE, + CUJ_SHADE_DIALOG_OPEN, + CUJ_USER_DIALOG_OPEN, + CUJ_TASKBAR_EXPAND, + CUJ_TASKBAR_COLLAPSE, + CUJ_SHADE_CLEAR_ALL, + CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION, + CUJ_LOCKSCREEN_OCCLUSION, + CUJ_RECENTS_SCROLLING, + CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS, + CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE, + CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME, + CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION, + CUJ_LAUNCHER_OPEN_SEARCH_RESULT, + CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK, + CUJ_IME_INSETS_SHOW_ANIMATION, + CUJ_IME_INSETS_HIDE_ANIMATION, + CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER, + CUJ_LAUNCHER_UNFOLD_ANIM, + CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY, + CUJ_PREDICTIVE_BACK_CROSS_TASK, + CUJ_PREDICTIVE_BACK_HOME, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CujType { + } + + private static final int NO_STATSD_LOGGING = -1; + + // Used to convert CujType to InteractionType enum value for statsd logging. + // Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd. + private static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = new int[LAST_CUJ + 1]; + static { + Arrays.fill(CUJ_TO_STATSD_INTERACTION_TYPE, NO_STATSD_LOGGING); + + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_SCROLL_FLING] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_EXPAND] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_PIP] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_QUICK_SWITCH] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_ADD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_REMOVE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_APP_START] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_FROM_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_TO_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_ALL_APPS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_ALL_APPS_SCROLL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_PAGE_SCROLL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_UNLOCK_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PIP_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_SWITCH] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_AVD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_EXIT_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF_SHOW_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_ENTER_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_EXIT_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_UNFOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_NEXT_FLOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_SCREEN_FOR_STATUS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_ENTER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_EXIT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_LAUNCH_CAMERA] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_RESIZE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_SLIDER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TAKE_SCREENSHOT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_VOLUME_CONTROL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_BIOMETRIC_PROMPT_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_TOGGLE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_DIALOG_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_DIALOG_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_EXPAND] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_CLEAR_ALL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_OCCLUSION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_RECENTS_SCROLLING] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_TASK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK; + CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME; + } + + private Cuj() { + } + + /** + * A helper method to translate CUJ type to CUJ name. + * + * @param cujType the cuj type defined in this file + * @return the name of the cuj type + */ + public static String getNameOfCuj(int cujType) { + // Please note: + // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME. + // 2. The returned string should be the same with the name defined in atoms.proto. + switch (cujType) { + case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE: + return "NOTIFICATION_SHADE_EXPAND_COLLAPSE"; + case CUJ_NOTIFICATION_SHADE_SCROLL_FLING: + return "NOTIFICATION_SHADE_SCROLL_FLING"; + case CUJ_NOTIFICATION_SHADE_ROW_EXPAND: + return "NOTIFICATION_SHADE_ROW_EXPAND"; + case CUJ_NOTIFICATION_SHADE_ROW_SWIPE: + return "NOTIFICATION_SHADE_ROW_SWIPE"; + case CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE: + return "NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE"; + case CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE: + return "NOTIFICATION_SHADE_QS_SCROLL_SWIPE"; + case CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS: + return "LAUNCHER_APP_LAUNCH_FROM_RECENTS"; + case CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON: + return "LAUNCHER_APP_LAUNCH_FROM_ICON"; + case CUJ_LAUNCHER_APP_CLOSE_TO_HOME: + return "LAUNCHER_APP_CLOSE_TO_HOME"; + case CUJ_LAUNCHER_APP_CLOSE_TO_PIP: + return "LAUNCHER_APP_CLOSE_TO_PIP"; + case CUJ_LAUNCHER_QUICK_SWITCH: + return "LAUNCHER_QUICK_SWITCH"; + case CUJ_NOTIFICATION_HEADS_UP_APPEAR: + return "NOTIFICATION_HEADS_UP_APPEAR"; + case CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR: + return "NOTIFICATION_HEADS_UP_DISAPPEAR"; + case CUJ_NOTIFICATION_ADD: + return "NOTIFICATION_ADD"; + case CUJ_NOTIFICATION_REMOVE: + return "NOTIFICATION_REMOVE"; + case CUJ_NOTIFICATION_APP_START: + return "NOTIFICATION_APP_START"; + case CUJ_LOCKSCREEN_PASSWORD_APPEAR: + return "LOCKSCREEN_PASSWORD_APPEAR"; + case CUJ_LOCKSCREEN_PATTERN_APPEAR: + return "LOCKSCREEN_PATTERN_APPEAR"; + case CUJ_LOCKSCREEN_PIN_APPEAR: + return "LOCKSCREEN_PIN_APPEAR"; + case CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR: + return "LOCKSCREEN_PASSWORD_DISAPPEAR"; + case CUJ_LOCKSCREEN_PATTERN_DISAPPEAR: + return "LOCKSCREEN_PATTERN_DISAPPEAR"; + case CUJ_LOCKSCREEN_PIN_DISAPPEAR: + return "LOCKSCREEN_PIN_DISAPPEAR"; + case CUJ_LOCKSCREEN_TRANSITION_FROM_AOD: + return "LOCKSCREEN_TRANSITION_FROM_AOD"; + case CUJ_LOCKSCREEN_TRANSITION_TO_AOD: + return "LOCKSCREEN_TRANSITION_TO_AOD"; + case CUJ_LAUNCHER_OPEN_ALL_APPS : + return "LAUNCHER_OPEN_ALL_APPS"; + case CUJ_LAUNCHER_ALL_APPS_SCROLL: + return "LAUNCHER_ALL_APPS_SCROLL"; + case CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET: + return "LAUNCHER_APP_LAUNCH_FROM_WIDGET"; + case CUJ_SETTINGS_PAGE_SCROLL: + return "SETTINGS_PAGE_SCROLL"; + case CUJ_LOCKSCREEN_UNLOCK_ANIMATION: + return "LOCKSCREEN_UNLOCK_ANIMATION"; + case CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON: + return "SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON"; + case CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER: + return "SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER"; + case CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE: + return "SHADE_APP_LAUNCH_FROM_QS_TILE"; + case CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON: + return "SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON"; + case CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP: + return "STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP"; + case CUJ_PIP_TRANSITION: + return "PIP_TRANSITION"; + case CUJ_WALLPAPER_TRANSITION: + return "WALLPAPER_TRANSITION"; + case CUJ_USER_SWITCH: + return "USER_SWITCH"; + case CUJ_SPLASHSCREEN_AVD: + return "SPLASHSCREEN_AVD"; + case CUJ_SPLASHSCREEN_EXIT_ANIM: + return "SPLASHSCREEN_EXIT_ANIM"; + case CUJ_SCREEN_OFF: + return "SCREEN_OFF"; + case CUJ_SCREEN_OFF_SHOW_AOD: + return "SCREEN_OFF_SHOW_AOD"; + case CUJ_ONE_HANDED_ENTER_TRANSITION: + return "ONE_HANDED_ENTER_TRANSITION"; + case CUJ_ONE_HANDED_EXIT_TRANSITION: + return "ONE_HANDED_EXIT_TRANSITION"; + case CUJ_UNFOLD_ANIM: + return "UNFOLD_ANIM"; + case CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS: + return "SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS"; + case CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS: + return "SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS"; + case CUJ_SUW_LOADING_TO_NEXT_FLOW: + return "SUW_LOADING_TO_NEXT_FLOW"; + case CUJ_SUW_LOADING_SCREEN_FOR_STATUS: + return "SUW_LOADING_SCREEN_FOR_STATUS"; + case CUJ_SPLIT_SCREEN_ENTER: + return "SPLIT_SCREEN_ENTER"; + case CUJ_SPLIT_SCREEN_EXIT: + return "SPLIT_SCREEN_EXIT"; + case CUJ_LOCKSCREEN_LAUNCH_CAMERA: + return "LOCKSCREEN_LAUNCH_CAMERA"; + case CUJ_SPLIT_SCREEN_RESIZE: + return "SPLIT_SCREEN_RESIZE"; + case CUJ_SETTINGS_SLIDER: + return "SETTINGS_SLIDER"; + case CUJ_TAKE_SCREENSHOT: + return "TAKE_SCREENSHOT"; + case CUJ_VOLUME_CONTROL: + return "VOLUME_CONTROL"; + case CUJ_BIOMETRIC_PROMPT_TRANSITION: + return "BIOMETRIC_PROMPT_TRANSITION"; + case CUJ_SETTINGS_TOGGLE: + return "SETTINGS_TOGGLE"; + case CUJ_SHADE_DIALOG_OPEN: + return "SHADE_DIALOG_OPEN"; + case CUJ_USER_DIALOG_OPEN: + return "USER_DIALOG_OPEN"; + case CUJ_TASKBAR_EXPAND: + return "TASKBAR_EXPAND"; + case CUJ_TASKBAR_COLLAPSE: + return "TASKBAR_COLLAPSE"; + case CUJ_SHADE_CLEAR_ALL: + return "SHADE_CLEAR_ALL"; + case CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION: + return "LAUNCHER_UNLOCK_ENTRANCE_ANIMATION"; + case CUJ_LOCKSCREEN_OCCLUSION: + return "LOCKSCREEN_OCCLUSION"; + case CUJ_RECENTS_SCROLLING: + return "RECENTS_SCROLLING"; + case CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS: + return "LAUNCHER_APP_SWIPE_TO_RECENTS"; + case CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE: + return "LAUNCHER_CLOSE_ALL_APPS_SWIPE"; + case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME: + return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME"; + case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION: + return "LOCKSCREEN_CLOCK_MOVE_ANIMATION"; + case CUJ_LAUNCHER_OPEN_SEARCH_RESULT: + return "LAUNCHER_OPEN_SEARCH_RESULT"; + case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK: + return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK"; + case CUJ_IME_INSETS_SHOW_ANIMATION: + return "IME_INSETS_SHOW_ANIMATION"; + case CUJ_IME_INSETS_HIDE_ANIMATION: + return "IME_INSETS_HIDE_ANIMATION"; + case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER: + return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER"; + case CUJ_LAUNCHER_UNFOLD_ANIM: + return "LAUNCHER_UNFOLD_ANIM"; + case CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY: + return "PREDICTIVE_BACK_CROSS_ACTIVITY"; + case CUJ_PREDICTIVE_BACK_CROSS_TASK: + return "PREDICTIVE_BACK_CROSS_TASK"; + case CUJ_PREDICTIVE_BACK_HOME: + return "PREDICTIVE_BACK_HOME"; + } + return "UNKNOWN"; + } + + public static int getStatsdInteractionType(@CujType int cujType) { + return CUJ_TO_STATSD_INTERACTION_TYPE[cujType]; + } + + /** Returns whether the measurements for the given CUJ should be written to statsd. */ + public static boolean logToStatsd(@CujType int cujType) { + return getStatsdInteractionType(cujType) != NO_STATSD_LOGGING; + } + + /** + * A helper method to translate interaction type to CUJ name. + * + * @param interactionType the interaction type defined in AtomsProto.java + * @return the name of the interaction type + */ + public static String getNameOfInteraction(int interactionType) { + // There is an offset amount of 1 between cujType and interactionType. + return Cuj.getNameOfCuj(getCujTypeFromInteraction(interactionType)); + } + + /** + * A helper method to translate interaction type to CUJ type. + * + * @param interactionType the interaction type defined in AtomsProto.java + * @return the integer in {@link Cuj.CujType} + */ + private static int getCujTypeFromInteraction(int interactionType) { + return interactionType - 1; + } +} diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java index c83452d88290..86729f74cd85 100644 --- a/core/java/com/android/internal/jank/FrameTracker.java +++ b/core/java/com/android/internal/jank/FrameTracker.java @@ -53,7 +53,6 @@ import android.view.WindowCallbacks; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.DisplayRefreshRate.RefreshRate; import com.android.internal.jank.InteractionJankMonitor.Configuration; -import com.android.internal.jank.InteractionJankMonitor.Session; import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; @@ -67,7 +66,6 @@ import java.util.concurrent.TimeUnit; public class FrameTracker extends SurfaceControl.OnJankDataListener implements HardwareRendererObserver.OnFrameMetricsAvailableListener { private static final String TAG = "FrameTracker"; - private static final boolean DEBUG = false; private static final long INVALID_ID = -1; public static final int NANOS_IN_MILLISECOND = 1_000_000; @@ -93,20 +91,19 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener REASON_CANCEL_NORMAL, REASON_CANCEL_NOT_BEGUN, REASON_CANCEL_SAME_VSYNC, + REASON_CANCEL_TIMEOUT, }) @Retention(RetentionPolicy.SOURCE) public @interface Reasons { } - @VisibleForTesting - public final InteractionJankMonitor mMonitor; private final HardwareRendererObserver mObserver; private final int mTraceThresholdMissedFrames; private final int mTraceThresholdFrameTimeMillis; private final ThreadedRendererWrapper mRendererWrapper; private final FrameMetricsWrapper mMetricsWrapper; private final SparseArray<JankInfo> mJankInfos = new SparseArray<>(); - private final Session mSession; + private final Configuration mConfig; private final ViewRootWrapper mViewRoot; private final SurfaceControlWrapper mSurfaceControlWrapper; private final int mDisplayId; @@ -197,19 +194,18 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } - public FrameTracker(@NonNull InteractionJankMonitor monitor, @NonNull Session session, - @NonNull Handler handler, @Nullable ThreadedRendererWrapper renderer, + public FrameTracker(@NonNull Configuration config, + @Nullable ThreadedRendererWrapper renderer, @Nullable ViewRootWrapper viewRootWrapper, @NonNull SurfaceControlWrapper surfaceControlWrapper, @NonNull ChoreographerWrapper choreographer, @Nullable FrameMetricsWrapper metrics, @NonNull StatsLogWrapper statsLog, int traceThresholdMissedFrames, int traceThresholdFrameTimeMillis, - @Nullable FrameTrackerListener listener, @NonNull Configuration config) { - mMonitor = monitor; + @Nullable FrameTrackerListener listener) { mSurfaceOnly = config.isSurfaceOnly(); - mSession = session; - mHandler = handler; + mConfig = config; + mHandler = config.getHandler(); mChoreographer = choreographer; mSurfaceControlWrapper = surfaceControlWrapper; mStatsLog = statsLog; @@ -222,7 +218,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mObserver = mSurfaceOnly ? null : new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), - handler, /* waitForPresentTime= */ false); + mHandler, /* waitForPresentTime= */ false); mTraceThresholdMissedFrames = traceThresholdMissedFrames; mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis; @@ -242,7 +238,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() { @Override public void surfaceCreated(SurfaceControl.Transaction t) { - getHandler().runWithScissors(() -> { + mHandler.runWithScissors(() -> { if (mSurfaceControl == null) { mSurfaceControl = mViewRoot.getSurfaceControl(); if (mBeginVsyncId != INVALID_ID) { @@ -262,13 +258,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener // Wait a while to give the system a chance for the remaining // frames to arrive, then force finish the session. - getHandler().postDelayed(() -> { - if (DEBUG) { - Log.d(TAG, "surfaceDestroyed: " + mSession.getName() - + ", finalized=" + mMetricsFinalized - + ", info=" + mJankInfos.size() - + ", vsync=" + mBeginVsyncId); - } + mHandler.postDelayed(() -> { if (!mMetricsFinalized) { end(REASON_END_SURFACE_DESTROYED); finish(); @@ -282,11 +272,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public Handler getHandler() { - return mHandler; - } - /** * Begin a trace session of the CUJ. */ @@ -300,10 +285,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mBeginVsyncId = mDeferMonitoring ? currentVsync + 1 : currentVsync; } if (mSurfaceControl != null) { - if (DEBUG) { - Log.d(TAG, "begin: " + mSession.getName() + ", begin=" + mBeginVsyncId - + ", defer=" + mDeferMonitoring + ", current=" + currentVsync); - } if (mDeferMonitoring && currentVsync < mBeginVsyncId) { markEvent("FT#deferMonitoring", 0); // Normal case, we begin the instrument from the very beginning, @@ -314,11 +295,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener // there is no need to skip the frame where the begin invocation happens. beginInternal(); } - } else { - if (DEBUG) { - Log.d(TAG, "begin: defer beginning since the surface is not ready for CUJ=" - + mSession.getName()); - } } } @@ -336,8 +312,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener return; } mTracingStarted = true; - Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, mSession.getName(), mSession.getName(), - (int) mBeginVsyncId); + String name = mConfig.getSessionName(); + Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, name, name, (int) mBeginVsyncId); markEvent("FT#beginVsync", mBeginVsyncId); markEvent("FT#layerId", mSurfaceControl.getLayerId()); mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl); @@ -361,15 +337,10 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } else if (mEndVsyncId <= mBeginVsyncId) { return cancel(REASON_CANCEL_SAME_VSYNC); } else { - if (DEBUG) { - Log.d(TAG, "end: " + mSession.getName() - + ", end=" + mEndVsyncId + ", reason=" + reason); - } + final String name = mConfig.getSessionName(); markEvent("FT#end", reason); markEvent("FT#endVsync", mEndVsyncId); - Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, mSession.getName(), - (int) mBeginVsyncId); - mSession.setReason(reason); + Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, name, (int) mBeginVsyncId); // We don't remove observer here, // will remove it when all the frame metrics in this duration are called back. @@ -395,16 +366,16 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mFlushAttempts++; } else { mWaitForFinishTimedOut = () -> { - Log.e(TAG, "force finish cuj, time out: " + mSession.getName()); + Log.e(TAG, "force finish cuj, time out: " + name); finish(); }; delay = TimeUnit.SECONDS.toMillis(10); } - getHandler().postDelayed(mWaitForFinishTimedOut, delay); + mHandler.postDelayed(mWaitForFinishTimedOut, delay); } }; - getHandler().postDelayed(mWaitForFinishTimedOut, FLUSH_DELAY_MILLISECOND); - notifyCujEvent(ACTION_SESSION_END); + mHandler.postDelayed(mWaitForFinishTimedOut, FLUSH_DELAY_MILLISECOND); + notifyCujEvent(ACTION_SESSION_END, reason); return true; } } @@ -421,22 +392,16 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener markEvent("FT#cancel", reason); // We don't need to end the trace section if it has never begun. if (mTracingStarted) { - Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, mSession.getName(), - (int) mBeginVsyncId); + Trace.asyncTraceForTrackEnd( + Trace.TRACE_TAG_APP, mConfig.getSessionName(), (int) mBeginVsyncId); } // Always remove the observers in cancel call to avoid leakage. removeObservers(); - if (DEBUG) { - Log.d(TAG, "cancel: " + mSession.getName() + ", begin=" + mBeginVsyncId - + ", end=" + mEndVsyncId + ", reason=" + reason); - } - - mSession.setReason(reason); // Notify the listener the session has been cancelled. // We don't notify the listeners if the session never begun. - notifyCujEvent(ACTION_SESSION_CANCEL); + notifyCujEvent(ACTION_SESSION_CANCEL, reason); return true; } @@ -455,13 +420,13 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener "The length of the trace event description <%s> exceeds %d", event, MAX_LENGTH_EVENT_DESC)); } - Trace.instantForTrack(Trace.TRACE_TAG_APP, mSession.getName(), event); + Trace.instantForTrack(Trace.TRACE_TAG_APP, mConfig.getSessionName(), event); } } - private void notifyCujEvent(String action) { + private void notifyCujEvent(String action, @Reasons int reason) { if (mListener == null) return; - mListener.onCujEvents(mSession, action); + mListener.onCujEvents(this, action, reason); } @Override @@ -496,7 +461,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener */ @VisibleForTesting public void postCallback(Runnable callback) { - getHandler().post(callback); + mHandler.post(callback); } @Nullable @@ -587,13 +552,15 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (mMetricsFinalized || mCancelled) return; mMetricsFinalized = true; - getHandler().removeCallbacks(mWaitForFinishTimedOut); + mHandler.removeCallbacks(mWaitForFinishTimedOut); mWaitForFinishTimedOut = null; markEvent("FT#finish", mJankInfos.size()); // The tracing has been ended, remove the observer, see if need to trigger perfetto. removeObservers(); + final String name = mConfig.getSessionName(); + int totalFramesCount = 0; long maxFrameTimeNanos = 0; int missedFramesCount = 0; @@ -616,7 +583,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener totalFramesCount++; boolean missedFrame = false; if ((info.jankType & JANK_APP_DEADLINE_MISSED) != 0) { - Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + mSession.getName()); + Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name); missedAppFramesCount++; missedFrame = true; } @@ -625,7 +592,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener || (info.jankType & JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED) != 0 || (info.jankType & SURFACE_FLINGER_SCHEDULING) != 0 || (info.jankType & PREDICTION_ERROR) != 0) { - Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + mSession.getName()); + Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name); missedSfFramesCount++; missedFrame = true; } @@ -646,7 +613,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (!mSurfaceOnly && !info.hwuiCallbackFired) { markEvent("FT#MissedHWUICallback", info.frameVsyncId); Log.w(TAG, "Missing HWUI jank callback for vsyncId: " + info.frameVsyncId - + ", CUJ=" + mSession.getName()); + + ", CUJ=" + name); } } if (!mSurfaceOnly && info.hwuiCallbackFired) { @@ -654,7 +621,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (!info.surfaceControlCallbackFired) { markEvent("FT#MissedSFCallback", info.frameVsyncId); Log.w(TAG, "Missing SF jank callback for vsyncId: " + info.frameVsyncId - + ", CUJ=" + mSession.getName()); + + ", CUJ=" + name); } } } @@ -662,29 +629,26 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener maxSuccessiveMissedFramesCount, successiveMissedFramesCount); // Log the frame stats as counters to make them easily accessible in traces. - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames", - missedFramesCount); - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedAppFrames", - missedAppFramesCount); - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedSfFrames", - missedSfFramesCount); - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames", - totalFramesCount); - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis", + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedFrames", missedFramesCount); + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedAppFrames", missedAppFramesCount); + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedSfFrames", missedSfFramesCount); + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#totalFrames", totalFramesCount); + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#maxFrameTimeMillis", (int) (maxFrameTimeNanos / NANOS_IN_MILLISECOND)); - Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxSuccessiveMissedFrames", + Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#maxSuccessiveMissedFrames", maxSuccessiveMissedFramesCount); // Trigger perfetto if necessary. - if (shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) { - triggerPerfetto(); + if (mListener != null + && shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) { + mListener.triggerPerfetto(mConfig); } - if (mSession.logToStatsd()) { + if (mConfig.logToStatsd()) { mStatsLog.write( FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED, mDisplayId, refreshRate, - mSession.getStatsdInteractionType(), + mConfig.getStatsdInteractionType(), totalFramesCount, missedFramesCount, maxFrameTimeNanos, /* will be 0 if mSurfaceOnly == true */ @@ -692,16 +656,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener missedAppFramesCount, maxSuccessiveMissedFramesCount); } - if (DEBUG) { - Log.i(TAG, "finish: CUJ=" + mSession.getName() - + " (" + mBeginVsyncId + "," + mEndVsyncId + ")" - + " totalFrames=" + totalFramesCount - + " missedAppFrames=" + missedAppFramesCount - + " missedSfFrames=" + missedSfFramesCount - + " missedFrames=" + missedFramesCount - + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND - + " maxSuccessiveMissedFramesCount=" + maxSuccessiveMissedFramesCount); - } } ThreadedRendererWrapper getThreadedRenderer() { @@ -736,13 +690,6 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } - /** - * Trigger the prefetto daemon. - */ - public void triggerPerfetto() { - mMonitor.trigger(mSession); - } - /** * A wrapper class that we can spy FrameMetrics (a final class) in unit tests. */ @@ -895,9 +842,17 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener /** * Notify that the CUJ session was created. * - * @param session the CUJ session + * @param tracker the tracker * @param action the specific action + * @param reason the reason for the action + */ + void onCujEvents(FrameTracker tracker, String action, @Reasons int reason); + + /** + * Notify that the Perfetto trace should be triggered. + * + * @param config the tracker configuration */ - void onCujEvents(Session session, String action); + void triggerPerfetto(Configuration config); } } diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index e6b036cfaa19..8b1879f5225d 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -23,89 +23,9 @@ import static android.provider.DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR; import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NORMAL; import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT; import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL; -import static com.android.internal.jank.FrameTracker.REASON_END_UNKNOWN; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL; -import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION; import android.Manifest; import android.annotation.ColorInt; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.UiThread; @@ -137,34 +57,31 @@ import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper; import com.android.internal.jank.FrameTracker.ViewRootWrapper; import com.android.internal.util.PerfettoTrigger; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.time.Instant; -import java.util.Locale; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; /** - * This class let users to begin and end the always on tracing mechanism. + * This class lets users begin and end the always on tracing mechanism. * * Enabling for local development: - * + *<pre> * adb shell device_config put interaction_jank_monitor enabled true * adb shell device_config put interaction_jank_monitor sampling_interval 1 - * + * </pre> * On debuggable builds, an overlay can be used to display the name of the * currently running cuj using: - * + * <pre> * adb shell device_config put interaction_jank_monitor debug_overlay_enabled true - * - * NOTE: The overlay will interfere with metrics, so it should only be used - * for understanding which UI events correspeond to which CUJs. + * </pre> + * <b>NOTE</b>: The overlay will interfere with metrics, so it should only be used + * for understanding which UI events correspond to which CUJs. * * @hide */ public class InteractionJankMonitor { private static final String TAG = InteractionJankMonitor.class.getSimpleName(); - private static final boolean DEBUG = false; private static final String ACTION_PREFIX = InteractionJankMonitor.class.getCanonicalName(); private static final String DEFAULT_WORKER_NAME = TAG + "-Worker"; @@ -186,218 +103,79 @@ public class InteractionJankMonitor { private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64; private static final boolean DEFAULT_DEBUG_OVERLAY_ENABLED = false; - @VisibleForTesting - public static final int MAX_LENGTH_OF_CUJ_NAME = 80; private static final int MAX_LENGTH_SESSION_NAME = 100; public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END"; public static final String ACTION_SESSION_CANCEL = ACTION_PREFIX + ".ACTION_SESSION_CANCEL"; - // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE. - public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0; - public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 2; - public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 3; - public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 4; - public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 5; - public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 6; - public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 7; - public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 8; - public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 9; - public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 10; - public static final int CUJ_LAUNCHER_QUICK_SWITCH = 11; - public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = 12; - public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = 13; - public static final int CUJ_NOTIFICATION_ADD = 14; - public static final int CUJ_NOTIFICATION_REMOVE = 15; - public static final int CUJ_NOTIFICATION_APP_START = 16; - public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = 17; - public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = 18; - public static final int CUJ_LOCKSCREEN_PIN_APPEAR = 19; - public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = 20; - public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = 21; - public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = 22; - public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = 23; - public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = 24; - public static final int CUJ_LAUNCHER_OPEN_ALL_APPS = 25; - public static final int CUJ_LAUNCHER_ALL_APPS_SCROLL = 26; - public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27; - public static final int CUJ_SETTINGS_PAGE_SCROLL = 28; - public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = 29; - public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = 30; - public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = 31; - public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = 32; - public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = 33; - public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = 34; - public static final int CUJ_PIP_TRANSITION = 35; - public static final int CUJ_WALLPAPER_TRANSITION = 36; - public static final int CUJ_USER_SWITCH = 37; - public static final int CUJ_SPLASHSCREEN_AVD = 38; - public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = 39; - public static final int CUJ_SCREEN_OFF = 40; - public static final int CUJ_SCREEN_OFF_SHOW_AOD = 41; - public static final int CUJ_ONE_HANDED_ENTER_TRANSITION = 42; - public static final int CUJ_ONE_HANDED_EXIT_TRANSITION = 43; - public static final int CUJ_UNFOLD_ANIM = 44; - public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = 45; - public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = 46; - public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = 47; - public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = 48; - public static final int CUJ_SPLIT_SCREEN_ENTER = 49; - public static final int CUJ_SPLIT_SCREEN_EXIT = 50; - public static final int CUJ_LOCKSCREEN_LAUNCH_CAMERA = 51; // reserved. - public static final int CUJ_SPLIT_SCREEN_RESIZE = 52; - public static final int CUJ_SETTINGS_SLIDER = 53; - public static final int CUJ_TAKE_SCREENSHOT = 54; - public static final int CUJ_VOLUME_CONTROL = 55; - public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = 56; - public static final int CUJ_SETTINGS_TOGGLE = 57; - public static final int CUJ_SHADE_DIALOG_OPEN = 58; - public static final int CUJ_USER_DIALOG_OPEN = 59; - public static final int CUJ_TASKBAR_EXPAND = 60; - public static final int CUJ_TASKBAR_COLLAPSE = 61; - public static final int CUJ_SHADE_CLEAR_ALL = 62; - public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION = 63; - public static final int CUJ_LOCKSCREEN_OCCLUSION = 64; - public static final int CUJ_RECENTS_SCROLLING = 65; - public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66; - public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67; - public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68; - public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70; - public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71; - // 72 - 77 are reserved for b/281564325. - - /** - * In some cases when we do not have any end-target, we play a simple slide-down animation. - * eg: Open an app from Overview/Task switcher such that there is no home-screen icon. - * eg: Exit the app using back gesture. - */ - public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78; - public static final int CUJ_IME_INSETS_SHOW_ANIMATION = 80; - public static final int CUJ_IME_INSETS_HIDE_ANIMATION = 81; - - public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82; - - public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83; - - public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = 84; - public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = 85; - public static final int CUJ_PREDICTIVE_BACK_HOME = 86; - - private static final int LAST_CUJ = CUJ_PREDICTIVE_BACK_HOME; - private static final int NO_STATSD_LOGGING = -1; - - // Used to convert CujType to InteractionType enum value for statsd logging. - // Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd. - @VisibleForTesting - public static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = new int[LAST_CUJ + 1]; - - static { - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE; - CUJ_TO_STATSD_INTERACTION_TYPE[1] = NO_STATSD_LOGGING; // This is deprecated. - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_SCROLL_FLING] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_EXPAND] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_PIP] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_QUICK_SWITCH] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_ADD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_REMOVE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_APP_START] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_FROM_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_TO_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_ALL_APPS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_ALL_APPS_SCROLL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_PAGE_SCROLL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_UNLOCK_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PIP_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_SWITCH] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_AVD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_EXIT_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF_SHOW_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_ENTER_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_EXIT_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_NEXT_FLOW] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_SCREEN_FOR_STATUS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_ENTER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_EXIT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_LAUNCH_CAMERA] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_RESIZE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_SLIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TAKE_SCREENSHOT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_VOLUME_CONTROL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_BIOMETRIC_PROMPT_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_TOGGLE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_DIALOG_OPEN] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_DIALOG_OPEN] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_EXPAND] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_CLEAR_ALL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_OCCLUSION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_RECENTS_SCROLLING] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME; - CUJ_TO_STATSD_INTERACTION_TYPE[69] = NO_STATSD_LOGGING; // This is deprecated. - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT; - // 72 - 77 are reserved for b/281564325. - CUJ_TO_STATSD_INTERACTION_TYPE[72] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[73] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[74] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[75] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[76] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[77] = NO_STATSD_LOGGING; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK; - CUJ_TO_STATSD_INTERACTION_TYPE[79] = NO_STATSD_LOGGING; // This is deprecated. - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY] = - UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_TASK] = - UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK; - CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_HOME] = - UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME; - } + // These are not the CUJ constants you are looking for. These constants simply forward their + // definition from {@link Cuj}. They are here only as a transition measure until all references + // have been updated to the new location. + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING; + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND; + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE; + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; + @Deprecated public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE; + @Deprecated public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME; + @Deprecated public static final int CUJ_LAUNCHER_QUICK_SWITCH = Cuj.CUJ_LAUNCHER_QUICK_SWITCH; + @Deprecated public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR; + @Deprecated public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR; + @Deprecated public static final int CUJ_NOTIFICATION_ADD = Cuj.CUJ_NOTIFICATION_ADD; + @Deprecated public static final int CUJ_NOTIFICATION_REMOVE = Cuj.CUJ_NOTIFICATION_REMOVE; + @Deprecated public static final int CUJ_NOTIFICATION_APP_START = Cuj.CUJ_NOTIFICATION_APP_START; + @Deprecated public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = Cuj.CUJ_LOCKSCREEN_PASSWORD_APPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = Cuj.CUJ_LOCKSCREEN_PATTERN_APPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_PIN_APPEAR = Cuj.CUJ_LOCKSCREEN_PIN_APPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PATTERN_DISAPPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PIN_DISAPPEAR; + @Deprecated public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = Cuj.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD; + @Deprecated public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = Cuj.CUJ_LOCKSCREEN_TRANSITION_TO_AOD; + @Deprecated public static final int CUJ_SETTINGS_PAGE_SCROLL = Cuj.CUJ_SETTINGS_PAGE_SCROLL; + @Deprecated public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = Cuj.CUJ_LOCKSCREEN_UNLOCK_ANIMATION; + @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON; + @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER; + @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE; + @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON; + @Deprecated public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = Cuj.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP; + @Deprecated public static final int CUJ_PIP_TRANSITION = Cuj.CUJ_PIP_TRANSITION; + @Deprecated public static final int CUJ_USER_SWITCH = Cuj.CUJ_USER_SWITCH; + @Deprecated public static final int CUJ_SPLASHSCREEN_AVD = Cuj.CUJ_SPLASHSCREEN_AVD; + @Deprecated public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = Cuj.CUJ_SPLASHSCREEN_EXIT_ANIM; + @Deprecated public static final int CUJ_SCREEN_OFF = Cuj.CUJ_SCREEN_OFF; + @Deprecated public static final int CUJ_SCREEN_OFF_SHOW_AOD = Cuj.CUJ_SCREEN_OFF_SHOW_AOD; + @Deprecated public static final int CUJ_UNFOLD_ANIM = Cuj.CUJ_UNFOLD_ANIM; + @Deprecated public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = Cuj.CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS; + @Deprecated public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = Cuj.CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS; + @Deprecated public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = Cuj.CUJ_SUW_LOADING_TO_NEXT_FLOW; + @Deprecated public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = Cuj.CUJ_SUW_LOADING_SCREEN_FOR_STATUS; + @Deprecated public static final int CUJ_SPLIT_SCREEN_RESIZE = Cuj.CUJ_SPLIT_SCREEN_RESIZE; + @Deprecated public static final int CUJ_SETTINGS_SLIDER = Cuj.CUJ_SETTINGS_SLIDER; + @Deprecated public static final int CUJ_TAKE_SCREENSHOT = Cuj.CUJ_TAKE_SCREENSHOT; + @Deprecated public static final int CUJ_VOLUME_CONTROL = Cuj.CUJ_VOLUME_CONTROL; + @Deprecated public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = Cuj.CUJ_BIOMETRIC_PROMPT_TRANSITION; + @Deprecated public static final int CUJ_SETTINGS_TOGGLE = Cuj.CUJ_SETTINGS_TOGGLE; + @Deprecated public static final int CUJ_SHADE_DIALOG_OPEN = Cuj.CUJ_SHADE_DIALOG_OPEN; + @Deprecated public static final int CUJ_USER_DIALOG_OPEN = Cuj.CUJ_USER_DIALOG_OPEN; + @Deprecated public static final int CUJ_TASKBAR_EXPAND = Cuj.CUJ_TASKBAR_EXPAND; + @Deprecated public static final int CUJ_TASKBAR_COLLAPSE = Cuj.CUJ_TASKBAR_COLLAPSE; + @Deprecated public static final int CUJ_SHADE_CLEAR_ALL = Cuj.CUJ_SHADE_CLEAR_ALL; + @Deprecated public static final int CUJ_LOCKSCREEN_OCCLUSION = Cuj.CUJ_LOCKSCREEN_OCCLUSION; + @Deprecated public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = Cuj.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION; + @Deprecated public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = Cuj.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER; + @Deprecated public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = Cuj.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY; + @Deprecated public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = Cuj.CUJ_PREDICTIVE_BACK_CROSS_TASK; + @Deprecated public static final int CUJ_PREDICTIVE_BACK_HOME = Cuj.CUJ_PREDICTIVE_BACK_HOME; private static class InstanceHolder { public static final InteractionJankMonitor INSTANCE = new InteractionJankMonitor(new HandlerThread(DEFAULT_WORKER_NAME)); } - private final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener = - this::updateProperties; - @GuardedBy("mLock") - private final SparseArray<FrameTracker> mRunningTrackers; - @GuardedBy("mLock") - private final SparseArray<Runnable> mTimeoutActions; - private final HandlerThread mWorker; + private final SparseArray<RunningTracker> mRunningTrackers = new SparseArray<>(); + private final Handler mWorker; private final DisplayResolutionTracker mDisplayResolutionTracker; private final Object mLock = new Object(); private @ColorInt int mDebugBgColor = Color.CYAN; @@ -409,91 +187,6 @@ public class InteractionJankMonitor { private int mTraceThresholdMissedFrames = DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES; private int mTraceThresholdFrameTimeMillis = DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS; - /** @hide */ - @IntDef({ - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, - CUJ_NOTIFICATION_SHADE_SCROLL_FLING, - CUJ_NOTIFICATION_SHADE_ROW_EXPAND, - CUJ_NOTIFICATION_SHADE_ROW_SWIPE, - CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, - CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, - CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS, - CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON, - CUJ_LAUNCHER_APP_CLOSE_TO_HOME, - CUJ_LAUNCHER_APP_CLOSE_TO_PIP, - CUJ_LAUNCHER_QUICK_SWITCH, - CUJ_NOTIFICATION_HEADS_UP_APPEAR, - CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, - CUJ_NOTIFICATION_ADD, - CUJ_NOTIFICATION_REMOVE, - CUJ_NOTIFICATION_APP_START, - CUJ_LOCKSCREEN_PASSWORD_APPEAR, - CUJ_LOCKSCREEN_PATTERN_APPEAR, - CUJ_LOCKSCREEN_PIN_APPEAR, - CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR, - CUJ_LOCKSCREEN_PATTERN_DISAPPEAR, - CUJ_LOCKSCREEN_PIN_DISAPPEAR, - CUJ_LOCKSCREEN_TRANSITION_FROM_AOD, - CUJ_LOCKSCREEN_TRANSITION_TO_AOD, - CUJ_LAUNCHER_OPEN_ALL_APPS, - CUJ_LAUNCHER_ALL_APPS_SCROLL, - CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET, - CUJ_SETTINGS_PAGE_SCROLL, - CUJ_LOCKSCREEN_UNLOCK_ANIMATION, - CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON, - CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER, - CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE, - CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON, - CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP, - CUJ_PIP_TRANSITION, - CUJ_WALLPAPER_TRANSITION, - CUJ_USER_SWITCH, - CUJ_SPLASHSCREEN_AVD, - CUJ_SPLASHSCREEN_EXIT_ANIM, - CUJ_SCREEN_OFF, - CUJ_SCREEN_OFF_SHOW_AOD, - CUJ_ONE_HANDED_ENTER_TRANSITION, - CUJ_ONE_HANDED_EXIT_TRANSITION, - CUJ_UNFOLD_ANIM, - CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS, - CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS, - CUJ_SUW_LOADING_TO_NEXT_FLOW, - CUJ_SUW_LOADING_SCREEN_FOR_STATUS, - CUJ_SPLIT_SCREEN_ENTER, - CUJ_SPLIT_SCREEN_EXIT, - CUJ_LOCKSCREEN_LAUNCH_CAMERA, - CUJ_SPLIT_SCREEN_RESIZE, - CUJ_SETTINGS_SLIDER, - CUJ_TAKE_SCREENSHOT, - CUJ_VOLUME_CONTROL, - CUJ_BIOMETRIC_PROMPT_TRANSITION, - CUJ_SETTINGS_TOGGLE, - CUJ_SHADE_DIALOG_OPEN, - CUJ_USER_DIALOG_OPEN, - CUJ_TASKBAR_EXPAND, - CUJ_TASKBAR_COLLAPSE, - CUJ_SHADE_CLEAR_ALL, - CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION, - CUJ_LOCKSCREEN_OCCLUSION, - CUJ_RECENTS_SCROLLING, - CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS, - CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE, - CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME, - CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION, - CUJ_LAUNCHER_OPEN_SEARCH_RESULT, - CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK, - CUJ_IME_INSETS_SHOW_ANIMATION, - CUJ_IME_INSETS_HIDE_ANIMATION, - CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER, - CUJ_LAUNCHER_UNFOLD_ANIM, - CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY, - CUJ_PREDICTIVE_BACK_CROSS_TASK, - CUJ_PREDICTIVE_BACK_HOME, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CujType { - } - /** * Get the singleton of InteractionJankMonitor. * @@ -511,71 +204,44 @@ public class InteractionJankMonitor { @VisibleForTesting @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) public InteractionJankMonitor(@NonNull HandlerThread worker) { - mRunningTrackers = new SparseArray<>(); - mTimeoutActions = new SparseArray<>(); - mWorker = worker; - mWorker.start(); - mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler()); - mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; - mEnabled = DEFAULT_ENABLED; + worker.start(); + mWorker = worker.getThreadHandler(); + mDisplayResolutionTracker = new DisplayResolutionTracker(mWorker); final Context context = ActivityThread.currentApplication(); - if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) != PERMISSION_GRANTED) { - if (DEBUG) { - Log.d(TAG, "Initialized the InteractionJankMonitor." - + " (No READ_DEVICE_CONFIG permission to change configs)" - + " enabled=" + mEnabled + ", interval=" + mSamplingInterval - + ", missedFrameThreshold=" + mTraceThresholdMissedFrames - + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis - + ", package=" + context.getPackageName()); - } + if (context == null || context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) != PERMISSION_GRANTED) { + Log.w(TAG, "Initializing without READ_DEVICE_CONFIG permission." + + " enabled=" + mEnabled + ", interval=" + mSamplingInterval + + ", missedFrameThreshold=" + mTraceThresholdMissedFrames + + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis + + ", package=" + (context == null ? "null" : context.getPackageName())); return; } // Post initialization to the background in case we're running on the main thread. - mWorker.getThreadHandler().post( - () -> { - try { - mPropertiesChangedListener.onPropertiesChanged( - DeviceConfig.getProperties(NAMESPACE_INTERACTION_JANK_MONITOR)); - DeviceConfig.addOnPropertiesChangedListener( - NAMESPACE_INTERACTION_JANK_MONITOR, - new HandlerExecutor(mWorker.getThreadHandler()), - mPropertiesChangedListener); - } catch (SecurityException ex) { - Log.d(TAG, "Can't get properties: READ_DEVICE_CONFIG granted=" - + context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) - + ", package=" + context.getPackageName()); - } - }); + mWorker.post(() -> { + try { + updateProperties(DeviceConfig.getProperties(NAMESPACE_INTERACTION_JANK_MONITOR)); + DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_INTERACTION_JANK_MONITOR, + new HandlerExecutor(mWorker), this::updateProperties); + } catch (SecurityException ex) { + Log.d(TAG, "Can't get properties: READ_DEVICE_CONFIG granted=" + + context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) + + ", package=" + context.getPackageName()); + } + }); } /** * Creates a {@link FrameTracker} instance. * - * @param config the config used in instrumenting - * @param session the session associates with this tracker + * @param config the conifg associates with this tracker * @return instance of the FrameTracker */ @VisibleForTesting - public FrameTracker createFrameTracker(Configuration config, Session session) { + public FrameTracker createFrameTracker(Configuration config) { final View view = config.mView; - if (!config.hasValidView()) { - boolean attached = false; - boolean hasViewRoot = false; - boolean hasRenderer = false; - if (view != null) { - attached = view.isAttachedToWindow(); - hasViewRoot = view.getViewRootImpl() != null; - hasRenderer = view.getThreadedRenderer() != null; - } - Log.d(TAG, "create FrameTracker fails: view=" + view - + ", attached=" + attached + ", hasViewRoot=" + hasViewRoot - + ", hasRenderer=" + hasRenderer, new Throwable()); - return null; - } - final ThreadedRendererWrapper threadedRenderer = view == null ? null : new ThreadedRendererWrapper(view.getThreadedRenderer()); final ViewRootWrapper viewRoot = @@ -583,52 +249,50 @@ public class InteractionJankMonitor { final SurfaceControlWrapper surfaceControl = new SurfaceControlWrapper(); final ChoreographerWrapper choreographer = new ChoreographerWrapper(Choreographer.getInstance()); - final FrameTrackerListener eventsListener = (s, act) -> handleCujEvents(act, s); + final FrameTrackerListener eventsListener = new FrameTrackerListener() { + @Override + public void onCujEvents(FrameTracker tracker, String action, int reason) { + config.getHandler().runWithScissors(() -> + handleCujEvents(config.mCujType, tracker, action, reason), + EXECUTOR_TASK_TIMEOUT); + } + + @Override + public void triggerPerfetto(Configuration config) { + mWorker.post(() -> PerfettoTrigger.trigger(config.getPerfettoTrigger())); + } + }; final FrameMetricsWrapper frameMetrics = new FrameMetricsWrapper(); - return new FrameTracker(this, session, config.getHandler(), threadedRenderer, viewRoot, + return new FrameTracker(config, threadedRenderer, viewRoot, surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(mDisplayResolutionTracker), mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, - eventsListener, config); + eventsListener); } @UiThread - private void handleCujEvents(String action, Session session) { + private void handleCujEvents( + @Cuj.CujType int cuj, FrameTracker tracker, String action, @Reasons int reason) { // Clear the running and timeout tasks if the end / cancel was fired within the tracker. // Or we might have memory leaks. - if (needRemoveTasks(action, session)) { - getTracker(session.getCuj()).getHandler().runWithScissors(() -> { - removeTimeout(session.getCuj()); - removeTracker(session.getCuj(), session.getReason()); - }, EXECUTOR_TASK_TIMEOUT); + if (needRemoveTasks(action, reason)) { + removeTrackerIfCurrent(cuj, tracker, reason); } } - private boolean needRemoveTasks(String action, Session session) { - final boolean badEnd = action.equals(ACTION_SESSION_END) - && session.getReason() != REASON_END_NORMAL; + private static boolean needRemoveTasks(String action, @Reasons int reason) { + final boolean badEnd = action.equals(ACTION_SESSION_END) && reason != REASON_END_NORMAL; final boolean badCancel = action.equals(ACTION_SESSION_CANCEL) - && !(session.getReason() == REASON_CANCEL_NORMAL - || session.getReason() == REASON_CANCEL_TIMEOUT); + && !(reason == REASON_CANCEL_NORMAL || reason == REASON_CANCEL_TIMEOUT); return badEnd || badCancel; } - private void removeTimeout(@CujType int cujType) { - synchronized (mLock) { - Runnable timeout = mTimeoutActions.get(cujType); - if (timeout != null) { - getTracker(cujType).getHandler().removeCallbacks(timeout); - mTimeoutActions.remove(cujType); - } - } - } - /** * @param cujType cuj type * @return true if the cuj is under instrumenting, false otherwise. */ - public boolean isInstrumenting(@CujType int cujType) { + public boolean isInstrumenting(@Cuj.CujType int cujType) { synchronized (mLock) { return mRunningTrackers.contains(cujType); } @@ -638,10 +302,10 @@ public class InteractionJankMonitor { * Begins a trace session. * * @param v an attached view. - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. * @return boolean true if the tracker is started successfully, false otherwise. */ - public boolean begin(View v, @CujType int cujType) { + public boolean begin(View v, @Cuj.CujType int cujType) { try { return begin(Configuration.Builder.withView(cujType, v)); } catch (IllegalArgumentException ex) { @@ -667,7 +331,7 @@ public class InteractionJankMonitor { final boolean success = config.getHandler().runWithScissors( () -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT); if (!success) { - Log.d(TAG, "begin failed due to timeout, CUJ=" + getNameOfCuj(config.mCujType)); + Log.d(TAG, "begin failed due to timeout, CUJ=" + Cuj.getNameOfCuj(config.mCujType)); return false; } return result.mResult; @@ -680,75 +344,59 @@ public class InteractionJankMonitor { @UiThread private boolean beginInternal(@NonNull Configuration conf) { int cujType = conf.mCujType; - if (!shouldMonitor(cujType)) return false; - FrameTracker tracker = getTracker(cujType); - // Skip subsequent calls if we already have an ongoing tracing. - if (tracker != null) return false; + if (!shouldMonitor()) { + return false; + } - // begin a new trace session. - tracker = createFrameTracker(conf, new Session(cujType, conf.mTag)); - if (tracker == null) return false; - putTracker(cujType, tracker); - tracker.begin(); + RunningTracker tracker = putTrackerIfNoCurrent(cujType, () -> + new RunningTracker( + conf, createFrameTracker(conf), () -> cancel(cujType, REASON_CANCEL_TIMEOUT))); + if (tracker == null) { + return false; + } + tracker.mTracker.begin(); // Cancel the trace if we don't get an end() call in specified duration. - scheduleTimeoutAction( - cujType, conf.mTimeout, () -> cancel(cujType, REASON_CANCEL_TIMEOUT)); + scheduleTimeoutAction(tracker.mConfig, tracker.mTimeoutAction); + return true; } /** * Check if the monitoring is enabled and if it should be sampled. */ - @SuppressWarnings("RandomModInteger") @VisibleForTesting - public boolean shouldMonitor(@CujType int cujType) { - boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; - if (!mEnabled || !shouldSample) { - if (DEBUG) { - Log.d(TAG, "Skip monitoring cuj: " + getNameOfCuj(cujType) - + ", enable=" + mEnabled + ", debuggable=" + DEFAULT_ENABLED - + ", sample=" + shouldSample + ", interval=" + mSamplingInterval); - } - return false; - } - return true; + public boolean shouldMonitor() { + return mEnabled && (ThreadLocalRandom.current().nextInt(mSamplingInterval) == 0); } - /** - * Schedules a timeout action. - * @param cuj cuj type - * @param timeout duration to timeout - * @param action action once timeout - */ @VisibleForTesting - public void scheduleTimeoutAction(@CujType int cuj, long timeout, Runnable action) { - synchronized (mLock) { - mTimeoutActions.put(cuj, action); - getTracker(cuj).getHandler().postDelayed(action, timeout); - } + public void scheduleTimeoutAction(Configuration config, Runnable action) { + config.getHandler().postDelayed(action, config.mTimeout); } /** * Ends a trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. * @return boolean true if the tracker is ended successfully, false otherwise. */ - public boolean end(@CujType int cujType) { + public boolean end(@Cuj.CujType int cujType) { postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> { EventLogTags.writeJankCujEventsEndRequest( cujType, unixNanos, elapsedNanos, realtimeNanos); }); - FrameTracker tracker = getTracker(cujType); + RunningTracker tracker = getTracker(cujType); // Skip this call since we haven't started a trace yet. - if (tracker == null) return false; + if (tracker == null) { + return false; + } try { final TrackerResult result = new TrackerResult(); - final boolean success = tracker.getHandler().runWithScissors( - () -> result.mResult = endInternal(cujType), EXECUTOR_TASK_TIMEOUT); + final boolean success = tracker.mConfig.getHandler().runWithScissors( + () -> result.mResult = endInternal(tracker), EXECUTOR_TASK_TIMEOUT); if (!success) { - Log.d(TAG, "end failed due to timeout, CUJ=" + getNameOfCuj(cujType)); + Log.d(TAG, "end failed due to timeout, CUJ=" + Cuj.getNameOfCuj(cujType)); return false; } return result.mResult; @@ -759,15 +407,11 @@ public class InteractionJankMonitor { } @UiThread - private boolean endInternal(@CujType int cujType) { - // remove the timeout action first. - removeTimeout(cujType); - FrameTracker tracker = getTracker(cujType); - if (tracker == null) return false; - // if the end call doesn't return true, another thread is handling end of the cuj. - if (tracker.end(REASON_END_NORMAL)) { - removeTracker(cujType, REASON_END_NORMAL); + private boolean endInternal(RunningTracker tracker) { + if (removeTrackerIfCurrent(tracker, REASON_END_NORMAL)) { + return false; } + tracker.mTracker.end(REASON_END_NORMAL); return true; } @@ -776,7 +420,7 @@ public class InteractionJankMonitor { * * @return boolean true if the tracker is cancelled successfully, false otherwise. */ - public boolean cancel(@CujType int cujType) { + public boolean cancel(@Cuj.CujType int cujType) { postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> { EventLogTags.writeJankCujEventsCancelRequest( cujType, unixNanos, elapsedNanos, realtimeNanos); @@ -790,16 +434,18 @@ public class InteractionJankMonitor { * @return boolean true if the tracker is cancelled successfully, false otherwise. */ @VisibleForTesting - public boolean cancel(@CujType int cujType, @Reasons int reason) { - FrameTracker tracker = getTracker(cujType); + public boolean cancel(@Cuj.CujType int cujType, @Reasons int reason) { + RunningTracker tracker = getTracker(cujType); // Skip this call since we haven't started a trace yet. - if (tracker == null) return false; + if (tracker == null) { + return false; + } try { final TrackerResult result = new TrackerResult(); - final boolean success = tracker.getHandler().runWithScissors( - () -> result.mResult = cancelInternal(cujType, reason), EXECUTOR_TASK_TIMEOUT); + final boolean success = tracker.mConfig.getHandler().runWithScissors( + () -> result.mResult = cancelInternal(tracker, reason), EXECUTOR_TASK_TIMEOUT); if (!success) { - Log.d(TAG, "cancel failed due to timeout, CUJ=" + getNameOfCuj(cujType)); + Log.d(TAG, "cancel failed due to timeout, CUJ=" + Cuj.getNameOfCuj(cujType)); return false; } return result.mResult; @@ -810,71 +456,86 @@ public class InteractionJankMonitor { } @UiThread - private boolean cancelInternal(@CujType int cujType, @Reasons int reason) { - // remove the timeout action first. - removeTimeout(cujType); - FrameTracker tracker = getTracker(cujType); - if (tracker == null) return false; - // if the cancel call doesn't return true, another thread is handling cancel of the cuj. - if (tracker.cancel(reason)) { - removeTracker(cujType, reason); + private boolean cancelInternal(RunningTracker tracker, @Reasons int reason) { + if (removeTrackerIfCurrent(tracker, reason)) { + return false; } + tracker.mTracker.cancel(reason); return true; } @UiThread - private void putTracker(@CujType int cuj, @NonNull FrameTracker tracker) { + private RunningTracker putTrackerIfNoCurrent( + @Cuj.CujType int cuj, Supplier<RunningTracker> supplier) { synchronized (mLock) { + if (mRunningTrackers.contains(cuj)) { + return null; + } + + RunningTracker tracker = supplier.get(); + if (tracker == null) { + return null; + } + mRunningTrackers.put(cuj, tracker); if (mDebugOverlay != null) { mDebugOverlay.onTrackerAdded(cuj, tracker); } - if (DEBUG) { - Log.d(TAG, "Added tracker for " + getNameOfCuj(cuj) - + ". mRunningTrackers=" + listNamesOfCujs(mRunningTrackers)); - } + + return tracker; } } - private FrameTracker getTracker(@CujType int cuj) { + private RunningTracker getTracker(@Cuj.CujType int cuj) { synchronized (mLock) { return mRunningTrackers.get(cuj); } } + /** + * @return {@code true} if another tracker is current + */ + @UiThread + private boolean removeTrackerIfCurrent(RunningTracker tracker, int reason) { + return removeTrackerIfCurrent(tracker.mConfig.mCujType, tracker.mTracker, reason); + } + + /** + * @return {@code true} if another tracker is current + */ @UiThread - private void removeTracker(@CujType int cuj, int reason) { + private boolean removeTrackerIfCurrent(@Cuj.CujType int cuj, FrameTracker tracker, int reason) { synchronized (mLock) { + RunningTracker running = mRunningTrackers.get(cuj); + if (running == null || running.mTracker != tracker) { + return true; + } + + running.mConfig.getHandler().removeCallbacks(running.mTimeoutAction); mRunningTrackers.remove(cuj); if (mDebugOverlay != null) { mDebugOverlay.onTrackerRemoved(cuj, reason, mRunningTrackers); } - if (DEBUG) { - Log.d(TAG, "Removed tracker for " + getNameOfCuj(cuj) - + ". mRunningTrackers=" + listNamesOfCujs(mRunningTrackers)); - } + return false; } } @WorkerThread - private void updateProperties(DeviceConfig.Properties properties) { + @VisibleForTesting + public void updateProperties(DeviceConfig.Properties properties) { for (String property : properties.getKeyset()) { switch (property) { - case SETTINGS_SAMPLING_INTERVAL_KEY: - mSamplingInterval = properties.getInt(property, DEFAULT_SAMPLING_INTERVAL); - break; - case SETTINGS_THRESHOLD_MISSED_FRAMES_KEY: - mTraceThresholdMissedFrames = - properties.getInt(property, DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES); - break; - case SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY: - mTraceThresholdFrameTimeMillis = - properties.getInt(property, DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS); - break; - case SETTINGS_ENABLED_KEY: - mEnabled = properties.getBoolean(property, DEFAULT_ENABLED); - break; - case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY: + case SETTINGS_SAMPLING_INTERVAL_KEY -> + mSamplingInterval = properties.getInt(property, DEFAULT_SAMPLING_INTERVAL); + case SETTINGS_THRESHOLD_MISSED_FRAMES_KEY -> + mTraceThresholdMissedFrames = + properties.getInt(property, DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES); + case SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY -> + mTraceThresholdFrameTimeMillis = + properties.getInt(property, DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS); + case SETTINGS_ENABLED_KEY -> + mEnabled = properties.getBoolean(property, DEFAULT_ENABLED); + case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY -> { // Never allow the debug overlay to be used on user builds boolean debugOverlayEnabled = Build.IS_DEBUGGABLE && properties.getBoolean(property, DEFAULT_DEBUG_OVERLAY_ENABLED); @@ -885,49 +546,35 @@ public class InteractionJankMonitor { mDebugOverlay.dispose(); mDebugOverlay = null; } - break; - default: - if (DEBUG) { - Log.d(TAG, "Got a change event for an unknown property: " - + property + " => " + properties.getString(property, "")); - } + } + default -> Log.w(TAG, "Got a change event for an unknown property: " + + property + " => " + properties.getString(property, "")); } } } - @VisibleForTesting - public DeviceConfig.OnPropertiesChangedListener getPropertiesChangedListener() { - return mPropertiesChangedListener; - } - - /** - * Triggers the perfetto daemon to collect and upload data. - */ - @VisibleForTesting - public void trigger(Session session) { - mWorker.getThreadHandler().post( - () -> PerfettoTrigger.trigger(session.getPerfettoTrigger())); - } - /** * A helper method to translate interaction type to CUJ name. * * @param interactionType the interaction type defined in AtomsProto.java * @return the name of the interaction type + * @deprecated use {@link Cuj#getNameOfInteraction(int)} */ + @Deprecated public static String getNameOfInteraction(int interactionType) { - // There is an offset amount of 1 between cujType and interactionType. - return getNameOfCuj(getCujTypeFromInteraction(interactionType)); + return Cuj.getNameOfInteraction(interactionType); } /** - * A helper method to translate interaction type to CUJ type. + * A helper method to translate CUJ type to CUJ name. * - * @param interactionType the interaction type defined in AtomsProto.java - * @return the integer in {@link CujType} + * @param cujType the cuj type defined in this file + * @return the name of the cuj type + * @deprecated use {@link Cuj#getNameOfCuj(int)} */ - private static int getCujTypeFromInteraction(int interactionType) { - return interactionType - 1; + @Deprecated + public static String getNameOfCuj(int cujType) { + return Cuj.getNameOfCuj(cujType); } /** @@ -943,195 +590,14 @@ public class InteractionJankMonitor { mDebugYOffset = yOffset; } - /** - * A helper method for getting a string representation of all running CUJs. For example, - * "(LOCKSCREEN_TRANSITION_FROM_AOD, IME_INSETS_ANIMATION)" - */ - private static String listNamesOfCujs(SparseArray<FrameTracker> trackers) { - if (!DEBUG) { - return null; - } - StringBuilder sb = new StringBuilder(); - sb.append('('); - for (int i = 0; i < trackers.size(); i++) { - sb.append(getNameOfCuj(trackers.keyAt(i))); - if (i < trackers.size() - 1) { - sb.append(", "); - } - } - sb.append(')'); - return sb.toString(); - } + private void postEventLogToWorkerThread(TimeFunction logFunction) { + final Instant now = Instant.now(); + final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS) + + now.getNano(); + final long elapsedNanos = SystemClock.elapsedRealtimeNanos(); + final long realtimeNanos = SystemClock.uptimeNanos(); - /** - * A helper method to translate CUJ type to CUJ name. - * - * @param cujType the cuj type defined in this file - * @return the name of the cuj type - */ - public static String getNameOfCuj(int cujType) { - // Please note: - // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME. - // 2. The returned string should be the same with the name defined in atoms.proto. - switch (cujType) { - case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE: - return "NOTIFICATION_SHADE_EXPAND_COLLAPSE"; - case CUJ_NOTIFICATION_SHADE_SCROLL_FLING: - return "NOTIFICATION_SHADE_SCROLL_FLING"; - case CUJ_NOTIFICATION_SHADE_ROW_EXPAND: - return "NOTIFICATION_SHADE_ROW_EXPAND"; - case CUJ_NOTIFICATION_SHADE_ROW_SWIPE: - return "NOTIFICATION_SHADE_ROW_SWIPE"; - case CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE: - return "NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE"; - case CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE: - return "NOTIFICATION_SHADE_QS_SCROLL_SWIPE"; - case CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS: - return "LAUNCHER_APP_LAUNCH_FROM_RECENTS"; - case CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON: - return "LAUNCHER_APP_LAUNCH_FROM_ICON"; - case CUJ_LAUNCHER_APP_CLOSE_TO_HOME: - return "LAUNCHER_APP_CLOSE_TO_HOME"; - case CUJ_LAUNCHER_APP_CLOSE_TO_PIP: - return "LAUNCHER_APP_CLOSE_TO_PIP"; - case CUJ_LAUNCHER_QUICK_SWITCH: - return "LAUNCHER_QUICK_SWITCH"; - case CUJ_NOTIFICATION_HEADS_UP_APPEAR: - return "NOTIFICATION_HEADS_UP_APPEAR"; - case CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR: - return "NOTIFICATION_HEADS_UP_DISAPPEAR"; - case CUJ_NOTIFICATION_ADD: - return "NOTIFICATION_ADD"; - case CUJ_NOTIFICATION_REMOVE: - return "NOTIFICATION_REMOVE"; - case CUJ_NOTIFICATION_APP_START: - return "NOTIFICATION_APP_START"; - case CUJ_LOCKSCREEN_PASSWORD_APPEAR: - return "LOCKSCREEN_PASSWORD_APPEAR"; - case CUJ_LOCKSCREEN_PATTERN_APPEAR: - return "LOCKSCREEN_PATTERN_APPEAR"; - case CUJ_LOCKSCREEN_PIN_APPEAR: - return "LOCKSCREEN_PIN_APPEAR"; - case CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR: - return "LOCKSCREEN_PASSWORD_DISAPPEAR"; - case CUJ_LOCKSCREEN_PATTERN_DISAPPEAR: - return "LOCKSCREEN_PATTERN_DISAPPEAR"; - case CUJ_LOCKSCREEN_PIN_DISAPPEAR: - return "LOCKSCREEN_PIN_DISAPPEAR"; - case CUJ_LOCKSCREEN_TRANSITION_FROM_AOD: - return "LOCKSCREEN_TRANSITION_FROM_AOD"; - case CUJ_LOCKSCREEN_TRANSITION_TO_AOD: - return "LOCKSCREEN_TRANSITION_TO_AOD"; - case CUJ_LAUNCHER_OPEN_ALL_APPS : - return "LAUNCHER_OPEN_ALL_APPS"; - case CUJ_LAUNCHER_ALL_APPS_SCROLL: - return "LAUNCHER_ALL_APPS_SCROLL"; - case CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET: - return "LAUNCHER_APP_LAUNCH_FROM_WIDGET"; - case CUJ_SETTINGS_PAGE_SCROLL: - return "SETTINGS_PAGE_SCROLL"; - case CUJ_LOCKSCREEN_UNLOCK_ANIMATION: - return "LOCKSCREEN_UNLOCK_ANIMATION"; - case CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON: - return "SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON"; - case CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER: - return "SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER"; - case CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE: - return "SHADE_APP_LAUNCH_FROM_QS_TILE"; - case CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON: - return "SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON"; - case CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP: - return "STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP"; - case CUJ_PIP_TRANSITION: - return "PIP_TRANSITION"; - case CUJ_WALLPAPER_TRANSITION: - return "WALLPAPER_TRANSITION"; - case CUJ_USER_SWITCH: - return "USER_SWITCH"; - case CUJ_SPLASHSCREEN_AVD: - return "SPLASHSCREEN_AVD"; - case CUJ_SPLASHSCREEN_EXIT_ANIM: - return "SPLASHSCREEN_EXIT_ANIM"; - case CUJ_SCREEN_OFF: - return "SCREEN_OFF"; - case CUJ_SCREEN_OFF_SHOW_AOD: - return "SCREEN_OFF_SHOW_AOD"; - case CUJ_ONE_HANDED_ENTER_TRANSITION: - return "ONE_HANDED_ENTER_TRANSITION"; - case CUJ_ONE_HANDED_EXIT_TRANSITION: - return "ONE_HANDED_EXIT_TRANSITION"; - case CUJ_UNFOLD_ANIM: - return "UNFOLD_ANIM"; - case CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS: - return "SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS"; - case CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS: - return "SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS"; - case CUJ_SUW_LOADING_TO_NEXT_FLOW: - return "SUW_LOADING_TO_NEXT_FLOW"; - case CUJ_SUW_LOADING_SCREEN_FOR_STATUS: - return "SUW_LOADING_SCREEN_FOR_STATUS"; - case CUJ_SPLIT_SCREEN_ENTER: - return "SPLIT_SCREEN_ENTER"; - case CUJ_SPLIT_SCREEN_EXIT: - return "SPLIT_SCREEN_EXIT"; - case CUJ_LOCKSCREEN_LAUNCH_CAMERA: - return "LOCKSCREEN_LAUNCH_CAMERA"; - case CUJ_SPLIT_SCREEN_RESIZE: - return "SPLIT_SCREEN_RESIZE"; - case CUJ_SETTINGS_SLIDER: - return "SETTINGS_SLIDER"; - case CUJ_TAKE_SCREENSHOT: - return "TAKE_SCREENSHOT"; - case CUJ_VOLUME_CONTROL: - return "VOLUME_CONTROL"; - case CUJ_BIOMETRIC_PROMPT_TRANSITION: - return "BIOMETRIC_PROMPT_TRANSITION"; - case CUJ_SETTINGS_TOGGLE: - return "SETTINGS_TOGGLE"; - case CUJ_SHADE_DIALOG_OPEN: - return "SHADE_DIALOG_OPEN"; - case CUJ_USER_DIALOG_OPEN: - return "USER_DIALOG_OPEN"; - case CUJ_TASKBAR_EXPAND: - return "TASKBAR_EXPAND"; - case CUJ_TASKBAR_COLLAPSE: - return "TASKBAR_COLLAPSE"; - case CUJ_SHADE_CLEAR_ALL: - return "SHADE_CLEAR_ALL"; - case CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION: - return "LAUNCHER_UNLOCK_ENTRANCE_ANIMATION"; - case CUJ_LOCKSCREEN_OCCLUSION: - return "LOCKSCREEN_OCCLUSION"; - case CUJ_RECENTS_SCROLLING: - return "RECENTS_SCROLLING"; - case CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS: - return "LAUNCHER_APP_SWIPE_TO_RECENTS"; - case CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE: - return "LAUNCHER_CLOSE_ALL_APPS_SWIPE"; - case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME: - return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME"; - case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION: - return "LOCKSCREEN_CLOCK_MOVE_ANIMATION"; - case CUJ_LAUNCHER_OPEN_SEARCH_RESULT: - return "LAUNCHER_OPEN_SEARCH_RESULT"; - case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK: - return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK"; - case CUJ_IME_INSETS_SHOW_ANIMATION: - return "IME_INSETS_SHOW_ANIMATION"; - case CUJ_IME_INSETS_HIDE_ANIMATION: - return "IME_INSETS_HIDE_ANIMATION"; - case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER: - return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER"; - case CUJ_LAUNCHER_UNFOLD_ANIM: - return "LAUNCHER_UNFOLD_ANIM"; - case CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY: - return "PREDICTIVE_BACK_CROSS_ACTIVITY"; - case CUJ_PREDICTIVE_BACK_CROSS_TASK: - return "PREDICTIVE_BACK_CROSS_TASK"; - case CUJ_PREDICTIVE_BACK_HOME: - return "PREDICTIVE_BACK_HOME"; - } - return "UNKNOWN"; + mWorker.post(() -> logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos)); } private static class TrackerResult { @@ -1147,9 +613,10 @@ public class InteractionJankMonitor { private final Context mContext; private final long mTimeout; private final String mTag; + private final String mSessionName; private final boolean mSurfaceOnly; private final SurfaceControl mSurfaceControl; - private final @CujType int mCujType; + private final @Cuj.CujType int mCujType; private final boolean mDeferMonitor; private final Handler mHandler; @@ -1167,17 +634,17 @@ public class InteractionJankMonitor { private String mAttrTag = ""; private boolean mAttrSurfaceOnly; private SurfaceControl mAttrSurfaceControl; - private @CujType int mAttrCujType; + private final @Cuj.CujType int mAttrCujType; private boolean mAttrDeferMonitor = true; /** * Creates a builder which instruments only surface. - * @param cuj The enum defined in {@link InteractionJankMonitor.CujType}. + * @param cuj The enum defined in {@link Cuj.CujType}. * @param context context * @param surfaceControl surface control * @return builder */ - public static Builder withSurface(@CujType int cuj, @NonNull Context context, + public static Builder withSurface(@Cuj.CujType int cuj, @NonNull Context context, @NonNull SurfaceControl surfaceControl) { return new Builder(cuj) .setContext(context) @@ -1187,16 +654,17 @@ public class InteractionJankMonitor { /** * Creates a builder which instruments both surface and view. - * @param cuj The enum defined in {@link InteractionJankMonitor.CujType}. + * @param cuj The enum defined in {@link Cuj.CujType}. * @param view view * @return builder */ - public static Builder withView(@CujType int cuj, @NonNull View view) { - return new Builder(cuj).setView(view) + public static Builder withView(@Cuj.CujType int cuj, @NonNull View view) { + return new Builder(cuj) + .setView(view) .setContext(view.getContext()); } - private Builder(@CujType int cuj) { + private Builder(@Cuj.CujType int cuj) { mAttrCujType = cuj; } @@ -1281,11 +749,12 @@ public class InteractionJankMonitor { } } - private Configuration(@CujType int cuj, View view, String tag, long timeout, + private Configuration(@Cuj.CujType int cuj, View view, @NonNull String tag, long timeout, boolean surfaceOnly, Context context, SurfaceControl surfaceControl, boolean deferMonitor) { mCujType = cuj; mTag = tag; + mSessionName = generateSessionName(Cuj.getNameOfCuj(cuj), tag); mTimeout = timeout; mView = view; mSurfaceOnly = surfaceOnly; @@ -1298,6 +767,23 @@ public class InteractionJankMonitor { mHandler = mSurfaceOnly ? mContext.getMainThreadHandler() : mView.getHandler(); } + @VisibleForTesting + public static String generateSessionName( + @NonNull String cujName, @NonNull String cujPostfix) { + final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix); + if (hasPostfix) { + final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length(); + if (cujPostfix.length() > remaining) { + cujPostfix = cujPostfix.substring(0, remaining - 3).concat("..."); + } + } + // The max length of the whole string should be: + // 105 with postfix, 83 without postfix + return hasPostfix + ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix) + : TextUtils.formatSimple("J<%s>", cujName); + } + private void validate() { boolean shouldThrow = false; final StringBuilder msg = new StringBuilder(); @@ -1360,10 +846,10 @@ public class InteractionJankMonitor { return mSurfaceControl; } - @VisibleForTesting /** * @return a view which is attached to the view tree. */ + @VisibleForTesting public View getView() { return mView; } @@ -1375,7 +861,7 @@ public class InteractionJankMonitor { return mDeferMonitor; } - @VisibleForTesting + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public Handler getHandler() { return mHandler; } @@ -1387,79 +873,27 @@ public class InteractionJankMonitor { public int getDisplayId() { return (mSurfaceOnly ? mContext : mView.getContext()).getDisplayId(); } - } - - /** - * A class to represent a session. - */ - public static class Session { - @CujType - private final int mCujType; - private final long mTimeStamp; - @Reasons - private int mReason = REASON_END_UNKNOWN; - private final String mName; - - public Session(@CujType int cujType, @NonNull String postfix) { - mCujType = cujType; - mTimeStamp = System.nanoTime(); - mName = generateSessionName(getNameOfCuj(cujType), postfix); - } - - private String generateSessionName(@NonNull String cujName, @NonNull String cujPostfix) { - final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix); - // We assert that the cujName shouldn't exceed MAX_LENGTH_OF_CUJ_NAME. - if (cujName.length() > MAX_LENGTH_OF_CUJ_NAME) { - throw new IllegalArgumentException(TextUtils.formatSimple( - "The length of cuj name <%s> exceeds %d", cujName, MAX_LENGTH_OF_CUJ_NAME)); - } - if (hasPostfix) { - final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length(); - if (cujPostfix.length() > remaining) { - cujPostfix = cujPostfix.substring(0, remaining - 3).concat("..."); - } - } - // The max length of the whole string should be: - // 105 with postfix, 83 without postfix - return hasPostfix - ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix) - : TextUtils.formatSimple("J<%s>", cujName); - } - @CujType - public int getCuj() { - return mCujType; + public String getSessionName() { + return mSessionName; } public int getStatsdInteractionType() { - return CUJ_TO_STATSD_INTERACTION_TYPE[mCujType]; + return Cuj.getStatsdInteractionType(mCujType); } /** Describes whether the measurement from this session should be written to statsd. */ public boolean logToStatsd() { - return getStatsdInteractionType() != NO_STATSD_LOGGING; + return Cuj.logToStatsd(mCujType); } public String getPerfettoTrigger() { - return String.format(Locale.US, "com.android.telemetry.interaction-jank-monitor-%d", - mCujType); - } - - public String getName() { - return mName; - } - - public long getTimeStamp() { - return mTimeStamp; - } - - public void setReason(@Reasons int reason) { - mReason = reason; + return TextUtils.formatSimple( + "com.android.telemetry.interaction-jank-monitor-%d", mCujType); } - @Reasons - public int getReason() { - return mReason; + public @Cuj.CujType int getCujType() { + return mCujType; } } @@ -1468,15 +902,15 @@ public class InteractionJankMonitor { void invoke(long unixNanos, long elapsedNanos, long realtimeNanos); } - private void postEventLogToWorkerThread(TimeFunction logFunction) { - final Instant now = Instant.now(); - final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS) - + now.getNano(); - final long elapsedNanos = SystemClock.elapsedRealtimeNanos(); - final long realtimeNanos = SystemClock.uptimeNanos(); + static class RunningTracker { + public final Configuration mConfig; + public final FrameTracker mTracker; + public final Runnable mTimeoutAction; - mWorker.getThreadHandler().post(() -> { - logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos); - }); + RunningTracker(Configuration config, FrameTracker tracker, Runnable timeoutAction) { + this.mConfig = config; + this.mTracker = tracker; + this.mTimeoutAction = timeoutAction; + } } } diff --git a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java index ef7944c21ad2..f3f16a0c662d 100644 --- a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java +++ b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java @@ -34,7 +34,6 @@ import android.view.WindowCallbacks; import com.android.internal.annotations.GuardedBy; import com.android.internal.jank.FrameTracker.Reasons; -import com.android.internal.jank.InteractionJankMonitor.CujType; /** * An overlay that uses WindowCallbacks to draw the names of all running CUJs to the window @@ -94,14 +93,14 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { } @UiThread - private boolean attachViewRootIfNeeded(FrameTracker tracker) { - FrameTracker.ViewRootWrapper viewRoot = tracker.getViewRoot(); + private boolean attachViewRootIfNeeded(InteractionJankMonitor.RunningTracker tracker) { + FrameTracker.ViewRootWrapper viewRoot = tracker.mTracker.getViewRoot(); if (mViewRoot == null && viewRoot != null) { // Add a trace marker so we can identify traces that were captured while the debug // overlay was enabled. Traces that use the debug overlay should NOT be used for // performance analysis. Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, TRACK_NAME, "DEBUG_OVERLAY_DRAW", 0); - mHandler = tracker.getHandler(); + mHandler = tracker.mConfig.getHandler(); mViewRoot = viewRoot; mHandler.runWithScissors(() -> viewRoot.addWindowCallbacks(this), InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT); @@ -111,11 +110,12 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { return false; } + @GuardedBy("mLock") private float getWidthOfLongestCujName(int cujFontSize) { mDebugPaint.setTextSize(cujFontSize); float maxLength = 0; for (int i = 0; i < mRunningCujs.size(); i++) { - String cujName = InteractionJankMonitor.getNameOfCuj(mRunningCujs.keyAt(i)); + String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i)); float textLength = mDebugPaint.measureText(cujName); if (textLength > maxLength) { maxLength = textLength; @@ -149,8 +149,8 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { } @UiThread - void onTrackerRemoved(@CujType int removedCuj, @Reasons int reason, - SparseArray<FrameTracker> runningTrackers) { + void onTrackerRemoved(@Cuj.CujType int removedCuj, @Reasons int reason, + SparseArray<InteractionJankMonitor.RunningTracker> runningTrackers) { synchronized (mLock) { mRunningCujs.put(removedCuj, reason); // If REASON_STILL_RUNNING is not in mRunningCujs, then all CUJs have ended @@ -164,7 +164,7 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { // trackers for (int i = 0; i < runningTrackers.size(); i++) { if (mViewRoot.equals( - runningTrackers.valueAt(i).getViewRoot())) { + runningTrackers.valueAt(i).mTracker.getViewRoot())) { needsNewViewRoot = false; break; } @@ -185,7 +185,7 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { } @UiThread - void onTrackerAdded(@CujType int addedCuj, FrameTracker tracker) { + void onTrackerAdded(@Cuj.CujType int addedCuj, InteractionJankMonitor.RunningTracker tracker) { synchronized (mLock) { // Use REASON_STILL_RUNNING (not technically one of the '@Reasons') to indicate the CUJ // is still running @@ -230,41 +230,44 @@ class InteractionMonitorDebugOverlay implements WindowCallbacks { int cujFontSize = dipToPx(18); final float cujNameTextHeight = getTextHeight(cujFontSize); final float packageNameTextHeight = getTextHeight(packageNameFontSize); - float maxLength = getWidthOfLongestCujName(cujFontSize); - final int dx = (int) ((w - maxLength) / 2f); - canvas.translate(dx, dy); - // Draw background rectangle for displaying the text showing the CUJ name - mDebugPaint.setColor(mBgColor); - canvas.drawRect( - -padding * 2, // more padding on top so we can draw the package name - -padding, - padding * 2 + maxLength, - padding * 2 + packageNameTextHeight + cujNameTextHeight * mRunningCujs.size(), - mDebugPaint); - mDebugPaint.setTextSize(packageNameFontSize); - mDebugPaint.setColor(Color.BLACK); - mDebugPaint.setStrikeThruText(false); - canvas.translate(0, packageNameTextHeight); - canvas.drawText("package:" + mPackageName, 0, 0, mDebugPaint); - mDebugPaint.setTextSize(cujFontSize); - // Draw text for CUJ names - for (int i = 0; i < mRunningCujs.size(); i++) { - int status = mRunningCujs.valueAt(i); - if (status == REASON_STILL_RUNNING) { - mDebugPaint.setColor(Color.BLACK); - mDebugPaint.setStrikeThruText(false); - } else if (status == REASON_END_NORMAL) { - mDebugPaint.setColor(Color.GRAY); - mDebugPaint.setStrikeThruText(false); - } else { - // Cancelled, or otherwise ended for a bad reason - mDebugPaint.setColor(Color.RED); - mDebugPaint.setStrikeThruText(true); + synchronized (mLock) { + float maxLength = getWidthOfLongestCujName(cujFontSize); + + final int dx = (int) ((w - maxLength) / 2f); + canvas.translate(dx, dy); + // Draw background rectangle for displaying the text showing the CUJ name + mDebugPaint.setColor(mBgColor); + canvas.drawRect( + -padding * 2, // more padding on top so we can draw the package name + -padding, + padding * 2 + maxLength, + padding * 2 + packageNameTextHeight + cujNameTextHeight * mRunningCujs.size(), + mDebugPaint); + mDebugPaint.setTextSize(packageNameFontSize); + mDebugPaint.setColor(Color.BLACK); + mDebugPaint.setStrikeThruText(false); + canvas.translate(0, packageNameTextHeight); + canvas.drawText("package:" + mPackageName, 0, 0, mDebugPaint); + mDebugPaint.setTextSize(cujFontSize); + // Draw text for CUJ names + for (int i = 0; i < mRunningCujs.size(); i++) { + int status = mRunningCujs.valueAt(i); + if (status == REASON_STILL_RUNNING) { + mDebugPaint.setColor(Color.BLACK); + mDebugPaint.setStrikeThruText(false); + } else if (status == REASON_END_NORMAL) { + mDebugPaint.setColor(Color.GRAY); + mDebugPaint.setStrikeThruText(false); + } else { + // Cancelled, or otherwise ended for a bad reason + mDebugPaint.setColor(Color.RED); + mDebugPaint.setStrikeThruText(true); + } + String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i)); + canvas.translate(0, cujNameTextHeight); + canvas.drawText(cujName, 0, 0, mDebugPaint); } - String cujName = InteractionJankMonitor.getNameOfCuj(mRunningCujs.keyAt(i)); - canvas.translate(0, cujNameTextHeight); - canvas.drawText(cujName, 0, 0, mDebugPaint); } } } diff --git a/core/tests/coretests/src/com/android/internal/jank/CujTest.java b/core/tests/coretests/src/com/android/internal/jank/CujTest.java new file mode 100644 index 000000000000..bf35ed0a1601 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/jank/CujTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.jank; + +import static android.text.TextUtils.formatSimple; + +import static com.android.internal.jank.Cuj.getNameOfCuj; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import androidx.test.filters.SmallTest; + +import com.android.internal.util.FrameworkStatsLog; + +import com.google.common.truth.Expect; + +import org.junit.Rule; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@SmallTest +public class CujTest { + private static final String ENUM_NAME_PREFIX = + "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__"; + private static final Set<String> DEPRECATED_VALUES = new HashSet<>() { + { + add(ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION"); + } + }; + private static final Map<Integer, String> ENUM_NAME_EXCEPTION_MAP = new HashMap<>() { + { + put(Cuj.CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD")); + put(Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR")); + put(Cuj.CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH")); + put(Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR")); + put(Cuj.CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE")); + put(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE")); + put(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE")); + put(Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE")); + put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND")); + put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE")); + put(Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING")); + } + }; + + @Rule + public final Expect mExpect = Expect.create(); + + @Test + public void testCujNameLimit() { + getCujConstants().forEach(f -> { + final int cuj = getIntFieldChecked(f); + mExpect.withMessage(formatSimple("Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj))) + .that(getNameOfCuj(cuj).length()) + .isAtMost(Cuj.MAX_LENGTH_OF_CUJ_NAME); + }); + } + + @Test + public void testCujTypeEnumCorrectlyDefined() throws Exception { + List<Field> cujEnumFields = getCujConstants().toList(); + + HashSet<Integer> allValues = new HashSet<>(); + for (Field field : cujEnumFields) { + int fieldValue = field.getInt(null); + assertWithMessage("All CujType values must be unique. Field %s repeats existing value.", + field.getName()) + .that(allValues.add(fieldValue)) + .isTrue(); + assertWithMessage("Field %s must have a value <= LAST_CUJ", field.getName()) + .that(fieldValue) + .isAtMost(Cuj.LAST_CUJ); + assertWithMessage("Field %s must have a statsd mapping.", field.getName()) + .that(Cuj.logToStatsd(fieldValue)) + .isTrue(); + } + } + + @Test + public void testCujsMapToEnumsCorrectly() { + List<Field> cujs = getCujConstants().toList(); + + Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields()) + .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX) + && !DEPRECATED_VALUES.contains(f.getName()) + && Modifier.isStatic(f.getModifiers()) + && f.getType() == int.class) + .collect(Collectors.toMap(CujTest::getIntFieldChecked, Field::getName)); + + assertThat(enumsMap.size() - 1).isEqualTo(cujs.size()); + + cujs.forEach(f -> { + final int cuj = getIntFieldChecked(f); + final String cujName = f.getName(); + final String expectedEnumName = + ENUM_NAME_EXCEPTION_MAP.getOrDefault(cuj, getEnumName(cujName.substring(4))); + final int enumKey = Cuj.getStatsdInteractionType(cuj); + final String enumName = enumsMap.get(enumKey); + final String expectedNameOfCuj = formatSimple("CUJ_%s", getNameOfCuj(cuj)); + + mExpect.withMessage( + formatSimple("%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey)) + .that(expectedEnumName.equals(enumName)) + .isTrue(); + mExpect.withMessage( + formatSimple("getNameOfCuj(%d) not matches: %s, expected=%s", + cuj, cujName, expectedNameOfCuj)) + .that(cujName.equals(expectedNameOfCuj)) + .isTrue(); + }); + } + + private static String getEnumName(String name) { + return formatSimple("%s%s", ENUM_NAME_PREFIX, name); + } + + private static int getIntFieldChecked(Field field) { + try { + return field.getInt(null); + } catch (IllegalAccessException ex) { + throw new RuntimeException(ex); + } + } + + private static Stream<Field> getCujConstants() { + return Arrays.stream(Cuj.class.getDeclaredFields()) + .filter(f -> f.getName().startsWith("CUJ_") + && Modifier.isStatic(f.getModifiers()) + && f.getType() == int.class); + } +} diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java index 1b9717a6dfc5..1a7117e3b4a1 100644 --- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java @@ -22,9 +22,8 @@ import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_ import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import static com.android.internal.jank.FrameTracker.ViewRootWrapper; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_WALLPAPER_TRANSITION; +import static com.android.internal.jank.Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; +import static com.android.internal.jank.Cuj.CUJ_WALLPAPER_TRANSITION; import static com.android.internal.util.FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED; import static com.google.common.truth.Truth.assertThat; @@ -49,15 +48,14 @@ import android.view.SurfaceControl.OnJankDataListener; import android.view.View; import android.view.ViewAttachTestActivity; +import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; -import androidx.test.rule.ActivityTestRule; import com.android.internal.jank.FrameTracker.ChoreographerWrapper; import com.android.internal.jank.FrameTracker.FrameMetricsWrapper; import com.android.internal.jank.FrameTracker.StatsLogWrapper; import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper; import com.android.internal.jank.InteractionJankMonitor.Configuration; -import com.android.internal.jank.InteractionJankMonitor.Session; import org.junit.Before; import org.junit.Rule; @@ -69,14 +67,14 @@ import java.util.concurrent.TimeUnit; @SmallTest public class FrameTrackerTest { - private static final String CUJ_POSTFIX = ""; + private static final String SESSION_NAME = "SessionName"; private static final long FRAME_TIME_60Hz = (long) 1e9 / 60; private ViewAttachTestActivity mActivity; @Rule - public ActivityTestRule<ViewAttachTestActivity> mRule = - new ActivityTestRule<>(ViewAttachTestActivity.class); + public ActivityScenarioRule<ViewAttachTestActivity> mRule = + new ActivityScenarioRule<>(ViewAttachTestActivity.class); private ThreadedRendererWrapper mRenderer; private FrameMetricsWrapper mWrapper; @@ -86,12 +84,13 @@ public class FrameTrackerTest { private StatsLogWrapper mStatsLog; private ArgumentCaptor<OnJankDataListener> mListenerCapture; private SurfaceControl mSurfaceControl; + private FrameTracker.FrameTrackerListener mTrackerListener; private ArgumentCaptor<Runnable> mRunnableArgumentCaptor; @Before public void setup() { // Prepare an activity for getting ThreadedRenderer later. - mActivity = mRule.getActivity(); + mRule.getScenario().onActivity(activity -> mActivity = activity); View view = mActivity.getWindow().getDecorView(); assertThat(view.isAttachedToWindow()).isTrue(); @@ -116,36 +115,38 @@ public class FrameTrackerTest { mChoreographer = mock(ChoreographerWrapper.class); mStatsLog = mock(StatsLogWrapper.class); mRunnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); + mTrackerListener = mock(FrameTracker.FrameTrackerListener.class); } - private FrameTracker spyFrameTracker(int cuj, String postfix, boolean surfaceOnly) { - InteractionJankMonitor monitor = mock(InteractionJankMonitor.class); - Handler handler = mRule.getActivity().getMainThreadHandler(); - Session session = new Session(cuj, postfix); + private FrameTracker spyFrameTracker(boolean surfaceOnly) { + Handler handler = mActivity.getMainThreadHandler(); Configuration config = mock(Configuration.class); + when(config.getSessionName()).thenReturn(SESSION_NAME); when(config.isSurfaceOnly()).thenReturn(surfaceOnly); when(config.getSurfaceControl()).thenReturn(mSurfaceControl); when(config.shouldDeferMonitor()).thenReturn(true); when(config.getDisplayId()).thenReturn(42); - View view = mRule.getActivity().getWindow().getDecorView(); + View view = mActivity.getWindow().getDecorView(); Handler spyHandler = spy(new Handler(handler.getLooper())); when(config.getView()).thenReturn(surfaceOnly ? null : view); when(config.getHandler()).thenReturn(spyHandler); + when(config.logToStatsd()).thenReturn(true); + when(config.getStatsdInteractionType()).thenReturn(surfaceOnly + ? Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION) + : Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)); FrameTracker frameTracker = Mockito.spy( - new FrameTracker(monitor, session, spyHandler, mRenderer, mViewRootWrapper, + new FrameTracker(config, mRenderer, mViewRootWrapper, mSurfaceControlWrapper, mChoreographer, mWrapper, mStatsLog, /* traceThresholdMissedFrames= */ 1, /* traceThresholdFrameTimeMillis= */ -1, - /* FrameTrackerListener= */ null, config)); - doNothing().when(frameTracker).triggerPerfetto(); + mTrackerListener)); doNothing().when(frameTracker).postTraceStartMarker(mRunnableArgumentCaptor.capture()); return frameTracker; } @Test public void testOnlyFirstWindowFrameOverThreshold() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); // Just provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP)) @@ -169,11 +170,11 @@ public class FrameTrackerTest { sendFrame(tracker, 500, JANK_APP_DEADLINE_MISSED, 103L); verify(tracker).removeObservers(); - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, eq(5000000L) /* maxFrameTimeNanos */, @@ -184,8 +185,7 @@ public class FrameTrackerTest { @Test public void testSfJank() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -206,12 +206,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); // We detected a janky frame - trigger Perfetto - verify(tracker).triggerPerfetto(); + verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, @@ -222,8 +222,7 @@ public class FrameTrackerTest { @Test public void testFirstFrameJankyNoTrigger() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -243,13 +242,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); - // We detected a janky frame - trigger Perfetto - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, @@ -260,8 +258,7 @@ public class FrameTrackerTest { @Test public void testOtherFrameOverThreshold() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -282,12 +279,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); // We detected a janky frame - trigger Perfetto - verify(tracker).triggerPerfetto(); + verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, @@ -298,8 +295,7 @@ public class FrameTrackerTest { @Test public void testLastFrameOverThresholdBeforeEnd() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -323,12 +319,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); // We detected a janky frame - trigger Perfetto - verify(tracker).triggerPerfetto(); + verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, eq(50000000L) /* maxFrameTimeNanos */, @@ -342,8 +338,7 @@ public class FrameTrackerTest { */ @Test public void testNoOvercountingAfterEnd() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -367,11 +362,11 @@ public class FrameTrackerTest { sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L); verify(tracker).removeObservers(); - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), + eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, @@ -382,8 +377,7 @@ public class FrameTrackerTest { @Test public void testBeginCancel() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -402,13 +396,12 @@ public class FrameTrackerTest { tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); verify(tracker).removeObservers(); // Since the tracker has been cancelled, shouldn't trigger perfetto. - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); } @Test public void testCancelIfEndVsyncIdEqualsToBeginVsyncId() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -426,13 +419,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); // Should never trigger Perfetto since it is a cancel. - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); } @Test public void testCancelIfEndVsyncIdLessThanBeginVsyncId() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -450,13 +442,12 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); // Should never trigger Perfetto since it is a cancel. - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); } @Test public void testCancelWhenSessionNeverBegun() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL); verify(tracker).removeObservers(); @@ -464,8 +455,7 @@ public class FrameTrackerTest { @Test public void testEndWhenSessionNeverBegun() { - FrameTracker tracker = spyFrameTracker( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false); tracker.end(FrameTracker.REASON_END_NORMAL); verify(tracker).removeObservers(); @@ -473,8 +463,7 @@ public class FrameTrackerTest { @Test public void testSurfaceOnlyOtherFrameJanky() { - FrameTracker tracker = spyFrameTracker( - CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -495,12 +484,12 @@ public class FrameTrackerTest { sendFrame(tracker, JANK_NONE, 103L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); - verify(tracker).triggerPerfetto(); + verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), + eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, @@ -511,8 +500,7 @@ public class FrameTrackerTest { @Test public void testSurfaceOnlyFirstFrameJanky() { - FrameTracker tracker = spyFrameTracker( - CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -533,12 +521,12 @@ public class FrameTrackerTest { sendFrame(tracker, JANK_NONE, 103L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), + eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, @@ -549,8 +537,7 @@ public class FrameTrackerTest { @Test public void testSurfaceOnlyLastFrameJanky() { - FrameTracker tracker = spyFrameTracker( - CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); @@ -571,12 +558,12 @@ public class FrameTrackerTest { sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 103L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); - verify(tracker, never()).triggerPerfetto(); + verify(mTrackerListener, never()).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), + eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, @@ -587,8 +574,7 @@ public class FrameTrackerTest { @Test public void testMaxSuccessiveMissedFramesCount() { - FrameTracker tracker = spyFrameTracker( - CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); + FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); mRunnableArgumentCaptor.getValue().run(); @@ -604,11 +590,11 @@ public class FrameTrackerTest { sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); - verify(tracker).triggerPerfetto(); + verify(mTrackerListener).triggerPerfetto(any()); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(DisplayRefreshRate.REFRESH_RATE_60_HZ), - eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), + eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)), eq(6L) /* totalFrames */, eq(5L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java index b61f995724e5..68095e5eb46c 100644 --- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java +++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java @@ -20,23 +20,9 @@ import static android.text.TextUtils.formatSimple; import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT; import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_ADD; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_APP_START; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_APPEAR; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_REMOVE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_EXPAND; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE; -import static com.android.internal.jank.InteractionJankMonitor.MAX_LENGTH_OF_CUJ_NAME; -import static com.android.internal.jank.InteractionJankMonitor.getNameOfCuj; +import static com.android.internal.jank.InteractionJankMonitor.Configuration.generateSessionName; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -52,12 +38,11 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.SystemClock; import android.provider.DeviceConfig; -import android.util.SparseArray; import android.view.View; import android.view.ViewAttachTestActivity; +import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; -import androidx.test.rule.ActivityTestRule; import com.android.internal.jank.FrameTracker.ChoreographerWrapper; import com.android.internal.jank.FrameTracker.FrameMetricsWrapper; @@ -66,101 +51,54 @@ import com.android.internal.jank.FrameTracker.SurfaceControlWrapper; import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper; import com.android.internal.jank.FrameTracker.ViewRootWrapper; import com.android.internal.jank.InteractionJankMonitor.Configuration; -import com.android.internal.jank.InteractionJankMonitor.Session; -import com.android.internal.util.FrameworkStatsLog; import com.google.common.truth.Expect; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; @SmallTest public class InteractionJankMonitorTest { - private static final String CUJ_POSTFIX = ""; - private static final SparseArray<String> ENUM_NAME_EXCEPTION_MAP = new SparseArray<>(); - private static final String ENUM_NAME_PREFIX = - "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__"; - - private static final ArrayList<String> DEPRECATED_VALUES = new ArrayList<>(); - private ViewAttachTestActivity mActivity; private View mView; + private Handler mHandler; private HandlerThread mWorker; @Rule - public ActivityTestRule<ViewAttachTestActivity> mRule = - new ActivityTestRule<>(ViewAttachTestActivity.class); + public ActivityScenarioRule<ViewAttachTestActivity> mRule = + new ActivityScenarioRule<>(ViewAttachTestActivity.class); @Rule public final Expect mExpect = Expect.create(); - @BeforeClass - public static void initialize() { - ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD")); - ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE")); - ENUM_NAME_EXCEPTION_MAP.put( - CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING")); - DEPRECATED_VALUES.add(ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION"); - } - - private static String getEnumName(String name) { - return formatSimple("%s%s", ENUM_NAME_PREFIX, name); - } - @Before public void setup() { - // Prepare an activity for getting ThreadedRenderer later. - mActivity = mRule.getActivity(); + mRule.getScenario().onActivity(activity -> mActivity = activity); mView = mActivity.getWindow().getDecorView(); assertThat(mView.isAttachedToWindow()).isTrue(); - Handler handler = spy(new Handler(mActivity.getMainLooper())); - doReturn(true).when(handler).sendMessageAtTime(any(), anyLong()); + mHandler = spy(new Handler(mActivity.getMainLooper())); + doReturn(true).when(mHandler).sendMessageAtTime(any(), anyLong()); mWorker = mock(HandlerThread.class); - doReturn(handler).when(mWorker).getThreadHandler(); + doReturn(mHandler).when(mWorker).getThreadHandler(); } @Test public void testBeginEnd() { InteractionJankMonitor monitor = createMockedInteractionJankMonitor(); - FrameTracker tracker = createMockedFrameTracker(monitor, null); - doReturn(tracker).when(monitor).createFrameTracker(any(), any()); + FrameTracker tracker = createMockedFrameTracker(); + doReturn(tracker).when(monitor).createFrameTracker(any()); doNothing().when(tracker).begin(); doReturn(true).when(tracker).end(anyInt()); // Simulate a trace session and see if begin / end are invoked. - assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); + assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); verify(tracker).begin(); - assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); + assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); verify(tracker).end(REASON_END_NORMAL); } @@ -172,10 +110,10 @@ public class InteractionJankMonitorTest { propertiesValues.put("enabled", "false"); DeviceConfig.Properties properties = new DeviceConfig.Properties( DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR, propertiesValues); - monitor.getPropertiesChangedListener().onPropertiesChanged(properties); + monitor.updateProperties(properties); - assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); - assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); + assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); + assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); } @Test @@ -185,145 +123,57 @@ public class InteractionJankMonitorTest { assertThat(view.isAttachedToWindow()).isFalse(); // Should return false if the view passed in is not attached to window yet. - assertThat(monitor.begin(view, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); - assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); + assertThat(monitor.begin(view, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); + assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse(); } @Test public void testBeginTimeout() { ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class); InteractionJankMonitor monitor = createMockedInteractionJankMonitor(); - FrameTracker tracker = createMockedFrameTracker(monitor, null); - doReturn(tracker).when(monitor).createFrameTracker(any(), any()); + FrameTracker tracker = createMockedFrameTracker(); + doReturn(tracker).when(monitor).createFrameTracker(any()); doNothing().when(tracker).begin(); doReturn(true).when(tracker).cancel(anyInt()); - assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); + assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); verify(tracker).begin(); - verify(monitor).scheduleTimeoutAction(anyInt(), anyLong(), captor.capture()); + verify(monitor).scheduleTimeoutAction(any(), captor.capture()); Runnable runnable = captor.getValue(); assertThat(runnable).isNotNull(); - mWorker.getThreadHandler().removeCallbacks(runnable); runnable.run(); - verify(monitor).cancel(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, REASON_CANCEL_TIMEOUT); + verify(monitor).cancel(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, REASON_CANCEL_TIMEOUT); verify(tracker).cancel(REASON_CANCEL_TIMEOUT); } - @Test - public void testCujTypeEnumCorrectlyDefined() throws Exception { - List<Field> cujEnumFields = - Arrays.stream(InteractionJankMonitor.class.getDeclaredFields()) - .filter(field -> field.getName().startsWith("CUJ_") - && Modifier.isStatic(field.getModifiers()) - && field.getType() == int.class) - .collect(Collectors.toList()); - - HashSet<Integer> allValues = new HashSet<>(); - for (Field field : cujEnumFields) { - int fieldValue = field.getInt(null); - assertWithMessage( - "Field %s must have a mapping to a value in CUJ_TO_STATSD_INTERACTION_TYPE", - field.getName()) - .that(fieldValue < CUJ_TO_STATSD_INTERACTION_TYPE.length) - .isTrue(); - assertWithMessage("All CujType values must be unique. Field %s repeats existing value.", - field.getName()) - .that(allValues.add(fieldValue)) - .isTrue(); - } - } - - @Test - public void testCujsMapToEnumsCorrectly() { - List<Field> cujs = Arrays.stream(InteractionJankMonitor.class.getDeclaredFields()) - .filter(f -> f.getName().startsWith("CUJ_") - && Modifier.isStatic(f.getModifiers()) - && f.getType() == int.class) - .collect(Collectors.toList()); - - Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields()) - .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX) - && !DEPRECATED_VALUES.contains(f.getName()) - && Modifier.isStatic(f.getModifiers()) - && f.getType() == int.class) - .collect(Collectors.toMap(this::getIntFieldChecked, Field::getName)); - - assertThat(enumsMap.size() - 1).isEqualTo(cujs.size()); - - cujs.forEach(f -> { - final int cuj = getIntFieldChecked(f); - final String cujName = f.getName(); - final String expectedEnumName = ENUM_NAME_EXCEPTION_MAP.contains(cuj) - ? ENUM_NAME_EXCEPTION_MAP.get(cuj) - : formatSimple("%s%s", ENUM_NAME_PREFIX, cujName.substring(4)); - final int enumKey = CUJ_TO_STATSD_INTERACTION_TYPE[cuj]; - final String enumName = enumsMap.get(enumKey); - final String expectedNameOfCuj = formatSimple("CUJ_%s", getNameOfCuj(cuj)); - - mExpect - .withMessage(formatSimple( - "%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey)) - .that(expectedEnumName.equals(enumName)) - .isTrue(); - mExpect - .withMessage( - formatSimple("getNameOfCuj(%d) not matches: %s, expected=%s", - cuj, cujName, expectedNameOfCuj)) - .that(cujName.equals(expectedNameOfCuj)) - .isTrue(); - }); - } - - @Test - public void testCujNameLimit() { - Arrays.stream(InteractionJankMonitor.class.getDeclaredFields()) - .filter(f -> f.getName().startsWith("CUJ_") - && Modifier.isStatic(f.getModifiers()) - && f.getType() == int.class) - .forEach(f -> { - final int cuj = getIntFieldChecked(f); - mExpect - .withMessage(formatSimple( - "Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj))) - .that(getNameOfCuj(cuj).length()) - .isAtMost(MAX_LENGTH_OF_CUJ_NAME); - }); - } - @Test public void testSessionNameLengthLimit() { - final int cujType = CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; - final String cujName = getNameOfCuj(cujType); + final int cujType = Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; + final String cujName = Cuj.getNameOfCuj(cujType); final String cujTag = "ThisIsTheCujTag"; final String tooLongTag = cujTag.repeat(10); // Normal case, no postfix. - Session noPostfix = new Session(cujType, ""); - assertThat(noPostfix.getName()).isEqualTo(formatSimple("J<%s>", cujName)); + assertThat(generateSessionName(cujName, "")).isEqualTo(formatSimple("J<%s>", cujName)); // Normal case, with postfix. - Session withPostfix = new Session(cujType, cujTag); - assertThat(withPostfix.getName()).isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag)); + assertThat(generateSessionName(cujName, cujTag)) + .isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag)); // Since the length of the cuj name is tested in another test, no need to test it here. // Too long postfix case, should trim the postfix and keep the cuj name completed. final String expectedTrimmedName = formatSimple("J<%s::%s>", cujName, "ThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThi..."); - Session longPostfix = new Session(cujType, tooLongTag); - assertThat(longPostfix.getName()).isEqualTo(expectedTrimmedName); + assertThat(generateSessionName(cujName, tooLongTag)).isEqualTo(expectedTrimmedName); } private InteractionJankMonitor createMockedInteractionJankMonitor() { InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker)); - doReturn(true).when(monitor).shouldMonitor(anyInt()); + doReturn(true).when(monitor).shouldMonitor(); return monitor; } - private FrameTracker createMockedFrameTracker(InteractionJankMonitor monitor, - FrameTracker.FrameTrackerListener listener) { - Session session = spy(new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX)); - doReturn(false).when(session).logToStatsd(); - + private FrameTracker createMockedFrameTracker() { ThreadedRendererWrapper threadedRenderer = mock(ThreadedRendererWrapper.class); doNothing().when(threadedRenderer).addObserver(any()); doNothing().when(threadedRenderer).removeObserver(any()); @@ -342,27 +192,19 @@ public class InteractionJankMonitorTest { Configuration configuration = mock(Configuration.class); when(configuration.isSurfaceOnly()).thenReturn(false); when(configuration.getView()).thenReturn(mView); - when(configuration.getHandler()).thenReturn(mView.getHandler()); when(configuration.getDisplayId()).thenReturn(42); + when(configuration.logToStatsd()).thenReturn(false); + when(configuration.getHandler()).thenReturn(mHandler); - FrameTracker tracker = spy(new FrameTracker(monitor, session, mWorker.getThreadHandler(), + FrameTracker tracker = spy(new FrameTracker(configuration, threadedRenderer, viewRoot, surfaceControl, choreographer, new FrameMetricsWrapper(), new StatsLogWrapper(null), /* traceThresholdMissedFrames= */ 1, - /* traceThresholdFrameTimeMillis= */ -1, listener, configuration)); + /* traceThresholdFrameTimeMillis= */ -1, + /* listener */ null)); doNothing().when(tracker).postTraceStartMarker(any()); - doNothing().when(tracker).triggerPerfetto(); - doReturn(configuration.getHandler()).when(tracker).getHandler(); return tracker; } - - private int getIntFieldChecked(Field field) { - try { - return field.getInt(null); - } catch (IllegalAccessException ex) { - throw new RuntimeException(ex); - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java index dc413b059fd7..a32b435ff99e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java @@ -28,7 +28,7 @@ import android.view.RemoteAnimationTarget; import android.window.IBackAnimationRunner; import android.window.IOnBackInvokedCallback; -import com.android.internal.jank.InteractionJankMonitor; +import com.android.internal.jank.Cuj.CujType; import com.android.wm.shell.common.InteractionJankMonitorUtils; /** @@ -42,7 +42,7 @@ public class BackAnimationRunner { private final IOnBackInvokedCallback mCallback; private final IRemoteAnimationRunner mRunner; - private final @InteractionJankMonitor.CujType int mCujType; + private final @CujType int mCujType; private final Context mContext; // Whether we are waiting to receive onAnimationStart @@ -55,7 +55,7 @@ public class BackAnimationRunner { @NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner, @NonNull Context context, - @InteractionJankMonitor.CujType int cujType) { + @CujType int cujType) { mCallback = callback; mRunner = runner; mCujType = cujType; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java index ec344d345139..86f00b83cadd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java @@ -23,6 +23,7 @@ import android.text.TextUtils; import android.view.SurfaceControl; import android.view.View; +import com.android.internal.jank.Cuj.CujType; import com.android.internal.jank.InteractionJankMonitor; /** Utils class for simplfy InteractionJank trancing call */ @@ -31,11 +32,11 @@ public class InteractionJankMonitorUtils { /** * Begin a trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link CujType}. * @param view the view to trace * @param tag the tag to distinguish different flow of same type CUJ. */ - public static void beginTracing(@InteractionJankMonitor.CujType int cujType, + public static void beginTracing(@CujType int cujType, @NonNull View view, @Nullable String tag) { final InteractionJankMonitor.Configuration.Builder builder = InteractionJankMonitor.Configuration.Builder.withView(cujType, view); @@ -48,12 +49,12 @@ public class InteractionJankMonitorUtils { /** * Begin a trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link CujType}. * @param context the context * @param surface the surface to trace * @param tag the tag to distinguish different flow of same type CUJ. */ - public static void beginTracing(@InteractionJankMonitor.CujType int cujType, + public static void beginTracing(@CujType int cujType, @NonNull Context context, @NonNull SurfaceControl surface, @Nullable String tag) { final InteractionJankMonitor.Configuration.Builder builder = InteractionJankMonitor.Configuration.Builder.withSurface(cujType, context, surface); @@ -66,18 +67,18 @@ public class InteractionJankMonitorUtils { /** * End a trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link CujType}. */ - public static void endTracing(@InteractionJankMonitor.CujType int cujType) { + public static void endTracing(@CujType int cujType) { InteractionJankMonitor.getInstance().end(cujType); } /** * Cancel the trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link CujType}. */ - public static void cancelTracing(@InteractionJankMonitor.CujType int cujType) { + public static void cancelTracing(@CujType int cujType) { InteractionJankMonitor.getInstance().cancel(cujType); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index 38ce16489b06..d157ca837608 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -16,8 +16,8 @@ package com.android.wm.shell.onehanded; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_ONE_HANDED_ENTER_TRANSITION; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_ONE_HANDED_EXIT_TRANSITION; +import static com.android.internal.jank.Cuj.CUJ_ONE_HANDED_ENTER_TRANSITION; +import static com.android.internal.jank.Cuj.CUJ_ONE_HANDED_EXIT_TRANSITION; import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT; import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER; @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import com.android.internal.jank.Cuj.CujType; import com.android.internal.jank.InteractionJankMonitor; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; @@ -327,7 +328,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { mTransitionCallbacks.add(callback); } - void beginCUJTracing(@InteractionJankMonitor.CujType int cujType, @Nullable String tag) { + void beginCUJTracing(@CujType int cujType, @Nullable String tag) { final Map.Entry<WindowContainerToken, SurfaceControl> firstEntry = getDisplayAreaTokenMap().entrySet().iterator().next(); final InteractionJankMonitor.Configuration.Builder builder = @@ -339,11 +340,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { mJankMonitor.begin(builder); } - void endCUJTracing(@InteractionJankMonitor.CujType int cujType) { + void endCUJTracing(@CujType int cujType) { mJankMonitor.end(cujType); } - void cancelCUJTracing(@InteractionJankMonitor.CujType int cujType) { + void cancelCUJTracing(@CujType int cujType) { mJankMonitor.cancel(cujType); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java index 25833b3ddbba..5aee8cdb8b9e 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java @@ -16,7 +16,7 @@ package com.android.settingslib.core.instrumentation; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_SETTINGS_TOGGLE; +import static com.android.internal.jank.Cuj.CUJ_SETTINGS_TOGGLE; import static com.android.settingslib.core.instrumentation.SettingsJankMonitor.MONITORED_ANIMATION_DURATION_MS; import static com.google.common.truth.Truth.assertThat; @@ -34,8 +34,8 @@ import androidx.preference.PreferenceGroupAdapter; import androidx.preference.SwitchPreference; import androidx.recyclerview.widget.RecyclerView; +import com.android.internal.jank.Cuj.CujType; import com.android.internal.jank.InteractionJankMonitor; -import com.android.internal.jank.InteractionJankMonitor.CujType; import com.android.settingslib.testutils.OverpoweredReflectionHelper; import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor; diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index 187d0739b734..168039ed5d3d 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -33,8 +33,8 @@ import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS import com.android.app.animation.Interpolators +import com.android.internal.jank.Cuj.CujType import com.android.internal.jank.InteractionJankMonitor -import com.android.internal.jank.InteractionJankMonitor.CujType import com.android.systemui.util.maybeForceFullscreen import com.android.systemui.util.registerAnimationOnBackInvoked import kotlin.math.roundToInt diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt index af35ea44322f..b738e2bc972b 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt @@ -33,6 +33,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroupOverlay import android.widget.FrameLayout +import com.android.internal.jank.Cuj.CujType import com.android.internal.jank.InteractionJankMonitor import java.util.LinkedList import kotlin.math.min @@ -58,7 +59,7 @@ constructor( /** The view that will be ghosted and from which the background will be extracted. */ private val ghostedView: View, - /** The [InteractionJankMonitor.CujType] associated to this animation. */ + /** The [CujType] associated to this animation. */ private val cujType: Int? = null, private var interactionJankMonitor: InteractionJankMonitor = InteractionJankMonitor.getInstance(), diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java index c505bd502985..df7182b90f12 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java @@ -21,6 +21,7 @@ import android.os.Build; import android.text.TextUtils; import android.view.View; +import com.android.internal.jank.Cuj; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.jank.InteractionJankMonitor.Configuration; @@ -29,40 +30,25 @@ import java.lang.annotation.RetentionPolicy; public final class InteractionJankMonitorWrapper { // Launcher journeys. - public static final int CUJ_APP_LAUNCH_FROM_RECENTS = - InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS; - public static final int CUJ_APP_LAUNCH_FROM_ICON = - InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON; - public static final int CUJ_APP_CLOSE_TO_HOME = - InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_HOME; + public static final int CUJ_APP_LAUNCH_FROM_RECENTS = Cuj.CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS; + public static final int CUJ_APP_LAUNCH_FROM_ICON = Cuj.CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON; + public static final int CUJ_APP_CLOSE_TO_HOME = Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME; public static final int CUJ_APP_CLOSE_TO_HOME_FALLBACK = - InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK; - public static final int CUJ_APP_CLOSE_TO_PIP = - InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP; - public static final int CUJ_QUICK_SWITCH = - InteractionJankMonitor.CUJ_LAUNCHER_QUICK_SWITCH; - public static final int CUJ_OPEN_ALL_APPS = - InteractionJankMonitor.CUJ_LAUNCHER_OPEN_ALL_APPS; - public static final int CUJ_CLOSE_ALL_APPS_SWIPE = - InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE; - public static final int CUJ_CLOSE_ALL_APPS_TO_HOME = - InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME; - public static final int CUJ_ALL_APPS_SCROLL = - InteractionJankMonitor.CUJ_LAUNCHER_ALL_APPS_SCROLL; - public static final int CUJ_APP_LAUNCH_FROM_WIDGET = - InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET; - public static final int CUJ_SPLIT_SCREEN_ENTER = - InteractionJankMonitor.CUJ_SPLIT_SCREEN_ENTER; + Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK; + public static final int CUJ_APP_CLOSE_TO_PIP = Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_PIP; + public static final int CUJ_QUICK_SWITCH = Cuj.CUJ_LAUNCHER_QUICK_SWITCH; + public static final int CUJ_OPEN_ALL_APPS = Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS; + public static final int CUJ_CLOSE_ALL_APPS_SWIPE = Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE; + public static final int CUJ_CLOSE_ALL_APPS_TO_HOME = Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME; + public static final int CUJ_ALL_APPS_SCROLL = Cuj.CUJ_LAUNCHER_ALL_APPS_SCROLL; + public static final int CUJ_APP_LAUNCH_FROM_WIDGET = Cuj.CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET; + public static final int CUJ_SPLIT_SCREEN_ENTER = Cuj.CUJ_SPLIT_SCREEN_ENTER; public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION = - InteractionJankMonitor.CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; - public static final int CUJ_RECENTS_SCROLLING = - InteractionJankMonitor.CUJ_RECENTS_SCROLLING; - public static final int CUJ_APP_SWIPE_TO_RECENTS = - InteractionJankMonitor.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS; - public static final int CUJ_OPEN_SEARCH_RESULT = - InteractionJankMonitor.CUJ_LAUNCHER_OPEN_SEARCH_RESULT; - public static final int CUJ_LAUNCHER_UNFOLD_ANIM = - InteractionJankMonitor.CUJ_LAUNCHER_UNFOLD_ANIM; + Cuj.CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION; + public static final int CUJ_RECENTS_SCROLLING = Cuj.CUJ_RECENTS_SCROLLING; + public static final int CUJ_APP_SWIPE_TO_RECENTS = Cuj.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS; + public static final int CUJ_OPEN_SEARCH_RESULT = Cuj.CUJ_LAUNCHER_OPEN_SEARCH_RESULT; + public static final int CUJ_LAUNCHER_UNFOLD_ANIM = Cuj.CUJ_LAUNCHER_UNFOLD_ANIM; @IntDef({ CUJ_APP_LAUNCH_FROM_RECENTS, @@ -89,7 +75,7 @@ public final class InteractionJankMonitorWrapper { * Begin a trace session. * * @param v an attached view. - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. */ public static void begin(View v, @CujType int cujType) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return; @@ -100,7 +86,7 @@ public final class InteractionJankMonitorWrapper { * Begin a trace session. * * @param v an attached view. - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. * @param timeout duration to cancel the instrumentation in ms */ public static void begin(View v, @CujType int cujType, long timeout) { @@ -115,7 +101,7 @@ public final class InteractionJankMonitorWrapper { * Begin a trace session. * * @param v an attached view. - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. * @param tag the tag to distinguish different flow of same type CUJ. */ public static void begin(View v, @CujType int cujType, String tag) { @@ -131,7 +117,7 @@ public final class InteractionJankMonitorWrapper { /** * End a trace session. * - * @param cujType the specific {@link InteractionJankMonitor.CujType}. + * @param cujType the specific {@link Cuj.CujType}. */ public static void end(@CujType int cujType) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return; -- GitLab