• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 
17 package android.server.wm;
18 
19 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
20 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
22 import static android.server.wm.ComponentNameUtils.getActivityName;
23 import static android.server.wm.UiDeviceUtils.pressHomeButton;
24 import static android.server.wm.app.Components.ENTRY_POINT_ALIAS_ACTIVITY;
25 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
26 import static android.server.wm.app.Components.SINGLE_TASK_ACTIVITY;
27 import static android.server.wm.app.Components.TEST_ACTIVITY;
28 import static android.view.Display.DEFAULT_DISPLAY;
29 
30 import static org.hamcrest.MatcherAssert.assertThat;
31 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertNotEquals;
34 import static org.junit.Assert.fail;
35 
36 import android.content.ComponentName;
37 import android.platform.test.annotations.Presubmit;
38 
39 import androidx.test.filters.FlakyTest;
40 
41 import org.junit.Test;
42 
43 import java.util.regex.Matcher;
44 import java.util.regex.Pattern;
45 
46 /**
47  * Build/Install/Run:
48  *     atest CtsWindowManagerDeviceTestCases:AmStartOptionsTests
49  */
50 @Presubmit
51 public class AmStartOptionsTests extends ActivityManagerTestBase {
52 
53     @Test
testDashD()54     public void testDashD() {
55         // Run at least 2 rounds to verify that -D works with an existing process.
56         // -D could fail in this case if the force stop of process is broken.
57         int prevProcId = -1;
58         for (int i = 0; i < 2; i++) {
59             executeShellCommand("am start -n " + getActivityName(TEST_ACTIVITY) + " -D");
60 
61             mAmWmState.waitForDebuggerWindowVisible(TEST_ACTIVITY);
62             int procId = mAmWmState.getAmState().getActivityProcId(TEST_ACTIVITY);
63 
64             assertThat("Invalid ProcId.", procId, greaterThanOrEqualTo(0));
65             if (i > 0) {
66                 assertNotEquals("Run " + i + " didn't start new proc.", prevProcId, procId);
67             }
68             prevProcId = procId;
69         }
70     }
71 
72     @Test
testDashW_Direct()73     public void testDashW_Direct() throws Exception {
74         testDashW(SINGLE_TASK_ACTIVITY, SINGLE_TASK_ACTIVITY);
75     }
76 
77     @Test
78     @FlakyTest
testDashW_Indirect()79     public void testDashW_Indirect() throws Exception {
80         testDashW(ENTRY_POINT_ALIAS_ACTIVITY, SINGLE_TASK_ACTIVITY);
81     }
82 
83     @Test
testDashW_FinishingTop()84     public void testDashW_FinishingTop() {
85         // Start LaunchingActivity and TestActivity
86         getLaunchActivityBuilder().setLaunchingActivity(LAUNCHING_ACTIVITY)
87                 .setTargetActivity(TEST_ACTIVITY).execute();
88 
89         // Return to home
90         pressHomeButton();
91 
92         // Start LaunchingActivity again and finish TestActivity
93         final int flags =
94                 FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP;
95         final String result = executeShellCommand(
96                 "am start -W -f " + flags + " -n " + getActivityName(LAUNCHING_ACTIVITY));
97         verifyShellOutput(result, LAUNCHING_ACTIVITY, false);
98     }
99 
testDashW(final ComponentName entryActivity, final ComponentName actualActivity)100     private void testDashW(final ComponentName entryActivity, final ComponentName actualActivity)
101             throws Exception {
102         // Test cold start
103         startActivityAndVerifyResult(entryActivity, actualActivity, true);
104 
105         // Test warm start
106         pressHomeButton();
107         startActivityAndVerifyResult(entryActivity, actualActivity, false);
108 
109         // Test "hot" start (app already in front)
110         startActivityAndVerifyResult(entryActivity, actualActivity, false);
111     }
112 
startActivityAndVerifyResult(final ComponentName entryActivity, final ComponentName actualActivity, boolean shouldStart)113     private void startActivityAndVerifyResult(final ComponentName entryActivity,
114             final ComponentName actualActivity, boolean shouldStart) {
115         // See TODO below
116         // final LogSeparator logSeparator = separateLogs();
117 
118         // Pass in different data only when cold starting. This is to make the intent
119         // different in subsequent warm/hot launches, so that the entrypoint alias
120         // activity is always started, but the actual activity is not started again
121         // because of the NEW_TASK and singleTask flags.
122         final String result = executeShellCommand(
123                 "am start -n " + getActivityName(entryActivity) + " -W"
124                 + (shouldStart ? " -d about:blank" : ""));
125 
126         // Verify shell command return value
127         verifyShellOutput(result, actualActivity, shouldStart);
128 
129         // TODO: Disable logcat check for now.
130         // Logcat of WM or AM tag could be lost (eg. chatty if earlier events generated
131         // too many lines), and make the test look flaky. We need to either use event
132         // log or swith to other mechanisms. Only verify shell output for now, it should
133         // still catch most failures.
134 
135         // Verify adb logcat log
136         //verifyLogcat(actualActivity, shouldStart, logSeparator);
137     }
138 
139     private static final Pattern sNotStartedWarningPattern = Pattern.compile(
140             "Warning: Activity not started(.*)");
141     private static final Pattern sStatusPattern = Pattern.compile(
142             "Status: (.*)");
143     private static final Pattern sActivityPattern = Pattern.compile(
144             "Activity: (.*)");
145     private static final String sStatusOk = "ok";
146 
verifyShellOutput( final String result, final ComponentName activity, boolean shouldStart)147     private void verifyShellOutput(
148             final String result, final ComponentName activity, boolean shouldStart) {
149         boolean warningFound = false;
150         String status = null;
151         String reportedActivity = null;
152 
153         final String[] lines = result.split("\\n");
154         // Going from the end of logs to beginning in case if some other activity is started first.
155         for (int i = lines.length - 1; i >= 0; i--) {
156             final String line = lines[i].trim();
157             Matcher matcher = sNotStartedWarningPattern.matcher(line);
158             if (matcher.matches()) {
159                 warningFound = true;
160                 continue;
161             }
162             matcher = sStatusPattern.matcher(line);
163             if (matcher.matches()) {
164                 status = matcher.group(1);
165                 continue;
166             }
167             matcher = sActivityPattern.matcher(line);
168             if (matcher.matches()) {
169                 reportedActivity = matcher.group(1);
170                 continue;
171             }
172         }
173 
174         assertEquals("Status is ok", sStatusOk, status);
175         assertEquals("Reported activity is " +  getActivityName(activity),
176                 getActivityName(activity), reportedActivity);
177 
178         if (shouldStart && warningFound) {
179             fail("Should start new activity but brought something to front.");
180         } else if (!shouldStart && !warningFound){
181             fail("Should bring existing activity to front but started new activity.");
182         }
183     }
184 }
185