[1/n] Launcher Startup Latency: add StartupLatencyLogger to launcher3 and log startup latency
More details at "Log Startup Latency" section in go/launcher-startup-latency
Test: tested on phone, foldable and tablet, print latency logs in logcat
Bug: 278092752
Change-Id: Ibf269b0ecd6007d29b95e36f65ab6f02c45deb3a
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4dfd918..86a5f9f 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -56,6 +56,14 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RECONFIGURED;
+import static com.android.launcher3.logging.StatsLogManager.LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION;
+import static com.android.launcher3.logging.StatsLogManager.LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_VIEW_INFLATION;
+import static com.android.launcher3.logging.StatsLogManager.LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC;
+import static com.android.launcher3.logging.StatsLogManager.LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC;
+import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.LatencyType.COLD;
+import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.LatencyType.COLD_DEVICE_REBOOTING;
+import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.LatencyType.WARM;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
@@ -64,7 +72,6 @@
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch;
import android.animation.Animator;
@@ -111,6 +118,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
@@ -157,6 +165,7 @@
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
+import com.android.launcher3.logging.StartupLatencyLogger;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.ItemInstallQueue;
@@ -190,6 +199,7 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.PendingRequestArgs;
@@ -293,6 +303,8 @@
public static final String ON_RESUME_EVT = "Launcher.onResume";
public static final String ON_NEW_INTENT_EVT = "Launcher.onNewIntent";
+ private static boolean sIsNewProcess = true;
+
private StateManager<LauncherState> mStateManager;
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
@@ -404,12 +416,22 @@
private StringCache mStringCache;
private BaseSearchConfig mBaseSearchConfig;
-
+ private StartupLatencyLogger mStartupLatencyLogger;
private CellPosMapper mCellPosMapper = CellPosMapper.DEFAULT;
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
+ mStartupLatencyLogger = createStartupLatencyLogger(
+ sIsNewProcess
+ ? LockedUserState.get(this).isUserUnlockedAtLauncherStartup()
+ ? COLD
+ : COLD_DEVICE_REBOOTING
+ : WARM);
+ sIsNewProcess = false;
+ mStartupLatencyLogger
+ .logStart(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
+ .logStart(LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE);
// Only use a hard-coded cookie since we only want to trace this once.
if (Utilities.ATLEAST_S) {
Trace.beginAsyncSection(
@@ -518,6 +540,7 @@
}
}
+ mStartupLatencyLogger.logWorkspaceLoadStartTime();
if (!mModel.addCallbacksAndLoad(this)) {
if (!internalStateHandled) {
// If we are not binding synchronously, pause drawing until initial bind complete,
@@ -557,6 +580,17 @@
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
setTitle(R.string.home_screen);
+ mStartupLatencyLogger.logEnd(LAUNCHER_LATENCY_STARTUP_ACTIVITY_ON_CREATE);
+ }
+
+ /**
+ * Create {@link StartupLatencyLogger} that only collects launcher startup latency metrics
+ * without sending them anywhere. Child class can override this method to create logger
+ * that overrides {@link StartupLatencyLogger#log()} to report those metrics.
+ */
+ protected StartupLatencyLogger createStartupLatencyLogger(
+ StatsLogManager.StatsLatencyLogger.LatencyType latencyType) {
+ return new StartupLatencyLogger(latencyType);
}
/**
@@ -1290,7 +1324,10 @@
* Finds all the views we need and configure them properly.
*/
protected void setupViews() {
+ mStartupLatencyLogger.logStart(LAUNCHER_LATENCY_STARTUP_VIEW_INFLATION);
inflateRootView(R.layout.launcher);
+ mStartupLatencyLogger.logEnd(LAUNCHER_LATENCY_STARTUP_VIEW_INFLATION);
+
mDragLayer = findViewById(R.id.drag_layer);
mFocusHandler = mDragLayer.getFocusIndicatorHelper();
mWorkspace = mDragLayer.findViewById(R.id.workspace);
@@ -2695,7 +2732,8 @@
@Override
@TargetApi(Build.VERSION_CODES.S)
- public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) {
+ public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks,
+ int workspaceItemCount, boolean isBindSync) {
mSynchronouslyBoundPages = boundPages;
mPagesToBindSynchronously = new IntSet();
@@ -2719,6 +2757,26 @@
Trace.endAsyncSection(DISPLAY_WORKSPACE_TRACE_METHOD_NAME,
DISPLAY_WORKSPACE_TRACE_COOKIE);
}
+ mStartupLatencyLogger
+ .logCardinality(workspaceItemCount)
+ .logEnd(isBindSync
+ ? LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC
+ : LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC);
+ // In the first rootview's onDraw after onInitialBindComplete(), log end of startup latency.
+ getRootView().getViewTreeObserver().addOnDrawListener(
+ new ViewTreeObserver.OnDrawListener() {
+
+ @Override
+ public void onDraw() {
+ mStartupLatencyLogger
+ .logEnd(LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION)
+ .log()
+ .reset();
+ MAIN_EXECUTOR.getHandler().postAtFrontOfQueue(
+ () -> getRootView().getViewTreeObserver()
+ .removeOnDrawListener(this));
+ }
+ });
}
/**