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

Commit e6c6bda6 authored by Vaibhav Devmurari's avatar Vaibhav Devmurari
Browse files

Test improvement: Cleanup usages for InputManagerGlobal.TestSession

Bug: 245989146
Test: atest InputTests
Flag: TEST_ONLY
Change-Id: Ic17bc9c00606b29b54af9a5d4e97c8c6f99dc2c7
parent 5529b651
Loading
Loading
Loading
Loading
+32 −43
Original line number Diff line number Diff line
@@ -18,13 +18,12 @@ package com.android.server.input

import android.Manifest
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.PackageManagerInternal
import android.hardware.display.DisplayManager
import android.hardware.display.DisplayViewport
import android.hardware.display.VirtualDisplay
import android.hardware.input.IKeyEventActivityListener
import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.input.InputSettings
import android.hardware.input.KeyGestureEvent
import android.os.InputEventInjectionSync
@@ -36,21 +35,20 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.Presubmit
import android.platform.test.flag.junit.SetFlagsRule
import android.provider.Settings
import android.test.mock.MockContentResolver
import android.testing.TestableContext
import android.view.InputDevice
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View.OnKeyListener
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.internal.util.test.FakeSettingsProvider
import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.server.LocalServices
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -62,14 +60,11 @@ import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoInteractions
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when`
import org.mockito.stubbing.OngoingStubbing

@@ -105,6 +100,10 @@ class InputManagerServiceTests {
            .mockStatic(InputSettings::class.java)
            .build()!!

    @JvmField
    @Rule
    val testableContext = TestableContext(ApplicationProvider.getApplicationContext())

    @get:Rule val setFlagsRule = SetFlagsRule()

    @get:Rule val fakeSettingsProviderRule = FakeSettingsProvider.rule()!!
@@ -121,35 +120,26 @@ class InputManagerServiceTests {
    private lateinit var kbdController: InputManagerService.KeyboardBacklightControllerInterface

    @Mock private lateinit var kcm: KeyCharacterMap
    @Mock private lateinit var inputManager: InputManager

    private lateinit var service: InputManagerService
    private lateinit var localService: InputManagerInternal
    private lateinit var context: Context
    private lateinit var testLooper: TestLooper
    private lateinit var contentResolver: MockContentResolver
    private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
    private lateinit var fakePermissionEnforcer: FakePermissionEnforcer

    @Before
    fun setup() {
        context = spy(ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext()))
        fakePermissionEnforcer = FakePermissionEnforcer()
        doReturn(Context.PERMISSION_ENFORCER_SERVICE)
            .`when`(context)
            .getSystemServiceName(eq(PermissionEnforcer::class.java))
        doReturn(fakePermissionEnforcer)
            .`when`(context)
            .getSystemService(eq(Context.PERMISSION_ENFORCER_SERVICE))

        contentResolver = MockContentResolver(context)
        contentResolver.addProvider(Settings.AUTHORITY, FakeSettingsProvider())
        whenever(context.contentResolver).thenReturn(contentResolver)
        testableContext.addMockSystemService(PermissionEnforcer::class.java, fakePermissionEnforcer)

        testableContext.contentResolver.addProvider(Settings.AUTHORITY, FakeSettingsProvider())
        testLooper = TestLooper()
        whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
        service =
            InputManagerService(
                object :
                    InputManagerService.Injector(
                        context,
                        testableContext,
                        testLooper.looper,
                        testLooper.looper,
                        uEventManager,
@@ -172,10 +162,8 @@ class InputManagerServiceTests {
                },
                fakePermissionEnforcer,
            )
        inputManagerGlobalSession = InputManagerGlobal.createTestSession(service)
        val inputManager = InputManager(context)
        whenever(context.getSystemService(InputManager::class.java)).thenReturn(inputManager)
        whenever(context.getSystemService(Context.INPUT_SERVICE)).thenReturn(inputManager)
        testableContext.addMockSystemService(InputManager::class.java, inputManager)
        testableContext.addMockSystemService(Context.INPUT_SERVICE, inputManager)
        fakePermissionEnforcer.grant(Manifest.permission.MANAGE_KEY_GESTURES)

        ExtendedMockito.doReturn(packageManagerInternal).`when` {
@@ -187,13 +175,6 @@ class InputManagerServiceTests {
        service.setWindowManagerCallbacks(wmCallbacks)
    }

    @After
    fun tearDown() {
        if (this::inputManagerGlobalSession.isInitialized) {
            inputManagerGlobalSession.close()
        }
    }

    @Test
    fun testStart() {
        verifyNoInteractions(native)
@@ -276,30 +257,31 @@ class InputManagerServiceTests {
    @EnableFlags(com.android.hardware.input.Flags.FLAG_KEY_EVENT_ACTIVITY_DETECTION)
    fun testKeyActivenessNotifyEventsLifecycle() {
        service.systemRunning()

        fakePermissionEnforcer.grant(android.Manifest.permission.LISTEN_FOR_KEY_ACTIVITY)

        val inputManager = context.getSystemService(InputManager::class.java)

        /* register for key event activeness */
        var listener = mock(InputManager.KeyEventActivityListener::class.java)
        assertEquals(true, inputManager.registerKeyEventActivityListener(listener))
        var callback = 0
        val listener = KeyEventListener {
            callback++
            true
        }
        assertEquals(true, service.registerKeyEventActivityListener(listener))

        /* mimic key event pressed */
        val event = createKeycodeAEvent(createInputDevice(), KeyEvent.ACTION_DOWN)
        service.interceptKeyBeforeQueueing(event, 0)

        /* verify onKeyEventActivity callback called */
        verify(listener, times(1)).onKeyEventActivity()
        assertEquals(1, callback)

        /* unregister for key event activeness */
        assertEquals(true, inputManager.unregisterKeyEventActivityListener(listener))
        assertEquals(true, service.unregisterKeyEventActivityListener(listener))

        /* mimic key event pressed */
        service.interceptKeyBeforeQueueing(event, /* policyFlags */ 0)

        /* verify onKeyEventActivity callback not called */
        verifyNoMoreInteractions(listener)
        assertEquals(1, callback)
    }

    private class AutoClosingVirtualDisplays(val displays: List<VirtualDisplay>) : AutoCloseable {
@@ -314,7 +296,7 @@ class InputManagerServiceTests {

    private fun createVirtualDisplays(count: Int): AutoClosingVirtualDisplays {
        val displayManager: DisplayManager =
            context.getSystemService(DisplayManager::class.java) as DisplayManager
            testableContext.getSystemService(DisplayManager::class.java) as DisplayManager
        val virtualDisplays = mutableListOf<VirtualDisplay>()
        for (i in 0 until count) {
            virtualDisplays.add(
@@ -570,6 +552,13 @@ class InputManagerServiceTests {

        verify(native).toggleCapsLock(anyInt())
    }

    inner class KeyEventListener(private var listener: () -> Boolean) :
        IKeyEventActivityListener.Stub() {
        override fun onKeyEventActivity() {
            listener.invoke()
        }
    }
}

private fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
+50 −57
Original line number Diff line number Diff line
@@ -18,19 +18,15 @@ package com.android.server.input

import android.Manifest
import android.content.Context
import android.content.ContextWrapper
import android.content.PermissionChecker
import android.content.pm.PackageManager
import android.content.res.Resources
import android.content.res.XmlResourceParser
import android.hardware.input.AidlKeyGestureEvent
import android.hardware.input.AppLaunchData
import android.hardware.input.IInputManager
import android.hardware.input.IKeyGestureEventListener
import android.hardware.input.IKeyGestureHandler
import android.hardware.input.InputGestureData
import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.input.KeyGestureEvent
import android.os.Handler
import android.os.IBinder
@@ -42,6 +38,8 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.Presubmit
import android.platform.test.flag.junit.SetFlagsRule
import android.provider.DeviceConfig
import android.testing.TestableContext
import android.testing.TestableResources
import android.util.AtomicFile
import android.view.Display.DEFAULT_DISPLAY
import android.view.InputDevice
@@ -69,7 +67,6 @@ import java.io.FileOutputStream
import java.io.InputStream
import junitparams.JUnitParamsRunner
import junitparams.Parameters
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
@@ -166,7 +163,11 @@ class KeyGestureControllerTests {

    @JvmField @Rule val rule = SetFlagsRule()

    @Mock private lateinit var iInputManager: IInputManager
    @JvmField
    @Rule
    val testableContext = TestableContext(ApplicationProvider.getApplicationContext())

    @Mock private lateinit var inputManager: InputManager
    @Mock private lateinit var packageManager: PackageManager
    @Mock private lateinit var wmCallbacks: WindowManagerCallbacks
    @Mock private lateinit var accessibilityShortcutController: AccessibilityShortcutController
@@ -174,18 +175,15 @@ class KeyGestureControllerTests {
    @Mock private lateinit var windowManagerInternal: WindowManagerInternal

    private var currentPid = 0
    private lateinit var context: Context
    private lateinit var resources: Resources
    private lateinit var testableResources: TestableResources
    private lateinit var keyGestureController: KeyGestureController
    private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
    private lateinit var testLooper: TestLooper
    private lateinit var tempFile: File
    private lateinit var inputDataStore: InputDataStore

    @Before
    fun setup() {
        context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
        resources = Mockito.spy(context.resources)
        testableResources = testableContext.orCreateTestableResources
        setupInputDevices()
        setupBehaviors()
        testLooper = TestLooper()
@@ -224,19 +222,11 @@ class KeyGestureControllerTests {
                    }
                }
            )
        startNewInputGlobalTestSession()
    }

    @After
    fun teardown() {
        if (this::inputManagerGlobalSession.isInitialized) {
            inputManagerGlobalSession.close()
        }
    }

    private fun setupBehaviors() {
        Mockito.`when`(SystemProperties.get("ro.debuggable")).thenReturn("1")
        Mockito.`when`(resources.getBoolean(R.bool.config_enableScreenshotChord)).thenReturn(true)
        testableResources.addOverride(R.bool.config_enableScreenshotChord, true)
        ExtendedMockito.`when`(
                DeviceConfig.getLong(
                    eq(DeviceConfig.NAMESPACE_SYSTEMUI),
@@ -245,50 +235,44 @@ class KeyGestureControllerTests {
                )
            )
            .thenReturn(SCREENSHOT_CHORD_DELAY)
        Mockito.`when`(context.resources).thenReturn(resources)
        Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH))
            .thenReturn(true)
        Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
            .thenReturn(true)
        Mockito.`when`(context.packageManager).thenReturn(packageManager)
        Mockito.`when`(resources.getInteger(R.integer.config_searchKeyBehavior))
            .thenReturn(SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY)
        Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
            .thenReturn(SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY)
        testableContext.setMockPackageManager(packageManager)
        testableResources.addOverride(
            R.integer.config_searchKeyBehavior,
            SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY,
        )
        testableResources.addOverride(
            R.integer.config_settingsKeyBehavior,
            SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY,
        )
    }

    private fun setupBookmarks(bookmarkRes: Int) {
        val testBookmarks: XmlResourceParser = context.resources.getXml(bookmarkRes)
        Mockito.`when`(resources.getXml(R.xml.bookmarks)).thenReturn(testBookmarks)
        val testBookmarks: XmlResourceParser = testableContext.resources.getXml(bookmarkRes)
        testableResources.addOverride(R.xml.bookmarks, testBookmarks)
    }

    private fun setupInputDevices() {
        val correctIm = context.getSystemService(InputManager::class.java)!!
        val correctIm = testableContext.getSystemService(InputManager::class.java)!!
        val virtualDevice = correctIm.getInputDevice(KeyCharacterMap.VIRTUAL_KEYBOARD)!!
        val kcm = virtualDevice.keyCharacterMap!!
        val keyboardDevice = InputDevice.Builder().setId(DEVICE_ID).build()
        Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
        Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardDevice)
        testableContext.addMockSystemService(Context.INPUT_SERVICE, inputManager)
        Mockito.`when`(inputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
        Mockito.`when`(inputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardDevice)
        // Need to mock KCM, to allow AppLaunchShortcutManager correctly initialize
        // bookmarks (for legacy bookmarks we use "character" instead of keycodes to define
        // key combinations, so we use Virtual KCM to reverse map character to keycodes)
        ExtendedMockito.`when`(KeyCharacterMap.load(anyInt())).thenReturn(kcm)
    }

    private fun startNewInputGlobalTestSession() {
        if (this::inputManagerGlobalSession.isInitialized) {
            inputManagerGlobalSession.close()
        }
        inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
        val inputManager = InputManager(context)
        Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
            .thenReturn(inputManager)
    }

    private fun setupKeyGestureController() {
        keyGestureController =
            KeyGestureController(
                context,
                testableContext,
                testLooper.looper,
                testLooper.looper,
                inputDataStore,
@@ -305,12 +289,16 @@ class KeyGestureControllerTests {
                    }
                },
            )
        Mockito.`when`(iInputManager.registerKeyGestureHandler(any(), any())).thenAnswer {
        Mockito.`when`(inputManager.registerKeyGestureEventHandler(any(), any())).thenAnswer {
            val args = it.arguments
            if (args[0] != null) {
                val gestures = args[0] as List<Int>
                val handler = args[1] as InputManager.KeyGestureEventHandler
                keyGestureController.registerKeyGestureHandler(
                    args[0] as IntArray,
                    args[1] as IKeyGestureHandler,
                    gestures.toIntArray(),
                    KeyGestureHandler { event, token ->
                        handler.handleKeyGestureEvent(KeyGestureEvent(event), token)
                    },
                    SYSTEM_PID,
                )
            }
@@ -321,8 +309,11 @@ class KeyGestureControllerTests {
                accessibilityShortcutController.isAccessibilityShortcutAvailable(anyBoolean())
            )
            .thenReturn(true)
        Mockito.`when`(iInputManager.appLaunchBookmarks)
            .thenReturn(keyGestureController.appLaunchBookmarks)
        Mockito.`when`(inputManager.appLaunchBookmarks).thenAnswer {
            keyGestureController.appLaunchBookmarks.map {
                bookmark -> InputGestureData(bookmark)
            }
        }
        keyGestureController.systemRunning()
        testLooper.dispatchAll()
    }
@@ -497,8 +488,10 @@ class KeyGestureControllerTests {

    @Test
    fun testSearchKeyGestures_defaultSearch() {
        Mockito.`when`(resources.getInteger(R.integer.config_searchKeyBehavior))
            .thenReturn(SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH)
        testableResources.addOverride(
            R.integer.config_searchKeyBehavior,
            SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH,
        )
        setupKeyGestureController()
        testKeyGestureNotProduced(
            KeyGestureData(
@@ -512,8 +505,10 @@ class KeyGestureControllerTests {

    @Test
    fun testSettingKeyGestures_doNothing() {
        Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
            .thenReturn(SETTINGS_KEY_BEHAVIOR_NOTHING)
        testableResources.addOverride(
            R.integer.config_settingsKeyBehavior,
            SETTINGS_KEY_BEHAVIOR_NOTHING,
        )
        setupKeyGestureController()

        testKeyGestureNotProduced(
@@ -536,8 +531,10 @@ class KeyGestureControllerTests {

    @Test
    fun testSettingKeyGestures_notificationPanel() {
        Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
            .thenReturn(SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL)
        testableResources.addOverride(
            R.integer.config_settingsKeyBehavior,
            SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL,
        )
        setupKeyGestureController()
        testKeyGestureProduced(
            KeyGestureData(
@@ -654,7 +651,6 @@ class KeyGestureControllerTests {
        testLooper.dispatchAll()

        // Reinitialize the gesture controller simulating a login/logout for the user.
        startNewInputGlobalTestSession()
        setupKeyGestureController()
        keyGestureController.setCurrentUserId(userId)
        testLooper.dispatchAll()
@@ -699,7 +695,6 @@ class KeyGestureControllerTests {

        // Delete the old data and reinitialize the controller simulating a "fresh" install.
        tempFile.delete()
        startNewInputGlobalTestSession()
        setupKeyGestureController()
        keyGestureController.setCurrentUserId(userId)
        testLooper.dispatchAll()
@@ -826,7 +821,6 @@ class KeyGestureControllerTests {
        testLooper.dispatchAll()

        // Reinitialize the gesture controller simulating a login/logout for the user.
        startNewInputGlobalTestSession()
        setupKeyGestureController()
        keyGestureController.setCurrentUserId(userId)
        testLooper.dispatchAll()
@@ -865,7 +859,6 @@ class KeyGestureControllerTests {

        // Delete the old data and reinitialize the controller simulating a "fresh" install.
        tempFile.delete()
        startNewInputGlobalTestSession()
        setupKeyGestureController()
        keyGestureController.setCurrentUserId(userId)
        testLooper.dispatchAll()