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