diff options
| author | 2023-09-27 00:25:09 +0000 | |
|---|---|---|
| committer | 2023-09-27 00:25:09 +0000 | |
| commit | 8c44d5bc20466b23e4860da9ebbfaa9899cb602e (patch) | |
| tree | d344d5110601ff1bc9360904eddc0adcfdccb49e | |
| parent | 3fdeba27362731ba803fb3a2c230224f5b13c017 (diff) | |
| parent | 2f6c56c9d8177af15984ad557f59f9dbce6640d5 (diff) | |
Merge "Disable face auth if any SIM is in secure state." into main
11 files changed, 138 insertions, 11 deletions
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 5e7e044947fd..104f3d2b2621 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -235,6 +235,9 @@ filegroup { srcs: [ /* Status bar fakes */ "tests/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt", + "tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt", + "tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt", + "tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt", "tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt", "tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt", diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt index 06cf7235ad2c..e8740a4b24c5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt @@ -26,7 +26,6 @@ import android.os.UserHandle import android.util.Log import com.android.internal.widget.LockPatternUtils import com.android.systemui.Dumpable -import com.android.systemui.res.R import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.data.repository.FacePropertyRepository import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository @@ -40,6 +39,8 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.shared.model.AuthenticationFlags import com.android.systemui.keyguard.shared.model.DevicePosture +import com.android.systemui.res.R +import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository import com.android.systemui.user.data.repository.UserRepository import java.io.PrintWriter import javax.inject.Inject @@ -133,6 +134,7 @@ constructor( devicePostureRepository: DevicePostureRepository, facePropertyRepository: FacePropertyRepository, fingerprintPropertyRepository: FingerprintPropertyRepository, + mobileConnectionsRepository: MobileConnectionsRepository, dumpManager: DumpManager, ) : BiometricSettingsRepository, Dumpable { @@ -346,14 +348,15 @@ constructor( .and(isFingerprintBiometricAllowed) .stateIn(scope, SharingStarted.Eagerly, false) - override val isFaceAuthEnrolledAndEnabled: Flow<Boolean> - get() = isFaceAuthenticationEnabled.and(isFaceEnrolled) + override val isFaceAuthEnrolledAndEnabled: Flow<Boolean> = + isFaceAuthenticationEnabled + .and(isFaceEnrolled) + .and(mobileConnectionsRepository.isAnySimSecure.isFalse()) - override val isFaceAuthCurrentlyAllowed: Flow<Boolean> - get() = - isFaceAuthEnrolledAndEnabled - .and(isFaceBiometricsAllowed) - .and(isFaceAuthSupportedInCurrentPosture) + override val isFaceAuthCurrentlyAllowed: Flow<Boolean> = + isFaceAuthEnrolledAndEnabled + .and(isFaceBiometricsAllowed) + .and(isFaceAuthSupportedInCurrentPosture) } @OptIn(ExperimentalCoroutinesApi::class) @@ -426,3 +429,5 @@ private fun DevicePolicyManager.isNotActive(userId: Int, policy: Int): Boolean = private fun Flow<Boolean>.and(anotherFlow: Flow<Boolean>): Flow<Boolean> = this.combine(anotherFlow) { a, b -> a && b } + +private fun Flow<Boolean>.isFalse(): Flow<Boolean> = this.map { !it } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt index 02473f276b4b..aacdc6323179 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt @@ -186,6 +186,10 @@ constructor( } ) } + + fun logOnSimStateChanged() { + buffer.log(TAG, LogLevel.INFO, "onSimStateChanged") + } } private const val TAG = "MobileInputLog" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt index ea77163f0556..cf1c97c7271f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt @@ -90,4 +90,12 @@ interface MobileConnectionsRepository { /** Fallback [MobileIconGroup] in the case where there is no icon in the mapping */ val defaultMobileIconGroup: Flow<MobileIconGroup> + + /** + * If any active SIM on the device is in + * [android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED] or + * [android.telephony.TelephonyManager.SIM_STATE_PUK_REQUIRED] or + * [android.telephony.TelephonyManager.SIM_STATE_PERM_DISABLED] + */ + val isAnySimSecure: Flow<Boolean> } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt index 991ff56e683c..22916315d274 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt @@ -151,6 +151,8 @@ constructor( override val defaultMobileIconGroup: Flow<SignalIcon.MobileIconGroup> = activeRepo.flatMapLatest { it.defaultMobileIconGroup } + override val isAnySimSecure: Flow<Boolean> = activeRepo.flatMapLatest { it.isAnySimSecure } + override val defaultDataSubId: StateFlow<Int> = activeRepo .flatMapLatest { it.defaultDataSubId } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt index ee13d93e735d..c7987e2f8eb1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt @@ -134,6 +134,8 @@ constructor( override val defaultMobileIconGroup = flowOf(TelephonyIcons.THREE_G) + override val isAnySimSecure: Flow<Boolean> = flowOf(false) + override val defaultMobileIconMapping = MutableStateFlow(TelephonyIcons.ICON_NAME_TO_ICON) /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt index ec54f08c9d7e..ecb80f28de3e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt @@ -28,9 +28,10 @@ import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener import android.telephony.TelephonyManager import androidx.annotation.VisibleForTesting import com.android.internal.telephony.PhoneConstants +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.SignalIcon.MobileIconGroup import com.android.settingslib.mobile.MobileMappings.Config -import com.android.systemui.res.R import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton @@ -38,6 +39,7 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.res.R import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger @@ -94,6 +96,7 @@ constructor( // See [CarrierMergedConnectionRepository] for details. wifiRepository: WifiRepository, private val fullMobileRepoFactory: FullMobileConnectionRepository.Factory, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, ) : MobileConnectionsRepository { private var subIdRepositoryCache: MutableMap<Int, FullMobileConnectionRepository> = mutableMapOf() @@ -253,6 +256,27 @@ constructor( .distinctUntilChanged() .onEach { logger.logDefaultMobileIconGroup(it) } + override val isAnySimSecure: Flow<Boolean> = + conflatedCallbackFlow { + val callback = + object : KeyguardUpdateMonitorCallback() { + override fun onSimStateChanged(subId: Int, slotId: Int, simState: Int) { + logger.logOnSimStateChanged() + trySend(keyguardUpdateMonitor.isSimPinSecure) + } + } + keyguardUpdateMonitor.registerCallback(callback) + trySend(false) + awaitClose { keyguardUpdateMonitor.removeCallback(callback) } + } + .logDiffsForTable( + tableLogger, + LOGGING_PREFIX, + columnName = "isAnySimSecure", + initialValue = false, + ) + .distinctUntilChanged() + override fun getRepoForSubId(subId: Int): FullMobileConnectionRepository = getOrCreateRepoForSubId(subId) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt index 360fa5652e20..944b059450c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt @@ -32,7 +32,6 @@ import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUT import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN -import com.android.systemui.res.R import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.AuthController @@ -48,6 +47,10 @@ import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPR import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT import com.android.systemui.keyguard.shared.model.DevicePosture +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.res.R +import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository +import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.policy.DevicePostureController import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.util.mockito.eq @@ -87,6 +90,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { @Mock private lateinit var devicePolicyManager: DevicePolicyManager @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var biometricManager: BiometricManager + @Mock private lateinit var tableLogger: TableLogBuffer @Captor private lateinit var strongAuthTracker: ArgumentCaptor<LockPatternUtils.StrongAuthTracker> @Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback> @@ -97,6 +101,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { private lateinit var devicePostureRepository: FakeDevicePostureRepository private lateinit var facePropertyRepository: FakeFacePropertyRepository private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository private lateinit var testDispatcher: TestDispatcher private lateinit var testScope: TestScope @@ -112,6 +117,8 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { devicePostureRepository = FakeDevicePostureRepository() facePropertyRepository = FakeFacePropertyRepository() fingerprintPropertyRepository = FakeFingerprintPropertyRepository() + mobileConnectionsRepository = + FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogger) } private suspend fun createBiometricSettingsRepository() { @@ -132,6 +139,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { dumpManager = dumpManager, facePropertyRepository = facePropertyRepository, fingerprintPropertyRepository = fingerprintPropertyRepository, + mobileConnectionsRepository = mobileConnectionsRepository, ) testScope.runCurrent() fingerprintPropertyRepository.setProperties( @@ -421,6 +429,50 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() { } @Test + fun anySimSecure_disablesFaceAuth() = + testScope.runTest { + faceAuthIsEnrolled() + createBiometricSettingsRepository() + + faceAuthIsEnabledByBiometricManager() + doNotDisableKeyguardAuthFeatures() + mobileConnectionsRepository.isAnySimSecure.value = false + runCurrent() + + val isFaceAuthEnabledAndEnrolled by + collectLastValue(underTest.isFaceAuthEnrolledAndEnabled) + + assertThat(isFaceAuthEnabledAndEnrolled).isTrue() + + mobileConnectionsRepository.isAnySimSecure.value = true + runCurrent() + + assertThat(isFaceAuthEnabledAndEnrolled).isFalse() + } + + @Test + fun anySimSecure_disablesFaceAuthToNotCurrentlyRun() = + testScope.runTest { + faceAuthIsEnrolled() + + createBiometricSettingsRepository() + val isFaceAuthCurrentlyAllowed by collectLastValue(underTest.isFaceAuthCurrentlyAllowed) + + deviceIsInPostureThatSupportsFaceAuth() + doNotDisableKeyguardAuthFeatures() + faceAuthIsStrongBiometric() + faceAuthIsEnabledByBiometricManager() + mobileConnectionsRepository.isAnySimSecure.value = false + + onStrongAuthChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID) + onNonStrongAuthChanged(false, PRIMARY_USER_ID) + assertThat(isFaceAuthCurrentlyAllowed).isTrue() + + mobileConnectionsRepository.isAnySimSecure.value = true + assertThat(isFaceAuthCurrentlyAllowed).isFalse() + } + + @Test fun biometricManagerControlsFaceAuthenticationEnabledStatus() = testScope.runTest { faceAuthIsEnrolled() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt index 99e4030e1192..b54fbd3c31b1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt @@ -90,6 +90,8 @@ class FakeMobileConnectionsRepository( private val _defaultMobileIconGroup = MutableStateFlow(DEFAULT_ICON) override val defaultMobileIconGroup = _defaultMobileIconGroup + override val isAnySimSecure = MutableStateFlow(false) + fun setSubscriptions(subs: List<SubscriptionModel>) { _subscriptions.value = subs } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt index d005972043d7..4d4f33b63f3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt @@ -135,6 +135,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() { FakeAirplaneModeRepository(), wifiRepository, mock(), + mock(), ) demoRepo = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index 6f9764a907fc..9148c7580296 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -37,6 +37,8 @@ import android.telephony.TelephonyManager import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.telephony.PhoneConstants +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.R import com.android.settingslib.mobile.MobileMappings import com.android.systemui.SysuiTestCase @@ -104,6 +106,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var summaryLogger: TableLogBuffer @Mock private lateinit var logBufferFactory: TableLogBufferFactory + @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor private val mobileMappings = FakeMobileMappingsProxy() private val subscriptionManagerProxy = FakeSubscriptionManagerProxy() @@ -214,6 +217,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { airplaneModeRepository, wifiRepository, fullConnectionFactory, + updateMonitor, ) testScope.runCurrent() @@ -1048,6 +1052,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { airplaneModeRepository, wifiRepository, fullConnectionFactory, + updateMonitor ) val latest by collectLastValue(underTest.defaultDataSubRatConfig) @@ -1103,7 +1108,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { @Test fun carrierConfig_initialValueIsFetched() = testScope.runTest { - // Value starts out false assertThat(underTest.defaultDataSubRatConfig.value.showAtLeast3G).isFalse() @@ -1151,6 +1155,26 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(latest).isEqualTo(null) } + @Test + fun anySimSecure_propagatesStateFromKeyguardUpdateMonitor() = + testScope.runTest { + val latest by collectLastValue(underTest.isAnySimSecure) + assertThat(latest).isFalse() + + val updateMonitorCallback = argumentCaptor<KeyguardUpdateMonitorCallback>() + verify(updateMonitor).registerCallback(updateMonitorCallback.capture()) + + whenever(updateMonitor.isSimPinSecure).thenReturn(true) + updateMonitorCallback.value.onSimStateChanged(0, 0, 0) + + assertThat(latest).isTrue() + + whenever(updateMonitor.isSimPinSecure).thenReturn(false) + updateMonitorCallback.value.onSimStateChanged(0, 0, 0) + + assertThat(latest).isFalse() + } + private fun TestScope.getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback { runCurrent() val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>() |