1 /* 2 * Copyright (C) 2025 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 17 package com.android.settings.safetycenter; 18 19 import static com.android.settings.safetycenter.BiometricSourcesUtils.REQUEST_CODE_FINGERPRINT_SETTING; 20 21 import android.content.Context; 22 import android.hardware.fingerprint.FingerprintManager; 23 import android.os.Bundle; 24 import android.os.Process; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.safetycenter.SafetyEvent; 28 29 import com.android.settings.Utils; 30 import com.android.settings.biometrics.BiometricEnrollActivity; 31 import com.android.settings.biometrics.BiometricNavigationUtils; 32 import com.android.settings.biometrics.fingerprint.FingerprintStatusUtils; 33 import com.android.settings.flags.Flags; 34 import com.android.settings.overlay.FeatureFactory; 35 import com.android.settingslib.RestrictedLockUtils; 36 37 /** Fingerprint biometrics Safety Source for Safety Center. */ 38 public final class FingerprintSafetySource { 39 40 public static final String SAFETY_SOURCE_ID = "AndroidFingerprintUnlock"; 41 FingerprintSafetySource()42 private FingerprintSafetySource() {} 43 44 /** Sets biometric safety data for Safety Center. */ setSafetySourceData(Context context, SafetyEvent safetyEvent)45 public static void setSafetySourceData(Context context, SafetyEvent safetyEvent) { 46 if (!SafetyCenterManagerWrapper.get().isEnabled(context)) { 47 return; 48 } 49 if (!Flags.biometricsOnboardingEducation()) { // this source is effectively turned off 50 sendNullData(context, safetyEvent); 51 return; 52 } 53 54 // Handle private profile case 55 UserManager userManager = UserManager.get(context); 56 if (android.os.Flags.allowPrivateProfile() 57 && android.multiuser.Flags.enablePrivateSpaceFeatures() 58 && userManager.isPrivateProfile()) { 59 // SC always expects a response from the source if the broadcast has been sent for this 60 // source, therefore, we need to send a null SafetySourceData. 61 sendNullData(context, safetyEvent); 62 return; 63 } 64 65 UserHandle userHandle = Process.myUserHandle(); 66 int userId = userHandle.getIdentifier(); 67 FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context); 68 FingerprintStatusUtils fingerprintStatusUtils = 69 new FingerprintStatusUtils(context, fingerprintManager, userId); 70 BiometricNavigationUtils biometricNavigationUtils = new BiometricNavigationUtils(userId); 71 UserHandle profileParentUserHandle = userManager.getProfileParent(userHandle); 72 if (profileParentUserHandle == null) { 73 profileParentUserHandle = userHandle; 74 } 75 Context profileParentContext = context.createContextAsUser(profileParentUserHandle, 0); 76 77 if (Utils.hasFingerprintHardware(context)) { 78 boolean isMultipleBiometricsEnrollmentNeeded = 79 BiometricSourcesUtils.isMultipleBiometricsEnrollmentNeeded(context, userId); 80 String settingClassName = isMultipleBiometricsEnrollmentNeeded 81 ? BiometricEnrollActivity.InternalActivity.class.getName() 82 : fingerprintStatusUtils.getSettingsClassName(); 83 RestrictedLockUtils.EnforcedAdmin disablingAdmin = 84 fingerprintStatusUtils.getDisablingAdmin(); 85 BiometricSourcesUtils.setBiometricSafetySourceData( 86 SAFETY_SOURCE_ID, 87 context, 88 fingerprintStatusUtils.getTitle(), 89 fingerprintStatusUtils.getSummary(), 90 BiometricSourcesUtils.createPendingIntent( 91 profileParentContext, 92 biometricNavigationUtils 93 .getBiometricSettingsIntent( 94 context, 95 settingClassName, 96 disablingAdmin, 97 Bundle.EMPTY) 98 .setIdentifier(Integer.toString(userId)), 99 REQUEST_CODE_FINGERPRINT_SETTING), 100 disablingAdmin == null /* enabled */, 101 fingerprintStatusUtils.hasEnrolled(), 102 safetyEvent, 103 FeatureFactory.getFeatureFactory().getBiometricsFeatureProvider() 104 .getSafetySourceIssue(SAFETY_SOURCE_ID)); 105 return; 106 } 107 108 sendNullData(context, safetyEvent); 109 } 110 sendNullData(Context context, SafetyEvent safetyEvent)111 private static void sendNullData(Context context, SafetyEvent safetyEvent) { 112 SafetyCenterManagerWrapper.get() 113 .setSafetySourceData( 114 context, SAFETY_SOURCE_ID, /* safetySourceData= */ null, safetyEvent); 115 } 116 117 /** Notifies Safety Center of a change in fingerprint biometrics settings. */ onBiometricsChanged(Context context)118 public static void onBiometricsChanged(Context context) { 119 setSafetySourceData( 120 context, 121 new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED) 122 .build()); 123 } 124 } 125