blob: 882a9297847ab701b208cb4ec02831e3de73e1fd [file] [log] [blame]
Kevin Chyn037c4d52018-06-11 19:17:32 -07001/*
2 * Copyright (C) 2018 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
Kevin Chyn836f2cf2018-08-27 11:06:39 -070017package com.android.server.biometrics;
Kevin Chyn037c4d52018-06-11 19:17:32 -070018
19import android.content.Context;
Kevin Chyna56dff72018-06-19 18:41:12 -070020import android.hardware.biometrics.BiometricAuthenticator;
Kevin Chyn037c4d52018-06-11 19:17:32 -070021import android.hardware.biometrics.BiometricConstants;
Kevin Chyn7782d142019-01-18 12:51:33 -080022import android.hardware.biometrics.BiometricsProtoEnums;
Kevin Chyn037c4d52018-06-11 19:17:32 -070023import android.os.IBinder;
24import android.os.RemoteException;
25import android.util.Slog;
26
Kevin Chyn6cf54e82018-09-18 19:13:27 -070027import java.util.ArrayList;
Kevin Chyn037c4d52018-06-11 19:17:32 -070028import java.util.Arrays;
29
30/**
31 * A class to keep track of the enrollment state for a given client.
32 */
33public abstract class EnrollClient extends ClientMonitor {
34 private static final long MS_PER_SEC = 1000;
35 private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
Kevin Chyna56dff72018-06-19 18:41:12 -070036 private final byte[] mCryptoToken;
37 private final BiometricUtils mBiometricUtils;
Kevin Chyn1f16c2d2018-12-07 13:06:08 -080038 private final int[] mDisabledFeatures;
Kevin Chyn037c4d52018-06-11 19:17:32 -070039
Kevin Chyn1429a312019-01-28 16:08:09 -080040 public abstract boolean shouldVibrate();
41
Kevin Chyn355c6bf2018-09-20 22:14:19 -070042 public EnrollClient(Context context, Metrics metrics,
43 BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
44 BiometricServiceBase.ServiceListener listener, int userId, int groupId,
Kevin Chyn1f16c2d2018-12-07 13:06:08 -080045 byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils,
46 final int[] disabledFeatures) {
Kevin Chyn037c4d52018-06-11 19:17:32 -070047 super(context, metrics, daemon, halDeviceId, token, listener, userId, groupId, restricted,
Kevin Chyn87f257a2018-11-27 16:26:07 -080048 owner, 0 /* cookie */);
Kevin Chyna56dff72018-06-19 18:41:12 -070049 mBiometricUtils = utils;
Kevin Chyn037c4d52018-06-11 19:17:32 -070050 mCryptoToken = Arrays.copyOf(cryptoToken, cryptoToken.length);
Kevin Chyn1f16c2d2018-12-07 13:06:08 -080051 mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
Kevin Chyn037c4d52018-06-11 19:17:32 -070052 }
53
54 @Override
Kevin Chyn7782d142019-01-18 12:51:33 -080055 protected int statsAction() {
56 return BiometricsProtoEnums.ACTION_ENROLL;
57 }
58
59 @Override
Kevin Chyna56dff72018-06-19 18:41:12 -070060 public boolean onEnrollResult(BiometricAuthenticator.Identifier identifier,
61 int remaining) {
Kevin Chyn037c4d52018-06-11 19:17:32 -070062 if (remaining == 0) {
Kevin Chyna56dff72018-06-19 18:41:12 -070063 mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(), identifier);
Kevin Chyn037c4d52018-06-11 19:17:32 -070064 }
Kevin Chyn03089b02019-01-31 12:37:21 -080065 notifyUserActivity();
Kevin Chyna56dff72018-06-19 18:41:12 -070066 return sendEnrollResult(identifier, remaining);
Kevin Chyn037c4d52018-06-11 19:17:32 -070067 }
68
69 /*
70 * @return true if we're done.
71 */
Kevin Chyna56dff72018-06-19 18:41:12 -070072 private boolean sendEnrollResult(BiometricAuthenticator.Identifier identifier,
73 int remaining) {
Kevin Chyn1429a312019-01-28 16:08:09 -080074 if (shouldVibrate()) {
75 vibrateSuccess();
76 }
Kevin Chyn037c4d52018-06-11 19:17:32 -070077 mMetricsLogger.action(mMetrics.actionBiometricEnroll());
78 try {
Kevin Chyna56dff72018-06-19 18:41:12 -070079 getListener().onEnrollResult(identifier, remaining);
Kevin Chyn037c4d52018-06-11 19:17:32 -070080 return remaining == 0;
81 } catch (RemoteException e) {
82 Slog.w(getLogTag(), "Failed to notify EnrollResult:", e);
83 return true;
84 }
85 }
86
87 @Override
88 public int start() {
89 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
90 try {
Kevin Chyn1f16c2d2018-12-07 13:06:08 -080091 final ArrayList<Integer> disabledFeatures = new ArrayList<>();
92 for (int i = 0; i < mDisabledFeatures.length; i++) {
93 disabledFeatures.add(mDisabledFeatures[i]);
94 }
95
96 final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), timeout,
97 disabledFeatures);
Kevin Chyn037c4d52018-06-11 19:17:32 -070098 if (result != 0) {
99 Slog.w(getLogTag(), "startEnroll failed, result=" + result);
100 mMetricsLogger.histogram(mMetrics.tagEnrollStartError(), result);
Kevin Chyna56dff72018-06-19 18:41:12 -0700101 onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
102 0 /* vendorCode */);
Kevin Chyn037c4d52018-06-11 19:17:32 -0700103 return result;
104 }
105 } catch (RemoteException e) {
106 Slog.e(getLogTag(), "startEnroll failed", e);
107 }
108 return 0; // success
109 }
110
111 @Override
112 public int stop(boolean initiatedByClient) {
113 if (mAlreadyCancelled) {
114 Slog.w(getLogTag(), "stopEnroll: already cancelled!");
115 return 0;
116 }
117
118 try {
119 final int result = getDaemonWrapper().cancel();
120 if (result != 0) {
121 Slog.w(getLogTag(), "startEnrollCancel failed, result = " + result);
122 return result;
123 }
124 } catch (RemoteException e) {
125 Slog.e(getLogTag(), "stopEnrollment failed", e);
126 }
127 if (initiatedByClient) {
Kevin Chyna56dff72018-06-19 18:41:12 -0700128 onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_CANCELED,
129 0 /* vendorCode */);
Kevin Chyn037c4d52018-06-11 19:17:32 -0700130 }
131 mAlreadyCancelled = true;
132 return 0;
133 }
134
135 @Override
Kevin Chyna56dff72018-06-19 18:41:12 -0700136 public boolean onRemoved(BiometricAuthenticator.Identifier identifier, int remaining) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700137 if (DEBUG) Slog.w(getLogTag(), "onRemoved() called for enroll!");
138 return true; // Invalid for EnrollClient
139 }
140
141 @Override
Kevin Chyna56dff72018-06-19 18:41:12 -0700142 public boolean onEnumerationResult(BiometricAuthenticator.Identifier identifier,
143 int remaining) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700144 if (DEBUG) Slog.w(getLogTag(), "onEnumerationResult() called for enroll!");
145 return true; // Invalid for EnrollClient
146 }
147
148 @Override
Kevin Chynb528d692018-07-20 11:53:14 -0700149 public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
Kevin Chyn6cf54e82018-09-18 19:13:27 -0700150 boolean authenticated, ArrayList<Byte> token) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700151 if (DEBUG) Slog.w(getLogTag(), "onAuthenticated() called for enroll!");
152 return true; // Invalid for EnrollClient
153 }
154
155}