diff --git a/src/com/android/settings/biometrics/BiometricsFeatureProvider.java b/src/com/android/settings/biometrics/BiometricsFeatureProvider.java new file mode 100644 index 00000000000..6ec7663e7a6 --- /dev/null +++ b/src/com/android/settings/biometrics/BiometricsFeatureProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2025 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.settings.biometrics; + +import android.safetycenter.SafetySourceIssue; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public interface BiometricsFeatureProvider { + + /** Returns a SafetySourceIssue for biometrics. */ + @Nullable + SafetySourceIssue getSafetySourceIssue(@NonNull String sourceId); + + /** Notifies that the action of an issue is launched */ + void notifySafetyIssueActionLaunched(); +} diff --git a/src/com/android/settings/biometrics/BiometricsFeatureProviderImpl.java b/src/com/android/settings/biometrics/BiometricsFeatureProviderImpl.java new file mode 100644 index 00000000000..a6d22066069 --- /dev/null +++ b/src/com/android/settings/biometrics/BiometricsFeatureProviderImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2025 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.settings.biometrics; + +import android.safetycenter.SafetySourceIssue; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class BiometricsFeatureProviderImpl implements BiometricsFeatureProvider { + @Nullable + @Override + public SafetySourceIssue getSafetySourceIssue(@NonNull String sourceId) { + return null; + } + + @Override + public void notifySafetyIssueActionLaunched() {} +} diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt index 84b82cbbb3a..6a419dd5fe0 100644 --- a/src/com/android/settings/overlay/FeatureFactory.kt +++ b/src/com/android/settings/overlay/FeatureFactory.kt @@ -20,6 +20,7 @@ import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider import com.android.settings.accessibility.AccessibilitySearchFeatureProvider import com.android.settings.accounts.AccountFeatureProvider import com.android.settings.applications.ApplicationFeatureProvider +import com.android.settings.biometrics.BiometricsFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProvider @@ -107,6 +108,11 @@ abstract class FeatureFactory { */ abstract val bluetoothFeatureProvider: BluetoothFeatureProvider + /** + * Retrieves implementation for Biometrics feature. + */ + abstract val biometricsFeatureProvider: BiometricsFeatureProvider + /** * Retrieves implementation for Face feature. */ diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt index a21d7e3f5b8..22d3f1b6a4d 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt @@ -27,6 +27,8 @@ import com.android.settings.accessibility.AccessibilitySearchFeatureProviderImpl import com.android.settings.accounts.AccountFeatureProvider import com.android.settings.accounts.AccountFeatureProviderImpl import com.android.settings.applications.ApplicationFeatureProviderImpl +import com.android.settings.biometrics.BiometricsFeatureProvider +import com.android.settings.biometrics.BiometricsFeatureProviderImpl import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProviderImpl import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider @@ -145,6 +147,10 @@ open class FeatureFactoryImpl : FeatureFactory() { BluetoothFeatureProviderImpl() } + override val biometricsFeatureProvider: BiometricsFeatureProvider by lazy { + BiometricsFeatureProviderImpl() + } + override val faceFeatureProvider: FaceFeatureProvider by lazy { FaceFeatureProviderImpl() } override val fingerprintFeatureProvider: FingerprintFeatureProvider by lazy { diff --git a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java index fcda654b761..9cadbbb5fcf 100644 --- a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java +++ b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.safetycenter.SafetyEvent; import android.safetycenter.SafetySourceData; +import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceStatus; /** Static helpers for setting SafetyCenter data for biometric safety sources. */ @@ -42,6 +43,30 @@ public final class BiometricSourcesUtils { boolean enabled, boolean hasEnrolled, SafetyEvent safetyEvent) { + setBiometricSafetySourceData( + safetySourceId, + context, + title, + summary, + pendingIntent, + enabled, + hasEnrolled, + safetyEvent, + null + ); + } + + /** Sets data for one of the biometrics sources */ + public static void setBiometricSafetySourceData( + String safetySourceId, + Context context, + String title, + String summary, + PendingIntent pendingIntent, + boolean enabled, + boolean hasEnrolled, + SafetyEvent safetyEvent, + SafetySourceIssue safetySourceIssue) { int severityLevel = enabled && hasEnrolled ? SafetySourceData.SEVERITY_LEVEL_INFORMATION @@ -52,8 +77,13 @@ public final class BiometricSourcesUtils { .setPendingIntent(pendingIntent) .setEnabled(enabled) .build(); - SafetySourceData safetySourceData = - new SafetySourceData.Builder().setStatus(status).build(); + + SafetySourceData.Builder builder = new SafetySourceData.Builder().setStatus(status); + if (safetySourceIssue != null) { + builder.addIssue(safetySourceIssue); + } + SafetySourceData safetySourceData = builder.build(); + SafetyCenterManagerWrapper.get() .setSafetySourceData(context, safetySourceId, safetySourceData, safetyEvent); diff --git a/src/com/android/settings/safetycenter/FaceSafetySource.java b/src/com/android/settings/safetycenter/FaceSafetySource.java index a945bc02c70..066de2bc26f 100644 --- a/src/com/android/settings/safetycenter/FaceSafetySource.java +++ b/src/com/android/settings/safetycenter/FaceSafetySource.java @@ -29,6 +29,7 @@ import android.safetycenter.SafetyEvent; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricNavigationUtils; import com.android.settings.biometrics.face.FaceStatusUtils; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils; /** Face biometrics Safety Source for Safety Center. */ @@ -87,7 +88,9 @@ public final class FaceSafetySource { REQUEST_CODE_FACE_SETTING), disablingAdmin == null /* enabled */, faceStatusUtils.hasEnrolled(), - safetyEvent); + safetyEvent, + FeatureFactory.getFeatureFactory().getBiometricsFeatureProvider() + .getSafetySourceIssue(SAFETY_SOURCE_ID)); return; } diff --git a/src/com/android/settings/safetycenter/FingerprintSafetySource.java b/src/com/android/settings/safetycenter/FingerprintSafetySource.java index 9d5d3b7e36e..b944ab50999 100644 --- a/src/com/android/settings/safetycenter/FingerprintSafetySource.java +++ b/src/com/android/settings/safetycenter/FingerprintSafetySource.java @@ -29,6 +29,7 @@ import android.safetycenter.SafetyEvent; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricNavigationUtils; import com.android.settings.biometrics.fingerprint.FingerprintStatusUtils; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils; /** Fingerprint biometrics Safety Source for Safety Center. */ @@ -89,7 +90,9 @@ public final class FingerprintSafetySource { REQUEST_CODE_FINGERPRINT_SETTING), disablingAdmin == null /* enabled */, fingerprintStatusUtils.hasEnrolled(), - safetyEvent); + safetyEvent, + FeatureFactory.getFeatureFactory().getBiometricsFeatureProvider() + .getSafetySourceIssue(SAFETY_SOURCE_ID)); return; } diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java index 2cb41bc8a76..cfa6357affd 100644 --- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java @@ -23,6 +23,7 @@ import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; +import com.android.settings.biometrics.BiometricsFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; @@ -80,6 +81,7 @@ public class FakeFeatureFactory extends FeatureFactory { public final UserFeatureProvider userFeatureProvider; public final AccountFeatureProvider mAccountFeatureProvider; public final BluetoothFeatureProvider mBluetoothFeatureProvider; + public final BiometricsFeatureProvider mBiometricsFeatureProvider; public final FaceFeatureProvider mFaceFeatureProvider; public final FingerprintFeatureProvider mFingerprintFeatureProvider; @@ -135,6 +137,7 @@ public class FakeFeatureFactory extends FeatureFactory { mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class); panelFeatureProvider = mock(PanelFeatureProvider.class); mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class); + mBiometricsFeatureProvider = mock(BiometricsFeatureProvider.class); mFaceFeatureProvider = mock(FaceFeatureProvider.class); mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class); wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class); @@ -258,6 +261,11 @@ public class FakeFeatureFactory extends FeatureFactory { return mBluetoothFeatureProvider; } + @Override + public BiometricsFeatureProvider getBiometricsFeatureProvider() { + return mBiometricsFeatureProvider; + } + @Override public FaceFeatureProvider getFaceFeatureProvider() { return mFaceFeatureProvider; diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt index 7c99ab1889a..37a6abe88f1 100644 --- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt +++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt @@ -21,6 +21,7 @@ import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider import com.android.settings.accessibility.AccessibilitySearchFeatureProvider import com.android.settings.accounts.AccountFeatureProvider import com.android.settings.applications.ApplicationFeatureProvider +import com.android.settings.biometrics.BiometricsFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProvider @@ -114,6 +115,8 @@ class FakeFeatureFactory : FeatureFactory() { override val bluetoothFeatureProvider: BluetoothFeatureProvider get() = TODO("Not yet implemented") + override val biometricsFeatureProvider: BiometricsFeatureProvider + get() = TODO("Not yet implemented") override val faceFeatureProvider: FaceFeatureProvider get() = TODO("Not yet implemented") override val fingerprintFeatureProvider: FingerprintFeatureProvider diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java index 6a50ffc4d55..46316d8626d 100644 --- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -23,6 +23,7 @@ import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; +import com.android.settings.biometrics.BiometricsFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; @@ -79,6 +80,7 @@ public class FakeFeatureFactory extends FeatureFactory { public final UserFeatureProvider userFeatureProvider; public final AccountFeatureProvider mAccountFeatureProvider; public final BluetoothFeatureProvider mBluetoothFeatureProvider; + public final BiometricsFeatureProvider mBiometricsFeatureProvider; public final FaceFeatureProvider mFaceFeatureProvider; public final FingerprintFeatureProvider mFingerprintFeatureProvider; @@ -136,6 +138,7 @@ public class FakeFeatureFactory extends FeatureFactory { mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class); panelFeatureProvider = mock(PanelFeatureProvider.class); mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class); + mBiometricsFeatureProvider = mock(BiometricsFeatureProvider.class); mFaceFeatureProvider = mock(FaceFeatureProvider.class); mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class); wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class); @@ -259,6 +262,11 @@ public class FakeFeatureFactory extends FeatureFactory { return mBluetoothFeatureProvider; } + @Override + public BiometricsFeatureProvider getBiometricsFeatureProvider() { + return mBiometricsFeatureProvider; + } + @Override public FaceFeatureProvider getFaceFeatureProvider() { return mFaceFeatureProvider;