Home | History | Annotate | Download | only in wm
      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
     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
     73     public void testDashW_Direct() throws Exception {
     74         testDashW(SINGLE_TASK_ACTIVITY, SINGLE_TASK_ACTIVITY);
     75     }
     76 
     77     @Test
     78     @FlakyTest
     79     public void testDashW_Indirect() throws Exception {
     80         testDashW(ENTRY_POINT_ALIAS_ACTIVITY, SINGLE_TASK_ACTIVITY);
     81     }
     82 
     83     @Test
     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 
    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 
    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 
    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