From 059c9678eebeefb97cb9cc075d526df546fe4b84 Mon Sep 17 00:00:00 2001 From: Milton Date: Thu, 25 Sep 2025 07:23:07 +0000 Subject: [PATCH 1/3] Ignore enrollAfterFace in FaceEnroll from ext pkg Remove key of enrollAfterFace in FaceEnroll if this intent is coming from external package Bug: 433252423 Flag: EXEMPT BUGFIX Test: atest FaceEnrollTest (cherry picked from commit 7ac22f2eae5d3e8e65bc7f8db5a173231ebba071) Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:c602fa951f06c4ae8b3fa4653e545fecd3e87193 Merged-In: Ibbb6340163613ea955516f11579d767b2ade4312 Change-Id: Ibbb6340163613ea955516f11579d767b2ade4312 --- .../settings/biometrics/face/FaceEnroll.kt | 24 +++++++------ .../biometrics/face/FaceEnrollTest.kt | 36 ++++++++++++------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/com/android/settings/biometrics/face/FaceEnroll.kt b/src/com/android/settings/biometrics/face/FaceEnroll.kt index 48ea527c032..40d3f08e76e 100644 --- a/src/com/android/settings/biometrics/face/FaceEnroll.kt +++ b/src/com/android/settings/biometrics/face/FaceEnroll.kt @@ -23,10 +23,11 @@ import android.util.Log import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AppCompatActivity import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED +import com.android.settings.biometrics.MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE import com.android.settings.biometrics.combination.CombinedBiometricStatusUtils import com.android.settings.overlay.FeatureFactory.Companion.featureFactory -class FaceEnroll: AppCompatActivity() { +class FaceEnroll : AppCompatActivity() { /** * The class of the next activity to launch. This is open to allow subclasses to provide their @@ -39,8 +40,7 @@ class FaceEnroll: AppCompatActivity() { private val enrollActivityProvider: FaceEnrollActivityClassProvider get() = featureFactory.faceFeatureProvider.enrollActivityClassProvider - @VisibleForTesting - var launchedFromProvider: () -> String? = { launchedFromPackage } + @VisibleForTesting var launchedFromProvider: () -> String? = { launchedFromPackage } private var isLaunched = false @@ -53,9 +53,9 @@ class FaceEnroll: AppCompatActivity() { if (!isLaunched) { /** - * Logs the next activity to be launched, creates an intent for that activity, - * adds flags to forward the result, includes any existing extras from the current intent, - * starts the new activity and then finishes the current one + * Logs the next activity to be launched, creates an intent for that activity, adds + * flags to forward the result, includes any existing extras from the current intent, + * starts the new activity and then finishes the current one */ Log.d("FaceEnroll", "forward to $nextActivityClass") val nextIntent = Intent(this, nextActivityClass) @@ -63,6 +63,7 @@ class FaceEnroll: AppCompatActivity() { // drop extras that are not allowed from external packages before launching if (launchedFromProvider() != packageName) { + nextIntent.removeExtra(EXTRA_ENROLL_AFTER_FACE) nextIntent.removeExtra(Intent.EXTRA_USER_ID) } startActivityForResult(nextIntent, 0) @@ -80,13 +81,16 @@ class FaceEnroll: AppCompatActivity() { requestCode: Int, resultCode: Int, data: Intent?, - caller: ComponentCaller + caller: ComponentCaller, ) { super.onActivityResult(requestCode, resultCode, data, caller) isLaunched = false - if (intent.getBooleanExtra( - CombinedBiometricStatusUtils.EXTRA_LAUNCH_FROM_SAFETY_SOURCE_ISSUE, false) - && resultCode != RESULT_FINISHED) { + if ( + intent.getBooleanExtra( + CombinedBiometricStatusUtils.EXTRA_LAUNCH_FROM_SAFETY_SOURCE_ISSUE, + false, + ) && resultCode != RESULT_FINISHED + ) { featureFactory.biometricsFeatureProvider.notifySafetyIssueActionLaunched() } setResult(resultCode, data) diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollTest.kt b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollTest.kt index ad4605aff98..b5ea747862f 100644 --- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollTest.kt +++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollTest.kt @@ -17,14 +17,17 @@ package com.android.settings.biometrics.face import android.app.Activity +import android.app.PendingIntent import android.content.Intent +import androidx.test.core.app.ApplicationProvider +import com.android.settings.biometrics.MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE import com.android.settings.overlay.FeatureFactory import com.android.settings.testutils.FakeFeatureFactory import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito.`when` as whenever +import org.mockito.kotlin.whenever import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows @@ -36,10 +39,6 @@ class FaceEnrollTest { private companion object { const val INTENT_KEY = "testKey" const val INTENT_VALUE = "testValue" - val INTENT = Intent().apply { - putExtra(INTENT_KEY, INTENT_VALUE) - putExtra(Intent.EXTRA_USER_ID, 11) - } } private val activityProvider = FaceEnrollActivityClassProvider() @@ -55,7 +54,21 @@ class FaceEnrollTest { activityClass: Class, launchedFrom: String? = null, ): FaceEnroll { - val activityController = Robolectric.buildActivity(activityClass, INTENT) + val activityIntent = + Intent().apply { + putExtra(INTENT_KEY, INTENT_VALUE) + putExtra(Intent.EXTRA_USER_ID, 11) + putExtra( + EXTRA_ENROLL_AFTER_FACE, + PendingIntent.getActivity( + ApplicationProvider.getApplicationContext()!!, + 1, + Intent(), + 0, + ), + ) + } + val activityController = Robolectric.buildActivity(activityClass, activityIntent) activityController.get().launchedFromProvider = { launchedFrom ?: activityController.get().packageName } @@ -68,23 +81,22 @@ class FaceEnrollTest { val nextActivityIntent = activity.asShadow().nextStartedActivity assertThat(nextActivityIntent.component!!.className).isEqualTo(activityProvider.next.name) - assertThat(nextActivityIntent.extras!!.size()).isEqualTo(2) + assertThat(nextActivityIntent.extras!!.size()).isEqualTo(3) assertThat(nextActivityIntent.getStringExtra(INTENT_KEY)).isEqualTo(INTENT_VALUE) assertThat(nextActivityIntent.hasExtra(Intent.EXTRA_USER_ID)).isTrue() + assertThat(nextActivityIntent.hasExtra(EXTRA_ENROLL_AFTER_FACE)).isTrue() } @Test - fun testFinishAndLaunchDefaultActivity_fromExternal_dropUser() { - val activity = setupActivity( - FaceEnroll::class.java, - launchedFrom = "com.foo.bar" - ) + fun testFinishAndLaunchDefaultActivity_fromExternal_dropUserAndDropEnrollAfterFace() { + val activity = setupActivity(FaceEnroll::class.java, launchedFrom = "com.foo.bar") val nextActivityIntent = activity.asShadow().nextStartedActivity assertThat(nextActivityIntent.component!!.className).isEqualTo(activityProvider.next.name) assertThat(nextActivityIntent.extras!!.size()).isEqualTo(1) assertThat(nextActivityIntent.getStringExtra(INTENT_KEY)).isEqualTo(INTENT_VALUE) assertThat(nextActivityIntent.hasExtra(Intent.EXTRA_USER_ID)).isFalse() + assertThat(nextActivityIntent.hasExtra(EXTRA_ENROLL_AFTER_FACE)).isFalse() } } -- GitLab From 48af8a13dd12ecbd0569c328a56d1a7b61a59ca3 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Fri, 26 Sep 2025 09:02:26 +0000 Subject: [PATCH 2/3] Check permission of the calling package in multi-pane devices Bug: 430047417 Test: manual test Flag: EXEMPT BUGFIX (cherry picked from commit bd4d57ade07792f2a9160acbe480603b30e79917) Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:2860bd01810adb2d0f00fba8f327cdae3f20ab9d Merged-In: I91dafa77d07970fdf2628b4d9e89ca1c4b74194c Change-Id: I91dafa77d07970fdf2628b4d9e89ca1c4b74194c --- AndroidManifest.xml | 2 +- .../settings/applications/AppInfoBase.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ed19890456f..e2d249add13 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2488,7 +2488,7 @@ android:name="Settings$AppUsageAccessSettingsActivity" android:exported="true" android:label="@string/usage_access_title"> - + diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java index 02237b886d9..14e54eb5b03 100644 --- a/src/com/android/settings/applications/AppInfoBase.java +++ b/src/com/android/settings/applications/AppInfoBase.java @@ -49,6 +49,7 @@ import androidx.fragment.app.Fragment; import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.activityembedding.ActivityEmbeddingUtils; import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; @@ -178,6 +179,25 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment if (!(activity instanceof SettingsActivity)) { return false; } + // Check the permission of the calling package if the device supports multi-pane. + if (ActivityEmbeddingUtils.isEmbeddingActivityEnabled(activity)) { + final String callingPackageName = + ((SettingsActivity) activity).getInitialCallingPackage(); + + if (TextUtils.isEmpty(callingPackageName)) { + Log.w(TAG, "Not able to get calling package name for permission check"); + return false; + } + if (mPm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, + callingPackageName) + != PackageManager.PERMISSION_GRANTED) { + Log.w(TAG, "Package " + callingPackageName + " does not have required permission " + + Manifest.permission.INTERACT_ACROSS_USERS_FULL); + return false; + } + return true; + } + try { int callerUid = ActivityManager.getService().getLaunchedFromUid( activity.getActivityToken()); -- GitLab From 7d8fbee887fc9577337c2a80513ae4399bf60111 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 14 Oct 2025 08:08:58 +0000 Subject: [PATCH 3/3] Fixed "Unlock your phone" unexpectedlly turned ON after OTA If the new settings key is not set, we should use the values of the old keys as default value. Bug: 444673089 Test: atest FaceSettingsAppsPreferenceControllerTest FaceSettingsKeyguardUnlockPreferenceControllerTest FingerprintSettingsAppsPreferenceControllerTest FingerprintSettingsKeyguardUnlockPreferenceControllerTest Flag: EXEMPT BUGFIX (cherry picked from commit 05f0884146a093e6311d7a30232d6850a28368ef) Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:feb931006ee2d56c146156d5bb1491117841ccf3 Merged-In: I345defc78500c244e29e8595f5fbc705b95f4ba6 Change-Id: I345defc78500c244e29e8595f5fbc705b95f4ba6 --- .../FaceSettingsAppsPreferenceController.java | 17 ++- ...ngsKeyguardUnlockPreferenceController.java | 13 ++ ...printSettingsAppsPreferenceController.java | 17 ++- ...ngsKeyguardUnlockPreferenceController.java | 13 ++ ...eSettingsAppsPreferenceControllerTest.java | 116 ++++++++++++++++++ ...eyguardUnlockPreferenceControllerTest.java | 90 ++++++++++++++ ...tSettingsAppsPreferenceControllerTest.java | 76 ++++++++++++ ...eyguardUnlockPreferenceControllerTest.java | 90 ++++++++++++++ 8 files changed, 428 insertions(+), 4 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java index 9500c25a8ec..78d9ffaf7c4 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.biometrics.face; +import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED; import static android.provider.Settings.Secure.FACE_APP_ENABLED; import android.app.settings.SettingsEnums; @@ -31,6 +32,7 @@ import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; public class FaceSettingsAppsPreferenceController extends FaceSettingsPreferenceController { + private static final int NOT_SET = -1; private static final int ON = 1; private static final int OFF = 0; private static final int DEFAULT = ON; @@ -40,12 +42,23 @@ public class FaceSettingsAppsPreferenceController extends public FaceSettingsAppsPreferenceController(@NonNull Context context, @NonNull String key) { super(context, key); mFaceManager = Utils.getFaceManagerOrNull(context); + + // For OTA case: if FACE_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is set, set the + // default value of the former to that of the latter. + final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + FACE_APP_ENABLED, NOT_SET, getUserId()); + final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, NOT_SET, getUserId()); + if (defValue == NOT_SET && oldDefValue != NOT_SET) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_APP_ENABLED, oldDefValue, getUserId()); + } } @Override public boolean isChecked() { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED, - DEFAULT, getUserId()) == ON; + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + FACE_APP_ENABLED, DEFAULT, getUserId()) == ON; } @Override diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java index 5ff15232a02..46731b94451 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.biometrics.face; +import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED; import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED; import android.app.settings.SettingsEnums; @@ -31,6 +32,7 @@ import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; public class FaceSettingsKeyguardUnlockPreferenceController extends FaceSettingsPreferenceController { + private static final int NOT_SET = -1; private static final int ON = 1; private static final int OFF = 0; private static final int DEFAULT = ON; @@ -41,6 +43,17 @@ public class FaceSettingsKeyguardUnlockPreferenceController extends @NonNull Context context, @NonNull String key) { super(context, key); mFaceManager = Utils.getFaceManagerOrNull(context); + + // For OTA case: if FACE_KEYGUARD_ENABLED is not set and BIOMETRIC_KEYGUARD_ENABLED is set, + // set the default value of the former to that of the latter. + final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, NOT_SET, getUserId()); + final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, NOT_SET, getUserId()); + if (defValue == NOT_SET && oldDefValue != NOT_SET) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, oldDefValue, getUserId()); + } } @Override diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java index 63fc3dcef23..574d406e382 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.biometrics.fingerprint; +import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED; import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED; import android.app.settings.SettingsEnums; @@ -31,6 +32,7 @@ import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; public class FingerprintSettingsAppsPreferenceController extends FingerprintSettingsPreferenceController { + private static final int NOT_SET = -1; private static final int ON = 1; private static final int OFF = 0; private static final int DEFAULT = ON; @@ -41,12 +43,23 @@ public class FingerprintSettingsAppsPreferenceController @NonNull Context context, @NonNull String key) { super(context, key); mFingerprintManager = Utils.getFingerprintManagerOrNull(context); + + // For OTA case: if FINGERPRINT_APP_ENABLED is not set and BIOMETRIC_APP_ENABLED is set, + // set the default value of the former to that of the latter. + final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + FINGERPRINT_APP_ENABLED, NOT_SET, getUserId()); + final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, NOT_SET, getUserId()); + if (defValue == NOT_SET && oldDefValue != NOT_SET) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_APP_ENABLED, oldDefValue, getUserId()); + } } @Override public boolean isChecked() { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED, - DEFAULT, getUserId()) == ON; + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + FINGERPRINT_APP_ENABLED, DEFAULT, getUserId()) == ON; } @Override diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java index 56ef2c3db8b..89bea9b5fde 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java @@ -16,6 +16,7 @@ package com.android.settings.biometrics.fingerprint; +import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED; import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED; import android.app.settings.SettingsEnums; @@ -32,6 +33,7 @@ import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; public class FingerprintSettingsKeyguardUnlockPreferenceController extends FingerprintSettingsPreferenceController { + private static final int NOT_SET = -1; private static final int ON = 1; private static final int OFF = 0; private static final int DEFAULT = ON; @@ -42,6 +44,17 @@ public class FingerprintSettingsKeyguardUnlockPreferenceController @NonNull Context context, @NonNull String key) { super(context, key); mFingerprintManager = Utils.getFingerprintManagerOrNull(context); + + // For OTA case: if FINGERPRINT_KEYGUARD_ENABLED is not set and BIOMETRIC_KEYGUARD_ENABLED + // is set, set the default value of the former to that of the latter. + final int defValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, NOT_SET, getUserId()); + final int oldDefValue = Settings.Secure.getIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, NOT_SET, getUserId()); + if (defValue == NOT_SET && oldDefValue != NOT_SET) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, oldDefValue, getUserId()); + } } @Override diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java new file mode 100644 index 00000000000..676031c4951 --- /dev/null +++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java @@ -0,0 +1,116 @@ +/* + * 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.face; + +import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED; +import static android.provider.Settings.Secure.FACE_APP_ENABLED; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.SensorProperties; +import android.hardware.face.FaceManager; +import android.hardware.face.FaceSensorProperties; +import android.hardware.face.FaceSensorPropertiesInternal; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSecureSettings; +import com.android.settings.testutils.shadow.ShadowUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSecureSettings.class}) +public class FaceSettingsAppsPreferenceControllerTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + private Context mContext = ApplicationProvider.getApplicationContext(); + @Mock + private FaceManager mFaceManager; + private FaceSettingsAppsPreferenceController mController; + + private FaceSensorPropertiesInternal mConvenienceSensorProperty = + new FaceSensorPropertiesInternal( + 0 /* sensorId */, + SensorProperties.STRENGTH_CONVENIENCE, + 1 /* maxEnrollmentsPerUser */, + new ArrayList(), + FaceSensorProperties.TYPE_UNKNOWN, + true /* supportsFaceDetection */, + true /* supportsSelfIllumination */, + true /* resetLockoutRequiresChallenge */); + private FakeFeatureFactory mFeatureFactory; + + @Before + public void setUp() { + when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager); + final ArrayList list = new ArrayList<>(); + list.add(mConvenienceSensorProperty); + when(mFaceManager.getSensorPropertiesInternal()).thenReturn(list); + mFeatureFactory = FakeFeatureFactory.setupForTest(); + } + + @After + public void tearDown() { + ShadowUtils.reset(); + } + + @Test + public void isChecked_BiometricAppEnableOff_FaceAppEnabledNotSet_returnFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_APP_ENABLED, -1, mContext.getUserId()); + + mController = new FaceSettingsAppsPreferenceController( + mContext, "biometric_settings_face_app"); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void isChecked_BiometricAppEnableOff_FaceAppEnabledOn_returnTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_APP_ENABLED, 1, mContext.getUserId()); + + mController = new FaceSettingsAppsPreferenceController( + mContext, "biometric_settings_face_app"); + + assertThat(mController.isChecked()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java new file mode 100644 index 00000000000..837f31e3bd6 --- /dev/null +++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java @@ -0,0 +1,90 @@ +/* + * 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.face; + +import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED; +import static android.provider.Settings.Secure.FACE_KEYGUARD_ENABLED; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserManager; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSecureSettings; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSecureSettings.class}) +public class FaceSettingsKeyguardUnlockPreferenceControllerTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); + private FaceSettingsKeyguardUnlockPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; + @Mock + private UserManager mUserManager; + + @Before + public void setUp() { + + mFeatureFactory = FakeFeatureFactory.setupForTest(); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + } + + @Test + public void isChecked_BiometricKeyguardEnabledOff_FaceKeyguardEnabledNotSet_returnFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, -1, mContext.getUserId()); + + mController = new FaceSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_face_keyguard"); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void isChecked_BiometricKeyguardEnabledOff_FaceKeyguardEnabledOn_returnTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, 1, mContext.getUserId()); + + mController = new FaceSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_face_keyguard"); + + assertThat(mController.isChecked()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java new file mode 100644 index 00000000000..841cec2f3de --- /dev/null +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java @@ -0,0 +1,76 @@ +/* + * 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.fingerprint; + +import static android.provider.Settings.Secure.BIOMETRIC_APP_ENABLED; +import static android.provider.Settings.Secure.FINGERPRINT_APP_ENABLED; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSecureSettings; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSecureSettings.class}) +public class FingerprintSettingsAppsPreferenceControllerTest { + private Context mContext; + private FingerprintSettingsAppsPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); + } + + @Test + public void isChecked_BiometricAppEnableOff_FingerprintAppEnabledNotSet_returnFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_APP_ENABLED, -1, mContext.getUserId()); + + mController = new FingerprintSettingsAppsPreferenceController( + mContext, "biometric_settings_fingerprint_app"); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void isChecked_BiometricAppEnableOff_FingerprintAppEnabledOn_returnTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_APP_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_APP_ENABLED, 1, mContext.getUserId()); + + mController = new FingerprintSettingsAppsPreferenceController( + mContext, "biometric_settings_fingerprint_app"); + + assertThat(mController.isChecked()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java new file mode 100644 index 00000000000..119fda8bbf2 --- /dev/null +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java @@ -0,0 +1,90 @@ +/* + * 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.fingerprint; + +import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED; +import static android.provider.Settings.Secure.FINGERPRINT_KEYGUARD_ENABLED; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserManager; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSecureSettings; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSecureSettings.class}) +public class FingerprintSettingsKeyguardUnlockPreferenceControllerTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); + private FingerprintSettingsKeyguardUnlockPreferenceController mController; + private FakeFeatureFactory mFeatureFactory; + @Mock + private UserManager mUserManager; + + @Before + public void setUp() { + mFeatureFactory = FakeFeatureFactory.setupForTest(); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + } + + @Test + public void + isChecked_BiometricKeyguardEnabledOff_FingerprintKeyguardEnabledNotSet_returnFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, -1, mContext.getUserId()); + + mController = new FingerprintSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_fingerprint_keyguard"); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void isChecked_BiometricKeyguardEnabledOff_FingerprintKeyguardEnabledOn_returnTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + BIOMETRIC_KEYGUARD_ENABLED, 0, mContext.getUserId()); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, 1, mContext.getUserId()); + + mController = new FingerprintSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_fingerprint_keyguard"); + + assertThat(mController.isChecked()).isTrue(); + } +} -- GitLab