1. 直观地观察应用启动时长
我们可以通过观察logcat日志查看Android应用启动耗时,过滤关键字"Displayed":
ActivityTaskManager: Displayed com.peter.viewgrouptutorial/.activity.DashboardActivity: +797ms
启动时长(在这个例子中797ms)表示从启动App到系统认为App启动完成所花费的时间。
2. 启动时间包含哪几个阶段
从用户点击桌面图标,到Activity启动并将界面第一帧绘制出来大概会经过以下几个阶段。
- system_server展示starting window
- Zygote fork Android 进程
- ActivityThread handleBindApplication(这个阶段又细分为)
• 加载程序代码和资源
• 初始化ContentProvider
• 执行Application.onCreate() - 启动Activity(执行 onCreate、onStart、onResume等方法)
- ViewRootImpl执行doFrame()绘制View,计算出首帧绘制时长。
流程图如下:

我们可以看出:阶段1和2都是由系统控制的。App开发者对这两个阶段的耗时能做的优化甚微。
3. 系统是如何测量启动时长的?
本文源码基于android-30
我们在cs.android.com源码阅读网站上全局搜索
1.在ActivityMetricsLogger.logAppDisplayed()方法中发现了打印日志语句
private void logAppDisplayed(
TransitionInfoSnapshot info
) {
if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
return;
}
EventLog.writeEvent(WM_ACTIVITY_LAUNCH_TIME,
info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName,
info.windowsDrawnDelayMs);
StringBuilder sb = mStringBuilder;
sb.setLength(0);
sb.append("Displayed ");
sb.append(info.launchedActivityShortComponentName);
sb.append(": ");
TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb);
Log.i(TAG, sb.toString());
}
- TransitionInfoSnapshot.windowsDrawnDelayMs是启动的时长。它在以下方法中被赋值:
• ActivityMetricsLogger.notifyWindowsDrawn()
• ➡️ TransitionInfo.calculateDelay()
//ActivityMetricsLogger.java
TransitionInfoSnapshot notifyWindowsDrawn(
ActivityRecord r,
long timestampNs
) {
TransitionInfo info = getActiveTransitionInfo(r);
info.mWindowsDrawnDelayMs = info.calculateDelay(timestampNs);
return new TransitionInfoSnapshot(info);
}
private static final class TransitionInfo {
int calculateDelay(long timestampNs) {
long delayNanos = timestampNs - mTransitionStartTimeNs;
return (int) TimeUnit.NANOSECONDS.toMillis(delayNanos);
}
}
- timestampNs表示启动结束时间,mTransitionStartTimeNs表示启动开始时间。它们分别是在哪赋值的呢?
mTransitionStartTimeNs启动开始时间在notifyActivityLaunching方法中被赋值。调用堆栈如下:
• ActivityManagerService.startActivity()
• ➡️ActivityManagerService.startActivityAsUser()
• ➡️ActivityStarter.execute()
• ➡️ActivityMetricsLogger.notifyActivityLaunching()

ActivityMetricsLogger.notifyActivityLaunching(…)
//ActivityMetricsLogger.java
private LaunchingState notifyActivityLaunching(
Intent intent,
ActivityRecord caller,
int callingUid
) {
...
long transitionStartNs = SystemClock.elapsedRealtimeNanos(



被折叠的 条评论
为什么被折叠?



