Merge "4-1/ KeyguardBypassController listen for device posture change" into tm-qpr-dev am: 89713888a1
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20880918 Change-Id: I9dc7f97ce158781ef0fea73e037b0666a16db394 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -30,6 +30,9 @@ import com.android.systemui.shade.ShadeExpansionStateManager
|
|||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
import com.android.systemui.statusbar.StatusBarState
|
import com.android.systemui.statusbar.StatusBarState
|
||||||
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
|
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.tuner.TunerService
|
import com.android.systemui.tuner.TunerService
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
@@ -40,11 +43,19 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
|
|||||||
|
|
||||||
private val mKeyguardStateController: KeyguardStateController
|
private val mKeyguardStateController: KeyguardStateController
|
||||||
private val statusBarStateController: StatusBarStateController
|
private val statusBarStateController: StatusBarStateController
|
||||||
|
private val devicePostureController: DevicePostureController
|
||||||
@BypassOverride private val bypassOverride: Int
|
@BypassOverride private val bypassOverride: Int
|
||||||
private var hasFaceFeature: Boolean
|
private var hasFaceFeature: Boolean
|
||||||
|
@DevicePostureInt private val configFaceAuthSupportedPosture: Int
|
||||||
|
@DevicePostureInt private var postureState: Int = DEVICE_POSTURE_UNKNOWN
|
||||||
private var pendingUnlock: PendingUnlock? = null
|
private var pendingUnlock: PendingUnlock? = null
|
||||||
private val listeners = mutableListOf<OnBypassStateChangedListener>()
|
private val listeners = mutableListOf<OnBypassStateChangedListener>()
|
||||||
|
private val postureCallback = DevicePostureController.Callback { posture ->
|
||||||
|
if (postureState != posture) {
|
||||||
|
postureState = posture
|
||||||
|
notifyListeners()
|
||||||
|
}
|
||||||
|
}
|
||||||
private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback {
|
private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback {
|
||||||
override fun onFaceAuthEnabledChanged() = notifyListeners()
|
override fun onFaceAuthEnabledChanged() = notifyListeners()
|
||||||
}
|
}
|
||||||
@@ -86,7 +97,8 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
|
|||||||
FACE_UNLOCK_BYPASS_NEVER -> false
|
FACE_UNLOCK_BYPASS_NEVER -> false
|
||||||
else -> field
|
else -> field
|
||||||
}
|
}
|
||||||
return enabled && mKeyguardStateController.isFaceAuthEnabled
|
return enabled && mKeyguardStateController.isFaceAuthEnabled &&
|
||||||
|
isPostureAllowedForFaceAuth()
|
||||||
}
|
}
|
||||||
private set(value) {
|
private set(value) {
|
||||||
field = value
|
field = value
|
||||||
@@ -106,18 +118,31 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
|
|||||||
lockscreenUserManager: NotificationLockscreenUserManager,
|
lockscreenUserManager: NotificationLockscreenUserManager,
|
||||||
keyguardStateController: KeyguardStateController,
|
keyguardStateController: KeyguardStateController,
|
||||||
shadeExpansionStateManager: ShadeExpansionStateManager,
|
shadeExpansionStateManager: ShadeExpansionStateManager,
|
||||||
|
devicePostureController: DevicePostureController,
|
||||||
dumpManager: DumpManager
|
dumpManager: DumpManager
|
||||||
) {
|
) {
|
||||||
this.mKeyguardStateController = keyguardStateController
|
this.mKeyguardStateController = keyguardStateController
|
||||||
this.statusBarStateController = statusBarStateController
|
this.statusBarStateController = statusBarStateController
|
||||||
|
this.devicePostureController = devicePostureController
|
||||||
|
|
||||||
bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override)
|
bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override)
|
||||||
|
configFaceAuthSupportedPosture =
|
||||||
|
context.resources.getInteger(R.integer.config_face_auth_supported_posture)
|
||||||
|
|
||||||
hasFaceFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)
|
hasFaceFeature = context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)
|
||||||
if (!hasFaceFeature) {
|
if (!hasFaceFeature) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
|
||||||
|
devicePostureController.addCallback { posture ->
|
||||||
|
if (postureState != posture) {
|
||||||
|
postureState = posture
|
||||||
|
notifyListeners()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dumpManager.registerDumpable("KeyguardBypassController", this)
|
dumpManager.registerDumpable("KeyguardBypassController", this)
|
||||||
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
|
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
|
||||||
override fun onStateChanged(newState: Int) {
|
override fun onStateChanged(newState: Int) {
|
||||||
@@ -203,6 +228,13 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
|
|||||||
pendingUnlock = null
|
pendingUnlock = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isPostureAllowedForFaceAuth(): Boolean {
|
||||||
|
return when (configFaceAuthSupportedPosture) {
|
||||||
|
DEVICE_POSTURE_UNKNOWN -> true
|
||||||
|
else -> (postureState == configFaceAuthSupportedPosture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
||||||
pw.println("KeyguardBypassController:")
|
pw.println("KeyguardBypassController:")
|
||||||
if (pendingUnlock != null) {
|
if (pendingUnlock != null) {
|
||||||
@@ -219,6 +251,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr
|
|||||||
pw.println(" launchingAffordance: $launchingAffordance")
|
pw.println(" launchingAffordance: $launchingAffordance")
|
||||||
pw.println(" qSExpanded: $qsExpanded")
|
pw.println(" qSExpanded: $qsExpanded")
|
||||||
pw.println(" hasFaceFeature: $hasFaceFeature")
|
pw.println(" hasFaceFeature: $hasFaceFeature")
|
||||||
|
pw.println(" postureState: $postureState")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registers a listener for bypass state changes. */
|
/** Registers a listener for bypass state changes. */
|
||||||
|
|||||||
@@ -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.statusbar.phone
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
|
import com.android.systemui.shade.ShadeExpansionStateManager
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_FLIPPED
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
|
||||||
|
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN
|
||||||
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
|
import com.android.systemui.tuner.TunerService
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.Captor
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.reset
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
class KeyguardBypassControllerTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private lateinit var keyguardBypassController: KeyguardBypassController
|
||||||
|
private lateinit var postureControllerCallback: DevicePostureController.Callback
|
||||||
|
@Mock private lateinit var tunerService: TunerService
|
||||||
|
@Mock private lateinit var statusBarStateController: StatusBarStateController
|
||||||
|
@Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager
|
||||||
|
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||||
|
@Mock private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
|
||||||
|
@Mock private lateinit var devicePostureController: DevicePostureController
|
||||||
|
@Mock private lateinit var dumpManager: DumpManager
|
||||||
|
@Mock private lateinit var packageManager: PackageManager
|
||||||
|
@Captor
|
||||||
|
private val postureCallbackCaptor =
|
||||||
|
ArgumentCaptor.forClass(DevicePostureController.Callback::class.java)
|
||||||
|
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
context.setMockPackageManager(packageManager)
|
||||||
|
whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true)
|
||||||
|
whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
reset(devicePostureController)
|
||||||
|
reset(keyguardStateController)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultConfigPostureClosed() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_auth_supported_posture,
|
||||||
|
DEVICE_POSTURE_CLOSED
|
||||||
|
)
|
||||||
|
initKeyguardBypassController()
|
||||||
|
verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
|
||||||
|
postureControllerCallback = postureCallbackCaptor.value
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultConfigPostureOpened() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_auth_supported_posture,
|
||||||
|
DEVICE_POSTURE_OPENED
|
||||||
|
)
|
||||||
|
initKeyguardBypassController()
|
||||||
|
verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
|
||||||
|
postureControllerCallback = postureCallbackCaptor.value
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultConfigPostureFlipped() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_auth_supported_posture,
|
||||||
|
DEVICE_POSTURE_FLIPPED
|
||||||
|
)
|
||||||
|
initKeyguardBypassController()
|
||||||
|
verify(devicePostureController).addCallback(postureCallbackCaptor.capture())
|
||||||
|
postureControllerCallback = postureCallbackCaptor.value
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun defaultConfigPostureUnknown() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_auth_supported_posture,
|
||||||
|
DEVICE_POSTURE_UNKNOWN
|
||||||
|
)
|
||||||
|
initKeyguardBypassController()
|
||||||
|
verify(devicePostureController, never()).addCallback(postureCallbackCaptor.capture())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initKeyguardBypassController() {
|
||||||
|
keyguardBypassController =
|
||||||
|
KeyguardBypassController(
|
||||||
|
context,
|
||||||
|
tunerService,
|
||||||
|
statusBarStateController,
|
||||||
|
lockscreenUserManager,
|
||||||
|
keyguardStateController,
|
||||||
|
shadeExpansionStateManager,
|
||||||
|
devicePostureController,
|
||||||
|
dumpManager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureClosed_matchState_isPostureAllowedForFaceAuth_returnTrue() {
|
||||||
|
defaultConfigPostureClosed()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureOpen_matchState_isPostureAllowedForFaceAuth_returnTrue() {
|
||||||
|
defaultConfigPostureOpened()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureFlipped_matchState_isPostureAllowedForFaceAuth_returnTrue() {
|
||||||
|
defaultConfigPostureFlipped()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureClosed_changeOpened_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureClosed()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureClosed_changeFlipped_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureClosed()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureOpened_changeClosed_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureOpened()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureOpened_changeFlipped_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureOpened()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_FLIPPED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureFlipped_changeClosed_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureFlipped()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_CLOSED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun configDevicePostureFlipped_changeOpened_isPostureAllowedForFaceAuth_returnFalse() {
|
||||||
|
defaultConfigPostureFlipped()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.isPostureAllowedForFaceAuth()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun defaultConfigPostureClosed_canOverrideByPassAlways_shouldReturnFalse() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_unlock_bypass_override,
|
||||||
|
1 /* FACE_UNLOCK_BYPASS_ALWAYS */
|
||||||
|
)
|
||||||
|
|
||||||
|
defaultConfigPostureClosed()
|
||||||
|
|
||||||
|
postureControllerCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.bypassEnabled).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun defaultConfigPostureUnknown_canNotOverrideByPassAlways_shouldReturnTrue() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_unlock_bypass_override,
|
||||||
|
1 /* FACE_UNLOCK_BYPASS_ALWAYS */
|
||||||
|
)
|
||||||
|
|
||||||
|
defaultConfigPostureUnknown()
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.bypassEnabled).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun defaultConfigPostureUnknown_canNotOverrideByPassNever_shouldReturnFalse() {
|
||||||
|
context.orCreateTestableResources.addOverride(
|
||||||
|
R.integer.config_face_unlock_bypass_override,
|
||||||
|
2 /* FACE_UNLOCK_BYPASS_NEVER */
|
||||||
|
)
|
||||||
|
|
||||||
|
defaultConfigPostureUnknown()
|
||||||
|
|
||||||
|
assertThat(keyguardBypassController.bypassEnabled).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user