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