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.safetycenter.BiometricsSafetySource;
33 
34 /**
35  * Responsible for making {@link FaceManager#enroll} and {@link FaceManager#remove} calls and thus
36  * updating the face setting.
37  */
38 public class FaceUpdater {
39 
40     private final Context mContext;
41     private final FaceManager mFaceManager;
42 
FaceUpdater(Context context)43     public FaceUpdater(Context context) {
44         mContext = context;
45         mFaceManager = Utils.getFaceManagerOrNull(context);
46     }
47 
FaceUpdater(Context context, FaceManager faceManager)48     public FaceUpdater(Context context, FaceManager faceManager) {
49         mContext = context;
50         mFaceManager = faceManager;
51     }
52 
53     /** Wrapper around the {@link FaceManager#enroll} method. */
enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel, FaceManager.EnrollmentCallback callback, int[] disabledFeatures, Intent intent)54     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
55             FaceManager.EnrollmentCallback callback, int[] disabledFeatures, Intent intent) {
56         this.enroll(userId, hardwareAuthToken, cancel,
57                 new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures,
58                 null, false, intent);
59     }
60 
61     /** 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)62     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
63             FaceManager.EnrollmentCallback callback, int[] disabledFeatures,
64             @Nullable Surface previewSurface, boolean debugConsent, Intent intent) {
65         mFaceManager.enroll(userId, hardwareAuthToken, cancel,
66                 new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures,
67                 previewSurface, debugConsent, toFaceEnrollOptions(intent));
68     }
69 
70     /** Wrapper around the {@link FaceManager#remove} method. */
remove(Face face, int userId, FaceManager.RemovalCallback callback)71     public void remove(Face face, int userId, FaceManager.RemovalCallback callback) {
72         mFaceManager.remove(face, userId, new NotifyingRemovalCallback(mContext, callback));
73     }
74 
75     /**
76      * Decorator of the {@link FaceManager.EnrollmentCallback} class that notifies other
77      * interested parties that a face setting has changed.
78      */
79     private static class NotifyingEnrollmentCallback
80             extends FaceManager.EnrollmentCallback {
81 
82         private final Context mContext;
83         private final FaceManager.EnrollmentCallback mCallback;
84 
NotifyingEnrollmentCallback(Context context, FaceManager.EnrollmentCallback callback)85         NotifyingEnrollmentCallback(Context context,
86                 FaceManager.EnrollmentCallback callback) {
87             mContext = context;
88             mCallback = callback;
89         }
90 
91         @Override
onEnrollmentError(int errMsgId, CharSequence errString)92         public void onEnrollmentError(int errMsgId, CharSequence errString) {
93             mCallback.onEnrollmentError(errMsgId, errString);
94         }
95 
96         @Override
onEnrollmentHelp(int helpMsgId, CharSequence helpString)97         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
98             mCallback.onEnrollmentHelp(helpMsgId, helpString);
99         }
100 
101         @Override
onEnrollmentFrame(int helpCode, @Nullable CharSequence helpMessage, @Nullable FaceEnrollCell cell, int stage, float pan, float tilt, float distance)102         public void onEnrollmentFrame(int helpCode, @Nullable CharSequence helpMessage,
103                 @Nullable FaceEnrollCell cell, int stage, float pan, float tilt, float distance) {
104             mCallback.onEnrollmentFrame(helpCode, helpMessage, cell, stage, pan, tilt, distance);
105         }
106 
107         @Override
onEnrollmentProgress(int remaining)108         public void onEnrollmentProgress(int remaining) {
109             mCallback.onEnrollmentProgress(remaining);
110             if (remaining == 0) {
111                 BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed
112             }
113         }
114     }
115 
116     /**
117      * Decorator of the {@link FaceManager.RemovalCallback} class that notifies other
118      * interested parties that a face setting has changed.
119      */
120     private static class NotifyingRemovalCallback extends FaceManager.RemovalCallback {
121 
122         private final Context mContext;
123         private final FaceManager.RemovalCallback mCallback;
124 
NotifyingRemovalCallback(Context context, FaceManager.RemovalCallback callback)125         NotifyingRemovalCallback(Context context, FaceManager.RemovalCallback callback) {
126             mContext = context;
127             mCallback = callback;
128         }
129 
130         @Override
onRemovalError(Face fp, int errMsgId, CharSequence errString)131         public void onRemovalError(Face fp, int errMsgId, CharSequence errString) {
132             mCallback.onRemovalError(fp, errMsgId, errString);
133         }
134 
135         @Override
onRemovalSucceeded(@ullable Face fp, int remaining)136         public void onRemovalSucceeded(@Nullable Face fp, int remaining) {
137             mCallback.onRemovalSucceeded(fp, remaining);
138             BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed
139         }
140     }
141 
toFaceEnrollOptions(Intent intent)142     private FaceEnrollOptions toFaceEnrollOptions(Intent intent) {
143         final int reason = intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1);
144         final FaceEnrollOptions.Builder builder = new FaceEnrollOptions.Builder();
145         builder.setEnrollReason(FaceEnrollOptions.ENROLL_REASON_UNKNOWN);
146         if (reason != -1) {
147             builder.setEnrollReason(reason);
148         }
149         return builder.build();
150     }
151 }
152