1 /* 2 * Copyright (C) 2020 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 package com.android.test.input 17 18 import androidx.test.ext.junit.runners.AndroidJUnit4 19 import androidx.test.platform.app.InstrumentationRegistry 20 import androidx.test.filters.MediumTest 21 22 import android.graphics.Rect 23 import android.os.SystemClock 24 import android.provider.Settings 25 import android.provider.Settings.Global.HIDE_ERROR_DIALOGS 26 import android.support.test.uiautomator.By 27 import android.support.test.uiautomator.UiDevice 28 import android.support.test.uiautomator.UiObject2 29 import android.support.test.uiautomator.Until 30 import android.view.InputDevice 31 import android.view.MotionEvent 32 33 import org.junit.After 34 import org.junit.Assert.fail 35 import org.junit.Before 36 import org.junit.Test 37 import org.junit.runner.RunWith 38 39 /** 40 * This test makes sure that an unresponsive gesture monitor gets an ANR. 41 * 42 * The gesture monitor must be registered from a different process than the instrumented process. 43 * Otherwise, when the test runs, you will get: 44 * Test failed to run to completion. 45 * Reason: 'Instrumentation run failed due to 'keyDispatchingTimedOut''. 46 * Check device logcat for details 47 * RUNNER ERROR: Instrumentation run failed due to 'keyDispatchingTimedOut' 48 */ 49 @MediumTest 50 @RunWith(AndroidJUnit4::class) 51 class AnrTest { 52 companion object { 53 private const val TAG = "AnrTest" 54 } 55 56 val mInstrumentation = InstrumentationRegistry.getInstrumentation() 57 var mHideErrorDialogs = 0 58 59 @Before setUpnull60 fun setUp() { 61 val contentResolver = mInstrumentation.targetContext.contentResolver 62 mHideErrorDialogs = Settings.Global.getInt(contentResolver, HIDE_ERROR_DIALOGS, 0) 63 Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, 0) 64 } 65 66 @After tearDownnull67 fun tearDown() { 68 val contentResolver = mInstrumentation.targetContext.contentResolver 69 Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, mHideErrorDialogs) 70 } 71 72 @Test testGestureMonitorAnrnull73 fun testGestureMonitorAnr() { 74 startUnresponsiveActivity() 75 val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation) 76 val obj: UiObject2? = uiDevice.wait(Until.findObject( 77 By.text("Unresponsive gesture monitor")), 10000) 78 79 if (obj == null) { 80 fail("Could not find unresponsive activity") 81 return 82 } 83 84 val rect: Rect = obj.visibleBounds 85 val downTime = SystemClock.uptimeMillis() 86 val downEvent = MotionEvent.obtain(downTime, downTime, 87 MotionEvent.ACTION_DOWN, rect.left.toFloat(), rect.top.toFloat(), 0 /* metaState */) 88 downEvent.source = InputDevice.SOURCE_TOUCHSCREEN 89 90 mInstrumentation.uiAutomation.injectInputEvent(downEvent, false /* sync*/) 91 92 // Todo: replace using timeout from android.hardware.input.IInputManager 93 SystemClock.sleep(5000) // default ANR timeout for gesture monitors 94 95 clickCloseAppOnAnrDialog() 96 } 97 clickCloseAppOnAnrDialognull98 private fun clickCloseAppOnAnrDialog() { 99 // Find anr dialog and kill app 100 val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation) 101 val closeAppButton: UiObject2? = 102 uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000) 103 if (closeAppButton == null) { 104 fail("Could not find anr dialog") 105 return 106 } 107 closeAppButton.click() 108 } 109 startUnresponsiveActivitynull110 private fun startUnresponsiveActivity() { 111 val flags = " -W -n " 112 val startCmd = "am start $flags com.android.test.input/.UnresponsiveGestureMonitorActivity" 113 mInstrumentation.uiAutomation.executeShellCommand(startCmd) 114 } 115 }