Merge "Add interactors for KeyEvents" into udc-qpr-dev

This commit is contained in:
Beverly Tai
2023-08-17 11:26:45 +00:00
committed by Android (Google) Code Review
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())
}
}