• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.server.wm.ShellCommandHelper.executeShellCommand;
20 import static android.server.wm.app.Components.HOST_ACTIVITY;
21 import static android.server.wm.app.Components.UNRESPONSIVE_ACTIVITY;
22 import static android.server.wm.app.Components.UnresponsiveActivity;
23 import static android.server.wm.app.Components.UnresponsiveActivity.EXTRA_DELAY_UI_THREAD_MS;
24 import static android.server.wm.app.Components.UnresponsiveActivity.EXTRA_ON_CREATE_DELAY_MS;
25 import static android.server.wm.app.Components.UnresponsiveActivity.EXTRA_ON_KEYDOWN_DELAY_MS;
26 import static android.server.wm.app.Components.UnresponsiveActivity.EXTRA_ON_MOTIONEVENT_DELAY_MS;
27 
28 import static org.junit.Assert.fail;
29 import static org.junit.Assume.assumeTrue;
30 
31 import android.content.ComponentName;
32 import android.os.SystemClock;
33 import android.platform.test.annotations.Presubmit;
34 import android.provider.Settings;
35 import android.server.wm.app.Components.RenderService;
36 import android.server.wm.settings.SettingsSession;
37 import android.util.EventLog;
38 import android.util.Log;
39 import android.view.KeyEvent;
40 
41 import androidx.test.core.app.ActivityScenario;
42 import androidx.test.filters.FlakyTest;
43 import androidx.test.platform.app.InstrumentationRegistry;
44 import androidx.test.uiautomator.By;
45 import androidx.test.uiautomator.UiDevice;
46 import androidx.test.uiautomator.UiObject2;
47 import androidx.test.uiautomator.Until;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Test;
52 
53 import java.util.List;
54 import java.util.concurrent.CountDownLatch;
55 
56 /**
57  * Test scenarios that lead to ANR dialog being shown.
58  *
59  * <p>Build/Install/Run:
60  *     atest CtsWindowManagerDeviceTestCases:AnrTests
61  */
62 @Presubmit
63 @FlakyTest(bugId = 280027157)
64 @android.server.wm.annotation.Group3
65 public class AnrTests extends ActivityManagerTestBase {
66     private static final String TAG = "AnrTests";
67     private LogSeparator mLogSeparator;
68     private SettingsSession<Integer> mHideDialogSetting;
69 
70     @Before
setup()71     public void setup() throws Exception {
72         super.setUp();
73         assumeTrue(mAtm.currentUiModeSupportsErrorDialogs(mContext));
74 
75         mLogSeparator = separateLogs(); // add a new separator for logs
76         mHideDialogSetting = new SettingsSession<>(
77                 Settings.Global.getUriFor(Settings.Global.HIDE_ERROR_DIALOGS),
78                 Settings.Global::getInt, Settings.Global::putInt);
79         mHideDialogSetting.set(0);
80     }
81 
82     @After
teardown()83     public void teardown() {
84         if (mHideDialogSetting != null) mHideDialogSetting.close();
85         stopTestPackage(UNRESPONSIVE_ACTIVITY.getPackageName());
86         stopTestPackage(HOST_ACTIVITY.getPackageName());
87     }
88 
89     @Test
slowOnCreateWithKeyEventTriggersAnr()90     public void slowOnCreateWithKeyEventTriggersAnr() {
91         startUnresponsiveActivity(EXTRA_ON_CREATE_DELAY_MS, false /* waitForCompletion */,
92                 UNRESPONSIVE_ACTIVITY);
93         // wait for app to be focused
94         mWmState.waitAndAssertAppFocus(UNRESPONSIVE_ACTIVITY.getPackageName(),
95                 2000 /* waitTime_ms */);
96         // wait for input manager to get the new focus app. This sleep can be removed once we start
97         // listing to input about the focused app.
98         SystemClock.sleep(500);
99         injectKey(KeyEvent.KEYCODE_BACK, false /* longpress */, false /* sync */);
100         clickCloseAppOnAnrDialog();
101         assertEventLogsContainsAnr(UnresponsiveActivity.PROCESS_NAME);
102     }
103 
104     @Test
slowUiThreadWithKeyEventTriggersAnr()105     public void slowUiThreadWithKeyEventTriggersAnr() {
106         startUnresponsiveActivity(EXTRA_DELAY_UI_THREAD_MS, true /* waitForCompletion */,
107                 UNRESPONSIVE_ACTIVITY);
108         injectKey(KeyEvent.KEYCODE_BACK, false /* longpress */, false /* sync */);
109         clickCloseAppOnAnrDialog();
110         assertEventLogsContainsAnr(UnresponsiveActivity.PROCESS_NAME);
111     }
112 
113     @Test
slowOnKeyEventHandleTriggersAnr()114     public void slowOnKeyEventHandleTriggersAnr() {
115         startUnresponsiveActivity(EXTRA_ON_KEYDOWN_DELAY_MS, true /* waitForCompletion */,
116                 UNRESPONSIVE_ACTIVITY);
117         injectKey(KeyEvent.KEYCODE_BACK, false /* longpress */, false /* sync */);
118         clickCloseAppOnAnrDialog();
119         assertEventLogsContainsAnr(UnresponsiveActivity.PROCESS_NAME);
120     }
121 
122     @Test
slowOnTouchEventHandleTriggersAnr()123     public void slowOnTouchEventHandleTriggersAnr() {
124         startUnresponsiveActivity(EXTRA_ON_MOTIONEVENT_DELAY_MS, true /* waitForCompletion */,
125                 UNRESPONSIVE_ACTIVITY);
126 
127         mWmState.computeState();
128         // Tap on the UnresponsiveActivity
129         final WindowManagerState.Task unresponsiveActivityTask =
130                 mWmState.getTaskByActivity(UNRESPONSIVE_ACTIVITY);
131         mTouchHelper.tapOnTaskCenterAsync(unresponsiveActivityTask);
132         clickCloseAppOnAnrDialog();
133         assertEventLogsContainsAnr(UnresponsiveActivity.PROCESS_NAME);
134     }
135 
136     /**
137      * Verify embedded windows can trigger ANR and the verify embedded app is blamed.
138      */
139     @Test
embeddedWindowTriggersAnr()140     public void embeddedWindowTriggersAnr() {
141         try (ActivityScenario<HostActivity> scenario =
142                      ActivityScenario.launch(HostActivity.class)) {
143             CountDownLatch[] latch = new CountDownLatch[1];
144             scenario.onActivity(activity -> latch[0] = activity.mEmbeddedViewAttachedLatch);
145             latch[0].await();
146             mWmState.computeState();
147             final WindowManagerState.Task hostActivityTask =
148                     mWmState.getTaskByActivity(new ComponentName("android.server.wm.cts",
149                             "android.server.wm.HostActivity"));
150             mTouchHelper.tapOnTaskCenterAsync(hostActivityTask);
151             clickCloseAppOnAnrDialog();
152         } catch (InterruptedException ignored) {
153         }
154         assertEventLogsContainsAnr(RenderService.PROCESS_NAME);
155     }
156 
assertEventLogsContainsAnr(String processName)157     private void assertEventLogsContainsAnr(String processName) {
158         final List<EventLog.Event> events = getEventLogsForComponents(mLogSeparator,
159                 android.util.EventLog.getTagCode("am_anr"));
160         for (EventLog.Event event : events) {
161             Object[] arr = (Object[]) event.getData();
162             final String name = (String) arr[2];
163             if (name.equals(processName)) {
164                 return;
165             }
166         }
167         fail("Could not find anr kill event for " + processName);
168     }
169 
clickCloseAppOnAnrDialog()170     private void clickCloseAppOnAnrDialog() {
171         // Find anr dialog and kill app
172         UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
173         UiObject2 closeAppButton = uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")),
174                 20000);
175         if (closeAppButton != null) {
176             Log.d(TAG, "found permission dialog after searching all windows, clicked");
177             closeAppButton.click();
178             return;
179         }
180         fail("Could not find anr dialog");
181     }
182 
startUnresponsiveActivity(String delayTypeExtra, boolean waitForCompletion, ComponentName activity)183     private void startUnresponsiveActivity(String delayTypeExtra, boolean waitForCompletion,
184             ComponentName activity) {
185         String flags = waitForCompletion ? " -W -n " : " -n ";
186         String startCmd = "am start" + flags + activity.flattenToString() +
187                 " --ei " + delayTypeExtra + " 30000";
188         executeShellCommand(startCmd);
189     }
190 }
191