Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +36 −17 Original line number Diff line number Diff line Loading @@ -21,12 +21,14 @@ import android.content.Context import android.content.pm.PackageManager import android.hardware.biometrics.BiometricSourceType import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.res.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.res.R import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm Loading @@ -35,6 +37,10 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POST import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import java.io.PrintWriter import javax.inject.Inject Loading @@ -43,6 +49,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr private val mKeyguardStateController: KeyguardStateController private val statusBarStateController: StatusBarStateController private val shadeRepository: ShadeRepository private val devicePostureController: DevicePostureController @BypassOverride private val bypassOverride: Int private var hasFaceFeature: Boolean Loading Loading @@ -107,16 +114,18 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr @Inject constructor( context: Context, @Application applicationScope: CoroutineScope, tunerService: TunerService, statusBarStateController: StatusBarStateController, lockscreenUserManager: NotificationLockscreenUserManager, keyguardStateController: KeyguardStateController, shadeExpansionStateManager: ShadeExpansionStateManager, shadeRepository: ShadeRepository, devicePostureController: DevicePostureController, dumpManager: DumpManager ) { this.mKeyguardStateController = keyguardStateController this.statusBarStateController = statusBarStateController this.shadeRepository = shadeRepository this.devicePostureController = devicePostureController bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override) Loading @@ -128,6 +137,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr return } if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) { devicePostureController.addCallback { posture -> if (postureState != posture) { Loading @@ -137,7 +147,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } } dumpManager.registerDumpable("KeyguardBypassController", this) dumpManager.registerNormalDumpable("KeyguardBypassController", this) statusBarStateController.addCallback(object : StatusBarStateController.StateListener { override fun onStateChanged(newState: Int) { if (newState != StatusBarState.KEYGUARD) { Loading @@ -146,19 +156,15 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } }) shadeExpansionStateManager.addQsExpansionListener { isQsExpanded -> val changed = qsExpanded != isQsExpanded qsExpanded = isQsExpanded if (changed && !isQsExpanded) { maybePerformPendingUnlock() } } listenForQsExpandedChange(applicationScope) val dismissByDefault = if (context.resources.getBoolean( com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 tunerService.addTunable({ key, _ -> bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) lockscreenUserManager.addUserChangedListener( object : NotificationLockscreenUserManager.UserChangedListener { override fun onUserChanged(userId: Int) { Loading @@ -167,6 +173,19 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr }) } @VisibleForTesting fun listenForQsExpandedChange(scope: CoroutineScope) = scope.launch { shadeRepository.qsExpansion.map { it > 0f }.distinctUntilChanged() .collect { isQsExpanded -> val changed = qsExpanded != isQsExpanded qsExpanded = isQsExpanded if (changed && !isQsExpanded) { maybePerformPendingUnlock() } } } private fun notifyListeners() = listeners.forEach { it.onBypassStateChanged(bypassEnabled) } /** Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt +38 −4 Original line number Diff line number Diff line Loading @@ -20,11 +20,14 @@ import android.content.pm.PackageManager import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.res.R import com.android.systemui.scene.SceneTestUtils import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.policy.DevicePostureController import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED Loading @@ -34,6 +37,9 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POST import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before import org.junit.Rule Loading @@ -54,6 +60,10 @@ import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper class KeyguardBypassControllerTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val featureFlags = FakeFeatureFlags() private val shadeRepository = FakeShadeRepository() private lateinit var keyguardBypassController: KeyguardBypassController private lateinit var postureControllerCallback: DevicePostureController.Callback Loading @@ -61,10 +71,10 @@ class KeyguardBypassControllerTest : SysuiTestCase() { @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) Loading @@ -73,6 +83,8 @@ class KeyguardBypassControllerTest : SysuiTestCase() { @Before fun setUp() { context.setMockPackageManager(packageManager) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true) whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true) } Loading Loading @@ -126,11 +138,12 @@ class KeyguardBypassControllerTest : SysuiTestCase() { keyguardBypassController = KeyguardBypassController( context, testScope.backgroundScope, tunerService, statusBarStateController, lockscreenUserManager, keyguardStateController, shadeExpansionStateManager, shadeRepository, devicePostureController, dumpManager ) Loading Loading @@ -267,4 +280,25 @@ class KeyguardBypassControllerTest : SysuiTestCase() { assertThat(keyguardBypassController.bypassEnabled).isFalse() } @OptIn(ExperimentalCoroutinesApi::class) @Test fun qsExpansion_updates() { testScope.runTest { initKeyguardBypassController() assertThat(keyguardBypassController.qsExpanded).isFalse() val job = keyguardBypassController.listenForQsExpandedChange(this) shadeRepository.setQsExpansion(0.5f) runCurrent() assertThat(keyguardBypassController.qsExpanded).isTrue() shadeRepository.setQsExpansion(0f) runCurrent() assertThat(keyguardBypassController.qsExpanded).isFalse() job.cancel() } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +36 −17 Original line number Diff line number Diff line Loading @@ -21,12 +21,14 @@ import android.content.Context import android.content.pm.PackageManager import android.hardware.biometrics.BiometricSourceType import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.res.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.res.R import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm Loading @@ -35,6 +37,10 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POST import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import java.io.PrintWriter import javax.inject.Inject Loading @@ -43,6 +49,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr private val mKeyguardStateController: KeyguardStateController private val statusBarStateController: StatusBarStateController private val shadeRepository: ShadeRepository private val devicePostureController: DevicePostureController @BypassOverride private val bypassOverride: Int private var hasFaceFeature: Boolean Loading Loading @@ -107,16 +114,18 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr @Inject constructor( context: Context, @Application applicationScope: CoroutineScope, tunerService: TunerService, statusBarStateController: StatusBarStateController, lockscreenUserManager: NotificationLockscreenUserManager, keyguardStateController: KeyguardStateController, shadeExpansionStateManager: ShadeExpansionStateManager, shadeRepository: ShadeRepository, devicePostureController: DevicePostureController, dumpManager: DumpManager ) { this.mKeyguardStateController = keyguardStateController this.statusBarStateController = statusBarStateController this.shadeRepository = shadeRepository this.devicePostureController = devicePostureController bypassOverride = context.resources.getInteger(R.integer.config_face_unlock_bypass_override) Loading @@ -128,6 +137,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr return } if (configFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) { devicePostureController.addCallback { posture -> if (postureState != posture) { Loading @@ -137,7 +147,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } } dumpManager.registerDumpable("KeyguardBypassController", this) dumpManager.registerNormalDumpable("KeyguardBypassController", this) statusBarStateController.addCallback(object : StatusBarStateController.StateListener { override fun onStateChanged(newState: Int) { if (newState != StatusBarState.KEYGUARD) { Loading @@ -146,19 +156,15 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } }) shadeExpansionStateManager.addQsExpansionListener { isQsExpanded -> val changed = qsExpanded != isQsExpanded qsExpanded = isQsExpanded if (changed && !isQsExpanded) { maybePerformPendingUnlock() } } listenForQsExpandedChange(applicationScope) val dismissByDefault = if (context.resources.getBoolean( com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 tunerService.addTunable({ key, _ -> bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) lockscreenUserManager.addUserChangedListener( object : NotificationLockscreenUserManager.UserChangedListener { override fun onUserChanged(userId: Int) { Loading @@ -167,6 +173,19 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr }) } @VisibleForTesting fun listenForQsExpandedChange(scope: CoroutineScope) = scope.launch { shadeRepository.qsExpansion.map { it > 0f }.distinctUntilChanged() .collect { isQsExpanded -> val changed = qsExpanded != isQsExpanded qsExpanded = isQsExpanded if (changed && !isQsExpanded) { maybePerformPendingUnlock() } } } private fun notifyListeners() = listeners.forEach { it.onBypassStateChanged(bypassEnabled) } /** Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt +38 −4 Original line number Diff line number Diff line Loading @@ -20,11 +20,14 @@ import android.content.pm.PackageManager import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.res.R import com.android.systemui.scene.SceneTestUtils import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.policy.DevicePostureController import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED Loading @@ -34,6 +37,9 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POST import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before import org.junit.Rule Loading @@ -54,6 +60,10 @@ import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper class KeyguardBypassControllerTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val featureFlags = FakeFeatureFlags() private val shadeRepository = FakeShadeRepository() private lateinit var keyguardBypassController: KeyguardBypassController private lateinit var postureControllerCallback: DevicePostureController.Callback Loading @@ -61,10 +71,10 @@ class KeyguardBypassControllerTest : SysuiTestCase() { @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) Loading @@ -73,6 +83,8 @@ class KeyguardBypassControllerTest : SysuiTestCase() { @Before fun setUp() { context.setMockPackageManager(packageManager) featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true) whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true) whenever(keyguardStateController.isFaceAuthEnabled).thenReturn(true) } Loading Loading @@ -126,11 +138,12 @@ class KeyguardBypassControllerTest : SysuiTestCase() { keyguardBypassController = KeyguardBypassController( context, testScope.backgroundScope, tunerService, statusBarStateController, lockscreenUserManager, keyguardStateController, shadeExpansionStateManager, shadeRepository, devicePostureController, dumpManager ) Loading Loading @@ -267,4 +280,25 @@ class KeyguardBypassControllerTest : SysuiTestCase() { assertThat(keyguardBypassController.bypassEnabled).isFalse() } @OptIn(ExperimentalCoroutinesApi::class) @Test fun qsExpansion_updates() { testScope.runTest { initKeyguardBypassController() assertThat(keyguardBypassController.qsExpanded).isFalse() val job = keyguardBypassController.listenForQsExpandedChange(this) shadeRepository.setQsExpansion(0.5f) runCurrent() assertThat(keyguardBypassController.qsExpanded).isTrue() shadeRepository.setQsExpansion(0f) runCurrent() assertThat(keyguardBypassController.qsExpanded).isFalse() job.cancel() } } }