Add interactors for KeyEvents

This is in preparation to swap over
to using the KeyEventInteractor instead of
calling methods on CentralSurfaces. However, this is NOT and ideal
way for the interactors themselves to be structured. In the future
the interactors should be updated to reflect true modern
architecture patterns.

The logic in these interactors match logic from
NotificationShadeWindowViewController and CentralSurfacesImpl.

Test: atest KeyEventInteractorTest
Test: atest KeyguardKeyEventInteractorTest
Bug: 295927655
Change-Id: Id5c5659a4a19a0b0feb45d6ee391930c2063a9b1
This commit is contained in:
Beverly
2023-08-14 20:57:54 +00:00
committed by Beverly Tai
parent 44a5fb6380
commit ce5fbaed64
5 changed files with 616 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2023 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.systemui.keyevent.domain.interactor
import android.view.KeyEvent
import com.android.systemui.back.domain.interactor.BackActionInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.KeyguardKeyEventInteractor
import javax.inject.Inject
/**
* Sends key events to the appropriate interactors and then acts upon key events that haven't
* already been handled but should be handled by SystemUI.
*/
@SysUISingleton
class KeyEventInteractor
@Inject
constructor(
private val backActionInteractor: BackActionInteractor,
private val keyguardKeyEventInteractor: KeyguardKeyEventInteractor,
) {
fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (keyguardKeyEventInteractor.dispatchKeyEvent(event)) {
return true
}
when (event.keyCode) {
KeyEvent.KEYCODE_BACK -> {
if (event.handleAction()) {
backActionInteractor.onBackRequested()
}
return true
}
}
return false
}
fun interceptMediaKey(event: KeyEvent): Boolean {
return keyguardKeyEventInteractor.interceptMediaKey(event)
}
fun dispatchKeyEventPreIme(event: KeyEvent): Boolean {
return keyguardKeyEventInteractor.dispatchKeyEventPreIme(event)
}
companion object {
// Most actions shouldn't be handled on the down event and instead handled on subsequent
// key events like ACTION_UP.
fun KeyEvent.handleAction(): Boolean {
return action != KeyEvent.ACTION_DOWN
}
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2023 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.systemui.keyguard.domain.interactor
import android.content.Context
import android.media.AudioManager
import android.view.KeyEvent
import com.android.systemui.back.domain.interactor.BackActionInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor.Companion.handleAction
import com.android.systemui.media.controls.util.MediaSessionLegacyHelperWrapper
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import javax.inject.Inject
/** Handles key events arriving when the keyguard is showing or device is dozing. */
@SysUISingleton
class KeyguardKeyEventInteractor
@Inject
constructor(
private val context: Context,
private val statusBarStateController: StatusBarStateController,
private val keyguardInteractor: KeyguardInteractor,
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
private val shadeController: ShadeController,
private val mediaSessionLegacyHelperWrapper: MediaSessionLegacyHelperWrapper,
private val backActionInteractor: BackActionInteractor,
) {
fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (statusBarStateController.isDozing) {
when (event.keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN,
KeyEvent.KEYCODE_VOLUME_UP -> return dispatchVolumeKeyEvent(event)
}
}
if (event.handleAction()) {
when (event.keyCode) {
KeyEvent.KEYCODE_MENU -> return dispatchMenuKeyEvent()
KeyEvent.KEYCODE_SPACE -> return dispatchSpaceEvent()
}
}
return false
}
/**
* While IME is active and a BACK event is detected, check with {@link
* StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event should be
* handled before routing to IME, in order to prevent the user from having to hit back twice to
* exit bouncer.
*/
fun dispatchKeyEventPreIme(event: KeyEvent): Boolean {
when (event.keyCode) {
KeyEvent.KEYCODE_BACK ->
if (
statusBarStateController.state == StatusBarState.KEYGUARD &&
statusBarKeyguardViewManager.dispatchBackKeyEventPreIme()
) {
return backActionInteractor.onBackRequested()
}
}
return false
}
fun interceptMediaKey(event: KeyEvent): Boolean {
return statusBarStateController.state == StatusBarState.KEYGUARD &&
statusBarKeyguardViewManager.interceptMediaKey(event)
}
private fun dispatchMenuKeyEvent(): Boolean {
val shouldUnlockOnMenuPressed =
isDeviceInteractive() &&
(statusBarStateController.state != StatusBarState.SHADE) &&
statusBarKeyguardViewManager.shouldDismissOnMenuPressed()
if (shouldUnlockOnMenuPressed) {
shadeController.animateCollapseShadeForced()
return true
}
return false
}
private fun dispatchSpaceEvent(): Boolean {
if (isDeviceInteractive() && statusBarStateController.state != StatusBarState.SHADE) {
shadeController.animateCollapseShadeForced()
return true
}
return false
}
private fun dispatchVolumeKeyEvent(event: KeyEvent): Boolean {
mediaSessionLegacyHelperWrapper
.getHelper(context)
.sendVolumeKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE, true)
return true
}
private fun isDeviceInteractive(): Boolean {
return keyguardInteractor.wakefulnessModel.value.isDeviceInteractive()
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 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.systemui.media.controls.util
import android.content.Context
import android.media.session.MediaSessionLegacyHelper
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
/** Injectable wrapper around `MediaSessionLegacyHelper` functions */
@SysUISingleton
class MediaSessionLegacyHelperWrapper @Inject constructor() {
fun getHelper(context: Context): MediaSessionLegacyHelper {
return MediaSessionLegacyHelper.getHelper(context)
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (C) 2023 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.systemui.keyevent.domain.interactor
import android.view.KeyEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.back.domain.interactor.BackActionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardKeyEventInteractor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
@SmallTest
@RunWith(AndroidJUnit4::class)
class KeyEventInteractorTest : SysuiTestCase() {
@JvmField @Rule var mockitoRule = MockitoJUnit.rule()
private lateinit var keyguardInteractorWithDependencies:
KeyguardInteractorFactory.WithDependencies
@Mock private lateinit var keyguardKeyEventInteractor: KeyguardKeyEventInteractor
@Mock private lateinit var backActionInteractor: BackActionInteractor
private lateinit var underTest: KeyEventInteractor
@Before
fun setup() {
keyguardInteractorWithDependencies = KeyguardInteractorFactory.create()
underTest =
KeyEventInteractor(
backActionInteractor,
keyguardKeyEventInteractor,
)
}
@Test
fun dispatchBackKey_notHandledByKeyguardKeyEventInteractor_handledByBackActionInteractor() {
val backKeyEventActionDown = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)
val backKeyEventActionUp = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)
// GIVEN back key ACTION_DOWN and ACTION_UP aren't handled by the keyguardKeyEventInteractor
whenever(keyguardKeyEventInteractor.dispatchKeyEvent(backKeyEventActionDown))
.thenReturn(false)
whenever(keyguardKeyEventInteractor.dispatchKeyEvent(backKeyEventActionUp))
.thenReturn(false)
// WHEN back key event ACTION_DOWN, the event is handled even though back isn't requested
assertThat(underTest.dispatchKeyEvent(backKeyEventActionDown)).isTrue()
// THEN back event isn't handled on ACTION_DOWN
verify(backActionInteractor, never()).onBackRequested()
// WHEN back key event ACTION_UP
assertThat(underTest.dispatchKeyEvent(backKeyEventActionUp)).isTrue()
// THEN back event is handled on ACTION_UP
verify(backActionInteractor).onBackRequested()
}
@Test
fun dispatchKeyEvent_isNotHandledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.dispatchKeyEvent(eq(keyEvent))).thenReturn(false)
assertThat(underTest.dispatchKeyEvent(keyEvent)).isFalse()
}
@Test
fun dispatchKeyEvent_handledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.dispatchKeyEvent(eq(keyEvent))).thenReturn(true)
assertThat(underTest.dispatchKeyEvent(keyEvent)).isTrue()
}
@Test
fun interceptMediaKey_isNotHandledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.interceptMediaKey(eq(keyEvent))).thenReturn(false)
assertThat(underTest.interceptMediaKey(keyEvent)).isFalse()
}
@Test
fun interceptMediaKey_handledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.interceptMediaKey(eq(keyEvent))).thenReturn(true)
assertThat(underTest.interceptMediaKey(keyEvent)).isTrue()
}
@Test
fun dispatchKeyEventPreIme_isNotHandledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.dispatchKeyEventPreIme(eq(keyEvent))).thenReturn(false)
assertThat(underTest.dispatchKeyEventPreIme(keyEvent)).isFalse()
}
@Test
fun dispatchKeyEventPreIme_handledByKeyguardKeyEventInteractor() {
val keyEvent =
KeyEvent(
KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_SPACE,
)
whenever(keyguardKeyEventInteractor.dispatchKeyEventPreIme(eq(keyEvent))).thenReturn(true)
assertThat(underTest.dispatchKeyEventPreIme(keyEvent)).isTrue()
}
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright (C) 2023 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.systemui.keyguard.domain.interactor
import android.media.AudioManager
import android.media.session.MediaSessionLegacyHelper
import android.view.KeyEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.back.domain.interactor.BackActionInteractor
import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.media.controls.util.MediaSessionLegacyHelperWrapper
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
@SmallTest
@RunWith(AndroidJUnit4::class)
class KeyguardKeyEventInteractorTest : SysuiTestCase() {
@JvmField @Rule var mockitoRule = MockitoJUnit.rule()
private val actionDownVolumeDownKeyEvent =
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN)
private val actionDownVolumeUpKeyEvent =
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP)
private val backKeyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK)
private val awakeWakefulnessMode =
WakefulnessModel(WakefulnessState.AWAKE, WakeSleepReason.OTHER, WakeSleepReason.OTHER)
private val asleepWakefulnessMode =
WakefulnessModel(WakefulnessState.ASLEEP, WakeSleepReason.OTHER, WakeSleepReason.OTHER)
private lateinit var keyguardInteractorWithDependencies:
KeyguardInteractorFactory.WithDependencies
@Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
@Mock private lateinit var shadeController: ShadeController
@Mock private lateinit var mediaSessionLegacyHelperWrapper: MediaSessionLegacyHelperWrapper
@Mock private lateinit var mediaSessionLegacyHelper: MediaSessionLegacyHelper
@Mock private lateinit var backActionInteractor: BackActionInteractor
private lateinit var underTest: KeyguardKeyEventInteractor
@Before
fun setup() {
whenever(mediaSessionLegacyHelperWrapper.getHelper(any()))
.thenReturn(mediaSessionLegacyHelper)
keyguardInteractorWithDependencies = KeyguardInteractorFactory.create()
underTest =
KeyguardKeyEventInteractor(
context,
statusBarStateController,
keyguardInteractorWithDependencies.keyguardInteractor,
statusBarKeyguardViewManager,
shadeController,
mediaSessionLegacyHelperWrapper,
backActionInteractor,
)
}
@Test
fun dispatchKeyEvent_volumeKey_dozing_handlesEvents() {
whenever(statusBarStateController.isDozing).thenReturn(true)
assertThat(underTest.dispatchKeyEvent(actionDownVolumeDownKeyEvent)).isTrue()
verify(mediaSessionLegacyHelper)
.sendVolumeKeyEvent(
eq(actionDownVolumeDownKeyEvent),
eq(AudioManager.USE_DEFAULT_STREAM_TYPE),
eq(true)
)
assertThat(underTest.dispatchKeyEvent(actionDownVolumeUpKeyEvent)).isTrue()
verify(mediaSessionLegacyHelper)
.sendVolumeKeyEvent(
eq(actionDownVolumeUpKeyEvent),
eq(AudioManager.USE_DEFAULT_STREAM_TYPE),
eq(true)
)
}
@Test
fun dispatchKeyEvent_volumeKey_notDozing_doesNotHandleEvents() {
whenever(statusBarStateController.isDozing).thenReturn(false)
assertThat(underTest.dispatchKeyEvent(actionDownVolumeDownKeyEvent)).isFalse()
verify(mediaSessionLegacyHelper, never())
.sendVolumeKeyEvent(
eq(actionDownVolumeDownKeyEvent),
eq(AudioManager.USE_DEFAULT_STREAM_TYPE),
eq(true)
)
assertThat(underTest.dispatchKeyEvent(actionDownVolumeUpKeyEvent)).isFalse()
verify(mediaSessionLegacyHelper, never())
.sendVolumeKeyEvent(
eq(actionDownVolumeUpKeyEvent),
eq(AudioManager.USE_DEFAULT_STREAM_TYPE),
eq(true)
)
}
@Test
fun dispatchKeyEvent_menuActionUp_interactiveKeyguard_collapsesShade() {
keyguardInteractorWithDependencies.repository.setWakefulnessModel(awakeWakefulnessMode)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.shouldDismissOnMenuPressed()).thenReturn(true)
val actionUpMenuKeyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU)
assertThat(underTest.dispatchKeyEvent(actionUpMenuKeyEvent)).isTrue()
verify(shadeController).animateCollapseShadeForced()
}
@Test
fun dispatchKeyEvent_menuActionUp_interactiveShadeLocked_collapsesShade() {
keyguardInteractorWithDependencies.repository.setWakefulnessModel(awakeWakefulnessMode)
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
whenever(statusBarKeyguardViewManager.shouldDismissOnMenuPressed()).thenReturn(true)
// action down: does NOT collapse the shade
val actionDownMenuKeyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU)
assertThat(underTest.dispatchKeyEvent(actionDownMenuKeyEvent)).isFalse()
verify(shadeController, never()).animateCollapseShadeForced()
// action up: collapses the shade
val actionUpMenuKeyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU)
assertThat(underTest.dispatchKeyEvent(actionUpMenuKeyEvent)).isTrue()
verify(shadeController).animateCollapseShadeForced()
}
@Test
fun dispatchKeyEvent_menuActionUp_nonInteractiveKeyguard_neverCollapsesShade() {
keyguardInteractorWithDependencies.repository.setWakefulnessModel(asleepWakefulnessMode)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.shouldDismissOnMenuPressed()).thenReturn(true)
val actionUpMenuKeyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU)
assertThat(underTest.dispatchKeyEvent(actionUpMenuKeyEvent)).isFalse()
verify(shadeController, never()).animateCollapseShadeForced()
}
@Test
fun dispatchKeyEvent_spaceActionUp_interactiveKeyguard_collapsesShade() {
keyguardInteractorWithDependencies.repository.setWakefulnessModel(awakeWakefulnessMode)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
// action down: does NOT collapse the shade
val actionDownMenuKeyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SPACE)
assertThat(underTest.dispatchKeyEvent(actionDownMenuKeyEvent)).isFalse()
verify(shadeController, never()).animateCollapseShadeForced()
// action up: collapses the shade
val actionUpMenuKeyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE)
assertThat(underTest.dispatchKeyEvent(actionUpMenuKeyEvent)).isTrue()
verify(shadeController).animateCollapseShadeForced()
}
@Test
fun dispatchKeyEventPreIme_back_keyguard_onBackRequested() {
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.dispatchBackKeyEventPreIme()).thenReturn(true)
whenever(backActionInteractor.onBackRequested()).thenReturn(false)
assertThat(underTest.dispatchKeyEventPreIme(backKeyEvent)).isFalse()
verify(backActionInteractor).onBackRequested()
clearInvocations(backActionInteractor)
whenever(backActionInteractor.onBackRequested()).thenReturn(true)
assertThat(underTest.dispatchKeyEventPreIme(backKeyEvent)).isTrue()
verify(backActionInteractor).onBackRequested()
}
@Test
fun dispatchKeyEventPreIme_back_keyguard_SBKVMdoesNotHandle_neverOnBackRequested() {
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.dispatchBackKeyEventPreIme()).thenReturn(false)
whenever(backActionInteractor.onBackRequested()).thenReturn(true)
assertThat(underTest.dispatchKeyEventPreIme(backKeyEvent)).isFalse()
verify(backActionInteractor, never()).onBackRequested()
}
@Test
fun dispatchKeyEventPreIme_back_shade_neverOnBackRequested() {
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
whenever(statusBarKeyguardViewManager.dispatchBackKeyEventPreIme()).thenReturn(true)
whenever(backActionInteractor.onBackRequested()).thenReturn(true)
assertThat(underTest.dispatchKeyEventPreIme(backKeyEvent)).isFalse()
verify(backActionInteractor, never()).onBackRequested()
}
@Test
fun interceptMediaKey_keyguard_SBKVMdoesNotHandle_doesNotHandleMediaKey() {
val keyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_VOLUME_UP)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.interceptMediaKey(eq(keyEvent))).thenReturn(false)
assertThat(underTest.interceptMediaKey(keyEvent)).isFalse()
verify(statusBarKeyguardViewManager).interceptMediaKey(eq(keyEvent))
}
@Test
fun interceptMediaKey_keyguard_handleMediaKey() {
val keyEvent = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_VOLUME_UP)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(statusBarKeyguardViewManager.interceptMediaKey(eq(keyEvent))).thenReturn(true)
assertThat(underTest.interceptMediaKey(keyEvent)).isTrue()
verify(statusBarKeyguardViewManager).interceptMediaKey(eq(keyEvent))
}
@Test
fun interceptMediaKey_shade_doesNotHandleMediaKey() {
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
assertThat(
underTest.interceptMediaKey(
KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_VOLUME_UP)
)
)
.isFalse()
verify(statusBarKeyguardViewManager, never()).interceptMediaKey(any())
}
}