blob: 62f8c7285e6e13933742c18190316014427a366e [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;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07005import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
Wale Ogunwale926aade2017-08-29 11:24:37 -07006import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
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;
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 Jaggi172e99f2017-10-20 14:33:18 +020015import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CANCELLED;
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;
Calin Juravle759fbda2018-02-20 19:52:30 +000026import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
27import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080028import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
29import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020030import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
31import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080032import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020033import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
Jorim Jaggif9704102016-05-05 19:14:22 -070034import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
35import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Ng Zhi Anbbefdec2018-01-30 17:12:39 -080036import static com.android.server.am.MemoryStatUtil.MemoryStat;
Rajeev Kumarbfcd9202018-03-02 22:42:13 +000037import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080038
Filip Gruszczynski77d94482015-12-11 13:59:52 -080039import android.content.Context;
Calin Juravle759fbda2018-02-20 19:52:30 +000040import android.content.pm.ApplicationInfo;
41import android.content.pm.dex.ArtManagerInternal;
42import android.content.pm.dex.PackageOptimizationInfo;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080043import android.metrics.LogMaker;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020044import android.os.Handler;
45import android.os.Looper;
46import android.os.Message;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080047import android.os.SystemClock;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020048import android.util.Slog;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080049import android.util.SparseArray;
50import android.util.SparseIntArray;
Olivier Gaillardaed7f122017-12-12 14:26:22 +000051import android.util.StatsLog;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080052
53import com.android.internal.logging.MetricsLogger;
Ng Zhi An83473542018-02-20 09:02:14 -080054import com.android.internal.os.BackgroundThread;
Jorim Jaggi172e99f2017-10-20 14:33:18 +020055import com.android.internal.os.SomeArgs;
Calin Juravle759fbda2018-02-20 19:52:30 +000056import com.android.server.LocalServices;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080057
Jorim Jaggi1e630c02016-05-16 12:13:13 -070058import java.util.ArrayList;
59
Filip Gruszczynski77d94482015-12-11 13:59:52 -080060/**
61 * Handles logging into Tron.
62 */
63class ActivityMetricsLogger {
Jorim Jaggif9704102016-05-05 19:14:22 -070064
65 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityMetricsLogger" : TAG_AM;
66
Filip Gruszczynski77d94482015-12-11 13:59:52 -080067 // Window modes we are interested in logging. If we ever introduce a new type, we need to add
68 // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
69 private static final int WINDOW_STATE_STANDARD = 0;
70 private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
71 private static final int WINDOW_STATE_FREEFORM = 2;
Winson Chung83471632016-12-13 11:02:12 -080072 private static final int WINDOW_STATE_ASSISTANT = 3;
Filip Gruszczynski77d94482015-12-11 13:59:52 -080073 private static final int WINDOW_STATE_INVALID = -1;
74
Jorim Jaggi275561a2016-02-23 10:11:02 -050075 private static final long INVALID_START_TIME = -1;
76
Jorim Jaggi172e99f2017-10-20 14:33:18 +020077 private static final int MSG_CHECK_VISIBILITY = 0;
78
Filip Gruszczynski77d94482015-12-11 13:59:52 -080079 // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
80 // time we log.
81 private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
Winson Chung83471632016-12-13 11:02:12 -080082 "window_time_0", "window_time_1", "window_time_2", "window_time_3"};
Filip Gruszczynski77d94482015-12-11 13:59:52 -080083
84 private int mWindowState = WINDOW_STATE_STANDARD;
85 private long mLastLogTimeSecs;
86 private final ActivityStackSupervisor mSupervisor;
87 private final Context mContext;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080088 private final MetricsLogger mMetricsLogger = new MetricsLogger();
Filip Gruszczynski77d94482015-12-11 13:59:52 -080089
Jorim Jaggi275561a2016-02-23 10:11:02 -050090 private long mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi4d27b842017-08-17 17:22:26 +020091 private long mLastTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -080092
93 private int mCurrentTransitionDeviceUptime;
94 private int mCurrentTransitionDelayMs;
Jorim Jaggi275561a2016-02-23 10:11:02 -050095 private boolean mLoggedTransitionStarting;
96
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +010097 private final SparseArray<WindowingModeTransitionInfo> mWindowingModeTransitionInfo =
98 new SparseArray<>();
99 private final SparseArray<WindowingModeTransitionInfo> mLastWindowingModeTransitionInfo =
100 new SparseArray<>();
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200101 private final H mHandler;
Calin Juravle759fbda2018-02-20 19:52:30 +0000102
103 private ArtManagerInternal mArtManagerInternal;
104
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200105 private final class H extends Handler {
106
107 public H(Looper looper) {
108 super(looper);
109 }
110
111 @Override
112 public void handleMessage(Message msg) {
113 switch (msg.what) {
114 case MSG_CHECK_VISIBILITY:
115 final SomeArgs args = (SomeArgs) msg.obj;
116 checkVisibility((TaskRecord) args.arg1, (ActivityRecord) args.arg2);
117 break;
118 }
119 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000120 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800121
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100122 private final class WindowingModeTransitionInfo {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800123 private ActivityRecord launchedActivity;
124 private int startResult;
125 private boolean currentTransitionProcessRunning;
126 private int windowsDrawnDelayMs;
Jorim Jaggi515dd682017-05-05 15:05:07 +0200127 private int startingWindowDelayMs = -1;
128 private int bindApplicationDelayMs = -1;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800129 private int reason = APP_TRANSITION_TIMEOUT;
130 private boolean loggedWindowsDrawn;
131 private boolean loggedStartingWindowDrawn;
132 }
133
Calin Juravle759fbda2018-02-20 19:52:30 +0000134 private final class WindowingModeTransitionInfoSnapshot {
135 final private ApplicationInfo applicationInfo;
Wale Ogunwalef6733932018-06-27 05:14:34 -0700136 final private WindowProcessController processRecord;
Calin Juravle759fbda2018-02-20 19:52:30 +0000137 final private String packageName;
138 final private String launchedActivityName;
139 final private String launchedActivityLaunchedFromPackage;
140 final private String launchedActivityLaunchToken;
141 final private String launchedActivityAppRecordRequiredAbi;
Ng Zhi An83473542018-02-20 09:02:14 -0800142 final private String processName;
Calin Juravle759fbda2018-02-20 19:52:30 +0000143 final private int reason;
144 final private int startingWindowDelayMs;
145 final private int bindApplicationDelayMs;
146 final private int windowsDrawnDelayMs;
147 final private int type;
148
149 private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info) {
150 applicationInfo = info.launchedActivity.appInfo;
151 packageName = info.launchedActivity.packageName;
152 launchedActivityName = info.launchedActivity.info.name;
153 launchedActivityLaunchedFromPackage = info.launchedActivity.launchedFromPackage;
154 launchedActivityLaunchToken = info.launchedActivity.info.launchToken;
155 launchedActivityAppRecordRequiredAbi = info.launchedActivity.app == null
156 ? null
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700157 : info.launchedActivity.app.getRequiredAbi();
Calin Juravle759fbda2018-02-20 19:52:30 +0000158 reason = info.reason;
159 startingWindowDelayMs = info.startingWindowDelayMs;
160 bindApplicationDelayMs = info.bindApplicationDelayMs;
161 windowsDrawnDelayMs = info.windowsDrawnDelayMs;
162 type = getTransitionType(info);
Ng Zhi An83473542018-02-20 09:02:14 -0800163 processRecord = findProcessForActivity(info.launchedActivity);
164 processName = info.launchedActivity.processName;
Calin Juravle759fbda2018-02-20 19:52:30 +0000165 }
166 }
167
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200168 ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context, Looper looper) {
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800169 mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
170 mSupervisor = supervisor;
171 mContext = context;
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200172 mHandler = new H(looper);
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800173 }
174
175 void logWindowState() {
176 final long now = SystemClock.elapsedRealtime() / 1000;
177 if (mWindowState != WINDOW_STATE_INVALID) {
178 // We log even if the window state hasn't changed, because the user might remain in
179 // home/fullscreen move forever and we would like to track this kind of behavior
180 // too.
181 MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
182 (int) (now - mLastLogTimeSecs));
183 }
184 mLastLogTimeSecs = now;
185
Wale Ogunwale926aade2017-08-29 11:24:37 -0700186 mWindowState = WINDOW_STATE_INVALID;
187 ActivityStack stack = mSupervisor.getFocusedStack();
lumarkf6c4a982018-06-15 15:43:12 +0800188 if (stack == null) {
189 return;
190 }
191
Wale Ogunwale926aade2017-08-29 11:24:37 -0700192 if (stack.isActivityTypeAssistant()) {
193 mWindowState = WINDOW_STATE_ASSISTANT;
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800194 return;
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800195 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700196
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700197 int windowingMode = stack.getWindowingMode();
198 if (windowingMode == WINDOWING_MODE_PINNED) {
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800199 stack = mSupervisor.findStackBehind(stack);
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700200 windowingMode = stack.getWindowingMode();
Filip Gruszczynskicaae14e2015-12-16 14:40:04 -0800201 }
Wale Ogunwale926aade2017-08-29 11:24:37 -0700202 switch (windowingMode) {
203 case WINDOWING_MODE_FULLSCREEN:
204 mWindowState = WINDOW_STATE_STANDARD;
205 break;
206 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
207 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
208 mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
209 break;
Bryce Lee6c605092017-10-12 11:14:49 -0700210 case WINDOWING_MODE_FREEFORM:
Wale Ogunwale926aade2017-08-29 11:24:37 -0700211 mWindowState = WINDOW_STATE_FREEFORM;
212 break;
213 default:
214 if (windowingMode != WINDOWING_MODE_UNDEFINED) {
215 throw new IllegalStateException("Unknown windowing mode for stack=" + stack
216 + " windowingMode=" + windowingMode);
217 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800218 }
219 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500220
221 /**
222 * Notifies the tracker at the earliest possible point when we are starting to launch an
223 * activity.
224 */
225 void notifyActivityLaunching() {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800226 if (!isAnyTransitionActive()) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200227 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunching");
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400228 mCurrentTransitionStartTime = SystemClock.uptimeMillis();
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200229 mLastTransitionStartTime = mCurrentTransitionStartTime;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800230 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500231 }
232
233 /**
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700234 * Notifies the tracker that the activity is actually launching.
235 *
236 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
237 * launch
238 * @param launchedActivity the activity that is being launched
239 */
240 void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity) {
Wale Ogunwalef6733932018-06-27 05:14:34 -0700241 final WindowProcessController processRecord = findProcessForActivity(launchedActivity);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700242 final boolean processRunning = processRecord != null;
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700243
244 // We consider this a "process switch" if the process of the activity that gets launched
245 // didn't have an activity that was in started state. In this case, we assume that lot
246 // of caches might be purged so the time until it produces the first frame is very
247 // interesting.
248 final boolean processSwitch = processRecord == null
Wale Ogunwalef6733932018-06-27 05:14:34 -0700249 || !processRecord.hasStartedActivity(launchedActivity);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700250
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800251 notifyActivityLaunched(resultCode, launchedActivity, processRunning, processSwitch);
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700252 }
253
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700254 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500255 * Notifies the tracker the the activity is actually launching.
256 *
257 * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
258 * launch
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800259 * @param launchedActivity the activity being launched
Jorim Jaggi275561a2016-02-23 10:11:02 -0500260 * @param processRunning whether the process that will contains the activity is already running
Jorim Jaggibe67c902016-04-12 00:53:16 -0700261 * @param processSwitch whether the process that will contain the activity didn't have any
262 * activity that was stopped, i.e. the started activity is "switching"
263 * processes
Jorim Jaggi275561a2016-02-23 10:11:02 -0500264 */
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800265 private void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700266 boolean processRunning, boolean processSwitch) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500267
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200268 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched"
269 + " resultCode=" + resultCode
270 + " launchedActivity=" + launchedActivity
271 + " processRunning=" + processRunning
272 + " processSwitch=" + processSwitch);
273
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800274 // If we are already in an existing transition, only update the activity name, but not the
275 // other attributes.
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100276 final int windowingMode = launchedActivity != null
277 ? launchedActivity.getWindowingMode()
278 : WINDOWING_MODE_UNDEFINED;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200279
280 if (mCurrentTransitionStartTime == INVALID_START_TIME) {
281 return;
282 }
283
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100284 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800285 if (launchedActivity != null && info != null) {
286 info.launchedActivity = launchedActivity;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500287 return;
288 }
289
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100290 final boolean otherWindowModesLaunching =
291 mWindowingModeTransitionInfo.size() > 0 && info == null;
Jorim Jaggi54cff642018-03-15 15:51:32 +0100292 if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100293 || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
Alison Cichowlas803054d2016-12-13 14:38:01 -0500294
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800295 // Failed to launch or it was not a process switch, so we don't care about the timing.
296 reset(true /* abort */);
297 return;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100298 } else if (otherWindowModesLaunching) {
299 // Don't log this windowing mode but continue with the other windowing modes.
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800300 return;
301 }
302
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200303 if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched successful");
304
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100305 final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800306 newInfo.launchedActivity = launchedActivity;
307 newInfo.currentTransitionProcessRunning = processRunning;
308 newInfo.startResult = resultCode;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100309 mWindowingModeTransitionInfo.put(windowingMode, newInfo);
310 mLastWindowingModeTransitionInfo.put(windowingMode, newInfo);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800311 mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500312 }
313
314 /**
Jorim Jaggi54cff642018-03-15 15:51:32 +0100315 * @return True if we should start logging an event for an activity start that returned
316 * {@code resultCode} and that we'll indeed get a windows drawn event.
317 */
318 private boolean isLoggableResultCode(int resultCode) {
319 return resultCode == START_SUCCESS || resultCode == START_TASK_TO_FRONT;
320 }
321
322 /**
Jorim Jaggi275561a2016-02-23 10:11:02 -0500323 * Notifies the tracker that all windows of the app have been drawn.
324 */
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100325 void notifyWindowsDrawn(int windowingMode, long timestamp) {
326 if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200327
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100328 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800329 if (info == null || info.loggedWindowsDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500330 return;
331 }
Sudheer Shankac766db02017-06-12 10:37:29 -0700332 info.windowsDrawnDelayMs = calculateDelay(timestamp);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800333 info.loggedWindowsDrawn = true;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100334 if (allWindowsDrawn() && mLoggedTransitionStarting) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800335 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500336 }
337 }
338
339 /**
340 * Notifies the tracker that the starting window was drawn.
341 */
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100342 void notifyStartingWindowDrawn(int windowingMode, long timestamp) {
343 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800344 if (info == null || info.loggedStartingWindowDrawn) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500345 return;
346 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800347 info.loggedStartingWindowDrawn = true;
Sudheer Shankac766db02017-06-12 10:37:29 -0700348 info.startingWindowDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500349 }
350
351 /**
352 * Notifies the tracker that the app transition is starting.
353 *
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100354 * @param windowingModeToReason A map from windowing mode to a reason integer, which must be on
355 * of ActivityManagerInternal.APP_TRANSITION_* reasons.
Jorim Jaggi275561a2016-02-23 10:11:02 -0500356 */
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100357 void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
Jorim Jaggid8a57772017-04-14 16:50:42 -0700358 if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
Jorim Jaggi275561a2016-02-23 10:11:02 -0500359 return;
360 }
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200361 if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
Sudheer Shankac766db02017-06-12 10:37:29 -0700362 mCurrentTransitionDelayMs = calculateDelay(timestamp);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500363 mLoggedTransitionStarting = true;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100364 for (int index = windowingModeToReason.size() - 1; index >= 0; index--) {
365 final int windowingMode = windowingModeToReason.keyAt(index);
366 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
367 windowingMode);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800368 if (info == null) {
369 continue;
370 }
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100371 info.reason = windowingModeToReason.valueAt(index);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800372 }
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100373 if (allWindowsDrawn()) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800374 reset(false /* abort */);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500375 }
376 }
377
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200378 /**
379 * Notifies the tracker that the visibility of an app is changing.
380 *
381 * @param activityRecord the app that is changing its visibility
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200382 */
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200383 void notifyVisibilityChanged(ActivityRecord activityRecord) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100384 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
385 activityRecord.getWindowingMode());
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200386 if (info == null) {
387 return;
388 }
389 if (info.launchedActivity != activityRecord) {
390 return;
391 }
392 final TaskRecord t = activityRecord.getTask();
393 final SomeArgs args = SomeArgs.obtain();
394 args.arg1 = t;
395 args.arg2 = activityRecord;
396 mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
397 }
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200398
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200399 private void checkVisibility(TaskRecord t, ActivityRecord r) {
Wale Ogunwalec9e57de2018-05-08 14:28:07 -0700400 synchronized (mSupervisor.mService.mGlobalLock) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200401
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100402 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
403 r.getWindowingMode());
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200404
405 // If we have an active transition that's waiting on a certain activity that will be
406 // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
407 if (info != null && !t.isVisible()) {
408 if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible"
409 + " activity=" + r);
410 logAppTransitionCancel(info);
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100411 mWindowingModeTransitionInfo.remove(r.getWindowingMode());
412 if (mWindowingModeTransitionInfo.size() == 0) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200413 reset(true /* abort */);
414 }
Jorim Jaggicdfc04e2017-04-28 19:06:24 +0200415 }
416 }
417 }
418
Jorim Jaggi515dd682017-05-05 15:05:07 +0200419 /**
420 * Notifies the tracker that we called immediately before we call bindApplication on the client.
421 *
422 * @param app The client into which we'll call bindApplication.
423 */
424 void notifyBindApplication(ProcessRecord app) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100425 for (int i = mWindowingModeTransitionInfo.size() - 1; i >= 0; i--) {
426 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.valueAt(i);
Jorim Jaggi515dd682017-05-05 15:05:07 +0200427
428 // App isn't attached to record yet, so match with info.
429 if (info.launchedActivity.appInfo == app.info) {
430 info.bindApplicationDelayMs = calculateCurrentDelay();
431 }
432 }
433 }
434
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100435 private boolean allWindowsDrawn() {
436 for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
437 if (!mWindowingModeTransitionInfo.valueAt(index).loggedWindowsDrawn) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800438 return false;
439 }
440 }
441 return true;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500442 }
443
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800444 private boolean isAnyTransitionActive() {
445 return mCurrentTransitionStartTime != INVALID_START_TIME
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100446 && mWindowingModeTransitionInfo.size() > 0;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800447 }
448
449 private void reset(boolean abort) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200450 if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800451 if (!abort && isAnyTransitionActive()) {
452 logAppTransitionMultiEvents();
453 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500454 mCurrentTransitionStartTime = INVALID_START_TIME;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800455 mCurrentTransitionDelayMs = -1;
Jorim Jaggi275561a2016-02-23 10:11:02 -0500456 mLoggedTransitionStarting = false;
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100457 mWindowingModeTransitionInfo.clear();
Jorim Jaggi275561a2016-02-23 10:11:02 -0500458 }
459
460 private int calculateCurrentDelay() {
461
462 // Shouldn't take more than 25 days to launch an app, so int is fine here.
Alison Cichowlasb7f67ab2017-04-25 18:04:40 -0400463 return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500464 }
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800465
Sudheer Shankac766db02017-06-12 10:37:29 -0700466 private int calculateDelay(long timestamp) {
467 // Shouldn't take more than 25 days to launch an app, so int is fine here.
468 return (int) (timestamp - mCurrentTransitionStartTime);
469 }
470
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100471 private void logAppTransitionCancel(WindowingModeTransitionInfo info) {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200472 final int type = getTransitionType(info);
473 if (type == -1) {
474 return;
475 }
476 final LogMaker builder = new LogMaker(APP_TRANSITION_CANCELLED);
477 builder.setPackageName(info.launchedActivity.packageName);
478 builder.setType(type);
479 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
480 mMetricsLogger.write(builder);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000481 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800482 StatsLog.APP_START_CANCELED,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000483 info.launchedActivity.appInfo.uid,
484 info.launchedActivity.packageName,
485 convertAppStartTransitionType(type),
486 info.launchedActivity.info.name);
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200487 }
488
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800489 private void logAppTransitionMultiEvents() {
Jorim Jaggi172e99f2017-10-20 14:33:18 +0200490 if (DEBUG_METRICS) Slog.i(TAG, "logging transition events");
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100491 for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
492 final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.valueAt(index);
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800493 final int type = getTransitionType(info);
494 if (type == -1) {
495 return;
496 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000497
498 // Take a snapshot of the transition info before sending it to the handler for logging.
499 // This will avoid any races with other operations that modify the ActivityRecord.
500 final WindowingModeTransitionInfoSnapshot infoSnapshot =
501 new WindowingModeTransitionInfoSnapshot(info);
Ng Zhi An83473542018-02-20 09:02:14 -0800502 final int currentTransitionDeviceUptime = mCurrentTransitionDeviceUptime;
503 final int currentTransitionDelayMs = mCurrentTransitionDelayMs;
504 BackgroundThread.getHandler().post(() -> logAppTransition(
505 currentTransitionDeviceUptime, currentTransitionDelayMs, infoSnapshot));
Calin Juravle759fbda2018-02-20 19:52:30 +0000506
507 info.launchedActivity.info.launchToken = null;
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800508 }
509 }
510
Ng Zhi An83473542018-02-20 09:02:14 -0800511 // This gets called on a background thread without holding the activity manager lock.
Calin Juravle759fbda2018-02-20 19:52:30 +0000512 private void logAppTransition(int currentTransitionDeviceUptime, int currentTransitionDelayMs,
513 WindowingModeTransitionInfoSnapshot info) {
514 final LogMaker builder = new LogMaker(APP_TRANSITION);
515 builder.setPackageName(info.packageName);
516 builder.setType(info.type);
517 builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivityName);
518 final boolean isInstantApp = info.applicationInfo.isInstantApp();
519 if (info.launchedActivityLaunchedFromPackage != null) {
520 builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
521 info.launchedActivityLaunchedFromPackage);
522 }
523 String launchToken = info.launchedActivityLaunchToken;
524 if (launchToken != null) {
525 builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, launchToken);
526 }
527 builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
528 builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
529 currentTransitionDeviceUptime);
530 builder.addTaggedData(APP_TRANSITION_DELAY_MS, currentTransitionDelayMs);
531 builder.setSubtype(info.reason);
532 if (info.startingWindowDelayMs != -1) {
533 builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
534 info.startingWindowDelayMs);
535 }
536 if (info.bindApplicationDelayMs != -1) {
537 builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
538 info.bindApplicationDelayMs);
539 }
540 builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
541 final ArtManagerInternal artManagerInternal = getArtManagerInternal();
542 final PackageOptimizationInfo packageOptimizationInfo =
543 (artManagerInternal == null) || (info.launchedActivityAppRecordRequiredAbi == null)
544 ? PackageOptimizationInfo.createWithNoInfo()
545 : artManagerInternal.getPackageOptimizationInfo(
546 info.applicationInfo,
547 info.launchedActivityAppRecordRequiredAbi);
548 builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_REASON,
549 packageOptimizationInfo.getCompilationReason());
550 builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER,
551 packageOptimizationInfo.getCompilationFilter());
552 mMetricsLogger.write(builder);
553 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800554 StatsLog.APP_START_OCCURRED,
Calin Juravle759fbda2018-02-20 19:52:30 +0000555 info.applicationInfo.uid,
556 info.packageName,
557 convertAppStartTransitionType(info.type),
558 info.launchedActivityName,
559 info.launchedActivityLaunchedFromPackage,
560 isInstantApp,
561 currentTransitionDeviceUptime * 1000,
562 info.reason,
563 currentTransitionDelayMs,
564 info.startingWindowDelayMs,
565 info.bindApplicationDelayMs,
566 info.windowsDrawnDelayMs,
567 launchToken,
568 packageOptimizationInfo.getCompilationReason(),
569 packageOptimizationInfo.getCompilationFilter());
Ng Zhi An83473542018-02-20 09:02:14 -0800570 logAppStartMemoryStateCapture(info);
Calin Juravle759fbda2018-02-20 19:52:30 +0000571 }
572
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000573 private int convertAppStartTransitionType(int tronType) {
574 if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800575 return StatsLog.APP_START_OCCURRED__TYPE__COLD;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000576 }
577 if (tronType == TYPE_TRANSITION_WARM_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800578 return StatsLog.APP_START_OCCURRED__TYPE__WARM;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000579 }
580 if (tronType == TYPE_TRANSITION_HOT_LAUNCH) {
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800581 return StatsLog.APP_START_OCCURRED__TYPE__HOT;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000582 }
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800583 return StatsLog.APP_START_OCCURRED__TYPE__UNKNOWN;
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000584 }
585
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200586 void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100587 final WindowingModeTransitionInfo info = mLastWindowingModeTransitionInfo.get(
588 r.getWindowingMode());
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200589 if (info == null) {
590 return;
591 }
592 final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
593 builder.setPackageName(r.packageName);
594 builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000595 long startupTimeMs = SystemClock.uptimeMillis() - mLastTransitionStartTime;
596 builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, startupTimeMs);
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200597 builder.setType(restoredFromBundle
598 ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
599 : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
600 builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
601 info.currentTransitionProcessRunning ? 1 : 0);
602 mMetricsLogger.write(builder);
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000603 StatsLog.write(
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800604 StatsLog.APP_START_FULLY_DRAWN,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000605 info.launchedActivity.appInfo.uid,
606 info.launchedActivity.packageName,
607 restoredFromBundle
Chenjie Yu5caaa9d2018-03-06 15:48:54 -0800608 ? StatsLog.APP_START_FULLY_DRAWN__TYPE__WITH_BUNDLE
609 : StatsLog.APP_START_FULLY_DRAWN__TYPE__WITHOUT_BUNDLE,
Olivier Gaillardaed7f122017-12-12 14:26:22 +0000610 info.launchedActivity.info.name,
611 info.currentTransitionProcessRunning,
612 startupTimeMs);
Jorim Jaggi4d27b842017-08-17 17:22:26 +0200613 }
614
Jorim Jaggi9b58f2d2018-02-19 17:48:44 +0100615 private int getTransitionType(WindowingModeTransitionInfo info) {
Jorim Jaggi3878ca32017-02-02 17:13:05 -0800616 if (info.currentTransitionProcessRunning) {
617 if (info.startResult == START_SUCCESS) {
618 return TYPE_TRANSITION_WARM_LAUNCH;
619 } else if (info.startResult == START_TASK_TO_FRONT) {
620 return TYPE_TRANSITION_HOT_LAUNCH;
621 }
622 } else if (info.startResult == START_SUCCESS) {
623 return TYPE_TRANSITION_COLD_LAUNCH;
624 }
625 return -1;
626 }
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800627
Ng Zhi An83473542018-02-20 09:02:14 -0800628 private void logAppStartMemoryStateCapture(WindowingModeTransitionInfoSnapshot info) {
629 if (info.processRecord == null) {
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800630 if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture processRecord null");
631 return;
632 }
633
Wale Ogunwalef6733932018-06-27 05:14:34 -0700634 final int pid = info.processRecord.getPid();
Ng Zhi An83473542018-02-20 09:02:14 -0800635 final int uid = info.applicationInfo.uid;
Rajeev Kumarbfcd9202018-03-02 22:42:13 +0000636 final MemoryStat memoryStat = readMemoryStatFromFilesystem(uid, pid);
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800637 if (memoryStat == null) {
638 if (DEBUG_METRICS) Slog.i(TAG, "logAppStartMemoryStateCapture memoryStat null");
639 return;
640 }
641
642 StatsLog.write(
643 StatsLog.APP_START_MEMORY_STATE_CAPTURED,
644 uid,
Ng Zhi An83473542018-02-20 09:02:14 -0800645 info.processName,
646 info.launchedActivityName,
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800647 memoryStat.pgfault,
648 memoryStat.pgmajfault,
649 memoryStat.rssInBytes,
650 memoryStat.cacheInBytes,
651 memoryStat.swapInBytes);
652 }
653
Wale Ogunwalef6733932018-06-27 05:14:34 -0700654 private WindowProcessController findProcessForActivity(ActivityRecord launchedActivity) {
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800655 return launchedActivity != null
Wale Ogunwalef6733932018-06-27 05:14:34 -0700656 ? mSupervisor.mService.mProcessNames.get(
Wale Ogunwalec9e57de2018-05-08 14:28:07 -0700657 launchedActivity.processName, launchedActivity.appInfo.uid)
Ng Zhi Anbbefdec2018-01-30 17:12:39 -0800658 : null;
659 }
Calin Juravle759fbda2018-02-20 19:52:30 +0000660
661 private ArtManagerInternal getArtManagerInternal() {
662 if (mArtManagerInternal == null) {
663 // Note that this may be null.
664 // ArtManagerInternal is registered during PackageManagerService
665 // initialization which happens after ActivityManagerService.
666 mArtManagerInternal = LocalServices.getService(ArtManagerInternal.class);
667 }
668 return mArtManagerInternal;
669 }
Filip Gruszczynski77d94482015-12-11 13:59:52 -0800670}