blob: fdcb8c695662ad54f93737533a012c8ff733ed84 [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;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08005import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08006import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
Wale Ogunwale926aade2017-08-29 11:24:37 -07007import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07008import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
9import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Wale Ogunwale926aade2017-08-29 11:24:37 -070010import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
11import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080012import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
Jorim Jaggi515dd682017-05-05 15:05:07 +020013import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070014import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080015import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
16import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070017import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020018import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING;
19import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
20import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080021import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
22import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +020023import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
Todd Kennedy50d946c12017-03-17 13:55:38 -070024import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080025import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
26import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020027import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
28import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080029import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
Jorim Jaggif9704102016-05-05 19:14:22 -070030import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
31import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080032
Filip Gruszczynski77d94482015-12-11 13:59:52 -080033import android.content.Context;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080034import android.metrics.LogMaker;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080035import android.os.SystemClock;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080036import android.util.SparseArray;
37import android.util.SparseIntArray;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080038
39import com.android.internal.logging.MetricsLogger;
40
Jorim Jaggi1e630c02016-05-16 12:13:13 -070041import java.util.ArrayList;
42
Filip Gruszczynski77d94482015-12-11 13:59:52 -080043/**
44 * Handles logging into Tron.
45 */
46class ActivityMetricsLogger {
Jorim Jaggif9704102016-05-05 19:14:22 -070047
48 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM;
49
Filip Gruszczynski77d94482015-12-11 13:59:52 -080050 // Window modes we are interested in logging. If we ever introduce a new type, we need to add
51 // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
52 private static final int WINDOW_STATE_STANDARD = 0;
53 private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
54 private static final int WINDOW_STATE_FREEFORM = 2;
Winson Chung83471632016-12-13 11:02:12 -080055 private static final int WINDOW_STATE_ASSISTANT = 3;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080056 private static final int WINDOW_STATE_INVALID = -1;
57
Jorim Jaggi275561a2016-02-23 10:11:02 -050058 private static final long INVALID_START_TIME = -1;
59
Filip Gruszczynski77d94482015-12-11 13:59:52 -080060 // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
61 // time we log.
62 private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
Winson Chung83471632016-12-13 11:02:12 -080063 "window_time_0", "window_time_1", "window_time_2", "window_time_3"};
Filip Gruszczynski77d94482015-12-11 13:59:52 -080064
65 private int mWindowState = WINDOW_STATE_STANDARD;
66 private long mLastLogTimeSecs;
67 private final ActivityStackSupervisor mSupervisor;
68 private final Context mContext;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080069 private final MetricsLogger mMetricsLogger = new MetricsLogger();
Filip Gruszczynski77d94482015-12-11 13:59:52 -080070
Jorim Jaggi275561a2016-02-23 10:11:02 -050071 private long mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020072 private long mLastTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080073
74 private int mCurrentTransitionDeviceUptime;
75 private int mCurrentTransitionDelayMs;
Jorim Jaggi275561a2016-02-23 10:11:02 -050076 private boolean mLoggedTransitionStarting;
77
Jorim Jaggi3878ca32017-02-02 17:13:05 -080078 private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>();
Jorim Jaggi4d27b842017-08-17 17:22:26 +020079 private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>();
Jorim Jaggi3878ca32017-02-02 17:13:05 -080080
81 private final class StackTransitionInfo {
82 private ActivityRecord launchedActivity;
83 private int startResult;
84 private boolean currentTransitionProcessRunning;
85 private int windowsDrawnDelayMs;
Jorim Jaggi515dd682017-05-05 15:05:07 +020086 private int startingWindowDelayMs = -1;
87 private int bindApplicationDelayMs = -1;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080088 private int reason = APP_TRANSITION_TIMEOUT;
89 private boolean loggedWindowsDrawn;
90 private boolean loggedStartingWindowDrawn;
91 }
92
Filip Gruszczynski77d94482015-12-11 13:59:52 -080093 ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
94 mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
95 mSupervisor = supervisor;
96 mContext = context;
97 }
98
99 void logWindowState() {
100 final long now = SystemClock.elapsedRealtime() / 1000;
101 if (mWindowState != WINDOW_STATE_INVALID) {
102 // We log even if the window state hasn't changed, because the user might remain in
103 // home/fullscreen move forever and we would like to track this kind of behavior
104 // too.
105 MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
106 (int) (now - mLastLogTimeSecs));
107 }
108 mLastLogTimeSecs = now;
109
Wale Ogunwale926aade2017-08-29 11:24:37 -0700110 mWindowState = WINDOW_STATE_INVALID;
111 ActivityStack stack = mSupervisor.getFocusedStack();
112 if (stack.isActivityTypeAssistant()) {
113 mWindowState = WINDOW_STATE_ASSISTANT;
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800114 return;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800115 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700116
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700117 int windowingMode = stack.getWindowingMode();
118 if (windowingMode == WINDOWING_MODE_PINNED) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800119 stack = mSupervisor.findStackBehind(stack);
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700120 windowingMode = stack.getWindowingMode();
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800121 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700122 switch (windowingMode) {
123 case WINDOWING_MODE_FULLSCREEN:
124 mWindowState = WINDOW_STATE_STANDARD;
125 break;
126 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
127 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
128 mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
129 break;
130 case WINDOW_STATE_FREEFORM:
131 mWindowState = WINDOW_STATE_FREEFORM;
132 break;
133 default:
134 if (windowingMode != WINDOWING_MODE_UNDEFINED) {
135 throw new IllegalStateException("Unknown windowing mode for stack=" + stack
136 + " windowingMode=" + windowingMode);
137 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800138 }
139 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500140
141 /**
142 * Notifies the tracker at the earliest possible point when we are starting to launch an
143 * activity.
144 */
145 void notifyActivityLaunching() {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800146 if (!isAnyTransitionActive()) {
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400147 mCurrentTransitionStartTime = SystemClock.uptimeMillis();
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200148 mLastTransitionStartTime = mCurrentTransitionStartTime;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800149 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500150 }
151
152 /**
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700153 * Notifies the tracker that the activity is actually launching.
154 *
155 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
156 * launch
157 * @param launchedActivity the activity that is being launched
158 */
159 void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
160 final ProcessRecord processRecord = launchedActivity != null
161 ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
162 launchedActivity.appInfo.uid)
163 : null;
164 final boolean processRunning = processRecord != null;
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700165
166 // We consider this a "process switch" if the process of the activity that gets launched
167 // didn't have an activity that was in started state. In this case, we assume that lot
168 // of caches might be purged so the time until it produces the first frame is very
169 // interesting.
170 final boolean processSwitch = processRecord == null
171 || !hasStartedActivity(processRecord, launchedActivity);
172
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800173 notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700174 }
175
176 private boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
177 final ArrayList<ActivityRecord> activities = record.activities;
178 for (int i = activities.size() - 1; i >= 0; i--) {
179 final ActivityRecord activity = activities.get(i);
180 if (launchedActivity == activity) {
181 continue;
182 }
183 if (!activity.stopped) {
184 return true;
185 }
186 }
187 return false;
188 }
189
190 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500191 * Notifies the tracker the the activity is actually launching.
192 *
193 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
194 * launch
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800195 * @param launchedActivity the activity being launched
Jorim Jaggi275561a2016-02-23 10:11:02 -0500196 * @param processRunning whether the process that will contains the activity is already running
Jorim Jaggibe67c902016-04-12 00:53:16 -0700197 * @param processSwitch whether the process that will contain the activity didn't have any
198 * activity that was stopped, i.e. the started activity is "switching"
199 * processes
Jorim Jaggi275561a2016-02-23 10:11:02 -0500200 */
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800201 private void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700202 boolean processRunning, boolean processSwitch) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500203
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800204 // If we are already in an existing transition, only update the activity name, but not the
205 // other attributes.
206 final int stackId = launchedActivity != null && launchedActivity.getStack() != null
207 ? launchedActivity.getStack().mStackId
208 : INVALID_STACK_ID;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200209
210 if (mCurrentTransitionStartTime == INVALID_START_TIME) {
211 return;
212 }
213
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800214 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
215 if (launchedActivity != null && info != null) {
216 info.launchedActivity = launchedActivity;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500217 return;
218 }
219
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800220 final boolean otherStacksLaunching = mStackTransitionInfo.size() > 0 && info == null;
221 if ((resultCode < 0 || launchedActivity == null || !processSwitch
222 || stackId == INVALID_STACK_ID) && !otherStacksLaunching) {
Alison Cichowlas803054d2016-12-13 14:38:01 -0500223
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800224 // Failed to launch or it was not a process switch, so we don't care about the timing.
225 reset(true /* abort */);
226 return;
227 } else if (otherStacksLaunching) {
228 // Don't log this stack but continue with the other stacks.
229 return;
230 }
231
232 final StackTransitionInfo newInfo = new StackTransitionInfo();
233 newInfo.launchedActivity = launchedActivity;
234 newInfo.currentTransitionProcessRunning = processRunning;
235 newInfo.startResult = resultCode;
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200236 mStackTransitionInfo.put(stackId, newInfo);
237 mLastStackTransitionInfo.put(stackId, newInfo);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800238 mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500239 }
240
241 /**
242 * Notifies the tracker that all windows of the app have been drawn.
243 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700244 void notifyWindowsDrawn(int stackId, long timestamp) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800245 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
246 if (info == null || info.loggedWindowsDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500247 return;
248 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700249 info.windowsDrawnDelayMs = calculateDelay(timestamp);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800250 info.loggedWindowsDrawn = true;
251 if (allStacksWindowsDrawn() && mLoggedTransitionStarting) {
252 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500253 }
254 }
255
256 /**
257 * Notifies the tracker that the starting window was drawn.
258 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700259 void notifyStartingWindowDrawn(int stackId, long timestamp) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800260 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
261 if (info == null || info.loggedStartingWindowDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500262 return;
263 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800264 info.loggedStartingWindowDrawn = true;
Sudheer Shankac766db02017-06-12 10:37:29 -0700265 info.startingWindowDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500266 }
267
268 /**
269 * Notifies the tracker that the app transition is starting.
270 *
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800271 * @param stackIdReasons A map from stack id to a reason integer, which must be on of
272 * ActivityManagerInternal.APP_TRANSITION_* reasons.
Jorim Jaggi275561a2016-02-23 10:11:02 -0500273 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700274 void notifyTransitionStarting(SparseIntArray stackIdReasons, long timestamp) {
Jorim Jaggid8a57772017-04-14 16:50:42 -0700275 if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500276 return;
277 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700278 mCurrentTransitionDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500279 mLoggedTransitionStarting = true;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800280 for (int index = stackIdReasons.size() - 1; index >= 0; index--) {
281 final int stackId = stackIdReasons.keyAt(index);
282 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
283 if (info == null) {
284 continue;
285 }
286 info.reason = stackIdReasons.valueAt(index);
287 }
288 if (allStacksWindowsDrawn()) {
289 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500290 }
291 }
292
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200293 /**
294 * Notifies the tracker that the visibility of an app is changing.
295 *
296 * @param activityRecord the app that is changing its visibility
297 * @param visible whether it's going to be visible or not
298 */
299 void notifyVisibilityChanged(ActivityRecord activityRecord, boolean visible) {
300 final StackTransitionInfo info = mStackTransitionInfo.get(activityRecord.getStackId());
301
302 // If we have an active transition that's waiting on a certain activity that will be
303 // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
304 if (info != null && !visible && info.launchedActivity == activityRecord) {
305 mStackTransitionInfo.remove(activityRecord.getStackId());
306 if (mStackTransitionInfo.size() == 0) {
307 reset(true /* abort */);
308 }
309 }
310 }
311
Jorim Jaggi515dd682017-05-05 15:05:07 +0200312 /**
313 * Notifies the tracker that we called immediately before we call bindApplication on the client.
314 *
315 * @param app The client into which we'll call bindApplication.
316 */
317 void notifyBindApplication(ProcessRecord app) {
318 for (int i = mStackTransitionInfo.size() - 1; i >= 0; i--) {
319 final StackTransitionInfo info = mStackTransitionInfo.valueAt(i);
320
321 // App isn't attached to record yet, so match with info.
322 if (info.launchedActivity.appInfo == app.info) {
323 info.bindApplicationDelayMs = calculateCurrentDelay();
324 }
325 }
326 }
327
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800328 private boolean allStacksWindowsDrawn() {
329 for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
330 if (!mStackTransitionInfo.valueAt(index).loggedWindowsDrawn) {
331 return false;
332 }
333 }
334 return true;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500335 }
336
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800337 private boolean isAnyTransitionActive() {
338 return mCurrentTransitionStartTime != INVALID_START_TIME
339 && mStackTransitionInfo.size() > 0;
340 }
341
342 private void reset(boolean abort) {
343 if (!abort && isAnyTransitionActive()) {
344 logAppTransitionMultiEvents();
345 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500346 mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800347 mCurrentTransitionDelayMs = -1;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500348 mLoggedTransitionStarting = false;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800349 mStackTransitionInfo.clear();
Jorim Jaggi275561a2016-02-23 10:11:02 -0500350 }
351
352 private int calculateCurrentDelay() {
353
354 // Shouldn't take more than 25 days to launch an app, so int is fine here.
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400355 return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500356 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800357
Sudheer Shankac766db02017-06-12 10:37:29 -0700358 private int calculateDelay(long timestamp) {
359 // Shouldn't take more than 25 days to launch an app, so int is fine here.
360 return (int) (timestamp - mCurrentTransitionStartTime);
361 }
362
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800363 private void logAppTransitionMultiEvents() {
364 for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
365 final StackTransitionInfo info = mStackTransitionInfo.valueAt(index);
366 final int type = getTransitionType(info);
367 if (type == -1) {
368 return;
369 }
370 final LogMaker builder = new LogMaker(APP_TRANSITION);
371 builder.setPackageName(info.launchedActivity.packageName);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800372 builder.setType(type);
Jason Monk8c09ac72017-03-16 11:53:40 -0400373 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
Todd Kennedy56279cb2017-04-17 14:53:49 -0700374 final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp();
Todd Kennedy7655b292017-08-18 15:05:01 -0700375 if (info.launchedActivity.launchedFromPackage != null) {
Todd Kennedy50d946c12017-03-17 13:55:38 -0700376 builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
377 info.launchedActivity.launchedFromPackage);
378 }
379 if (info.launchedActivity.info.launchToken != null) {
380 builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN,
381 info.launchedActivity.info.launchToken);
Todd Kennedyb3b431302017-03-20 16:05:48 -0700382 info.launchedActivity.info.launchToken = null;
Todd Kennedy50d946c12017-03-17 13:55:38 -0700383 }
Todd Kennedy56279cb2017-04-17 14:53:49 -0700384 builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800385 builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
386 mCurrentTransitionDeviceUptime);
387 builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs);
388 builder.setSubtype(info.reason);
389 if (info.startingWindowDelayMs != -1) {
390 builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
391 info.startingWindowDelayMs);
392 }
Jorim Jaggi515dd682017-05-05 15:05:07 +0200393 if (info.bindApplicationDelayMs != -1) {
394 builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
395 info.bindApplicationDelayMs);
396 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800397 builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
398 mMetricsLogger.write(builder);
399 }
400 }
401
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200402 void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
403 final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId());
404 if (info == null) {
405 return;
406 }
407 final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
408 builder.setPackageName(r.packageName);
409 builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
410 builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS,
411 SystemClock.uptimeMillis() - mLastTransitionStartTime);
412 builder.setType(restoredFromBundle
413 ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
414 : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
415 builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
416 info.currentTransitionProcessRunning ? 1 : 0);
417 mMetricsLogger.write(builder);
418 }
419
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800420 private int getTransitionType(StackTransitionInfo info) {
421 if (info.currentTransitionProcessRunning) {
422 if (info.startResult == START_SUCCESS) {
423 return TYPE_TRANSITION_WARM_LAUNCH;
424 } else if (info.startResult == START_TASK_TO_FRONT) {
425 return TYPE_TRANSITION_HOT_LAUNCH;
426 }
427 } else if (info.startResult == START_SUCCESS) {
428 return TYPE_TRANSITION_COLD_LAUNCH;
429 }
430 return -1;
431 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800432}