• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 android.app.PendingIntent;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.hardware.face.FaceManager;
23 import android.hardware.fingerprint.FingerprintManager;
24 import android.os.Bundle;
25 import android.os.Process;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.safetycenter.SafetyEvent;
29 import android.safetycenter.SafetySourceData;
30 import android.safetycenter.SafetySourceStatus;
31 
32 import com.android.settings.Utils;
33 import com.android.settings.biometrics.BiometricNavigationUtils;
34 import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
35 import com.android.settings.biometrics.combination.CombinedBiometricStatusUtils;
36 import com.android.settings.biometrics.face.FaceStatusUtils;
37 import com.android.settings.biometrics.fingerprint.FingerprintStatusUtils;
38 import com.android.settingslib.RestrictedLockUtils;
39 
40 /** Combined Biometrics Safety Source for Safety Center. */
41 public final class BiometricsSafetySource {
42 
43     public static final String SAFETY_SOURCE_ID = "AndroidBiometrics";
44     private static final int REQUEST_CODE_COMBINED_BIOMETRIC_SETTING = 10;
45     private static final int REQUEST_CODE_FACE_SETTING = 20;
46     private static final int REQUEST_CODE_FINGERPRINT_SETTING = 30;
47 
BiometricsSafetySource()48     private BiometricsSafetySource() {}
49 
50     /** Sets biometric safety data for Safety Center. */
setSafetySourceData(Context context, SafetyEvent safetyEvent)51     public static void setSafetySourceData(Context context, SafetyEvent safetyEvent) {
52         if (!SafetyCenterManagerWrapper.get().isEnabled(context)) {
53             return;
54         }
55 
56         final UserHandle userHandle = Process.myUserHandle();
57         final int userId = userHandle.getIdentifier();
58         final UserManager userManager = UserManager.get(context);
59         UserHandle profileParentUserHandle = userManager.getProfileParent(userHandle);
60         if (profileParentUserHandle == null) {
61             profileParentUserHandle = userHandle;
62         }
63         final Context profileParentContext =
64                 context.createContextAsUser(profileParentUserHandle, 0);
65         if (android.os.Flags.allowPrivateProfile()
66                 && android.multiuser.Flags.enablePrivateSpaceFeatures()
67                 && userManager.isPrivateProfile()) {
68             // SC always expects a response from the source if the broadcast has been sent for this
69             // source, therefore, we need to send a null SafetySourceData.
70             SafetyCenterManagerWrapper.get().setSafetySourceData(
71                     context,
72                     SAFETY_SOURCE_ID,
73                     /* safetySourceData= */ null,
74                     safetyEvent);
75             return;
76         }
77 
78         final BiometricNavigationUtils biometricNavigationUtils =
79                 new BiometricNavigationUtils(userId);
80         final CombinedBiometricStatusUtils combinedBiometricStatusUtils =
81                 new CombinedBiometricStatusUtils(context, userId);
82         final ActiveUnlockStatusUtils activeUnlockStatusUtils =
83                 new ActiveUnlockStatusUtils(context);
84         if (!userManager.isProfile() && activeUnlockStatusUtils.isAvailable()) {
85             final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
86                     combinedBiometricStatusUtils.getDisablingAdmin();
87             setBiometricSafetySourceData(
88                     context,
89                     activeUnlockStatusUtils.getTitleForActiveUnlock(),
90                     combinedBiometricStatusUtils.getSummary(),
91                     createPendingIntent(
92                             context,
93                             biometricNavigationUtils.getBiometricSettingsIntent(
94                                     context,
95                                     combinedBiometricStatusUtils.getSettingsClassName(),
96                                     disablingAdmin,
97                                     Bundle.EMPTY),
98                             REQUEST_CODE_COMBINED_BIOMETRIC_SETTING),
99                     disablingAdmin == null /* enabled */,
100                     combinedBiometricStatusUtils.hasEnrolled(),
101                     safetyEvent);
102             return;
103         }
104         if (combinedBiometricStatusUtils.isAvailable()) {
105             final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
106                     combinedBiometricStatusUtils.getDisablingAdmin();
107             setBiometricSafetySourceData(
108                     context,
109                     combinedBiometricStatusUtils.getTitle(),
110                     combinedBiometricStatusUtils.getSummary(),
111                     createPendingIntent(
112                             profileParentContext,
113                             biometricNavigationUtils
114                                     .getBiometricSettingsIntent(
115                                             context,
116                                             combinedBiometricStatusUtils
117                                                     .getSettingsClassNameBasedOnUser(),
118                                             disablingAdmin,
119                                             Bundle.EMPTY)
120                                     .setIdentifier(Integer.toString(userId)),
121                             REQUEST_CODE_COMBINED_BIOMETRIC_SETTING),
122                     disablingAdmin == null /* enabled */,
123                     combinedBiometricStatusUtils.hasEnrolled(),
124                     safetyEvent);
125             return;
126         }
127 
128         final FaceManager faceManager = Utils.getFaceManagerOrNull(context);
129         final FaceStatusUtils faceStatusUtils = new FaceStatusUtils(context, faceManager, userId);
130 
131         if (faceStatusUtils.isAvailable()) {
132             final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
133                     faceStatusUtils.getDisablingAdmin();
134             setBiometricSafetySourceData(
135                     context,
136                     faceStatusUtils.getTitle(),
137                     faceStatusUtils.getSummary(),
138                     createPendingIntent(
139                             profileParentContext,
140                             biometricNavigationUtils
141                                     .getBiometricSettingsIntent(
142                                             context,
143                                             faceStatusUtils.getSettingsClassName(),
144                                             disablingAdmin,
145                                             Bundle.EMPTY)
146                                     .setIdentifier(Integer.toString(userId)),
147                             REQUEST_CODE_FACE_SETTING),
148                     disablingAdmin == null /* enabled */,
149                     faceStatusUtils.hasEnrolled(),
150                     safetyEvent);
151 
152             return;
153         }
154 
155         final FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
156         final FingerprintStatusUtils fingerprintStatusUtils =
157                 new FingerprintStatusUtils(context, fingerprintManager, userId);
158 
159         if (fingerprintStatusUtils.isAvailable()) {
160             final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
161                     fingerprintStatusUtils.getDisablingAdmin();
162             setBiometricSafetySourceData(
163                     context,
164                     fingerprintStatusUtils.getTitle(),
165                     fingerprintStatusUtils.getSummary(),
166                     createPendingIntent(
167                             profileParentContext,
168                             biometricNavigationUtils
169                                     .getBiometricSettingsIntent(
170                                             context,
171                                             fingerprintStatusUtils.getSettingsClassName(),
172                                             disablingAdmin,
173                                             Bundle.EMPTY)
174                                     .setIdentifier(Integer.toString(userId)),
175                             REQUEST_CODE_FINGERPRINT_SETTING),
176                     disablingAdmin == null /* enabled */,
177                     fingerprintStatusUtils.hasEnrolled(),
178                     safetyEvent);
179             return;
180         }
181 
182         SafetyCenterManagerWrapper.get()
183                 .setSafetySourceData(
184                         context, SAFETY_SOURCE_ID, /* safetySourceData= */ null, safetyEvent);
185     }
186 
187     /** Notifies Safety Center of a change in biometrics settings. */
onBiometricsChanged(Context context)188     public static void onBiometricsChanged(Context context) {
189         setSafetySourceData(
190                 context,
191                 new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
192                         .build());
193     }
194 
setBiometricSafetySourceData( Context context, String title, String summary, PendingIntent pendingIntent, boolean enabled, boolean hasEnrolled, SafetyEvent safetyEvent)195     private static void setBiometricSafetySourceData(
196             Context context,
197             String title,
198             String summary,
199             PendingIntent pendingIntent,
200             boolean enabled,
201             boolean hasEnrolled,
202             SafetyEvent safetyEvent) {
203         final int severityLevel =
204                 enabled && hasEnrolled
205                         ? SafetySourceData.SEVERITY_LEVEL_INFORMATION
206                         : SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED;
207 
208         final SafetySourceStatus status =
209                 new SafetySourceStatus.Builder(title, summary, severityLevel)
210                         .setPendingIntent(pendingIntent)
211                         .setEnabled(enabled)
212                         .build();
213         final SafetySourceData safetySourceData =
214                 new SafetySourceData.Builder().setStatus(status).build();
215 
216         SafetyCenterManagerWrapper.get()
217                 .setSafetySourceData(context, SAFETY_SOURCE_ID, safetySourceData, safetyEvent);
218     }
219 
createPendingIntent( Context context, Intent intent, int requestCode)220     private static PendingIntent createPendingIntent(
221             Context context, Intent intent, int requestCode) {
222         return PendingIntent.getActivity(
223                 context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE);
224     }
225 }
226