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.biometrics.face; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.hardware.face.Face; 22 import android.hardware.face.FaceEnrollCell; 23 import android.hardware.face.FaceEnrollOptions; 24 import android.hardware.face.FaceManager; 25 import android.os.CancellationSignal; 26 import android.view.Surface; 27 28 import androidx.annotation.Nullable; 29 30 import com.android.settings.Utils; 31 import com.android.settings.biometrics.BiometricUtils; 32 import com.android.settings.flags.Flags; 33 import com.android.settings.safetycenter.BiometricsSafetySource; 34 import com.android.settings.safetycenter.FaceSafetySource; 35 36 /** 37 * Responsible for making {@link FaceManager#enroll} and {@link FaceManager#remove} calls and thus 38 * updating the face setting. 39 */ 40 public class FaceUpdater { 41 42 private final Context mContext; 43 private final FaceManager mFaceManager; 44 FaceUpdater(Context context)45 public FaceUpdater(Context context) { 46 mContext = context; 47 mFaceManager = Utils.getFaceManagerOrNull(context); 48 } 49 FaceUpdater(Context context, FaceManager faceManager)50 public FaceUpdater(Context context, FaceManager faceManager) { 51 mContext = context; 52 mFaceManager = faceManager; 53 } 54 55 /** Wrapper around the {@link FaceManager#enroll} method. */ enroll( int userId, byte[] hardwareAuthToken, CancellationSignal cancel, FaceManager.EnrollmentCallback callback, int[] disabledFeatures, Intent intent)56 public void enroll( 57 int userId, 58 byte[] hardwareAuthToken, 59 CancellationSignal cancel, 60 FaceManager.EnrollmentCallback callback, 61 int[] disabledFeatures, 62 Intent intent) { 63 this.enroll( 64 userId, 65 hardwareAuthToken, 66 cancel, 67 new NotifyingEnrollmentCallback(mContext, callback), 68 disabledFeatures, 69 null, 70 false, 71 intent); 72 } 73 74 /** Wrapper around the {@link FaceManager#enroll} method. */ enroll( int userId, byte[] hardwareAuthToken, CancellationSignal cancel, FaceManager.EnrollmentCallback callback, int[] disabledFeatures, @Nullable Surface previewSurface, boolean debugConsent, Intent intent)75 public void enroll( 76 int userId, 77 byte[] hardwareAuthToken, 78 CancellationSignal cancel, 79 FaceManager.EnrollmentCallback callback, 80 int[] disabledFeatures, 81 @Nullable Surface previewSurface, 82 boolean debugConsent, 83 Intent intent) { 84 mFaceManager.enroll( 85 userId, 86 hardwareAuthToken, 87 cancel, 88 new NotifyingEnrollmentCallback(mContext, callback), 89 disabledFeatures, 90 previewSurface, 91 debugConsent, 92 toFaceEnrollOptions(intent)); 93 } 94 95 /** Wrapper around the {@link FaceManager#remove} method. */ remove(Face face, int userId, FaceManager.RemovalCallback callback)96 public void remove(Face face, int userId, FaceManager.RemovalCallback callback) { 97 mFaceManager.remove(face, userId, new NotifyingRemovalCallback(mContext, callback)); 98 } 99 100 /** 101 * Decorator of the {@link FaceManager.EnrollmentCallback} class that notifies other interested 102 * parties that a face setting has changed. 103 */ 104 private static class NotifyingEnrollmentCallback extends FaceManager.EnrollmentCallback { 105 106 private final Context mContext; 107 private final FaceManager.EnrollmentCallback mCallback; 108 NotifyingEnrollmentCallback(Context context, FaceManager.EnrollmentCallback callback)109 NotifyingEnrollmentCallback(Context context, FaceManager.EnrollmentCallback callback) { 110 mContext = context; 111 mCallback = callback; 112 } 113 114 @Override onEnrollmentError(int errMsgId, CharSequence errString)115 public void onEnrollmentError(int errMsgId, CharSequence errString) { 116 mCallback.onEnrollmentError(errMsgId, errString); 117 } 118 119 @Override onEnrollmentHelp(int helpMsgId, CharSequence helpString)120 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { 121 mCallback.onEnrollmentHelp(helpMsgId, helpString); 122 } 123 124 @Override onEnrollmentFrame( int helpCode, @Nullable CharSequence helpMessage, @Nullable FaceEnrollCell cell, int stage, float pan, float tilt, float distance)125 public void onEnrollmentFrame( 126 int helpCode, 127 @Nullable CharSequence helpMessage, 128 @Nullable FaceEnrollCell cell, 129 int stage, 130 float pan, 131 float tilt, 132 float distance) { 133 mCallback.onEnrollmentFrame(helpCode, helpMessage, cell, stage, pan, tilt, distance); 134 } 135 136 @Override onEnrollmentProgress(int remaining)137 public void onEnrollmentProgress(int remaining) { 138 mCallback.onEnrollmentProgress(remaining); 139 if (remaining == 0) { 140 if (Flags.biometricsOnboardingEducation()) { 141 FaceSafetySource.onBiometricsChanged(mContext); 142 } else { 143 BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed 144 } 145 } 146 } 147 } 148 149 /** 150 * Decorator of the {@link FaceManager.RemovalCallback} class that notifies other interested 151 * parties that a face setting has changed. 152 */ 153 private static class NotifyingRemovalCallback extends FaceManager.RemovalCallback { 154 155 private final Context mContext; 156 private final FaceManager.RemovalCallback mCallback; 157 NotifyingRemovalCallback(Context context, FaceManager.RemovalCallback callback)158 NotifyingRemovalCallback(Context context, FaceManager.RemovalCallback callback) { 159 mContext = context; 160 mCallback = callback; 161 } 162 163 @Override onRemovalError(Face fp, int errMsgId, CharSequence errString)164 public void onRemovalError(Face fp, int errMsgId, CharSequence errString) { 165 mCallback.onRemovalError(fp, errMsgId, errString); 166 } 167 168 @Override onRemovalSucceeded(@ullable Face fp, int remaining)169 public void onRemovalSucceeded(@Nullable Face fp, int remaining) { 170 mCallback.onRemovalSucceeded(fp, remaining); 171 if (Flags.biometricsOnboardingEducation()) { 172 FaceSafetySource.onBiometricsChanged(mContext); 173 } else { 174 BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed 175 } 176 } 177 } 178 toFaceEnrollOptions(Intent intent)179 private FaceEnrollOptions toFaceEnrollOptions(Intent intent) { 180 final int reason = intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1); 181 final FaceEnrollOptions.Builder builder = new FaceEnrollOptions.Builder(); 182 builder.setEnrollReason(FaceEnrollOptions.ENROLL_REASON_UNKNOWN); 183 if (reason != -1) { 184 builder.setEnrollReason(reason); 185 } 186 return builder.build(); 187 } 188 } 189