summaryrefslogtreecommitdiff
path: root/tests/Input
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Input')
-rw-r--r--tests/Input/Android.bp12
-rw-r--r--tests/Input/AndroidManifest.xml35
-rw-r--r--tests/Input/AndroidTest.xml25
-rw-r--r--tests/Input/src/com/android/test/input/AnrTest.kt115
-rw-r--r--tests/Input/src/com/android/test/input/UnresponsiveGestureMonitorActivity.kt52
5 files changed, 239 insertions, 0 deletions
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
new file mode 100644
index 000000000000..9d35cbc3de7f
--- /dev/null
+++ b/tests/Input/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+ name: "InputTests",
+ srcs: ["src/**/*.kt"],
+ platform_apis: true,
+ certificate: "platform",
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "android-support-test",
+ "ub-uiautomator",
+ ],
+}
diff --git a/tests/Input/AndroidManifest.xml b/tests/Input/AndroidManifest.xml
new file mode 100644
index 000000000000..4195df72864c
--- /dev/null
+++ b/tests/Input/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.input">
+ <uses-permission android:name="android.permission.MONITOR_INPUT"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.INJECT_EVENTS"/>
+
+ <application android:label="InputTest">
+
+ <activity android:name=".UnresponsiveGestureMonitorActivity"
+ android:label="Unresponsive gesture monitor"
+ android:process=":externalProcess">
+ </activity>
+
+
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.test.input"
+ android:label="Input Tests"/>
+</manifest>
diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml
new file mode 100644
index 000000000000..c62db1ea5ca9
--- /dev/null
+++ b/tests/Input/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2020 Google Inc. All Rights Reserved.
+ -->
+<configuration description="Runs Input Tests">
+ <option name="test-tag" value="InputTests" />
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- keeps the screen on during tests -->
+ <option name="screen-always-on" value="on" />
+ <!-- prevents the phone from restarting -->
+ <option name="force-skip-system-props" value="true" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="InputTests.apk"/>
+
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.test.input"/>
+ <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
+ <option name="shell-timeout" value="660s" />
+ <option name="test-timeout" value="600s" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
new file mode 100644
index 000000000000..4da3eca25ea0
--- /dev/null
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.input
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.filters.MediumTest
+
+import android.graphics.Rect
+import android.os.SystemClock
+import android.provider.Settings
+import android.provider.Settings.Global.HIDE_ERROR_DIALOGS
+import android.support.test.uiautomator.By
+import android.support.test.uiautomator.UiDevice
+import android.support.test.uiautomator.UiObject2
+import android.support.test.uiautomator.Until
+import android.view.InputDevice
+import android.view.MotionEvent
+
+import org.junit.After
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * This test makes sure that an unresponsive gesture monitor gets an ANR.
+ *
+ * The gesture monitor must be registered from a different process than the instrumented process.
+ * Otherwise, when the test runs, you will get:
+ * Test failed to run to completion.
+ * Reason: 'Instrumentation run failed due to 'keyDispatchingTimedOut''.
+ * Check device logcat for details
+ * RUNNER ERROR: Instrumentation run failed due to 'keyDispatchingTimedOut'
+ */
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class AnrTest {
+ companion object {
+ private const val TAG = "AnrTest"
+ }
+
+ val mInstrumentation = InstrumentationRegistry.getInstrumentation()
+ var mHideErrorDialogs = 0
+
+ @Before
+ fun setUp() {
+ val contentResolver = mInstrumentation.targetContext.contentResolver
+ mHideErrorDialogs = Settings.Global.getInt(contentResolver, HIDE_ERROR_DIALOGS, 0)
+ Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, 0)
+ }
+
+ @After
+ fun tearDown() {
+ val contentResolver = mInstrumentation.targetContext.contentResolver
+ Settings.Global.putInt(contentResolver, HIDE_ERROR_DIALOGS, mHideErrorDialogs)
+ }
+
+ @Test
+ fun testGestureMonitorAnr() {
+ startUnresponsiveActivity()
+ val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
+ val obj: UiObject2? = uiDevice.wait(Until.findObject(
+ By.text("Unresponsive gesture monitor")), 10000)
+
+ if (obj == null) {
+ fail("Could not find unresponsive activity")
+ return
+ }
+
+ val rect: Rect = obj.visibleBounds
+ val downTime = SystemClock.uptimeMillis()
+ val downEvent = MotionEvent.obtain(downTime, downTime,
+ MotionEvent.ACTION_DOWN, rect.left.toFloat(), rect.top.toFloat(), 0 /* metaState */)
+ downEvent.source = InputDevice.SOURCE_TOUCHSCREEN
+
+ mInstrumentation.uiAutomation.injectInputEvent(downEvent, false /* sync*/)
+
+ // Todo: replace using timeout from android.hardware.input.IInputManager
+ SystemClock.sleep(5000) // default ANR timeout for gesture monitors
+
+ clickCloseAppOnAnrDialog()
+ }
+
+ private fun clickCloseAppOnAnrDialog() {
+ // Find anr dialog and kill app
+ val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
+ val closeAppButton: UiObject2? =
+ uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000)
+ if (closeAppButton == null) {
+ fail("Could not find anr dialog")
+ return
+ }
+ closeAppButton.click()
+ }
+
+ private fun startUnresponsiveActivity() {
+ val flags = " -W -n "
+ val startCmd = "am start $flags com.android.test.input/.UnresponsiveGestureMonitorActivity"
+ mInstrumentation.uiAutomation.executeShellCommand(startCmd)
+ }
+} \ No newline at end of file
diff --git a/tests/Input/src/com/android/test/input/UnresponsiveGestureMonitorActivity.kt b/tests/Input/src/com/android/test/input/UnresponsiveGestureMonitorActivity.kt
new file mode 100644
index 000000000000..d83a4570fedc
--- /dev/null
+++ b/tests/Input/src/com/android/test/input/UnresponsiveGestureMonitorActivity.kt
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.input
+
+import android.app.Activity
+import android.hardware.input.InputManager
+import android.os.Bundle
+import android.os.Looper
+import android.util.Log
+import android.view.InputChannel
+import android.view.InputEvent
+import android.view.InputEventReceiver
+import android.view.InputMonitor
+
+class UnresponsiveReceiver(channel: InputChannel, looper: Looper) :
+ InputEventReceiver(channel, looper) {
+ companion object {
+ const val TAG = "UnresponsiveReceiver"
+ }
+ override fun onInputEvent(event: InputEvent) {
+ Log.i(TAG, "Received $event")
+ // Not calling 'finishInputEvent' in order to trigger the ANR
+ }
+}
+
+class UnresponsiveGestureMonitorActivity : Activity() {
+ companion object {
+ const val MONITOR_NAME = "unresponsive gesture monitor"
+ }
+ private lateinit var mInputEventReceiver: InputEventReceiver
+ private lateinit var mInputMonitor: InputMonitor
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mInputMonitor = InputManager.getInstance().monitorGestureInput(MONITOR_NAME, displayId)
+ mInputEventReceiver = UnresponsiveReceiver(
+ mInputMonitor.getInputChannel(), Looper.myLooper())
+ }
+}