blob: aae98a6e50132d97ebececdbb30653f53c403f02 [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;
Winson Chung83471632016-12-13 11:02:12 -08005import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski77d94482015-12-11 13:59:52 -08006import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08007import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Jorim Jaggi3878ca32017-02-02 17:13:05 -08008import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07009import static android.app.WindowConfiguration.WINDOWING_MODE_DOCKED;
10import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
11import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
12import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080013import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
Jorim Jaggi515dd682017-05-05 15:05:07 +020014import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070015import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080016import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
17import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
Todd Kennedy50d946c12017-03-17 13:55:38 -070018import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020019import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING;
20import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
21import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080022import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
23import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +020024import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
Todd Kennedy50d946c12017-03-17 13:55:38 -070025import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080026import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
27import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020028import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
29import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080030import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
Jorim Jaggif9704102016-05-05 19:14:22 -070031import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
32import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080033import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080034
35import android.app.ActivityManager.StackId;
36import android.content.Context;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080037import android.metrics.LogMaker;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080038import android.os.SystemClock;
Jorim Jaggif9704102016-05-05 19:14:22 -070039import android.util.Slog;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080040import android.util.SparseArray;
41import android.util.SparseIntArray;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080042
43import com.android.internal.logging.MetricsLogger;
44
Jorim Jaggi1e630c02016-05-16 12:13:13 -070045import java.util.ArrayList;
46
Filip Gruszczynski77d94482015-12-11 13:59:52 -080047/**
48 * Handles logging into Tron.
49 */
50class ActivityMetricsLogger {
Jorim Jaggif9704102016-05-05 19:14:22 -070051
52 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM;
53
Filip Gruszczynski77d94482015-12-11 13:59:52 -080054 // Window modes we are interested in logging. If we ever introduce a new type, we need to add
55 // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
56 private static final int WINDOW_STATE_STANDARD = 0;
57 private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
58 private static final int WINDOW_STATE_FREEFORM = 2;
Winson Chung83471632016-12-13 11:02:12 -080059 private static final int WINDOW_STATE_ASSISTANT = 3;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080060 private static final int WINDOW_STATE_INVALID = -1;
61
Jorim Jaggi275561a2016-02-23 10:11:02 -050062 private static final long INVALID_START_TIME = -1;
63
Filip Gruszczynski77d94482015-12-11 13:59:52 -080064 // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
65 // time we log.
66 private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
Winson Chung83471632016-12-13 11:02:12 -080067 "window_time_0", "window_time_1", "window_time_2", "window_time_3"};
Filip Gruszczynski77d94482015-12-11 13:59:52 -080068
69 private int mWindowState = WINDOW_STATE_STANDARD;
70 private long mLastLogTimeSecs;
71 private final ActivityStackSupervisor mSupervisor;
72 private final Context mContext;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080073 private final MetricsLogger mMetricsLogger = new MetricsLogger();
Filip Gruszczynski77d94482015-12-11 13:59:52 -080074
Jorim Jaggi275561a2016-02-23 10:11:02 -050075 private long mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020076 private long mLastTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080077
78 private int mCurrentTransitionDeviceUptime;
79 private int mCurrentTransitionDelayMs;
Jorim Jaggi275561a2016-02-23 10:11:02 -050080 private boolean mLoggedTransitionStarting;
81
Jorim Jaggi3878ca32017-02-02 17:13:05 -080082 private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>();
Jorim Jaggi4d27b842017-08-17 17:22:26 +020083 private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>();
Jorim Jaggi3878ca32017-02-02 17:13:05 -080084
85 private final class StackTransitionInfo {
86 private ActivityRecord launchedActivity;
87 private int startResult;
88 private boolean currentTransitionProcessRunning;
89 private int windowsDrawnDelayMs;
Jorim Jaggi515dd682017-05-05 15:05:07 +020090 private int startingWindowDelayMs = -1;
91 private int bindApplicationDelayMs = -1;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080092 private int reason = APP_TRANSITION_TIMEOUT;
93 private boolean loggedWindowsDrawn;
94 private boolean loggedStartingWindowDrawn;
95 }
96
Filip Gruszczynski77d94482015-12-11 13:59:52 -080097 ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
98 mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
99 mSupervisor = supervisor;
100 mContext = context;
101 }
102
103 void logWindowState() {
104 final long now = SystemClock.elapsedRealtime() / 1000;
105 if (mWindowState != WINDOW_STATE_INVALID) {
106 // We log even if the window state hasn't changed, because the user might remain in
107 // home/fullscreen move forever and we would like to track this kind of behavior
108 // too.
109 MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
110 (int) (now - mLastLogTimeSecs));
111 }
112 mLastLogTimeSecs = now;
113
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800114 ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700115 if (stack != null && stack.shouldBeVisible(null) != STACK_INVISIBLE) {
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800116 mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800117 return;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800118 }
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800119 mWindowState = WINDOW_STATE_INVALID;
120 stack = mSupervisor.getFocusedStack();
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700121 int windowingMode = stack.getWindowingMode();
122 if (windowingMode == WINDOWING_MODE_PINNED) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800123 stack = mSupervisor.findStackBehind(stack);
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700124 windowingMode = stack.getWindowingMode();
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800125 }
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800126 if (StackId.isHomeOrRecentsStack(stack.mStackId)
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700127 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800128 mWindowState = WINDOW_STATE_STANDARD;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700129 } else if (windowingMode == WINDOWING_MODE_DOCKED) {
Jorim Jaggif9704102016-05-05 19:14:22 -0700130 Slog.wtf(TAG, "Docked stack shouldn't be the focused stack, because it reported not"
131 + " being visible.");
132 mWindowState = WINDOW_STATE_INVALID;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700133 } else if (windowingMode == WINDOWING_MODE_FREEFORM) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800134 mWindowState = WINDOW_STATE_FREEFORM;
Winson Chung83471632016-12-13 11:02:12 -0800135 } else if (stack.mStackId == ASSISTANT_STACK_ID) {
136 mWindowState = WINDOW_STATE_ASSISTANT;
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800137 } else if (StackId.isStaticStack(stack.mStackId)) {
138 throw new IllegalStateException("Unknown stack=" + stack);
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800139 }
140 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500141
142 /**
143 * Notifies the tracker at the earliest possible point when we are starting to launch an
144 * activity.
145 */
146 void notifyActivityLaunching() {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800147 if (!isAnyTransitionActive()) {
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400148 mCurrentTransitionStartTime = SystemClock.uptimeMillis();
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200149 mLastTransitionStartTime = mCurrentTransitionStartTime;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800150 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500151 }
152
153 /**
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700154 * Notifies the tracker that the activity is actually launching.
155 *
156 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
157 * launch
158 * @param launchedActivity the activity that is being launched
159 */
160 void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
161 final ProcessRecord processRecord = launchedActivity != null
162 ? mSupervisor.mService.mProcessNames.get(launchedActivity.processName,
163 launchedActivity.appInfo.uid)
164 : null;
165 final boolean processRunning = processRecord != null;
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700166
167 // We consider this a "process switch" if the process of the activity that gets launched
168 // didn't have an activity that was in started state. In this case, we assume that lot
169 // of caches might be purged so the time until it produces the first frame is very
170 // interesting.
171 final boolean processSwitch = processRecord == null
172 || !hasStartedActivity(processRecord, launchedActivity);
173
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800174 notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700175 }
176
177 private boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
178 final ArrayList<ActivityRecord> activities = record.activities;
179 for (int i = activities.size() - 1; i >= 0; i--) {
180 final ActivityRecord activity = activities.get(i);
181 if (launchedActivity == activity) {
182 continue;
183 }
184 if (!activity.stopped) {
185 return true;
186 }
187 }
188 return false;
189 }
190
191 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500192 * Notifies the tracker the the activity is actually launching.
193 *
194 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
195 * launch
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800196 * @param launchedActivity the activity being launched
Jorim Jaggi275561a2016-02-23 10:11:02 -0500197 * @param processRunning whether the process that will contains the activity is already running
Jorim Jaggibe67c902016-04-12 00:53:16 -0700198 * @param processSwitch whether the process that will contain the activity didn't have any
199 * activity that was stopped, i.e. the started activity is "switching"
200 * processes
Jorim Jaggi275561a2016-02-23 10:11:02 -0500201 */
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800202 private void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700203 boolean processRunning, boolean processSwitch) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500204
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800205 // If we are already in an existing transition, only update the activity name, but not the
206 // other attributes.
207 final int stackId = launchedActivity != null && launchedActivity.getStack() != null
208 ? launchedActivity.getStack().mStackId
209 : INVALID_STACK_ID;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200210
211 if (mCurrentTransitionStartTime == INVALID_START_TIME) {
212 return;
213 }
214
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800215 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
216 if (launchedActivity != null && info != null) {
217 info.launchedActivity = launchedActivity;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500218 return;
219 }
220
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800221 final boolean otherStacksLaunching = mStackTransitionInfo.size() > 0 && info == null;
222 if ((resultCode < 0 || launchedActivity == null || !processSwitch
223 || stackId == INVALID_STACK_ID) && !otherStacksLaunching) {
Alison Cichowlas803054d2016-12-13 14:38:01 -0500224
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800225 // Failed to launch or it was not a process switch, so we don't care about the timing.
226 reset(true /* abort */);
227 return;
228 } else if (otherStacksLaunching) {
229 // Don't log this stack but continue with the other stacks.
230 return;
231 }
232
233 final StackTransitionInfo newInfo = new StackTransitionInfo();
234 newInfo.launchedActivity = launchedActivity;
235 newInfo.currentTransitionProcessRunning = processRunning;
236 newInfo.startResult = resultCode;
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200237 mStackTransitionInfo.put(stackId, newInfo);
238 mLastStackTransitionInfo.put(stackId, newInfo);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800239 mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500240 }
241
242 /**
243 * Notifies the tracker that all windows of the app have been drawn.
244 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700245 void notifyWindowsDrawn(int stackId, long timestamp) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800246 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
247 if (info == null || info.loggedWindowsDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500248 return;
249 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700250 info.windowsDrawnDelayMs = calculateDelay(timestamp);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800251 info.loggedWindowsDrawn = true;
252 if (allStacksWindowsDrawn() && mLoggedTransitionStarting) {
253 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500254 }
255 }
256
257 /**
258 * Notifies the tracker that the starting window was drawn.
259 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700260 void notifyStartingWindowDrawn(int stackId, long timestamp) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800261 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
262 if (info == null || info.loggedStartingWindowDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500263 return;
264 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800265 info.loggedStartingWindowDrawn = true;
Sudheer Shankac766db02017-06-12 10:37:29 -0700266 info.startingWindowDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500267 }
268
269 /**
270 * Notifies the tracker that the app transition is starting.
271 *
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800272 * @param stackIdReasons A map from stack id to a reason integer, which must be on of
273 * ActivityManagerInternal.APP_TRANSITION_* reasons.
Jorim Jaggi275561a2016-02-23 10:11:02 -0500274 */
Sudheer Shankac766db02017-06-12 10:37:29 -0700275 void notifyTransitionStarting(SparseIntArray stackIdReasons, long timestamp) {
Jorim Jaggid8a57772017-04-14 16:50:42 -0700276 if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500277 return;
278 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700279 mCurrentTransitionDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500280 mLoggedTransitionStarting = true;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800281 for (int index = stackIdReasons.size() - 1; index >= 0; index--) {
282 final int stackId = stackIdReasons.keyAt(index);
283 final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
284 if (info == null) {
285 continue;
286 }
287 info.reason = stackIdReasons.valueAt(index);
288 }
289 if (allStacksWindowsDrawn()) {
290 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500291 }
292 }
293
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200294 /**
295 * Notifies the tracker that the visibility of an app is changing.
296 *
297 * @param activityRecord the app that is changing its visibility
298 * @param visible whether it's going to be visible or not
299 */
300 void notifyVisibilityChanged(ActivityRecord activityRecord, boolean visible) {
301 final StackTransitionInfo info = mStackTransitionInfo.get(activityRecord.getStackId());
302
303 // If we have an active transition that's waiting on a certain activity that will be
304 // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
305 if (info != null && !visible && info.launchedActivity == activityRecord) {
306 mStackTransitionInfo.remove(activityRecord.getStackId());
307 if (mStackTransitionInfo.size() == 0) {
308 reset(true /* abort */);
309 }
310 }
311 }
312
Jorim Jaggi515dd682017-05-05 15:05:07 +0200313 /**
314 * Notifies the tracker that we called immediately before we call bindApplication on the client.
315 *
316 * @param app The client into which we'll call bindApplication.
317 */
318 void notifyBindApplication(ProcessRecord app) {
319 for (int i = mStackTransitionInfo.size() - 1; i >= 0; i--) {
320 final StackTransitionInfo info = mStackTransitionInfo.valueAt(i);
321
322 // App isn't attached to record yet, so match with info.
323 if (info.launchedActivity.appInfo == app.info) {
324 info.bindApplicationDelayMs = calculateCurrentDelay();
325 }
326 }
327 }
328
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800329 private boolean allStacksWindowsDrawn() {
330 for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
331 if (!mStackTransitionInfo.valueAt(index).loggedWindowsDrawn) {
332 return false;
333 }
334 }
335 return true;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500336 }
337
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800338 private boolean isAnyTransitionActive() {
339 return mCurrentTransitionStartTime != INVALID_START_TIME
340 && mStackTransitionInfo.size() > 0;
341 }
342
343 private void reset(boolean abort) {
344 if (!abort && isAnyTransitionActive()) {
345 logAppTransitionMultiEvents();
346 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500347 mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800348 mCurrentTransitionDelayMs = -1;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500349 mLoggedTransitionStarting = false;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800350 mStackTransitionInfo.clear();
Jorim Jaggi275561a2016-02-23 10:11:02 -0500351 }
352
353 private int calculateCurrentDelay() {
354
355 // Shouldn't take more than 25 days to launch an app, so int is fine here.
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400356 return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500357 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800358
Sudheer Shankac766db02017-06-12 10:37:29 -0700359 private int calculateDelay(long timestamp) {
360 // Shouldn't take more than 25 days to launch an app, so int is fine here.
361 return (int) (timestamp - mCurrentTransitionStartTime);
362 }
363
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800364 private void logAppTransitionMultiEvents() {
365 for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
366 final StackTransitionInfo info = mStackTransitionInfo.valueAt(index);
367 final int type = getTransitionType(info);
368 if (type == -1) {
369 return;
370 }
371 final LogMaker builder = new LogMaker(APP_TRANSITION);
372 builder.setPackageName(info.launchedActivity.packageName);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800373 builder.setType(type);
Jason Monk8c09ac72017-03-16 11:53:40 -0400374 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
Todd Kennedy56279cb2017-04-17 14:53:49 -0700375 final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp();
Todd Kennedy7655b292017-08-18 15:05:01 -0700376 if (info.launchedActivity.launchedFromPackage != null) {
Todd Kennedy50d946c12017-03-17 13:55:38 -0700377 builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
378 info.launchedActivity.launchedFromPackage);
379 }
380 if (info.launchedActivity.info.launchToken != null) {
381 builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN,
382 info.launchedActivity.info.launchToken);
Todd Kennedyb3b431302017-03-20 16:05:48 -0700383 info.launchedActivity.info.launchToken = null;
Todd Kennedy50d946c12017-03-17 13:55:38 -0700384 }
Todd Kennedy56279cb2017-04-17 14:53:49 -0700385 builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800386 builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
387 mCurrentTransitionDeviceUptime);
388 builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs);
389 builder.setSubtype(info.reason);
390 if (info.startingWindowDelayMs != -1) {
391 builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
392 info.startingWindowDelayMs);
393 }
Jorim Jaggi515dd682017-05-05 15:05:07 +0200394 if (info.bindApplicationDelayMs != -1) {
395 builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
396 info.bindApplicationDelayMs);
397 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800398 builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
399 mMetricsLogger.write(builder);
400 }
401 }
402
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200403 void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
404 final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId());
405 if (info == null) {
406 return;
407 }
408 final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
409 builder.setPackageName(r.packageName);
410 builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
411 builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS,
412 SystemClock.uptimeMillis() - mLastTransitionStartTime);
413 builder.setType(restoredFromBundle
414 ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
415 : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
416 builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
417 info.currentTransitionProcessRunning ? 1 : 0);
418 mMetricsLogger.write(builder);
419 }
420
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800421 private int getTransitionType(StackTransitionInfo info) {
422 if (info.currentTransitionProcessRunning) {
423 if (info.startResult == START_SUCCESS) {
424 return TYPE_TRANSITION_WARM_LAUNCH;
425 } else if (info.startResult == START_TASK_TO_FRONT) {
426 return TYPE_TRANSITION_HOT_LAUNCH;
427 }
428 } else if (info.startResult == START_SUCCESS) {
429 return TYPE_TRANSITION_COLD_LAUNCH;
430 }
431 return -1;
432 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800433}