Merge "Add interactors for KeyEvents" into udc-qpr-dev
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user