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