blob: 5cbd8fd1cd60d36689501123c3a72af7e32acfde [file] [log] [blame]
Filip Gruszczynski77d94482015-12-11 13:59:52 -08001package com.android.server.am;
2
Jorim Jaggi3878ca32017-02-02 17:13:05 -08003import static android.app.ActivityManager.START_SUCCESS;
4import static android.app.ActivityManager.START_TASK_TO_FRONT;
Michal Karpinski3eab9512018-07-20 15:32:00 +01005import static android.app.ActivityManager.processStateAmToProto;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08006import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
Bryce Lee6c605092017-10-12 11:14:49 -07007import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07008import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
9import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Vishnu Naircf235042018-11-02 13:27:00 -070010import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale926aade2017-08-29 11:24:37 -070011import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
12import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Vishnu Naircf235042018-11-02 13:27:00 -070013
Michal Karpinski3eab9512018-07-20 15:32:00 +010014import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080015import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
Jorim Jaggi515dd682017-05-05 15:05:07 +020016import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070017import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020018import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CANCELLED;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080019import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
20import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070021import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020022import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING;
23import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
24import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080025import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
26import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
Michal Karpinski3eab9512018-07-20 15:32:00 +010027import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_FLAGS;
28import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_FULLSCREEN;
29import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY;
30import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE;
31import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD;
Vishnu Naircf235042018-11-02 13:27:00 -070032import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
Michal Karpinski3eab9512018-07-20 15:32:00 +010033import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH;
34import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE;
Michal Karpinski3eab9512018-07-20 15:32:00 +010035import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME;
36import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY;
37import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME;
38import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME;
39import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME;
40import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY;
41import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_PACKAGE_NAME;
42import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID;
43import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
44import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_PROC_STATE;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +020045import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
Michal Karpinski3eab9512018-07-20 15:32:00 +010046import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_COMING_FROM_PENDING_INTENT;
Todd Kennedy50d946c12017-03-17 13:55:38 -070047import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
Michal Karpinski3eab9512018-07-20 15:32:00 +010048import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INTENT_ACTION;
49import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_CUR_PROC_STATE;
50import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES;
51import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES;
52import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES;
53import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_OVERLAY_UI;
54import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_TOP_UI;
55import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION;
56import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT;
57import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT;
58import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN;
59import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME;
60import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID;
Michal Karpinski3eab9512018-07-20 15:32:00 +010061import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
Vishnu Naircf235042018-11-02 13:27:00 -070062import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
Michal Karpinski3eab9512018-07-20 15:32:00 +010063import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME;
64import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME;
65import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID;
66import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW;
67import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE;
68import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG;
Calin Juravle759fbda2018-02-20 19:52:30 +000069import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
Vishnu Naircf235042018-11-02 13:27:00 -070070import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080071import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
72import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020073import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
74import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080075import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020076import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
Jorim Jaggif9704102016-05-05 19:14:22 -070077import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
78import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Vishnu Naircf235042018-11-02 13:27:00 -070079import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
Ng Zhi Anbbefdec2018-01-30 17:12:39 -080080import static com.android.server.am.MemoryStatUtil.MemoryStat;
Rajeev Kumarbfcd9202018-03-02 22:42:13 +000081import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080082
Filip Gruszczynski77d94482015-12-11 13:59:52 -080083import android.content.Context;
Michal Karpinski3eab9512018-07-20 15:32:00 +010084import android.content.Intent;
Calin Juravle759fbda2018-02-20 19:52:30 +000085import android.content.pm.ApplicationInfo;
86import android.content.pm.dex.ArtManagerInternal;
87import android.content.pm.dex.PackageOptimizationInfo;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080088import android.metrics.LogMaker;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020089import android.os.Handler;
90import android.os.Looper;
91import android.os.Message;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080092import android.os.SystemClock;
Vishnu Naircf235042018-11-02 13:27:00 -070093import android.os.Trace;
94import android.util.EventLog;
95import android.util.Log;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020096import android.util.Slog;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080097import android.util.SparseArray;
98import android.util.SparseIntArray;
Olivier Gaillardaed7f122017-12-12 14:26:22 +000099import android.util.StatsLog;
Vishnu Naircf235042018-11-02 13:27:00 -0700100import android.util.TimeUtils;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800101
102import com.android.internal.logging.MetricsLogger;
Ng Zhi An83473542018-02-20 09:02:14 -0800103import com.android.internal.os.BackgroundThread;
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200104import com.android.internal.os.SomeArgs;
Calin Juravle759fbda2018-02-20 19:52:30 +0000105import com.android.server.LocalServices;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800106
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700107import java.util.ArrayList;
108
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800109/**
Vishnu Naircf235042018-11-02 13:27:00 -0700110 * Listens to activity launches, transitions, visibility changes and window drawn callbacks to
111 * determine app launch times and draw delays. Source of truth for activity metrics and provides
112 * data for Tron, logcat, event logs and {@link android.app.WaitResult}.
113 *
114 * Tests:
115 * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800116 */
117class ActivityMetricsLogger {
Jorim Jaggif9704102016-05-05 19:14:22 -0700118
119 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM;
120
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800121 // Window modes we are interested in logging. If we ever introduce a new type, we need to add
122 // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
123 private static final int WINDOW_STATE_STANDARD = 0;
124 private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
125 private static final int WINDOW_STATE_FREEFORM = 2;
Winson Chung83471632016-12-13 11:02:12 -0800126 private static final int WINDOW_STATE_ASSISTANT = 3;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800127 private static final int WINDOW_STATE_INVALID = -1;
128
Jorim Jaggi275561a2016-02-23 10:11:02 -0500129 private static final long INVALID_START_TIME = -1;
Vishnu Naircf235042018-11-02 13:27:00 -0700130 private static final int INVALID_DELAY = -1;
131 private static final int INVALID_TRANSITION_TYPE = -1;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500132
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200133 private static final int MSG_CHECK_VISIBILITY = 0;
134
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800135 // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
136 // time we log.
137 private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
Winson Chung83471632016-12-13 11:02:12 -0800138 "window_time_0", "window_time_1", "window_time_2", "window_time_3"};
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800139
140 private int mWindowState = WINDOW_STATE_STANDARD;
141 private long mLastLogTimeSecs;
142 private final ActivityStackSupervisor mSupervisor;
143 private final Context mContext;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800144 private final MetricsLogger mMetricsLogger = new MetricsLogger();
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800145
Jorim Jaggi275561a2016-02-23 10:11:02 -0500146 private long mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200147 private long mLastTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800148
149 private int mCurrentTransitionDeviceUptime;
150 private int mCurrentTransitionDelayMs;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500151 private boolean mLoggedTransitionStarting;
152
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100153 private final SparseArray<WindowingModeTransitionInfo> mWindowingModeTransitionInfo =
154 new SparseArray<>();
155 private final SparseArray<WindowingModeTransitionInfo> mLastWindowingModeTransitionInfo =
156 new SparseArray<>();
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200157 private final H mHandler;
Calin Juravle759fbda2018-02-20 19:52:30 +0000158
159 private ArtManagerInternal mArtManagerInternal;
Vishnu Naircf235042018-11-02 13:27:00 -0700160 private boolean mDrawingTraceActive;
161 private final StringBuilder mStringBuilder = new StringBuilder();
Calin Juravle759fbda2018-02-20 19:52:30 +0000162
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200163 private final class H extends Handler {
164
165 public H(Looper looper) {
166 super(looper);
167 }
168
169 @Override
170 public void handleMessage(Message msg) {
171 switch (msg.what) {
172 case MSG_CHECK_VISIBILITY:
173 final SomeArgs args = (SomeArgs) msg.obj;
174 checkVisibility((TaskRecord) args.arg1, (ActivityRecord) args.arg2);
175 break;
176 }
177 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000178 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800179
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100180 private final class WindowingModeTransitionInfo {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800181 private ActivityRecord launchedActivity;
182 private int startResult;
183 private boolean currentTransitionProcessRunning;
Vishnu Naircf235042018-11-02 13:27:00 -0700184 /** Elapsed time from when we launch an activity to when its windows are drawn. */
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800185 private int windowsDrawnDelayMs;
Vishnu Naircf235042018-11-02 13:27:00 -0700186 private int startingWindowDelayMs = INVALID_DELAY;
187 private int bindApplicationDelayMs = INVALID_DELAY;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800188 private int reason = APP_TRANSITION_TIMEOUT;
189 private boolean loggedWindowsDrawn;
190 private boolean loggedStartingWindowDrawn;
Vishnu Naircf235042018-11-02 13:27:00 -0700191 private boolean launchTraceActive;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800192 }
193
Vishnu Naircf235042018-11-02 13:27:00 -0700194 final class WindowingModeTransitionInfoSnapshot {
Calin Juravle759fbda2018-02-20 19:52:30 +0000195 final private ApplicationInfo applicationInfo;
Ng Zhi An83473542018-02-20 09:02:14 -0800196 final private ProcessRecord processRecord;
Vishnu Naircf235042018-11-02 13:27:00 -0700197 final String packageName;
198 final String launchedActivityName;
Calin Juravle759fbda2018-02-20 19:52:30 +0000199 final private String launchedActivityLaunchedFromPackage;
200 final private String launchedActivityLaunchToken;
201 final private String launchedActivityAppRecordRequiredAbi;
Vishnu Naircf235042018-11-02 13:27:00 -0700202 final String launchedActivityShortComponentName;
Ng Zhi An83473542018-02-20 09:02:14 -0800203 final private String processName;
Calin Juravle759fbda2018-02-20 19:52:30 +0000204 final private int reason;
205 final private int startingWindowDelayMs;
206 final private int bindApplicationDelayMs;
Vishnu Naircf235042018-11-02 13:27:00 -0700207 final int windowsDrawnDelayMs;
208 final int type;
209 final int userId;
210 /**
211 * Elapsed time from when we launch an activity to when the app reported it was
212 * fully drawn. If this is not reported then the value is set to INVALID_DELAY.
213 */
214 final int windowsFullyDrawnDelayMs;
215 final int activityRecordIdHashCode;
Calin Juravle759fbda2018-02-20 19:52:30 +0000216
217 private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info) {
Vishnu Naircf235042018-11-02 13:27:00 -0700218 this(info, info.launchedActivity);
219 }
220
221 private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info,
222 ActivityRecord launchedActivity) {
223 this(info, launchedActivity, INVALID_DELAY);
224 }
225
226 private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info,
227 ActivityRecord launchedActivity, int windowsFullyDrawnDelayMs) {
228 applicationInfo = launchedActivity.appInfo;
229 packageName = launchedActivity.packageName;
230 launchedActivityName = launchedActivity.info.name;
231 launchedActivityLaunchedFromPackage = launchedActivity.launchedFromPackage;
232 launchedActivityLaunchToken = launchedActivity.info.launchToken;
233 launchedActivityAppRecordRequiredAbi = launchedActivity.app == null
Calin Juravle759fbda2018-02-20 19:52:30 +0000234 ? null
Vishnu Naircf235042018-11-02 13:27:00 -0700235 : launchedActivity.app.requiredAbi;
Calin Juravle759fbda2018-02-20 19:52:30 +0000236 reason = info.reason;
237 startingWindowDelayMs = info.startingWindowDelayMs;
238 bindApplicationDelayMs = info.bindApplicationDelayMs;
239 windowsDrawnDelayMs = info.windowsDrawnDelayMs;
240 type = getTransitionType(info);
Vishnu Naircf235042018-11-02 13:27:00 -0700241 processRecord = findProcessForActivity(launchedActivity);
242 processName = launchedActivity.processName;
243 userId = launchedActivity.userId;
244 launchedActivityShortComponentName = launchedActivity.shortComponentName;
245 activityRecordIdHashCode = System.identityHashCode(launchedActivity);
246 this.windowsFullyDrawnDelayMs = windowsFullyDrawnDelayMs;
Calin Juravle759fbda2018-02-20 19:52:30 +0000247 }
248 }
249
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200250 ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context, Looper looper) {
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800251 mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
252 mSupervisor = supervisor;
253 mContext = context;
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200254 mHandler = new H(looper);
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800255 }
256
257 void logWindowState() {
258 final long now = SystemClock.elapsedRealtime() / 1000;
259 if (mWindowState != WINDOW_STATE_INVALID) {
260 // We log even if the window state hasn't changed, because the user might remain in
261 // home/fullscreen move forever and we would like to track this kind of behavior
262 // too.
263 MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
264 (int) (now - mLastLogTimeSecs));
265 }
266 mLastLogTimeSecs = now;
267
Wale Ogunwale926aade2017-08-29 11:24:37 -0700268 mWindowState = WINDOW_STATE_INVALID;
269 ActivityStack stack = mSupervisor.getFocusedStack();
270 if (stack.isActivityTypeAssistant()) {
271 mWindowState = WINDOW_STATE_ASSISTANT;
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800272 return;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800273 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700274
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700275 int windowingMode = stack.getWindowingMode();
276 if (windowingMode == WINDOWING_MODE_PINNED) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800277 stack = mSupervisor.findStackBehind(stack);
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700278 windowingMode = stack.getWindowingMode();
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800279 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700280 switch (windowingMode) {
281 case WINDOWING_MODE_FULLSCREEN:
282 mWindowState = WINDOW_STATE_STANDARD;
283 break;
284 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
285 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
286 mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
287 break;
Bryce Lee6c605092017-10-12 11:14:49 -0700288 case WINDOWING_MODE_FREEFORM:
Wale Ogunwale926aade2017-08-29 11:24:37 -0700289 mWindowState = WINDOW_STATE_FREEFORM;
290 break;
291 default:
292 if (windowingMode != WINDOWING_MODE_UNDEFINED) {
293 throw new IllegalStateException("Unknown windowing mode for stack=" + stack
294 + " windowingMode=" + windowingMode);
295 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800296 }
297 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500298
299 /**
300 * Notifies the tracker at the earliest possible point when we are starting to launch an
301 * activity.
302 */
303 void notifyActivityLaunching() {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800304 if (!isAnyTransitionActive()) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200305 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunching");
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400306 mCurrentTransitionStartTime = SystemClock.uptimeMillis();
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200307 mLastTransitionStartTime = mCurrentTransitionStartTime;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800308 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500309 }
310
311 /**
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700312 * Notifies the tracker that the activity is actually launching.
313 *
314 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
315 * launch
316 * @param launchedActivity the activity that is being launched
317 */
318 void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800319 final ProcessRecord processRecord = findProcessForActivity(launchedActivity);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700320 final boolean processRunning = processRecord != null;
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700321
322 // We consider this a "process switch" if the process of the activity that gets launched
323 // didn't have an activity that was in started state. In this case, we assume that lot
324 // of caches might be purged so the time until it produces the first frame is very
325 // interesting.
326 final boolean processSwitch = processRecord == null
327 || !hasStartedActivity(processRecord, launchedActivity);
328
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800329 notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700330 }
331
332 private boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
333 final ArrayList<ActivityRecord> activities = record.activities;
334 for (int i = activities.size() - 1; i >= 0; i--) {
335 final ActivityRecord activity = activities.get(i);
336 if (launchedActivity == activity) {
337 continue;
338 }
339 if (!activity.stopped) {
340 return true;
341 }
342 }
343 return false;
344 }
345
346 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500347 * Notifies the tracker the the activity is actually launching.
348 *
349 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
350 * launch
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800351 * @param launchedActivity the activity being launched
Jorim Jaggi275561a2016-02-23 10:11:02 -0500352 * @param processRunning whether the process that will contains the activity is already running
Jorim Jaggibe67c902016-04-12 00:53:16 -0700353 * @param processSwitch whether the process that will contain the activity didn't have any
354 * activity that was stopped, i.e. the started activity is "switching"
355 * processes
Jorim Jaggi275561a2016-02-23 10:11:02 -0500356 */
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800357 private void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700358 boolean processRunning, boolean processSwitch) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500359
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200360 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched"
361 + " resultCode=" + resultCode
362 + " launchedActivity=" + launchedActivity
363 + " processRunning=" + processRunning
364 + " processSwitch=" + processSwitch);
365
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100366 final int windowingMode = launchedActivity != null
367 ? launchedActivity.getWindowingMode()
368 : WINDOWING_MODE_UNDEFINED;
Vishnu Naircf235042018-11-02 13:27:00 -0700369 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200370 if (mCurrentTransitionStartTime == INVALID_START_TIME) {
Vishnu Naircf235042018-11-02 13:27:00 -0700371 // No transition is active ignore this launch.
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200372 return;
373 }
374
Vishnu Nairc1d2ff62018-11-08 16:50:12 -0800375 if (launchedActivity != null && launchedActivity.drawn) {
Vishnu Naircf235042018-11-02 13:27:00 -0700376 // Launched activity is already visible. We cannot measure windows drawn delay.
377 reset(true /* abort */, info);
378 return;
379 }
380
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800381 if (launchedActivity != null && info != null) {
Vishnu Naircf235042018-11-02 13:27:00 -0700382 // If we are already in an existing transition, only update the activity name, but not
383 // the other attributes.
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800384 info.launchedActivity = launchedActivity;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500385 return;
386 }
387
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100388 final boolean otherWindowModesLaunching =
389 mWindowingModeTransitionInfo.size() > 0 && info == null;
Jorim Jaggi54cff642018-03-15 15:51:32 +0100390 if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100391 || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800392 // Failed to launch or it was not a process switch, so we don't care about the timing.
Vishnu Naircf235042018-11-02 13:27:00 -0700393 reset(true /* abort */, info);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800394 return;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100395 } else if (otherWindowModesLaunching) {
396 // Don't log this windowing mode but continue with the other windowing modes.
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800397 return;
398 }
399
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200400 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched successful");
401
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100402 final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800403 newInfo.launchedActivity = launchedActivity;
404 newInfo.currentTransitionProcessRunning = processRunning;
405 newInfo.startResult = resultCode;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100406 mWindowingModeTransitionInfo.put(windowingMode, newInfo);
407 mLastWindowingModeTransitionInfo.put(windowingMode, newInfo);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800408 mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
Vishnu Naircf235042018-11-02 13:27:00 -0700409 startTraces(newInfo);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500410 }
411
412 /**
Jorim Jaggi54cff642018-03-15 15:51:32 +0100413 * @return True if we should start logging an event for an activity start that returned
414 * {@code resultCode} and that we'll indeed get a windows drawn event.
415 */
416 private boolean isLoggableResultCode(int resultCode) {
417 return resultCode == START_SUCCESS || resultCode == START_TASK_TO_FRONT;
418 }
419
420 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500421 * Notifies the tracker that all windows of the app have been drawn.
422 */
Vishnu Naircf235042018-11-02 13:27:00 -0700423 WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(int windowingMode, long timestamp) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100424 if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200425
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100426 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800427 if (info == null || info.loggedWindowsDrawn) {
Vishnu Naircf235042018-11-02 13:27:00 -0700428 return null;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500429 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700430 info.windowsDrawnDelayMs = calculateDelay(timestamp);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800431 info.loggedWindowsDrawn = true;
Vishnu Naircf235042018-11-02 13:27:00 -0700432 final WindowingModeTransitionInfoSnapshot infoSnapshot =
433 new WindowingModeTransitionInfoSnapshot(info);
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100434 if (allWindowsDrawn() && mLoggedTransitionStarting) {
Vishnu Naircf235042018-11-02 13:27:00 -0700435 reset(false /* abort */, info);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500436 }
Vishnu Naircf235042018-11-02 13:27:00 -0700437 return infoSnapshot;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500438 }
439
440 /**
441 * Notifies the tracker that the starting window was drawn.
442 */
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100443 void notifyStartingWindowDrawn(int windowingMode, long timestamp) {
444 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800445 if (info == null || info.loggedStartingWindowDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500446 return;
447 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800448 info.loggedStartingWindowDrawn = true;
Sudheer Shankac766db02017-06-12 10:37:29 -0700449 info.startingWindowDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500450 }
451
452 /**
453 * Notifies the tracker that the app transition is starting.
454 *
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100455 * @param windowingModeToReason A map from windowing mode to a reason integer, which must be on
Vishnu Naircf235042018-11-02 13:27:00 -0700456 * of ActivityTaskManagerInternal.APP_TRANSITION_* reasons.
Jorim Jaggi275561a2016-02-23 10:11:02 -0500457 */
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100458 void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
Jorim Jaggid8a57772017-04-14 16:50:42 -0700459 if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500460 return;
461 }
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200462 if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
Sudheer Shankac766db02017-06-12 10:37:29 -0700463 mCurrentTransitionDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500464 mLoggedTransitionStarting = true;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100465 for (int index = windowingModeToReason.size() - 1; index >= 0; index--) {
466 final int windowingMode = windowingModeToReason.keyAt(index);
467 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
468 windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800469 if (info == null) {
470 continue;
471 }
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100472 info.reason = windowingModeToReason.valueAt(index);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800473 }
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100474 if (allWindowsDrawn()) {
Vishnu Naircf235042018-11-02 13:27:00 -0700475 reset(false /* abort */, null /* WindowingModeTransitionInfo */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500476 }
477 }
478
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200479 /**
480 * Notifies the tracker that the visibility of an app is changing.
481 *
482 * @param activityRecord the app that is changing its visibility
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200483 */
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200484 void notifyVisibilityChanged(ActivityRecord activityRecord) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100485 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
486 activityRecord.getWindowingMode());
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200487 if (info == null) {
488 return;
489 }
490 if (info.launchedActivity != activityRecord) {
491 return;
492 }
493 final TaskRecord t = activityRecord.getTask();
494 final SomeArgs args = SomeArgs.obtain();
495 args.arg1 = t;
496 args.arg2 = activityRecord;
497 mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
498 }
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200499
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200500 private void checkVisibility(TaskRecord t, ActivityRecord r) {
501 synchronized (mSupervisor.mService) {
502
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100503 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
504 r.getWindowingMode());
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200505
506 // If we have an active transition that's waiting on a certain activity that will be
507 // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
508 if (info != null && !t.isVisible()) {
509 if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible"
510 + " activity=" + r);
511 logAppTransitionCancel(info);
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100512 mWindowingModeTransitionInfo.remove(r.getWindowingMode());
513 if (mWindowingModeTransitionInfo.size() == 0) {
Vishnu Naircf235042018-11-02 13:27:00 -0700514 reset(true /* abort */, info);
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200515 }
Vishnu Naircf235042018-11-02 13:27:00 -0700516 stopFullyDrawnTraceIfNeeded();
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200517 }
518 }
519 }
520
Jorim Jaggi515dd682017-05-05 15:05:07 +0200521 /**
522 * Notifies the tracker that we called immediately before we call bindApplication on the client.
523 *
524 * @param app The client into which we'll call bindApplication.
525 */
526 void notifyBindApplication(ProcessRecord app) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100527 for (int i = mWindowingModeTransitionInfo.size() - 1; i >= 0; i--) {
528 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.valueAt(i);
Jorim Jaggi515dd682017-05-05 15:05:07 +0200529
530 // App isn't attached to record yet, so match with info.
531 if (info.launchedActivity.appInfo == app.info) {
532 info.bindApplicationDelayMs = calculateCurrentDelay();
533 }
534 }
535 }
536
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100537 private boolean allWindowsDrawn() {
538 for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
539 if (!mWindowingModeTransitionInfo.valueAt(index).loggedWindowsDrawn) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800540 return false;
541 }
542 }
543 return true;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500544 }
545
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800546 private boolean isAnyTransitionActive() {
547 return mCurrentTransitionStartTime != INVALID_START_TIME
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100548 && mWindowingModeTransitionInfo.size() > 0;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800549 }
550
Vishnu Naircf235042018-11-02 13:27:00 -0700551 private void reset(boolean abort, WindowingModeTransitionInfo info) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200552 if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800553 if (!abort && isAnyTransitionActive()) {
554 logAppTransitionMultiEvents();
555 }
Vishnu Naircf235042018-11-02 13:27:00 -0700556 stopLaunchTrace(info);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500557 mCurrentTransitionStartTime = INVALID_START_TIME;
Vishnu Naircf235042018-11-02 13:27:00 -0700558 mCurrentTransitionDelayMs = INVALID_DELAY;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500559 mLoggedTransitionStarting = false;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100560 mWindowingModeTransitionInfo.clear();
Jorim Jaggi275561a2016-02-23 10:11:02 -0500561 }
562
563 private int calculateCurrentDelay() {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500564 // Shouldn't take more than 25 days to launch an app, so int is fine here.
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400565 return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500566 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800567
Sudheer Shankac766db02017-06-12 10:37:29 -0700568 private int calculateDelay(long timestamp) {
569 // Shouldn't take more than 25 days to launch an app, so int is fine here.
570 return (int) (timestamp - mCurrentTransitionStartTime);
571 }
572
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100573 private void logAppTransitionCancel(WindowingModeTransitionInfo info) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200574 final int type = getTransitionType(info);
Vishnu Naircf235042018-11-02 13:27:00 -0700575 if (type == INVALID_TRANSITION_TYPE) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200576 return;
577 }
578 final LogMaker builder = new LogMaker(APP_TRANSITION_CANCELLED);
579 builder.setPackageName(info.launchedActivity.packageName);
580 builder.setType(type);
581 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
582 mMetricsLogger.write(builder);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000583 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800584 StatsLog.APP_START_CANCELED,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000585 info.launchedActivity.appInfo.uid,
586 info.launchedActivity.packageName,
587 convertAppStartTransitionType(type),
588 info.launchedActivity.info.name);
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200589 }
590
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800591 private void logAppTransitionMultiEvents() {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200592 if (DEBUG_METRICS) Slog.i(TAG, "logging transition events");
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100593 for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
594 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.valueAt(index);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800595 final int type = getTransitionType(info);
Vishnu Naircf235042018-11-02 13:27:00 -0700596 if (type == INVALID_TRANSITION_TYPE) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800597 return;
598 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000599
600 // Take a snapshot of the transition info before sending it to the handler for logging.
601 // This will avoid any races with other operations that modify the ActivityRecord.
602 final WindowingModeTransitionInfoSnapshot infoSnapshot =
603 new WindowingModeTransitionInfoSnapshot(info);
Ng Zhi An83473542018-02-20 09:02:14 -0800604 final int currentTransitionDeviceUptime = mCurrentTransitionDeviceUptime;
605 final int currentTransitionDelayMs = mCurrentTransitionDelayMs;
606 BackgroundThread.getHandler().post(() -> logAppTransition(
607 currentTransitionDeviceUptime, currentTransitionDelayMs, infoSnapshot));
Vishnu Naircf235042018-11-02 13:27:00 -0700608 BackgroundThread.getHandler().post(() -> logAppDisplayed(infoSnapshot));
Calin Juravle759fbda2018-02-20 19:52:30 +0000609
610 info.launchedActivity.info.launchToken = null;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800611 }
612 }
613
Ng Zhi An83473542018-02-20 09:02:14 -0800614 // This gets called on a background thread without holding the activity manager lock.
Calin Juravle759fbda2018-02-20 19:52:30 +0000615 private void logAppTransition(int currentTransitionDeviceUptime, int currentTransitionDelayMs,
616 WindowingModeTransitionInfoSnapshot info) {
617 final LogMaker builder = new LogMaker(APP_TRANSITION);
618 builder.setPackageName(info.packageName);
619 builder.setType(info.type);
620 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivityName);
621 final boolean isInstantApp = info.applicationInfo.isInstantApp();
622 if (info.launchedActivityLaunchedFromPackage != null) {
623 builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
624 info.launchedActivityLaunchedFromPackage);
625 }
626 String launchToken = info.launchedActivityLaunchToken;
627 if (launchToken != null) {
628 builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, launchToken);
629 }
630 builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
631 builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
632 currentTransitionDeviceUptime);
633 builder.addTaggedData(APP_TRANSITION_DELAY_MS, currentTransitionDelayMs);
634 builder.setSubtype(info.reason);
Vishnu Naircf235042018-11-02 13:27:00 -0700635 if (info.startingWindowDelayMs != INVALID_DELAY) {
Calin Juravle759fbda2018-02-20 19:52:30 +0000636 builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
637 info.startingWindowDelayMs);
638 }
Vishnu Naircf235042018-11-02 13:27:00 -0700639 if (info.bindApplicationDelayMs != INVALID_DELAY) {
Calin Juravle759fbda2018-02-20 19:52:30 +0000640 builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
641 info.bindApplicationDelayMs);
642 }
643 builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
644 final ArtManagerInternal artManagerInternal = getArtManagerInternal();
645 final PackageOptimizationInfo packageOptimizationInfo =
646 (artManagerInternal == null) || (info.launchedActivityAppRecordRequiredAbi == null)
647 ? PackageOptimizationInfo.createWithNoInfo()
648 : artManagerInternal.getPackageOptimizationInfo(
649 info.applicationInfo,
650 info.launchedActivityAppRecordRequiredAbi);
651 builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_REASON,
652 packageOptimizationInfo.getCompilationReason());
653 builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER,
654 packageOptimizationInfo.getCompilationFilter());
655 mMetricsLogger.write(builder);
656 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800657 StatsLog.APP_START_OCCURRED,
Calin Juravle759fbda2018-02-20 19:52:30 +0000658 info.applicationInfo.uid,
659 info.packageName,
660 convertAppStartTransitionType(info.type),
661 info.launchedActivityName,
662 info.launchedActivityLaunchedFromPackage,
663 isInstantApp,
664 currentTransitionDeviceUptime * 1000,
665 info.reason,
666 currentTransitionDelayMs,
667 info.startingWindowDelayMs,
668 info.bindApplicationDelayMs,
669 info.windowsDrawnDelayMs,
670 launchToken,
671 packageOptimizationInfo.getCompilationReason(),
672 packageOptimizationInfo.getCompilationFilter());
Ng Zhi An83473542018-02-20 09:02:14 -0800673 logAppStartMemoryStateCapture(info);
Calin Juravle759fbda2018-02-20 19:52:30 +0000674 }
675
Vishnu Naircf235042018-11-02 13:27:00 -0700676 private void logAppDisplayed(WindowingModeTransitionInfoSnapshot info) {
677 if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
678 return;
679 }
680
681 EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
682 info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName,
683 info.windowsDrawnDelayMs);
684
685 StringBuilder sb = mStringBuilder;
686 sb.setLength(0);
687 sb.append("Displayed ");
688 sb.append(info.launchedActivityShortComponentName);
689 sb.append(": ");
690 TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb);
691 Log.i(TAG, sb.toString());
692 }
693
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000694 private int convertAppStartTransitionType(int tronType) {
695 if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800696 return StatsLog.APP_START_OCCURRED__TYPE__COLD;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000697 }
698 if (tronType == TYPE_TRANSITION_WARM_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800699 return StatsLog.APP_START_OCCURRED__TYPE__WARM;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000700 }
701 if (tronType == TYPE_TRANSITION_HOT_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800702 return StatsLog.APP_START_OCCURRED__TYPE__HOT;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000703 }
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800704 return StatsLog.APP_START_OCCURRED__TYPE__UNKNOWN;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000705 }
706
Vishnu Naircf235042018-11-02 13:27:00 -0700707 WindowingModeTransitionInfoSnapshot logAppTransitionReportedDrawn(ActivityRecord r,
708 boolean restoredFromBundle) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100709 final WindowingModeTransitionInfo info = mLastWindowingModeTransitionInfo.get(
710 r.getWindowingMode());
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200711 if (info == null) {
Vishnu Naircf235042018-11-02 13:27:00 -0700712 return null;
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200713 }
714 final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
715 builder.setPackageName(r.packageName);
716 builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000717 long startupTimeMs = SystemClock.uptimeMillis() - mLastTransitionStartTime;
718 builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, startupTimeMs);
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200719 builder.setType(restoredFromBundle
720 ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
721 : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
722 builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
723 info.currentTransitionProcessRunning ? 1 : 0);
724 mMetricsLogger.write(builder);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000725 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800726 StatsLog.APP_START_FULLY_DRAWN,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000727 info.launchedActivity.appInfo.uid,
728 info.launchedActivity.packageName,
729 restoredFromBundle
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800730 ? StatsLog.APP_START_FULLY_DRAWN__TYPE__WITH_BUNDLE
731 : StatsLog.APP_START_FULLY_DRAWN__TYPE__WITHOUT_BUNDLE,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000732 info.launchedActivity.info.name,
733 info.currentTransitionProcessRunning,
734 startupTimeMs);
Vishnu Naircf235042018-11-02 13:27:00 -0700735 stopFullyDrawnTraceIfNeeded();
736 final WindowingModeTransitionInfoSnapshot infoSnapshot =
737 new WindowingModeTransitionInfoSnapshot(info, r, (int) startupTimeMs);
738 BackgroundThread.getHandler().post(() -> logAppFullyDrawn(infoSnapshot));
739 return infoSnapshot;
740 }
741
742 private void logAppFullyDrawn(WindowingModeTransitionInfoSnapshot info) {
743 if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
744 return;
745 }
746
747 StringBuilder sb = mStringBuilder;
748 sb.setLength(0);
749 sb.append("Fully drawn ");
750 sb.append(info.launchedActivityShortComponentName);
751 sb.append(": ");
752 TimeUtils.formatDuration(info.windowsFullyDrawnDelayMs, sb);
753 Log.i(TAG, sb.toString());
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200754 }
755
Michal Karpinski3eab9512018-07-20 15:32:00 +0100756 void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r,
757 int callingUid, String callingPackage, int callingUidProcState,
758 boolean callingUidHasAnyVisibleWindow,
759 int realCallingUid, int realCallingUidProcState,
760 boolean realCallingUidHasAnyVisibleWindow,
761 int targetUid, String targetPackage, int targetUidProcState,
762 boolean targetUidHasAnyVisibleWindow, String targetWhitelistTag,
763 boolean comingFromPendingIntent) {
764
765 final long nowElapsed = SystemClock.elapsedRealtime();
766 final long nowUptime = SystemClock.uptimeMillis();
767 final LogMaker builder = new LogMaker(ACTION_ACTIVITY_START);
768 builder.setTimestamp(System.currentTimeMillis());
769 builder.addTaggedData(FIELD_CALLING_UID, callingUid);
770 builder.addTaggedData(FIELD_CALLING_PACKAGE_NAME, callingPackage);
771 builder.addTaggedData(FIELD_CALLING_UID_PROC_STATE,
772 processStateAmToProto(callingUidProcState));
773 builder.addTaggedData(FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW,
774 callingUidHasAnyVisibleWindow ? 1 : 0);
775 builder.addTaggedData(FIELD_REAL_CALLING_UID, realCallingUid);
776 builder.addTaggedData(FIELD_REAL_CALLING_UID_PROC_STATE,
777 processStateAmToProto(realCallingUidProcState));
778 builder.addTaggedData(FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW,
779 realCallingUidHasAnyVisibleWindow ? 1 : 0);
780 builder.addTaggedData(FIELD_TARGET_UID, targetUid);
781 builder.addTaggedData(FIELD_TARGET_PACKAGE_NAME, targetPackage);
782 builder.addTaggedData(FIELD_TARGET_UID_PROC_STATE,
783 processStateAmToProto(targetUidProcState));
784 builder.addTaggedData(FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW,
785 targetUidHasAnyVisibleWindow ? 1 : 0);
786 builder.addTaggedData(FIELD_TARGET_WHITELIST_TAG, targetWhitelistTag);
787 builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName);
788 builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0);
789 builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction());
790 if (callerApp != null) {
791 builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.processName);
792 builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE,
793 processStateAmToProto(callerApp.curProcState));
794 builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES,
795 callerApp.hasClientActivities ? 1 : 0);
796 builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES,
797 callerApp.hasForegroundServices() ? 1 : 0);
798 builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES,
799 callerApp.foregroundActivities ? 1 : 0);
800 builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi ? 1 : 0);
801 builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_OVERLAY_UI,
802 callerApp.hasOverlayUi ? 1 : 0);
803 builder.addTaggedData(FIELD_PROCESS_RECORD_PENDING_UI_CLEAN,
804 callerApp.pendingUiClean ? 1 : 0);
805 if (callerApp.interactionEventTime != 0) {
806 builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT,
807 (nowElapsed - callerApp.interactionEventTime));
808 }
809 if (callerApp.fgInteractionTime != 0) {
810 builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION,
811 (nowElapsed - callerApp.fgInteractionTime));
812 }
813 if (callerApp.whenUnimportant != 0) {
814 builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT,
815 (nowUptime - callerApp.whenUnimportant));
816 }
817 }
818 builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode);
819 builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity);
820 builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags);
821 builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY, r.realActivity.toShortString());
822 builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName);
823 builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName);
824 builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0);
825 builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0);
826 if (r.lastVisibleTime != 0) {
827 builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE,
828 (nowUptime - r.lastVisibleTime));
829 }
830 if (r.resultTo != null) {
831 builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME, r.resultTo.packageName);
832 builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME,
833 r.resultTo.shortComponentName);
834 }
835 builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0);
836 builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD,
837 r.visibleIgnoringKeyguard ? 1 : 0);
838 if (r.lastLaunchTime != 0) {
839 builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH,
840 (nowUptime - r.lastLaunchTime));
841 }
842 mMetricsLogger.write(builder);
843 }
844
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100845 private int getTransitionType(WindowingModeTransitionInfo info) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800846 if (info.currentTransitionProcessRunning) {
847 if (info.startResult == START_SUCCESS) {
848 return TYPE_TRANSITION_WARM_LAUNCH;
849 } else if (info.startResult == START_TASK_TO_FRONT) {
850 return TYPE_TRANSITION_HOT_LAUNCH;
851 }
852 } else if (info.startResult == START_SUCCESS) {
853 return TYPE_TRANSITION_COLD_LAUNCH;
854 }
Vishnu Naircf235042018-11-02 13:27:00 -0700855 return INVALID_TRANSITION_TYPE;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800856 }
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800857
Ng Zhi An83473542018-02-20 09:02:14 -0800858 private void logAppStartMemoryStateCapture(WindowingModeTransitionInfoSnapshot info) {
859 if (info.processRecord == null) {
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800860 if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture processRecord null");
861 return;
862 }
863
Ng Zhi An83473542018-02-20 09:02:14 -0800864 final int pid = info.processRecord.pid;
865 final int uid = info.applicationInfo.uid;
Rajeev Kumarbfcd9202018-03-02 22:42:13 +0000866 final MemoryStat memoryStat = readMemoryStatFromFilesystem(uid, pid);
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800867 if (memoryStat == null) {
868 if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture memoryStat null");
869 return;
870 }
871
872 StatsLog.write(
873 StatsLog.APP_START_MEMORY_STATE_CAPTURED,
874 uid,
Ng Zhi An83473542018-02-20 09:02:14 -0800875 info.processName,
876 info.launchedActivityName,
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800877 memoryStat.pgfault,
878 memoryStat.pgmajfault,
879 memoryStat.rssInBytes,
880 memoryStat.cacheInBytes,
881 memoryStat.swapInBytes);
882 }
883
884 private ProcessRecord findProcessForActivity(ActivityRecord launchedActivity) {
885 return launchedActivity != null
886 ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
887 launchedActivity.appInfo.uid)
888 : null;
889 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000890
891 private ArtManagerInternal getArtManagerInternal() {
892 if (mArtManagerInternal == null) {
893 // Note that this may be null.
894 // ArtManagerInternal is registered during PackageManagerService
895 // initialization which happens after ActivityManagerService.
896 mArtManagerInternal = LocalServices.getService(ArtManagerInternal.class);
897 }
898 return mArtManagerInternal;
899 }
Vishnu Naircf235042018-11-02 13:27:00 -0700900
901 /**
902 * Starts traces for app launch and draw times. We stop the fully drawn trace if its already
903 * active since the app may not have reported fully drawn in the previous launch.
904 *
905 * See {@link android.app.Activity#reportFullyDrawn()}
906 *
907 * @param info
908 * */
909 private void startTraces(WindowingModeTransitionInfo info) {
910 if (info == null) {
911 return;
912 }
913 stopFullyDrawnTraceIfNeeded();
914 int transitionType = getTransitionType(info);
915 if (!info.launchTraceActive && transitionType == TYPE_TRANSITION_WARM_LAUNCH
916 || transitionType == TYPE_TRANSITION_COLD_LAUNCH) {
917 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
918 + info.launchedActivity.packageName, 0);
919 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
920 mDrawingTraceActive = true;
921 info.launchTraceActive = true;
922 }
923 }
924
925 private void stopLaunchTrace(WindowingModeTransitionInfo info) {
926 if (info == null) {
927 return;
928 }
929 if (info.launchTraceActive) {
930 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
931 + info.launchedActivity.packageName, 0);
932 info.launchTraceActive = false;
933 }
934 }
935
936 void stopFullyDrawnTraceIfNeeded() {
937 if (mDrawingTraceActive) {
938 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
939 mDrawingTraceActive = false;
940 }
941 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800942}