Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6102c38 authored by Morgan Law's avatar Morgan Law Committed by Android (Google) Code Review
Browse files

Merge "Add integration test for KeyEventActivityListener" into main

parents 5faf9e92 f184eeb6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -8736,7 +8736,8 @@
    <!-- Allows applications to register listeners for key activeness through
         InputManagerService.
         <p>Protection level: signature
         @hide -->
         @hide
         @FlaggedApi("com.android.hardware.input.key_event_activity_detection") -->
    <permission android:name="android.permission.LISTEN_FOR_KEY_ACTIVITY"
                android:protectionLevel="signature"
                android:featureFlag="com.android.hardware.input.key_event_activity_detection" />
+2 −0
Original line number Diff line number Diff line
@@ -632,6 +632,8 @@ applications that come with the platform
        <permission name="android.permission.ACCESS_TEXT_CLASSIFIER_BY_TYPE"/>
        <!-- Permission required for CTS test - CtsSecurityTestCases -->
        <permission name="android.permission.MANAGE_DEVICE_POLICY_MTE"/>
        <!-- Permission required for integration test - InputTest -->
        <permission name="android.permission.LISTEN_FOR_KEY_ACTIVITY"/>
    </privapp-permissions>

    <privapp-permissions package="com.android.soundpicker">
+3 −0
Original line number Diff line number Diff line
@@ -1031,6 +1031,9 @@
    <!-- Permission required to test mouse movement on display -->
    <uses-permission android:name="android.permission.SET_POINTER_SPEED" />

    <!-- Permissions required for integration test - InputTest -->
    <uses-permission android:name="android.permission.LISTEN_FOR_KEY_ACTIVITY" />

    <application
        android:label="@string/app_label"
        android:theme="@android:style/Theme.DeviceDefault.DayNight"
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.LISTEN_FOR_KEY_ACTIVITY"/>

    <application android:label="InputTest" android:debuggable="true">

+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.Manifest
import android.hardware.input.InputManager
import android.platform.test.annotations.RequiresFlagsEnabled
import android.view.KeyEvent
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.AdoptShellPermissionsRule
import com.android.compatibility.common.util.PollingCheck
import com.android.cts.input.CaptureEventActivity
import com.android.cts.input.UinputKeyboard
import com.android.hardware.input.Flags.FLAG_KEY_EVENT_ACTIVITY_DETECTION
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when`

@RequiresFlagsEnabled(FLAG_KEY_EVENT_ACTIVITY_DETECTION)
class KeyEventActivityListenerTest {
    private lateinit var inputManager: InputManager
    private lateinit var listener: InputManager.KeyEventActivityListener
    private val instrumentation = InstrumentationRegistry.getInstrumentation()
    @get:Rule
    val rule = ActivityScenarioRule<CaptureEventActivity>(CaptureEventActivity::class.java)

    @get:Rule
    val adoptShellPermissionsRule =
        AdoptShellPermissionsRule(
            instrumentation.getUiAutomation(),
            Manifest.permission.LISTEN_FOR_KEY_ACTIVITY,
        )

    companion object {
        const val KEY_A = 30
    }

    @Before
    fun setUp() {
        lateinit var activity: CaptureEventActivity
        rule.getScenario().onActivity {
            inputManager = it.getSystemService(InputManager::class.java)
            activity = it
        }
        PollingCheck.waitFor { activity.hasWindowFocus() }
        listener = mock(InputManager.KeyEventActivityListener::class.java)
    }

    @After
    fun tearDown() {
        inputManager.unregisterKeyEventActivityListener(listener)
    }

    @Test
    fun testKeyActivityListener() {
        UinputKeyboard(instrumentation).use { keyboardDevice ->
            val isRegistered = inputManager.registerKeyEventActivityListener(listener)
            assertTrue(isRegistered)
            val latch = CountDownLatch(1)
            doAnswer {
                    latch.countDown()
                    null
                }
                .`when`(listener)
                .onKeyEventActivity()
            keyboardDevice.injectKeyDown(KEY_A)
            keyboardDevice.injectKeyUp(KEY_A)
            assertTrue(latch.await(10, TimeUnit.SECONDS))
            verify(listener, times(1)).onKeyEventActivity()
            val isUnregistered = inputManager.unregisterKeyEventActivityListener(listener)
            assertTrue(isUnregistered)
            keyboardDevice.injectKeyDown(KEY_A)
            keyboardDevice.injectKeyUp(KEY_A)
            verifyNoMoreInteractions(listener)
        }
    }
}