From 2b8a2020283400284cb4c1837680fbd92925bb9d Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Sun, 12 Jan 2025 06:12:52 +0000 Subject: [PATCH 1/6] [Biometric Onboarding & Edu] Support ways to use section for Face & FP Move "Ways to use" section from "Face & Fingerprint Unlock" page to "Face unlock" & "Fingerprint unlock" pages which means Face & Fingerprint settings now have their own "Unlock your phone" & "Verify it's your in app" settings. Bug: 370940762 Test: atest FaceSettingsAppsPreferenceControllerTest FaceSettingsKeyguardUnlockPreferenceControllerTest FingerprintSettingsAppsPreferenceControllerTest FingerprintSettingsKeyguardUnlockPreferenceControllerTest FingerprintSettingsFragmentTest Flag: com.android.settings.flags.biometrics_onboarding_education Change-Id: I702da9bb9415b6deb741132ccde6b8be7ae38de0 --- res/values/strings.xml | 8 ++ res/xml/security_settings_face.xml | 18 +++++ res/xml/security_settings_fingerprint.xml | 18 +++++ .../CombinedBiometricSettings.java | 7 ++ .../biometrics/face/FaceSettings.java | 9 +++ .../FaceSettingsAppsPreferenceController.java | 74 ++++++++++++++++++ ...ngsKeyguardUnlockPreferenceController.java | 68 +++++++++++++++++ .../fingerprint/FingerprintSettings.java | 29 +++++++ ...printSettingsAppsPreferenceController.java | 76 +++++++++++++++++++ ...ngsKeyguardUnlockPreferenceController.java | 69 +++++++++++++++++ .../FingerprintSettingsFragmentTest.java | 13 ++++ ...eSettingsAppsPreferenceControllerTest.java | 46 +++++++++++ ...eyguardUnlockPreferenceControllerTest.java | 46 +++++++++++ ...tSettingsAppsPreferenceControllerTest.java | 46 +++++++++++ ...eyguardUnlockPreferenceControllerTest.java | 46 +++++++++++ 15 files changed, 573 insertions(+) create mode 100644 src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java create mode 100644 src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java create mode 100644 src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java create mode 100644 src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java create mode 100644 tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java create mode 100644 tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java create mode 100644 tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java create mode 100644 tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 236959d2530..e3577165005 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -901,6 +901,10 @@ Delete your current face model to set up Face Unlock again.\n\nYour face model will be permanently and securely deleted.\n\nAfter deletion, you will need your fingerprint, PIN, pattern, or password to unlock your phone or for authentication in apps. Use Face Unlock for + + Face + + Use Face to When using Face Unlock @@ -932,6 +936,10 @@ Fingerprint + + Fingerprints + + Use fingerprint to Fingerprint diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml index fd3498ea26a..e32148c458b 100644 --- a/res/xml/security_settings_face.xml +++ b/res/xml/security_settings_face.xml @@ -19,6 +19,24 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/security_settings_face_preference_title"> + + + + + + + + + + + + + + diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java index 7b3a72446f7..9fe47946fbd 100644 --- a/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java +++ b/src/com/android/settings/biometrics/combination/CombinedBiometricSettings.java @@ -29,6 +29,7 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.Nullable; import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; import com.android.settings.R; import com.android.settings.biometrics.BiometricEnrollBase; @@ -76,6 +77,12 @@ public class CombinedBiometricSettings extends BiometricsSettingsBase { if (mActiveUnlockStatusUtils.isAvailable()) { updateUiForActiveUnlock(); } + if (Flags.biometricsOnboardingEducation()) { + final PreferenceCategory category = findPreference(KEY_USE_BIOMETRIC_PREFERENCE); + if (category != null) { + category.setVisible(false); + } + } } private void updateUiForActiveUnlock() { diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java index 5a3949b8923..26b5c3735c5 100644 --- a/src/com/android/settings/biometrics/face/FaceSettings.java +++ b/src/com/android/settings/biometrics/face/FaceSettings.java @@ -47,6 +47,7 @@ import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ConfirmDeviceCredentialActivity; @@ -76,6 +77,8 @@ public class FaceSettings extends DashboardFragment { "security_settings_face_delete_faces_container"; private static final String PREF_KEY_ENROLL_FACE_UNLOCK = "security_settings_face_enroll_faces_container"; + private static final String PREF_KEY_USE_FACE_TO_CATEGORY = + "biometric_settings_use_face_to"; public static final String SECURITY_SETTINGS_FACE_MANAGE_CATEGORY = "security_settings_face_manage_category"; @@ -238,6 +241,12 @@ public class FaceSettings extends DashboardFragment { if (savedInstanceState != null) { mToken = savedInstanceState.getByteArray(KEY_TOKEN); } + + if (Flags.biometricsOnboardingEducation()) { + final PreferenceCategory category = + findPreference(PREF_KEY_USE_FACE_TO_CATEGORY); + category.setVisible(true); + } } @Override diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java new file mode 100644 index 00000000000..f859060f83a --- /dev/null +++ b/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceController.java @@ -0,0 +1,74 @@ +/* + * 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.FACE_APP_ENABLED; + +import android.content.Context; +import android.hardware.face.FaceManager; +import android.provider.Settings; + +import androidx.annotation.NonNull; + +import com.android.settings.Utils; +import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; + +public class FaceSettingsAppsPreferenceController extends + FaceSettingsPreferenceController { + private static final int ON = 1; + private static final int OFF = 0; + private static final int DEFAULT = ON; + + private FaceManager mFaceManager; + + public FaceSettingsAppsPreferenceController(@NonNull Context context, @NonNull String key) { + super(context, key); + mFaceManager = Utils.getFaceManagerOrNull(context); + } + + @Override + public boolean isChecked() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED, + DEFAULT, getUserId()) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putIntForUser(mContext.getContentResolver(), FACE_APP_ENABLED, + isChecked ? ON : OFF, getUserId()); + } + + @Override + public int getAvailabilityStatus() { + final ActiveUnlockStatusUtils activeUnlockStatusUtils = + new ActiveUnlockStatusUtils(mContext); + if (!Utils.hasFaceHardware(mContext) + && !activeUnlockStatusUtils.isAvailable()) { + return UNSUPPORTED_ON_DEVICE; + } + if (mFaceManager == null) { + return AVAILABLE_UNSEARCHABLE; + } + // This preference will be available only if the user has registered face. + final boolean hasFaceEnrolledUser = mFaceManager.hasEnrolledTemplates(getUserId()); + if (hasFaceEnrolledUser) { + return AVAILABLE; + } else { + return AVAILABLE_UNSEARCHABLE; + } + } +} diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java new file mode 100644 index 00000000000..e6298c09190 --- /dev/null +++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceController.java @@ -0,0 +1,68 @@ +/* + * 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.FACE_KEYGUARD_ENABLED; + +import android.content.Context; +import android.provider.Settings; + +import androidx.annotation.NonNull; + +import com.android.settings.Utils; +import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; + +public class FaceSettingsKeyguardUnlockPreferenceController extends + FaceSettingsPreferenceController { + private static final int ON = 1; + private static final int OFF = 0; + private static final int DEFAULT = ON; + + public FaceSettingsKeyguardUnlockPreferenceController( + @NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + public boolean isChecked() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, DEFAULT, getUserId()) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putIntForUser(mContext.getContentResolver(), + FACE_KEYGUARD_ENABLED, isChecked ? ON : OFF, getUserId()); + } + + @Override + public int getAvailabilityStatus() { + final ActiveUnlockStatusUtils activeUnlockStatusUtils = + new ActiveUnlockStatusUtils(mContext); + if (activeUnlockStatusUtils.isAvailable()) { + return getAvailabilityFromRestrictingAdmin(); + } + if (!Utils.hasFaceHardware(mContext)) { + return UNSUPPORTED_ON_DEVICE; + } + return getAvailabilityFromRestrictingAdmin(); + } + + private int getAvailabilityFromRestrictingAdmin() { + return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE; + } +} diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java index e50b0e515ac..e618ae358b3 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java @@ -273,6 +273,8 @@ public class FingerprintSettings extends SubSettings { "security_settings_fingerprint_footer"; private static final String KEY_BIOMETRICS_AUTHENTICATION_REQUESTED = "biometrics_authentication_requested"; + private static final String KEY_BIOMETRICS_USE_FINGERPRINT_TO_CATEGORY = + "biometric_settings_use_fingerprint_to"; private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000; private static final int MSG_FINGER_AUTH_SUCCESS = 1001; @@ -656,6 +658,9 @@ public class FingerprintSettings extends SubSettings { private PreferenceScreen createPreferenceHierarchy() { PreferenceScreen root = getPreferenceScreen(); addFingerprintPreferences(root); + if (Flags.biometricsOnboardingEducation()) { + setupUseFingerprintToPreferences(); + } setPreferenceScreen(root); return root; } @@ -685,6 +690,10 @@ public class FingerprintSettings extends SubSettings { if (mFingerprintsEnrolledCategory != null) { mFingerprintsEnrolledCategory.removeAll(); } + if (Flags.biometricsOnboardingEducation()) { + mFingerprintsEnrolledCategory.setTitle(root.getContext().getString( + R.string.security_settings_fingerprint_title)); + } String keyToReturn = mIsExpressiveThemeStyle ? KEY_FINGERPRINT_ADD_EXPRESSIVE : KEY_FINGERPRINT_ADD; @@ -815,6 +824,26 @@ public class FingerprintSettings extends SubSettings { }); } + private void setupUseFingerprintToPreferences() { + final PreferenceCategory category = + findPreference(KEY_BIOMETRICS_USE_FINGERPRINT_TO_CATEGORY); + category.setVisible(true); + + // Setup use fingerprint to unlock preference + final FingerprintSettingsKeyguardUnlockPreferenceController fpUnlockController = + use(FingerprintSettingsKeyguardUnlockPreferenceController.class); + fpUnlockController.setUserId(mUserId); + findPreference(fpUnlockController.getPreferenceKey()) + .setOnPreferenceChangeListener(fpUnlockController); + + // Setup use fingerprint to verify it's you in apps preference + final FingerprintSettingsAppsPreferenceController fingerprintAppController = + use(FingerprintSettingsAppsPreferenceController.class); + fingerprintAppController.setUserId(mUserId); + findPreference(fingerprintAppController.getPreferenceKey()) + .setOnPreferenceChangeListener(fingerprintAppController); + } + private void updatePreferencesAfterFingerprintRemoved() { updateAddPreference(); if (isSfps() || (screenOffUnlockUdfps() && isUltrasnoicUdfps())) { diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.java new file mode 100644 index 00000000000..2cd92fc03e4 --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceController.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.FINGERPRINT_APP_ENABLED; + +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; +import android.provider.Settings; + +import androidx.annotation.NonNull; + +import com.android.settings.Utils; +import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; + +public class FingerprintSettingsAppsPreferenceController + extends FingerprintSettingsPreferenceController { + private static final int ON = 1; + private static final int OFF = 0; + private static final int DEFAULT = ON; + + private FingerprintManager mFingerprintManager; + + public FingerprintSettingsAppsPreferenceController( + @NonNull Context context, @NonNull String key) { + super(context, key); + mFingerprintManager = Utils.getFingerprintManagerOrNull(context); + } + + @Override + public boolean isChecked() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED, + DEFAULT, getUserId()) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putIntForUser(mContext.getContentResolver(), FINGERPRINT_APP_ENABLED, + isChecked ? ON : OFF, getUserId()); + } + + @Override + public int getAvailabilityStatus() { + final ActiveUnlockStatusUtils activeUnlockStatusUtils = + new ActiveUnlockStatusUtils(mContext); + if (!Utils.hasFingerprintHardware(mContext) + && !activeUnlockStatusUtils.isAvailable()) { + return UNSUPPORTED_ON_DEVICE; + } + if (mFingerprintManager == null) { + return AVAILABLE_UNSEARCHABLE; + } + // This preference will be available only if the user has registered fingerprint. + final boolean hasFingerprintEnrolledUser = + mFingerprintManager.hasEnrolledTemplates(getUserId()); + if (hasFingerprintEnrolledUser) { + return AVAILABLE; + } else { + return AVAILABLE_UNSEARCHABLE; + } + } +} diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java new file mode 100644 index 00000000000..55c75abbcae --- /dev/null +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceController.java @@ -0,0 +1,69 @@ +/* + * 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.FINGERPRINT_KEYGUARD_ENABLED; + +import android.content.Context; +import android.provider.Settings; + +import androidx.annotation.NonNull; + +import com.android.settings.Utils; +import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; + +public class FingerprintSettingsKeyguardUnlockPreferenceController + extends FingerprintSettingsPreferenceController { + + private static final int ON = 1; + private static final int OFF = 0; + private static final int DEFAULT = ON; + + public FingerprintSettingsKeyguardUnlockPreferenceController( + @NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + public boolean isChecked() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, DEFAULT, getUserId()) == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putIntForUser(mContext.getContentResolver(), + FINGERPRINT_KEYGUARD_ENABLED, isChecked ? ON : OFF, getUserId()); + } + + @Override + public int getAvailabilityStatus() { + final ActiveUnlockStatusUtils activeUnlockStatusUtils = + new ActiveUnlockStatusUtils(mContext); + if (activeUnlockStatusUtils.isAvailable()) { + return getAvailabilityFromRestrictingAdmin(); + } + if (!Utils.hasFingerprintHardware(mContext)) { + return UNSUPPORTED_ON_DEVICE; + } + return getAvailabilityFromRestrictingAdmin(); + } + + private int getAvailabilityFromRestrictingAdmin() { + return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE; + } +} diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java index a570baadd59..02825d2aa50 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java @@ -383,6 +383,19 @@ public class FingerprintSettingsFragmentTest { assertThat(checkEnrolledPerf).isNull(); } + @Test + @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) + public void testUseFingerprintToPreference_isShown() { + doReturn(List.of()).when(mFingerprintManager).getEnrolledFingerprints(anyInt()); + setUpFragment(false, PRIMARY_USER_ID, TYPE_UDFPS_OPTICAL, 5); + + shadowOf(Looper.getMainLooper()).idle(); + + final Preference preference = + mFragment.findPreference("biometric_settings_use_fingerprint_to"); + assertThat(preference.isVisible()).isTrue(); + } + @Test @EnableFlags(com.android.settings.flags.Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION) public void testCheckEnrolledHide_nonUdfps() { diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java new file mode 100644 index 00000000000..bf96cacbeef --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppsPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * 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 com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FaceSettingsAppsPreferenceControllerTest { + private Context mContext; + private FaceSettingsAppsPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FaceSettingsAppsPreferenceController( + mContext, "biometric_settings_face_app"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java new file mode 100644 index 00000000000..4eb7d3edcaa --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardUnlockPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * 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 com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FaceSettingsKeyguardUnlockPreferenceControllerTest { + private Context mContext; + private FaceSettingsKeyguardUnlockPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FaceSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_face_keyguard"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java new file mode 100644 index 00000000000..4aa21b88f3c --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsAppsPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * 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 com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FingerprintSettingsAppsPreferenceControllerTest { + private Context mContext; + private FingerprintSettingsAppsPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FingerprintSettingsAppsPreferenceController( + mContext, "biometric_settings_fingerprint_app"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java new file mode 100644 index 00000000000..13a58b1ea63 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardUnlockPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * 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 com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FingerprintSettingsKeyguardUnlockPreferenceControllerTest { + private Context mContext; + private FingerprintSettingsKeyguardUnlockPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FingerprintSettingsKeyguardUnlockPreferenceController( + mContext, "biometric_settings_fingerprint_keyguard"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} From 41a7b5ee9ba41e4fe31dc4ff7e2f4796fbdea46f Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Thu, 16 Jan 2025 08:50:02 +0000 Subject: [PATCH 2/6] [Settings] Show intro preference in numbering system as well Bug: 377664066 Test: manual Flag: EXEMPT refactor Change-Id: I63cbaaa1e9fa3f3530cb05b1a62020bf8f54d1ac --- res/values/strings.xml | 1 + res/xml/system_language_picker.xml | 3 +-- ...ocalePickerBaseListPreferenceController.java | 3 +++ .../RegionAndNumberingSystemPickerFragment.java | 4 ++-- .../SystemLocalePickerFragment.java | 17 ++++++++++++----- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 9930c3685c0..22fa66cafd0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -531,6 +531,7 @@ Change region to %s ? Your device will keep %s as a system language + The digits used will be dependent on the numbering system diff --git a/res/xml/system_language_picker.xml b/res/xml/system_language_picker.xml index 52623928eb4..3d8e9d90ebe 100644 --- a/res/xml/system_language_picker.xml +++ b/res/xml/system_language_picker.xml @@ -22,8 +22,7 @@ + android:title="@string/top_intro_region_title"/> { + // TODO: b/390347399 - Should pop up a dialog when changes the region. switchFragment(locale); + ((Activity) mContext).finish(); return true; }); mPreferences.put(locale.getId(), pref); diff --git a/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java b/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java index 293c1ee0a6a..091e55bf765 100644 --- a/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java +++ b/src/com/android/settings/localepicker/RegionAndNumberingSystemPickerFragment.java @@ -116,8 +116,8 @@ public class RegionAndNumberingSystemPickerFragment extends DashboardFragment im } TopIntroPreference topIntroPreference = findPreference(KEY_TOP_INTRO_PREFERENCE); - if (topIntroPreference != null) { - topIntroPreference.setVisible(!mIsNumberingMode); + if (topIntroPreference != null && mIsNumberingMode) { + topIntroPreference.setTitle(R.string.top_intro_numbering_system_title); } if (mSystemLocaleAllListPreferenceController != null) { diff --git a/src/com/android/settings/localepicker/SystemLocalePickerFragment.java b/src/com/android/settings/localepicker/SystemLocalePickerFragment.java index 183990bfb75..f9e211bdc05 100644 --- a/src/com/android/settings/localepicker/SystemLocalePickerFragment.java +++ b/src/com/android/settings/localepicker/SystemLocalePickerFragment.java @@ -47,6 +47,7 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.TopIntroPreference; import com.google.android.material.appbar.AppBarLayout; @@ -71,14 +72,13 @@ public class SystemLocalePickerFragment extends DashboardFragment implements private static final String KEY_PREFERENCE_SYSTEM_LOCALE_LIST = "system_locale_list"; private static final String KEY_PREFERENCE_SYSTEM_LOCALE_SUGGESTED_LIST = "system_locale_suggested_list"; + private static final String KEY_TOP_INTRO_PREFERENCE = "top_intro_region"; @Nullable private SearchView mSearchView = null; @Nullable private SearchFilter mSearchFilter = null; @Nullable - private Set mLocaleList; - @Nullable private List mLocaleOptions; @Nullable private List mOriginalLocaleInfos; @@ -106,8 +106,15 @@ public class SystemLocalePickerFragment extends DashboardFragment implements } SystemLocaleCollector systemLocaleCollector = new SystemLocaleCollector(getContext(), null); - mLocaleList = systemLocaleCollector.getSupportedLocaleList(null, false, false); - mLocaleOptions = new ArrayList<>(mLocaleList.size()); + Set localeList = systemLocaleCollector.getSupportedLocaleList(null, + false, false); + mLocaleOptions = new ArrayList<>(localeList.size()); + + TopIntroPreference topIntroPreference = findPreference(KEY_TOP_INTRO_PREFERENCE); + if (topIntroPreference != null) { + topIntroPreference.setVisible(false); + } + } @Override @@ -175,7 +182,7 @@ public class SystemLocalePickerFragment extends DashboardFragment implements FilterResults results = new FilterResults(); if (mOriginalLocaleInfos == null) { - mOriginalLocaleInfos = new ArrayList<>(mLocaleList); + mOriginalLocaleInfos = new ArrayList<>(mLocaleOptions); } if (TextUtils.isEmpty(prefix)) { From f4e86178215cc03b8fe5d88659846571a57e2713 Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Fri, 17 Jan 2025 07:32:17 -0800 Subject: [PATCH 3/6] Give input team ownership of mouse-related settings files Bug: 245989146 Change-Id: I5961839b290af88784da525ff937ff6d6f148963 Test: none Flag: EXEMPT only changing OWNERS --- src/com/android/settings/inputmethod/OWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/inputmethod/OWNERS b/src/com/android/settings/inputmethod/OWNERS index c8850fee0d7..e2ce68519fb 100644 --- a/src/com/android/settings/inputmethod/OWNERS +++ b/src/com/android/settings/inputmethod/OWNERS @@ -2,8 +2,9 @@ include platform/frameworks/base:/services/core/java/com/android/server/inputmethod/OWNERS include /OWNERS -# Settings for physical keyboard, gamepad, and touchpad are better reviewed by the input team +# Settings for physical keyboard, mouse, gamepad, and touchpad are better reviewed by the input team per-file GameControllerPreferenceController.java = file:platform/frameworks/base:/INPUT_OWNERS per-file KeyboardLayoutPicker*.java = file:platform/frameworks/base:/INPUT_OWNERS +per-file Mouse*.java = file:platform/frameworks/base:/INPUT_OWNERS per-file PhysicalKeyboard*.java = file:platform/frameworks/base:/INPUT_OWNERS per-file Trackpad*.java,Touchpad*.java,PointerTouchpad*.java = file:platform/frameworks/base:/INPUT_OWNERS From 8d318b21d810ca6cbe7808d026775fb14af4bc70 Mon Sep 17 00:00:00 2001 From: Fan Wu Date: Fri, 17 Jan 2025 06:39:23 +0000 Subject: [PATCH 4/6] [Catalyst] Update RangeValue usages to IntRangeValuePreference Bug: 388167302 Test: atest and manual Flag: EXEMPT refactor NO_IFTTT=refactor Change-Id: If7412da90a5b5c1b4e3c31ea36361eae9e8bb8b9 --- .../android/settings/display/BrightnessLevelPreference.kt | 6 ++---- .../android/settings/fuelgauge/BatteryHeaderPreference.kt | 8 +++----- .../android/settings/notification/CallVolumePreference.kt | 6 ++---- .../settings/notification/MediaVolumePreference.kt | 6 ++---- .../settings/notification/SeparateRingVolumePreference.kt | 6 ++---- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/display/BrightnessLevelPreference.kt b/src/com/android/settings/display/BrightnessLevelPreference.kt index 0465d22361e..3e0d07ed947 100644 --- a/src/com/android/settings/display/BrightnessLevelPreference.kt +++ b/src/com/android/settings/display/BrightnessLevelPreference.kt @@ -41,11 +41,10 @@ import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN import com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat -import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.IntRangeValuePreference import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceSummaryProvider -import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding @@ -55,8 +54,7 @@ import java.text.NumberFormat // LINT.IfChange class BrightnessLevelPreference : - PersistentPreference, - RangeValue, + IntRangeValuePreference, PreferenceBinding, PreferenceRestrictionMixin, PreferenceSummaryProvider, diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt index 36654691c36..e08a111d683 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt @@ -26,11 +26,10 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.fuelgauge.BatteryUtils -import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.IntRangeValuePreference import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceMetadata -import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding @@ -38,10 +37,9 @@ import com.android.settingslib.widget.UsageProgressBarPreference // LINT.IfChange class BatteryHeaderPreference : - PersistentPreference, + IntRangeValuePreference, PreferenceBinding, - PreferenceLifecycleProvider, - RangeValue { + PreferenceLifecycleProvider { @VisibleForTesting var batteryBroadcastReceiver: BatteryBroadcastReceiver? = null diff --git a/src/com/android/settings/notification/CallVolumePreference.kt b/src/com/android/settings/notification/CallVolumePreference.kt index cc6f45fe270..f3ee3ca7022 100644 --- a/src/com/android/settings/notification/CallVolumePreference.kt +++ b/src/com/android/settings/notification/CallVolumePreference.kt @@ -32,20 +32,18 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.datastore.and -import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.IntRangeValuePreference import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceIconProvider import com.android.settingslib.metadata.PreferenceMetadata -import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class CallVolumePreference : + IntRangeValuePreference, PreferenceBinding, - PersistentPreference, - RangeValue, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceRestrictionMixin { diff --git a/src/com/android/settings/notification/MediaVolumePreference.kt b/src/com/android/settings/notification/MediaVolumePreference.kt index 71f2f91276f..b2a2fbe7bc7 100644 --- a/src/com/android/settings/notification/MediaVolumePreference.kt +++ b/src/com/android/settings/notification/MediaVolumePreference.kt @@ -29,20 +29,18 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.datastore.and -import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.IntRangeValuePreference import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceIconProvider import com.android.settingslib.metadata.PreferenceMetadata -import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class MediaVolumePreference : + IntRangeValuePreference, PreferenceBinding, - PersistentPreference, - RangeValue, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceRestrictionMixin { diff --git a/src/com/android/settings/notification/SeparateRingVolumePreference.kt b/src/com/android/settings/notification/SeparateRingVolumePreference.kt index 7bc39a82d10..16e6e5950c9 100644 --- a/src/com/android/settings/notification/SeparateRingVolumePreference.kt +++ b/src/com/android/settings/notification/SeparateRingVolumePreference.kt @@ -45,22 +45,20 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.datastore.and -import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.IntRangeValuePreference import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceIconProvider import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceMetadata -import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class SeparateRingVolumePreference : + IntRangeValuePreference, PreferenceBinding, - PersistentPreference, - RangeValue, PreferenceAvailabilityProvider, PreferenceIconProvider, PreferenceLifecycleProvider, From 4c9bf742bfec8c206e261239f8f402d83758f117 Mon Sep 17 00:00:00 2001 From: Menghan Li Date: Fri, 17 Jan 2025 06:33:00 +0000 Subject: [PATCH 5/6] chore(magnification suw): Hide feedback preference in setup wizard Bug: 380346799 Flag: com.android.server.accessibility.enable_low_vision_hats Test: atest MagnificationFeedbackPreferenceControllerTest MagnificationFollowTypingPreferenceControllerTest MagnificationJoystickPreferenceControllerTest MagnificationOneFingerPanningPreferenceControllerTest ToggleScreenMagnificationPreferenceFragmentTest Change-Id: I84f673235a8a4d97667edaabf72d46b985f33351 --- ...ificationAlwaysOnPreferenceController.java | 2 +- ...MagnificationBasePreferenceController.java | 42 +++++++++++++++++++ ...ificationFeedbackPreferenceController.java | 5 +-- ...ationFollowTypingPreferenceController.java | 2 +- ...ificationJoystickPreferenceController.java | 2 +- ...nOneFingerPanningPreferenceController.java | 2 +- ...nificationTogglePreferenceController.java} | 6 +-- ...ScreenMagnificationPreferenceFragment.java | 1 + ...ationFeedbackPreferenceControllerTest.java | 16 +++++++ 9 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 src/com/android/settings/accessibility/MagnificationBasePreferenceController.java rename src/com/android/settings/accessibility/{MagnificationFeaturePreferenceController.java => MagnificationTogglePreferenceController.java} (81%) diff --git a/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java b/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java index ff271c1e016..059b85e62a4 100644 --- a/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationAlwaysOnPreferenceController.java @@ -44,7 +44,7 @@ import com.android.settingslib.core.lifecycle.events.OnResume; * to 100%. */ public class MagnificationAlwaysOnPreferenceController extends - MagnificationFeaturePreferenceController implements LifecycleObserver, OnResume, OnPause { + MagnificationTogglePreferenceController implements LifecycleObserver, OnResume, OnPause { private static final String TAG = MagnificationAlwaysOnPreferenceController.class.getSimpleName(); diff --git a/src/com/android/settings/accessibility/MagnificationBasePreferenceController.java b/src/com/android/settings/accessibility/MagnificationBasePreferenceController.java new file mode 100644 index 00000000000..cf710a0928f --- /dev/null +++ b/src/com/android/settings/accessibility/MagnificationBasePreferenceController.java @@ -0,0 +1,42 @@ +/* + * 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.accessibility; + +import android.content.Context; + +import com.android.settings.core.BasePreferenceController; + +/** + * A base preference controller of magnification feature with common methods. + */ +public abstract class MagnificationBasePreferenceController extends BasePreferenceController { + + private boolean mInSetupWizard; + + protected MagnificationBasePreferenceController(Context context, + String preferenceKey) { + super(context, preferenceKey); + } + + protected final boolean isInSetupWizard() { + return mInSetupWizard; + } + + protected final void setInSetupWizard(boolean inSetupWizard) { + mInSetupWizard = inSetupWizard; + } +} diff --git a/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceController.java b/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceController.java index bfcd2930513..578a172b5b7 100644 --- a/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceController.java @@ -25,7 +25,6 @@ import androidx.lifecycle.DefaultLifecycleObserver; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.SurveyFeatureProvider; @@ -35,7 +34,7 @@ import com.android.settings.overlay.SurveyFeatureProvider; * visibility and click behavior of the preference based on the availability of a user survey * related to magnification. */ -public class MagnificationFeedbackPreferenceController extends BasePreferenceController +public class MagnificationFeedbackPreferenceController extends MagnificationBasePreferenceController implements DefaultLifecycleObserver { private static final String TAG = "MagnificationFeedbackPreferenceController"; public static final String PREF_KEY = "magnification_feedback"; @@ -53,7 +52,7 @@ public class MagnificationFeedbackPreferenceController extends BasePreferenceCon @Override public int getAvailabilityStatus() { - return AVAILABLE; + return isInSetupWizard() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE; } @Override diff --git a/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java b/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java index 6092b4b809c..c247ecb517e 100644 --- a/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationFollowTypingPreferenceController.java @@ -26,7 +26,7 @@ import com.android.settings.R; /** Controller that accesses and switches the preference status of following typing feature */ public class MagnificationFollowTypingPreferenceController extends - MagnificationFeaturePreferenceController { + MagnificationTogglePreferenceController { private static final String TAG = MagnificationFollowTypingPreferenceController.class.getSimpleName(); diff --git a/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java b/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java index 690a9453c29..17ea9f42820 100644 --- a/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationJoystickPreferenceController.java @@ -28,7 +28,7 @@ import com.android.settings.R; * Controller that accesses and switches the preference status of the magnification joystick feature */ public class MagnificationJoystickPreferenceController extends - MagnificationFeaturePreferenceController { + MagnificationTogglePreferenceController { private static final String TAG = MagnificationJoystickPreferenceController.class.getSimpleName(); diff --git a/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java b/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java index a6d87f268e6..f6ed209942e 100644 --- a/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationOneFingerPanningPreferenceController.java @@ -41,7 +41,7 @@ import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; public class MagnificationOneFingerPanningPreferenceController extends - MagnificationFeaturePreferenceController implements LifecycleObserver, OnResume, OnPause { + MagnificationTogglePreferenceController implements LifecycleObserver, OnResume, OnPause { static final String PREF_KEY = Settings.Secure.ACCESSIBILITY_SINGLE_FINGER_PANNING_ENABLED; private TwoStatePreference mSwitchPreference; diff --git a/src/com/android/settings/accessibility/MagnificationFeaturePreferenceController.java b/src/com/android/settings/accessibility/MagnificationTogglePreferenceController.java similarity index 81% rename from src/com/android/settings/accessibility/MagnificationFeaturePreferenceController.java rename to src/com/android/settings/accessibility/MagnificationTogglePreferenceController.java index 9664756ac45..62a877cd0a0 100644 --- a/src/com/android/settings/accessibility/MagnificationFeaturePreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationTogglePreferenceController.java @@ -21,13 +21,13 @@ import android.content.Context; import com.android.settings.core.TogglePreferenceController; /** - * A base preference controller of magnification feature with common methods. + * A base toggle preference controller of magnification feature with common methods. */ -public abstract class MagnificationFeaturePreferenceController extends TogglePreferenceController { +public abstract class MagnificationTogglePreferenceController extends TogglePreferenceController { private boolean mInSetupWizard; - protected MagnificationFeaturePreferenceController(Context context, + protected MagnificationTogglePreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index fef83ae2ef1..0d0c7fa7b02 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -387,6 +387,7 @@ public class ToggleScreenMagnificationPreferenceFragment extends final MagnificationFeedbackPreferenceController magnificationFeedbackPreferenceController = new MagnificationFeedbackPreferenceController(getContext(), this, MagnificationFeedbackPreferenceController.PREF_KEY); + magnificationFeedbackPreferenceController.setInSetupWizard(mInSetupWizard); magnificationFeedbackPreferenceController.displayPreference(getPreferenceScreen()); addPreferenceController(magnificationFeedbackPreferenceController); } diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceControllerTest.java index 389e12756bf..d34cc9b5926 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationFeedbackPreferenceControllerTest.java @@ -18,6 +18,8 @@ package com.android.settings.accessibility; import static com.android.settings.accessibility.MagnificationFeedbackPreferenceController.FEEDBACK_KEY; import static com.android.settings.accessibility.MagnificationFeedbackPreferenceController.PREF_KEY; +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; import static com.google.common.truth.Truth.assertThat; @@ -118,4 +120,18 @@ public class MagnificationFeedbackPreferenceControllerTest { verify(mSurveyFeatureProvider).sendActivityIfAvailable(FEEDBACK_KEY); } + + @Test + public void getAvailableStatus_notInSetupWizard_returnAvailable() { + mController.setInSetupWizard(false); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailableStatus_inSetupWizard_returnConditionallyUnavailable() { + mController.setInSetupWizard(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } } From 71f4b0f8e3813150ed0360a901f91262ce62d0dd Mon Sep 17 00:00:00 2001 From: Angela Wang Date: Wed, 15 Jan 2025 04:36:00 +0000 Subject: [PATCH 6/6] Offer a way to hide LE Audio toggle for ASHA device Flag: EXEMPT bugfix Bug: 390070780 Test: atest BluetoothDetailsProfilesControllerTest Test: manually check on real device Change-Id: I078403f7071c1011acbedae2d1d0e55783cc0661 --- .../BluetoothDetailsProfilesController.java | 8 ++++++++ .../BluetoothDetailsProfilesControllerTest.java | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java index f782c6b2a6a..58d278704b2 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java @@ -85,6 +85,8 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll "persist.bluetooth.leaudio.toggle_visible"; private static final String BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY = "persist.bluetooth.leaudio.bypass_allow_list"; + private static final String LE_AUDIO_TOGGLE_VISIBLE_FOR_ASHA_PROPERTY = + "bluetooth.leaudio.toggle_visible_for_asha"; private Set mInvisibleProfiles = Collections.emptySet(); private final AtomicReference> mAdditionalInvisibleProfiles = @@ -378,6 +380,12 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll // Remove hearing aids toggle anyway since showing the toggle will confuse users if (hearingAidSupported) { result.remove(mManager.getProfileManager().getHearingAidProfile()); + if (leAudioSupported + && !SystemProperties.getBoolean(BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, false) + && !SystemProperties.getBoolean( + LE_AUDIO_TOGGLE_VISIBLE_FOR_ASHA_PROPERTY, true)) { + result.remove(mManager.getProfileManager().getLeAudioProfile()); + } } if (leAudioSupported && !classicAudioSupported && !hearingAidSupported) { mIsLeAudioOnlyDevice = true; diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java index 2d007e1b134..a2ad063a464 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java @@ -29,6 +29,7 @@ import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; +import android.os.SystemProperties; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; @@ -646,6 +647,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont List switches = getProfileSwitches(false); assertThat(switches.isEmpty()).isTrue(); } + @Test public void ashaHearingAidWithLeAudio_showLeAudioToggle() { setupDevice(makeDefaultDeviceConfig()); @@ -658,4 +660,16 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(switches.getFirst().getTitle()).isEqualTo( mContext.getString(mLeAudioProfile.getNameResource(mDevice))); } + + @Test + public void ashaHearingAidWithLeAudio_hideLeAudioToggleFromSystemProperties() { + setupDevice(makeDefaultDeviceConfig()); + addHearingAidProfileToDevice(false); + addLeAudioProfileToDevice(true); + SystemProperties.set("bluetooth.leaudio.toggle_visible_for_asha", "false"); + showScreen(mController); + + List switches = getProfileSwitches(false); + assertThat(switches.isEmpty()).isTrue(); + } }