blob: abde1dfa9db06f379011e11c36cfb2b19b869a9b [file] [log] [blame]
Vishnu Nair8e3f5f72018-10-01 11:12:51 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
Tadashi G. Takaokae2bd5c52019-04-15 14:29:33 +090017package android.server.wm;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070018
Vishnu Nair6caf4172018-10-29 21:46:56 -070019import static android.os.SystemClock.sleep;
Riddle Hsud63da272020-02-14 00:13:35 +080020import static android.server.wm.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
21import static android.server.wm.ActivityLauncher.KEY_TARGET_COMPONENT;
Wale Ogunwalecd739102020-01-29 06:15:52 -080022import static android.server.wm.WindowManagerState.STATE_STOPPED;
Tadashi G. Takaokae2bd5c52019-04-15 14:29:33 +090023import static android.server.wm.app.Components.ENTRY_POINT_ALIAS_ACTIVITY;
Riddle Hsud63da272020-02-14 00:13:35 +080024import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
Tadashi G. Takaokae2bd5c52019-04-15 14:29:33 +090025import static android.server.wm.app.Components.NO_DISPLAY_ACTIVITY;
26import static android.server.wm.app.Components.REPORT_FULLY_DRAWN_ACTIVITY;
27import static android.server.wm.app.Components.SINGLE_TASK_ACTIVITY;
28import static android.server.wm.app.Components.TEST_ACTIVITY;
29import static android.server.wm.app.Components.TRANSLUCENT_TEST_ACTIVITY;
Riddle Hsu230d2312019-10-29 14:47:14 +080030import static android.server.wm.app.Components.TRANSLUCENT_TOP_ACTIVITY;
31import static android.server.wm.app.Components.TopActivity.EXTRA_FINISH_IN_ON_CREATE;
Tadashi G. Takaokae2bd5c52019-04-15 14:29:33 +090032import static android.server.wm.second.Components.SECOND_ACTIVITY;
33import static android.server.wm.third.Components.THIRD_ACTIVITY;
Vishnu Nair86b03b82018-10-31 08:48:08 -070034import static android.util.TimeUtils.formatDuration;
Vishnu Nair9fc15c92018-12-21 08:28:24 -080035
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070036import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
Riddle Hsu230d2312019-10-29 14:47:14 +080037import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CANCELLED;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070038import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
39import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
40import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
41import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
42import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
43import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
44import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
45import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
Vishnu Nair9fc15c92018-12-21 08:28:24 -080046import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070047import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
48import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
49
50import static org.hamcrest.MatcherAssert.assertThat;
51import static org.hamcrest.Matchers.containsString;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070052import static org.hamcrest.Matchers.greaterThanOrEqualTo;
53import static org.hamcrest.Matchers.lessThanOrEqualTo;
54import static org.junit.Assert.assertEquals;
Riddle Hsu3c5a1da2019-11-27 00:24:44 +080055import static org.junit.Assert.assertNotEquals;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070056import static org.junit.Assert.assertNotNull;
Vishnu Nair1cb588a2018-10-11 10:07:55 -070057import static org.junit.Assert.assertNull;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070058import static org.junit.Assert.fail;
59
60import android.app.Activity;
61import android.content.ComponentName;
62import android.metrics.LogMaker;
63import android.metrics.MetricsReader;
64import android.os.SystemClock;
Vishnu Nair9fc15c92018-12-21 08:28:24 -080065import android.platform.test.annotations.Presubmit;
Riddle Hsub2452a32019-11-04 17:32:57 +080066import android.server.wm.CommandSession.ActivitySessionClient;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070067import android.support.test.metricshelper.MetricsAsserts;
68import android.util.EventLog.Event;
69
Charles Chen00a11b32019-11-04 15:46:08 +080070
Riddle Hsu6caae9c2020-03-11 18:06:24 +080071import androidx.annotation.NonNull;
72import androidx.annotation.Nullable;
Charles Chen00a11b32019-11-04 15:46:08 +080073
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +090074import com.android.compatibility.common.util.SystemUtil;
75
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070076import org.hamcrest.collection.IsIn;
77import org.junit.Before;
78import org.junit.Test;
79
80import java.util.Arrays;
81import java.util.List;
Riddle Hsu6caae9c2020-03-11 18:06:24 +080082import java.util.Objects;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070083import java.util.Queue;
Vishnu Nair1cb588a2018-10-11 10:07:55 -070084import java.util.concurrent.TimeUnit;
Riddle Hsu3c5a1da2019-11-27 00:24:44 +080085import java.util.function.IntConsumer;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070086
87/**
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +090088 * CTS device tests for {@link com.android.server.wm.ActivityMetricsLogger}.
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070089 * Build/Install/Run:
Tadashi G. Takaokae2bd5c52019-04-15 14:29:33 +090090 * atest CtsWindowManagerDeviceTestCases:ActivityMetricsLoggerTests
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070091 */
Wale Ogunwale5871c5b2019-02-21 15:56:14 -080092@Presubmit
Vishnu Nair8e3f5f72018-10-01 11:12:51 -070093public class ActivityMetricsLoggerTests extends ActivityManagerTestBase {
Vishnu Nair6caf4172018-10-29 21:46:56 -070094 private static final String TAG_ATM = "ActivityTaskManager";
Riddle Hsud63da272020-02-14 00:13:35 +080095 private static final String LAUNCH_STATE_COLD = "COLD";
96 private static final String LAUNCH_STATE_WARM = "WARM";
97 private static final String LAUNCH_STATE_HOT = "HOT";
Riddle Hsu7efc47e2020-11-19 15:47:16 +080098 private static final String LAUNCH_STATE_RELAUNCH = "RELAUNCH";
Riddle Hsu3c5a1da2019-11-27 00:24:44 +080099 private static final int EVENT_WM_ACTIVITY_LAUNCH_TIME = 30009;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700100 private final MetricsReader mMetricsReader = new MetricsReader();
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700101 private long mPreUptimeMs;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700102 private LogSeparator mLogSeparator;
103
104 @Before
105 public void setUp() throws Exception {
106 super.setUp();
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700107 mPreUptimeMs = SystemClock.uptimeMillis();
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700108 mMetricsReader.checkpoint(); // clear out old logs
109 mLogSeparator = separateLogs(); // add a new separator for logs
110 }
111
112 /**
113 * Launch an app and verify:
114 * - appropriate metrics logs are added
115 * - "Displayed activity ..." log is added to logcat
116 * - am_activity_launch_time event is generated
117 * In all three cases, verify the delay measurements are the same.
118 */
119 @Test
120 public void testAppLaunchIsLogged() {
Riddle Hsu230d2312019-10-29 14:47:14 +0800121 launchAndWaitForActivity(TEST_ACTIVITY);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700122
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800123 final LogMaker metricsLog = waitForMetricsLog(TEST_ACTIVITY, APP_TRANSITION);
Vishnu Nair6caf4172018-10-29 21:46:56 -0700124 final String[] deviceLogs = getDeviceLogsForComponents(mLogSeparator, TAG_ATM);
125 final List<Event> eventLogs = getEventLogsForComponents(mLogSeparator,
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800126 EVENT_WM_ACTIVITY_LAUNCH_TIME);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700127
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700128 final long postUptimeMs = SystemClock.uptimeMillis();
129 assertMetricsLogs(TEST_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs, postUptimeMs);
Vishnu Nairce3ba632018-11-16 07:50:27 -0800130 assertTransitionIsStartingWindow(metricsLog);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700131 final int windowsDrawnDelayMs =
132 (int) metricsLog.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
133 final String expectedLog =
134 "Displayed " + TEST_ACTIVITY.flattenToShortString()
Vishnu Nair86b03b82018-10-31 08:48:08 -0700135 + ": " + formatDuration(windowsDrawnDelayMs);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700136 assertLogsContain(deviceLogs, expectedLog);
137 assertEventLogsContainsLaunchTime(eventLogs, TEST_ACTIVITY, windowsDrawnDelayMs);
138 }
139
140 private void assertMetricsLogs(ComponentName componentName,
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700141 int category, LogMaker log, long preUptimeMs, long postUptimeMs) {
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700142 assertNotNull("did not find the metrics log for: " + componentName
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800143 + " category:" + categoryToString(category), log);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700144 int startUptimeSec =
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700145 ((Number) log.getTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS)).intValue();
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700146 int preUptimeSec = (int) (TimeUnit.MILLISECONDS.toSeconds(preUptimeMs));
147 int postUptimeSec = (int) (TimeUnit.MILLISECONDS.toSeconds(postUptimeMs));
148 long testElapsedTimeMs = postUptimeMs - preUptimeMs;
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700149 assertThat("must be either cold or warm launch", log.getType(),
150 IsIn.oneOf(TYPE_TRANSITION_COLD_LAUNCH, TYPE_TRANSITION_WARM_LAUNCH));
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700151 assertThat("reported uptime should be after the app was started", startUptimeSec,
152 greaterThanOrEqualTo(preUptimeSec));
153 assertThat("reported uptime should be before assertion time", startUptimeSec,
154 lessThanOrEqualTo(postUptimeSec));
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700155 assertNotNull("log should have delay", log.getTaggedData(APP_TRANSITION_DELAY_MS));
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700156 assertNotNull("log should have windows drawn delay",
157 log.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS));
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700158 long windowsDrawnDelayMs = (int) log.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
159 assertThat("windows drawn delay should be less that total elapsed time",
160 windowsDrawnDelayMs, lessThanOrEqualTo(testElapsedTimeMs));
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700161 }
162
Vishnu Nairce3ba632018-11-16 07:50:27 -0800163 private void assertTransitionIsStartingWindow(LogMaker log) {
164 assertEquals("transition should be started because of starting window",
165 1 /* APP_TRANSITION_STARTING_WINDOW */, log.getSubtype());
166 assertNotNull("log should have starting window delay",
167 log.getTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS));
168 }
169
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700170 private void assertEventLogsContainsLaunchTime(List<Event> events, ComponentName componentName,
171 int windowsDrawnDelayMs) {
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800172 verifyLaunchTimeEventLogs(events, componentName,
173 delay -> assertEquals("Unexpected windows drawn delay for " + componentName,
174 delay, windowsDrawnDelayMs));
175 }
176
177 private void verifyLaunchTimeEventLogs(List<Event> launchTimeEvents,
178 ComponentName componentName, IntConsumer launchTimeVerifier) {
179 for (Event event : launchTimeEvents) {
180 final Object[] arr = (Object[]) event.getData();
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700181 assertEquals(4, arr.length);
182 final String name = (String) arr[2];
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800183 final int launchTime = (int) arr[3];
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700184 if (name.equals(componentName.flattenToShortString())) {
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800185 launchTimeVerifier.accept(launchTime);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700186 return;
187 }
188 }
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800189 fail("Could not find wm_activity_launch_time for " + componentName);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700190 }
191
192 /**
193 * Start an activity that reports full drawn and verify:
194 * - fully drawn metrics are added to metrics logs
195 * - "Fully drawn activity ..." log is added to logcat
196 * In both cases verify fully drawn delay measurements are equal.
197 * See {@link Activity#reportFullyDrawn()}
198 */
199 @Test
200 public void testAppFullyDrawnReportIsLogged() {
Riddle Hsu230d2312019-10-29 14:47:14 +0800201 launchAndWaitForActivity(REPORT_FULLY_DRAWN_ACTIVITY);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700202
203 // Sleep until activity under test has reported drawn (after 500ms)
Vishnu Nair6caf4172018-10-29 21:46:56 -0700204 sleep(1000);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700205
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800206 final LogMaker metricsLog = waitForMetricsLog(REPORT_FULLY_DRAWN_ACTIVITY,
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700207 APP_TRANSITION_REPORTED_DRAWN);
Vishnu Nair6caf4172018-10-29 21:46:56 -0700208 final String[] deviceLogs = getDeviceLogsForComponents(mLogSeparator, TAG_ATM);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700209
210 assertNotNull("did not find the metrics log for: " + REPORT_FULLY_DRAWN_ACTIVITY
211 + " category:" + APP_TRANSITION_REPORTED_DRAWN, metricsLog);
212 assertThat("test activity has a 500ms delay before reporting fully drawn",
213 (long) metricsLog.getTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS),
214 greaterThanOrEqualTo(500L));
215 assertEquals(TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE, metricsLog.getType());
216
217 final long fullyDrawnDelayMs =
218 (long) metricsLog.getTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS);
219 final String expectedLog =
220 "Fully drawn " + REPORT_FULLY_DRAWN_ACTIVITY.flattenToShortString()
Vishnu Nair86b03b82018-10-31 08:48:08 -0700221 + ": " + formatDuration(fullyDrawnDelayMs);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700222 assertLogsContain(deviceLogs, expectedLog);
223 }
224
225 /**
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800226 * Warm launch an activity with wait option and verify that {@link android.app.WaitResult#totalTime}
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700227 * totalTime is set correctly. Make sure the reported value is consistent with value reported to
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800228 * metrics logs. Verify we output the correct launch state.
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700229 */
230 @Test
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800231 public void testAppWarmLaunchSetsWaitResultDelayData() {
Riddle Hsub2452a32019-11-04 17:32:57 +0800232 try (ActivitySessionClient client = createActivitySessionClient()) {
233 client.startActivity(getLaunchActivityBuilder()
234 .setUseInstrumentation()
235 .setTargetActivity(TEST_ACTIVITY)
236 .setWaitForLaunched(true));
237 separateTestJournal();
238 // The activity will be finished when closing the session client.
239 }
240 assertActivityDestroyed(TEST_ACTIVITY);
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800241 mMetricsReader.checkpoint(); // clear out old logs
242
Riddle Hsub2452a32019-11-04 17:32:57 +0800243 // This is warm launch because its process should be alive after the above steps.
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +0900244 final String amStartOutput = SystemUtil.runShellCommand(
245 "am start -W " + TEST_ACTIVITY.flattenToShortString());
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800246
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800247 final LogMaker metricsLog = waitForMetricsLog(TEST_ACTIVITY, APP_TRANSITION);
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800248 final int windowsDrawnDelayMs =
249 (int) metricsLog.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
250
251 assertEquals("Expected a cold launch.", metricsLog.getType(), TYPE_TRANSITION_WARM_LAUNCH);
252
Riddle Hsud63da272020-02-14 00:13:35 +0800253 assertLaunchComponentStateAndTime(amStartOutput, TEST_ACTIVITY, LAUNCH_STATE_WARM,
254 windowsDrawnDelayMs);
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800255 }
256
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800257 /**
258 * Hot launch an activity with wait option and verify that {@link android.app.WaitResult#totalTime}
259 * totalTime is set correctly. Make sure the reported value is consistent with value reported to
260 * metrics logs. Verify we output the correct launch state.
261 */
262 @Test
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800263 public void testAppHotLaunchSetsWaitResultDelayData() {
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +0900264 SystemUtil.runShellCommand("am start -S -W " + TEST_ACTIVITY.flattenToShortString());
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800265
266 // Test hot launch
Riddle Hsu79c77e02019-09-23 23:56:41 +0800267 launchHomeActivityNoWait();
Riddle Hsub2452a32019-11-04 17:32:57 +0800268 waitAndAssertActivityState(TEST_ACTIVITY, STATE_STOPPED, "Activity should be stopped");
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800269 mMetricsReader.checkpoint(); // clear out old logs
270
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +0900271 final String amStartOutput = SystemUtil.runShellCommand(
272 "am start -W " + TEST_ACTIVITY.flattenToShortString());
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800273
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800274 final LogMaker metricsLog = waitForMetricsLog(TEST_ACTIVITY, APP_TRANSITION);
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800275 final int windowsDrawnDelayMs =
276 (int) metricsLog.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
277
278 assertEquals("Expected a cold launch.", metricsLog.getType(), TYPE_TRANSITION_HOT_LAUNCH);
279
Riddle Hsud63da272020-02-14 00:13:35 +0800280 assertLaunchComponentStateAndTime(amStartOutput, TEST_ACTIVITY, LAUNCH_STATE_HOT,
281 windowsDrawnDelayMs);
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800282 }
283
Tadashi G. Takaokaf34fd012019-04-18 10:18:02 +0900284 /**
Riddle Hsu7efc47e2020-11-19 15:47:16 +0800285 * Launch an existing background activity after the device configuration is changed and the
286 * activity doesn't declare to handle the change. The state should be RELAUNCH instead of HOT.
287 */
288 @Test
289 public void testAppRelaunchSetsWaitResultDelayData() {
290 final String startTestActivityCmd = "am start -W " + TEST_ACTIVITY.flattenToShortString();
291 SystemUtil.runShellCommand(startTestActivityCmd);
292
293 // Launch another task and make sure a configuration change triggers relaunch.
294 launchAndWaitForActivity(SECOND_ACTIVITY);
Jing Jia2e87c32021-02-02 17:53:13 -0800295 separateTestJournal();
296
Riddle Hsu7efc47e2020-11-19 15:47:16 +0800297 final FontScaleSession fontScaleSession = mObjectTracker.manage(new FontScaleSession());
298 final Float originalScale = fontScaleSession.get();
299 fontScaleSession.set((originalScale == null ? 1f : originalScale) + 0.1f);
300 assertActivityLifecycle(SECOND_ACTIVITY, true /* relaunched */);
301
302 // Move the task of test activity to front.
303 final String amStartOutput = SystemUtil.runShellCommand(startTestActivityCmd);
304 assertLaunchComponentState(amStartOutput, TEST_ACTIVITY, LAUNCH_STATE_RELAUNCH);
305 }
306
307 /**
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800308 * Cold launch an activity with wait option and verify that {@link android.app.WaitResult#totalTime}
309 * totalTime is set correctly. Make sure the reported value is consistent with value reported to
310 * metrics logs. Verify we output the correct launch state.
311 */
312 @Test
Vishnu Nair9fc15c92018-12-21 08:28:24 -0800313 public void testAppColdLaunchSetsWaitResultDelayData() {
Tadashi G. Takaokaf280a9b2019-02-01 15:28:04 +0900314 final String amStartOutput = SystemUtil.runShellCommand(
315 "am start -S -W " + TEST_ACTIVITY.flattenToShortString());
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700316
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800317 final LogMaker metricsLog = waitForMetricsLog(TEST_ACTIVITY, APP_TRANSITION);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700318 final int windowsDrawnDelayMs =
319 (int) metricsLog.getTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS);
320
321 assertEquals("Expected a cold launch.", metricsLog.getType(), TYPE_TRANSITION_COLD_LAUNCH);
322
Riddle Hsud63da272020-02-14 00:13:35 +0800323 assertLaunchComponentStateAndTime(amStartOutput, TEST_ACTIVITY, LAUNCH_STATE_COLD,
324 windowsDrawnDelayMs);
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700325 }
326
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700327 /**
328 * Launch an app that is already visible and verify we handle cases where we will not
329 * receive a windows drawn message.
330 * see b/117148004
331 */
332 @Test
333 public void testLaunchOfVisibleApp() {
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700334 // Launch an activity.
Riddle Hsu230d2312019-10-29 14:47:14 +0800335 launchAndWaitForActivity(SECOND_ACTIVITY);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700336
337 // Launch a translucent activity on top.
Riddle Hsu230d2312019-10-29 14:47:14 +0800338 launchAndWaitForActivity(TRANSLUCENT_TEST_ACTIVITY);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700339
340 // Launch the first activity again. This will not trigger a windows drawn message since
341 // its windows were visible before launching.
342 mMetricsReader.checkpoint(); // clear out old logs
Riddle Hsu230d2312019-10-29 14:47:14 +0800343 launchAndWaitForActivity(SECOND_ACTIVITY);
344
Vishnu Nair6caf4172018-10-29 21:46:56 -0700345 LogMaker metricsLog = getMetricsLog(SECOND_ACTIVITY, APP_TRANSITION);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700346 // Verify transition logs are absent since we cannot measure windows drawn delay.
347 assertNull("transition logs should be reset.", metricsLog);
348
349 // Verify metrics for subsequent launches are generated as expected.
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700350 mPreUptimeMs = SystemClock.uptimeMillis();
351 mMetricsReader.checkpoint(); // clear out old logs
352
Riddle Hsu230d2312019-10-29 14:47:14 +0800353 launchAndWaitForActivity(THIRD_ACTIVITY);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700354
355 long postUptimeMs = SystemClock.uptimeMillis();
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800356 metricsLog = waitForMetricsLog(THIRD_ACTIVITY, APP_TRANSITION);
Vishnu Nair6caf4172018-10-29 21:46:56 -0700357 assertMetricsLogs(THIRD_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs,
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700358 postUptimeMs);
Vishnu Nairce3ba632018-11-16 07:50:27 -0800359 assertTransitionIsStartingWindow(metricsLog);
360 }
361
Riddle Hsu230d2312019-10-29 14:47:14 +0800362 @Test
363 public void testAppLaunchCancelledSameTask() {
364 launchAndWaitForActivity(TEST_ACTIVITY);
365
366 // Start a non-opaque activity in a different process in the same task.
367 getLaunchActivityBuilder()
368 .setUseInstrumentation()
369 .setTargetActivity(TRANSLUCENT_TOP_ACTIVITY)
370 .setIntentExtra(extra -> extra.putBoolean(EXTRA_FINISH_IN_ON_CREATE, true))
371 .setWaitForLaunched(false)
372 .execute();
373
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800374 final LogMaker metricsLog = waitForMetricsLog(TRANSLUCENT_TOP_ACTIVITY,
375 APP_TRANSITION_CANCELLED);
Riddle Hsu230d2312019-10-29 14:47:14 +0800376
377 assertNotNull("Metrics log APP_TRANSITION_CANCELLED not found", metricsLog);
378 }
379
Vishnu Nairce3ba632018-11-16 07:50:27 -0800380 /**
381 * Launch a NoDisplay activity and verify it does not affect subsequent activity launch
382 * metrics. NoDisplay activities do not draw any windows and may be incorrectly identified as a
383 * trampoline activity. See b/80380150 (Long warm launch times reported in dev play console)
384 */
385 @Test
386 public void testNoDisplayActivityLaunch() {
Riddle Hsu230d2312019-10-29 14:47:14 +0800387 launchAndWaitForActivity(NO_DISPLAY_ACTIVITY);
Vishnu Nairce3ba632018-11-16 07:50:27 -0800388
389 mPreUptimeMs = SystemClock.uptimeMillis();
Riddle Hsu230d2312019-10-29 14:47:14 +0800390 launchAndWaitForActivity(SECOND_ACTIVITY);
391
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800392 final LogMaker metricsLog = waitForMetricsLog(SECOND_ACTIVITY, APP_TRANSITION);
Vishnu Nairce3ba632018-11-16 07:50:27 -0800393 final long postUptimeMs = SystemClock.uptimeMillis();
394 assertMetricsLogs(SECOND_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs, postUptimeMs);
395 assertTransitionIsStartingWindow(metricsLog);
396 }
397
398 /**
399 * Launch an activity with a trampoline activity and verify launch metrics measures the complete
400 * launch sequence from when the trampoline activity is launching to when the target activity
401 * draws on screen.
402 */
403 @Test
404 public void testTrampolineActivityLaunch() {
405 // Launch a trampoline activity that will launch single task activity.
Riddle Hsu230d2312019-10-29 14:47:14 +0800406 launchAndWaitForActivity(ENTRY_POINT_ALIAS_ACTIVITY);
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800407 final LogMaker metricsLog = waitForMetricsLog(SINGLE_TASK_ACTIVITY, APP_TRANSITION);
Vishnu Nairce3ba632018-11-16 07:50:27 -0800408 final long postUptimeMs = SystemClock.uptimeMillis();
409 assertMetricsLogs(SINGLE_TASK_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs,
410 postUptimeMs);
Vishnu Nair1cb588a2018-10-11 10:07:55 -0700411 }
412
Riddle Hsud63da272020-02-14 00:13:35 +0800413 /**
414 * Launch an activity which will start another activity immediately. The reported component
415 * name should be the last one with valid launch state.
416 */
417 @Test
418 public void testConsecutiveLaunch() {
419 final String amStartOutput = executeShellCommand("am start --ez " + KEY_LAUNCH_ACTIVITY
420 + " true --es " + KEY_TARGET_COMPONENT + " " + TEST_ACTIVITY.flattenToShortString()
421 + " -W " + LAUNCHING_ACTIVITY.flattenToShortString());
422 assertLaunchComponentState(amStartOutput, TEST_ACTIVITY, LAUNCH_STATE_COLD);
423 }
424
Riddle Hsu3c5a1da2019-11-27 00:24:44 +0800425 @Test
426 public void testLaunchTimeEventLogNonProcessSwitch() {
427 launchAndWaitForActivity(SINGLE_TASK_ACTIVITY);
428 mLogSeparator = separateLogs();
429
430 // Launch another activity in the same process.
431 launchAndWaitForActivity(TEST_ACTIVITY);
432 final List<Event> eventLogs = getEventLogsForComponents(mLogSeparator,
433 EVENT_WM_ACTIVITY_LAUNCH_TIME);
434 verifyLaunchTimeEventLogs(eventLogs, TEST_ACTIVITY, time -> assertNotEquals(0, time));
435 }
436
Riddle Hsu230d2312019-10-29 14:47:14 +0800437 private void launchAndWaitForActivity(ComponentName activity) {
438 getLaunchActivityBuilder()
439 .setUseInstrumentation()
440 .setTargetActivity(activity)
441 .setWaitForLaunched(true)
442 .execute();
443 }
444
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800445 @NonNull
446 private LogMaker waitForMetricsLog(ComponentName componentName, int category) {
447 final String categoryName = categoryToString(category);
448 final String message = componentName.toShortString() + " with category " + categoryName;
449 final LogMaker metricsLog = Condition.waitForResult(new Condition<LogMaker>(message)
450 .setResultSupplier(() -> getMetricsLog(componentName, category))
451 .setResultValidator(Objects::nonNull));
452 if (metricsLog != null) {
453 return metricsLog;
454 }
455
456 // Fallback to check again from raw event log. Not sure if sometimes MetricsAsserts cannot
457 // find the expected log.
458 final LogMaker template = new LogMaker(category);
459 final List<Event> eventLogs = getEventLogsForComponents(mLogSeparator,
460 android.util.EventLog.getTagCode("sysui_multi_action"));
461 for (Event event : eventLogs) {
462 final LogMaker log = new LogMaker((Object[]) event.getData());
463 if (isComponentMatched(log, componentName) && template.isSubsetOf(log)) {
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700464 return log;
465 }
466 }
Riddle Hsu6caae9c2020-03-11 18:06:24 +0800467
468 throw new AssertionError("Log should have " + categoryName + " of " + componentName);
469 }
470
471 @Nullable
472 private LogMaker getMetricsLog(ComponentName componentName, int category) {
473 final Queue<LogMaker> startLogs = MetricsAsserts.findMatchingLogs(mMetricsReader,
474 new LogMaker(category));
475 return startLogs.stream().filter(log -> isComponentMatched(log, componentName))
476 .findFirst().orElse(null);
477 }
478
479 private static boolean isComponentMatched(LogMaker log, ComponentName componentName) {
480 final String actualClassName = (String) log.getTaggedData(FIELD_CLASS_NAME);
481 final String actualPackageName = log.getPackageName();
482 return componentName.getClassName().equals(actualClassName) &&
483 componentName.getPackageName().equals(actualPackageName);
484 }
485
486 private static String categoryToString(int category) {
487 return (category == APP_TRANSITION ? "APP_TRANSITION"
488 : category == APP_TRANSITION_CANCELLED ? "APP_TRANSITION_CANCELLED"
489 : category == APP_TRANSITION_REPORTED_DRAWN ? "APP_TRANSITION_REPORTED_DRAWN"
490 : "Unknown") + "(" + category + ")";
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700491 }
492
Riddle Hsud63da272020-02-14 00:13:35 +0800493 private static void assertLaunchComponentState(String amStartOutput, ComponentName component,
494 String state) {
495 assertThat("did not find component in am start output.", amStartOutput,
496 containsString(component.flattenToShortString()));
497 assertThat("did not find launch state in am start output.", amStartOutput,
498 containsString(state));
499 }
500
501 private static void assertLaunchComponentStateAndTime(String amStartOutput,
502 ComponentName component, String state, int windowsDrawnDelayMs) {
503 assertLaunchComponentState(amStartOutput, component, state);
504 assertThat("did not find windows drawn delay time in am start output.", amStartOutput,
505 containsString(Integer.toString(windowsDrawnDelayMs)));
506 }
507
Vishnu Nair8e3f5f72018-10-01 11:12:51 -0700508 private void assertLogsContain(String[] logs, String expectedLog) {
509 for (String line : logs) {
510 if (line.contains(expectedLog)) {
511 return;
512 }
513 }
514 fail("Expected to find '" + expectedLog + "' in " + Arrays.toString(logs));
515 }
516}