1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.biometrics.combination; 17 18 import static com.android.settings.biometrics.activeunlock.ActiveUnlockStatusPreferenceController.KEY_ACTIVE_UNLOCK_SETTINGS; 19 import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; 20 21 import android.app.settings.SettingsEnums; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Bundle; 25 import android.os.UserHandle; 26 27 import androidx.activity.result.ActivityResult; 28 import androidx.activity.result.ActivityResultLauncher; 29 import androidx.activity.result.contract.ActivityResultContracts; 30 import androidx.annotation.Nullable; 31 import androidx.preference.Preference; 32 import androidx.preference.PreferenceCategory; 33 34 import com.android.settings.R; 35 import com.android.settings.biometrics.BiometricEnrollBase; 36 import com.android.settings.biometrics.activeunlock.ActiveUnlockContentListener.OnContentChangedListener; 37 import com.android.settings.biometrics.activeunlock.ActiveUnlockDeviceNameListener; 38 import com.android.settings.biometrics.activeunlock.ActiveUnlockRequireBiometricSetup; 39 import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils; 40 import com.android.settings.flags.Flags; 41 import com.android.settings.search.BaseSearchIndexProvider; 42 import com.android.settingslib.search.SearchIndexable; 43 44 /** 45 * Settings screen for multiple biometrics. 46 */ 47 @SearchIndexable 48 public class CombinedBiometricSettings extends BiometricsSettingsBase { 49 private static final String TAG = "BiometricSettings"; 50 private static final String KEY_FACE_SETTINGS = "biometric_face_settings"; 51 private static final String KEY_FINGERPRINT_SETTINGS = "biometric_fingerprint_settings"; 52 private static final String KEY_UNLOCK_PHONE = "biometric_settings_biometric_keyguard"; 53 private static final String KEY_USE_IN_APPS = "biometric_settings_biometric_app"; 54 private static final String KEY_INTRO_PREFERENCE = "biometric_intro"; 55 private static final String KEY_USE_BIOMETRIC_PREFERENCE = "biometric_ways_to_use"; 56 57 private ActiveUnlockStatusUtils mActiveUnlockStatusUtils; 58 private CombinedBiometricStatusUtils mCombinedBiometricStatusUtils; 59 @Nullable private ActiveUnlockDeviceNameListener mActiveUnlockDeviceNameListener; 60 61 private final ActivityResultLauncher<Intent> mActiveUnlockPreferenceLauncher = 62 registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), 63 this::onActiveUnlockPreferenceResult); 64 65 @Override onAttach(Context context)66 public void onAttach(Context context) { 67 super.onAttach(context); 68 use(BiometricSettingsKeyguardPreferenceController.class).setUserId(mUserId); 69 use(BiometricSettingsAppPreferenceController.class).setUserId(mUserId); 70 } 71 72 @Override onCreate(Bundle savedInstanceState)73 public void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 mActiveUnlockStatusUtils = new ActiveUnlockStatusUtils(getActivity()); 76 mCombinedBiometricStatusUtils = new CombinedBiometricStatusUtils(getActivity(), mUserId); 77 if (mActiveUnlockStatusUtils.isAvailable()) { 78 updateUiForActiveUnlock(); 79 } 80 if (Flags.biometricsOnboardingEducation()) { 81 final PreferenceCategory category = findPreference(KEY_USE_BIOMETRIC_PREFERENCE); 82 if (category != null) { 83 category.setVisible(false); 84 } 85 } 86 } 87 updateUiForActiveUnlock()88 private void updateUiForActiveUnlock() { 89 OnContentChangedListener listener = new OnContentChangedListener() { 90 @Override 91 public void onContentChanged(String newValue) { 92 updateUnlockPhonePreferenceSummary(); 93 } 94 }; 95 96 mActiveUnlockDeviceNameListener = 97 new ActiveUnlockDeviceNameListener(getActivity(), listener); 98 mActiveUnlockDeviceNameListener.subscribe(); 99 final Preference introPreference = findPreference(KEY_INTRO_PREFERENCE); 100 if (introPreference != null) { 101 introPreference.setTitle(mActiveUnlockStatusUtils.getIntroForActiveUnlock()); 102 } 103 final Preference useBiometricPreference = findPreference(KEY_USE_BIOMETRIC_PREFERENCE); 104 if (useBiometricPreference != null) { 105 useBiometricPreference.setTitle( 106 mActiveUnlockStatusUtils.getUseBiometricTitleForActiveUnlock()); 107 } 108 getActivity().setTitle(mActiveUnlockStatusUtils.getTitleForActiveUnlock()); 109 } 110 111 @Override onDestroy()112 public void onDestroy() { 113 if (mActiveUnlockDeviceNameListener != null) { 114 mActiveUnlockDeviceNameListener.unsubscribe(); 115 } 116 super.onDestroy(); 117 } 118 119 @Override getPreferenceScreenResId()120 protected int getPreferenceScreenResId() { 121 return R.xml.security_settings_combined_biometric; 122 } 123 124 @Override getFacePreferenceKey()125 public String getFacePreferenceKey() { 126 return KEY_FACE_SETTINGS; 127 } 128 129 @Override getFingerprintPreferenceKey()130 public String getFingerprintPreferenceKey() { 131 return KEY_FINGERPRINT_SETTINGS; 132 } 133 134 @Override getUnlockPhonePreferenceKey()135 public String getUnlockPhonePreferenceKey() { 136 return KEY_UNLOCK_PHONE; 137 } 138 139 @Override getUseInAppsPreferenceKey()140 public String getUseInAppsPreferenceKey() { 141 return KEY_USE_IN_APPS; 142 } 143 144 @Override getLogTag()145 protected String getLogTag() { 146 return TAG; 147 } 148 149 @Override getMetricsCategory()150 public int getMetricsCategory() { 151 return SettingsEnums.COMBINED_BIOMETRIC; 152 } 153 154 @Override onRetryPreferenceTreeClick(Preference preference, final boolean retry)155 protected boolean onRetryPreferenceTreeClick(Preference preference, final boolean retry) { 156 if (!mActiveUnlockStatusUtils.isAvailable() 157 || !KEY_ACTIVE_UNLOCK_SETTINGS.equals(preference.getKey())) { 158 return super.onRetryPreferenceTreeClick(preference, retry); 159 } 160 mDoNotFinishActivity = true; 161 Intent intent; 162 if (mActiveUnlockStatusUtils.useBiometricFailureLayout() 163 && mActiveUnlockDeviceNameListener != null 164 && !mActiveUnlockDeviceNameListener.hasEnrolled() 165 && !mCombinedBiometricStatusUtils.hasEnrolled()) { 166 intent = new Intent(getActivity(), ActiveUnlockRequireBiometricSetup.class); 167 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 168 int userId = mUserId; 169 if (mUserId != UserHandle.USER_NULL) { 170 intent.putExtra(Intent.EXTRA_USER_ID, mUserId); 171 } 172 intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, getGkPwHandle()); 173 } else { 174 intent = mActiveUnlockStatusUtils.getIntent(); 175 } 176 if (intent != null) { 177 if (Flags.activeUnlockFinishParent()) { 178 mActiveUnlockPreferenceLauncher.launch(intent); 179 } else { 180 startActivityForResult(intent, ACTIVE_UNLOCK_REQUEST); 181 } 182 } 183 return true; 184 185 } 186 onActiveUnlockPreferenceResult(@ullable ActivityResult result)187 private void onActiveUnlockPreferenceResult(@Nullable ActivityResult result) { 188 if (result != null && result.getResultCode() == BiometricEnrollBase.RESULT_TIMEOUT) { 189 mDoNotFinishActivity = false; 190 // When "Watch Unlock" is closed due to entering onStop(), 191 // "Face & Fingerprint Unlock" shall also close itself and back to "Security" page. 192 finish(); 193 } 194 } 195 196 @Override getUseAnyBiometricSummary()197 protected String getUseAnyBiometricSummary() { 198 // either Active Unlock is not enabled or no device is enrolled. 199 if (mActiveUnlockDeviceNameListener == null 200 || !mActiveUnlockDeviceNameListener.hasEnrolled()) { 201 return super.getUseAnyBiometricSummary(); 202 } 203 return mActiveUnlockStatusUtils.getUnlockDeviceSummaryForActiveUnlock(); 204 } 205 206 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 207 new CombinedBiometricSearchIndexProvider(R.xml.security_settings_combined_biometric) { 208 @Override 209 protected boolean isPageSearchEnabled(Context context) { 210 return super.isPageSearchEnabled(context) 211 && !Flags.biometricsOnboardingEducation(); 212 } 213 }; 214 } 215