Merge "1/n: Add ClientMonitors for authenticatorId invalidation"

This commit is contained in:
Kevin Chyn
2021-01-10 04:28:24 +00:00
committed by Android (Google) Code Review
36 changed files with 381 additions and 131 deletions

View File

@@ -56,9 +56,9 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I
public AcquisitionClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality,
int statsAction, int statsClient, boolean shouldLogMetrics) {
int statsAction, int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId, statsModality,
statsAction, statsClient, shouldLogMetrics);
statsAction, statsClient);
mPowerManager = context.getSystemService(PowerManager.class);
mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);

View File

@@ -66,8 +66,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient,
true /* shouldLogMetrics */);
statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;

View File

@@ -21,8 +21,10 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
@@ -35,6 +37,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -46,17 +49,16 @@ import java.util.List;
public abstract class BiometricUserState<T extends BiometricAuthenticator.Identifier> {
private static final String TAG = "UserState";
private static final String TAG_INVALIDATION = "authenticatorIdInvalidation_tag";
private static final String ATTR_INVALIDATION = "authenticatorIdInvalidation_attr";
@GuardedBy("this")
protected final ArrayList<T> mBiometrics = new ArrayList<>();
protected boolean mInvalidationInProgress;
protected final Context mContext;
protected final File mFile;
private final Runnable mWriteStateRunnable = new Runnable() {
@Override
public void run() {
doWriteState();
}
};
private final Runnable mWriteStateRunnable = this::doWriteStateInternal;
/**
* @return The tag for the biometrics. There may be multiple instances of a biometric within.
@@ -73,10 +75,40 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi
*/
protected abstract ArrayList<T> getCopy(ArrayList<T> array);
protected abstract void doWriteState(@NonNull TypedXmlSerializer serializer) throws Exception;
/**
* @return Writes the cached data to persistent storage.
* @Writes the cached data to persistent storage.
*/
protected abstract void doWriteState();
private void doWriteStateInternal() {
AtomicFile destination = new AtomicFile(mFile);
FileOutputStream out = null;
try {
out = destination.startWrite();
TypedXmlSerializer serializer = Xml.resolveSerializer(out);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
// Store the authenticatorId
serializer.startTag(null, TAG_INVALIDATION);
serializer.attributeBoolean(null, ATTR_INVALIDATION, mInvalidationInProgress);
serializer.endTag(null, TAG_INVALIDATION);
// Do any additional serialization that subclasses may require
doWriteState(serializer);
serializer.endDocument();
destination.finishWrite(out);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed to write settings, restoring backup", t);
destination.failWrite(out);
throw new IllegalStateException("Failed to write to file: " + mFile.toString(), t);
} finally {
IoUtils.closeQuietly(out);
}
}
/**
* @return
@@ -93,6 +125,19 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi
}
}
public void setInvalidationInProgress(boolean invalidationInProgress) {
synchronized (this) {
mInvalidationInProgress = invalidationInProgress;
scheduleWriteStateLocked();
}
}
public boolean isInvalidationInProgress() {
synchronized (this) {
return mInvalidationInProgress;
}
}
public void addBiometric(T identifier) {
synchronized (this) {
mBiometrics.add(identifier);
@@ -202,6 +247,8 @@ public abstract class BiometricUserState<T extends BiometricAuthenticator.Identi
String tagName = parser.getName();
if (tagName.equals(getBiometricsTag())) {
parseBiometricsLocked(parser);
} else if (tagName.equals(TAG_INVALIDATION)) {
mInvalidationInProgress = parser.getAttributeBoolean(null, ATTR_INVALIDATION);
}
}
}

View File

@@ -31,4 +31,6 @@ public interface BiometricUtils<T extends BiometricAuthenticator.Identifier> {
void removeBiometricForUser(Context context, int userId, int biometricId);
void renameBiometricForUser(Context context, int userId, int biometricId, CharSequence name);
CharSequence getUniqueName(Context context, int userId);
void setInvalidationInProgress(Context context, int userId, boolean inProgress);
boolean isInvalidationInProgress(Context context, int userId);
}

View File

@@ -105,8 +105,8 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde
public ClientMonitor(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
int statsClient, boolean shouldLogMetrics) {
super(statsModality, statsAction, statsClient, shouldLogMetrics);
int statsClient) {
super(statsModality, statsAction, statsClient);
mSequentialId = sCount++;
mContext = context;
mLazyDaemon = lazyDaemon;

View File

@@ -49,10 +49,10 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> {
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
int timeoutSec, int statsModality, int sensorId,
boolean shouldVibrate, boolean shouldLogMetrics) {
boolean shouldVibrate) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
statsModality, BiometricsProtoEnums.ACTION_ENROLL,
BiometricsProtoEnums.CLIENT_UNKNOWN, shouldLogMetrics);
BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricUtils = utils;
mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
mTimeoutSec = timeoutSec;

View File

@@ -32,7 +32,7 @@ public abstract class GenerateChallengeClient<T> extends ClientMonitor<T> {
@NonNull String owner, int sensorId) {
super(context, lazyDaemon, token, listener, 0 /* userId */, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN, true /* shouldLogMetrics */);
BiometricsProtoEnums.CLIENT_UNKNOWN);
}
@Override

View File

@@ -107,8 +107,7 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* ClientMonitorCallbackConverter */,
userId, owner, 0 /* cookie */, sensorId, statsModality,
BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;
mEnrolledList = enrolledList;

View File

@@ -51,7 +51,7 @@ public abstract class InternalEnumerateClient<T> extends ClientMonitor<T>
// is all done internally.
super(context, lazyDaemon, token, null /* ClientMonitorCallbackConverter */, userId, owner,
0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN, true /* shouldLogMetrics */);
BiometricsProtoEnums.CLIENT_UNKNOWN);
mEnrolledList = enrolledList;
mUtils = utils;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricsProtoEnums;
/**
* ClientMonitor subclass for requesting authenticatorId invalidation. See
* {@link InvalidationRequesterClient} for more info.
*/
public abstract class InvalidationClient<S extends BiometricAuthenticator.Identifier, T>
extends ClientMonitor<T> {
private final BiometricUtils<S> mUtils;
public InvalidationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
int userId, int sensorId, @NonNull BiometricUtils<S> utils) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId,
context.getOpPackageName(), 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN);
mUtils = utils;
}
public void onAuthenticatorIdInvalidated(long newAuthenticatorId) {
// TODO: Update framework w/ newAuthenticatorId
mCallback.onClientFinished(this, true /* success */);
}
@Override
public void start(@NonNull Callback callback) {
super.start(callback);
startHalOperation();
}
@Override
public void unableToStart() {
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
/**
* ClientMonitor subclass responsible for coordination of authenticatorId invalidation of other
* sensors. See {@link InvalidationClient} for the ClientMonitor subclass responsible for initiating
* the invalidation with individual HALs. AuthenticatorId invalidation is required on devices with
* multiple strong biometric sensors.
*
* The public Keystore and Biometric APIs are biometric-tied, not modality-tied, meaning that keys
* are unlockable by "any/all strong biometrics on the device", and not "only a specific strong
* sensor". The Keystore API allows for creation of biometric-tied keys that are invalidated upon
* new biometric enrollment. See
* {@link android.security.keystore.KeyGenParameterSpec.Builder#setInvalidatedByBiometricEnrollment}
*
* This has been supported on single-sensor devices by the various getAuthenticatorId APIs on the
* HIDL and AIDL biometric HAL interfaces, where:
* 1) authenticatorId is requested and stored during key generation
* 2) authenticatorId is contained within the HAT when biometric authentication succeeds
* 3) authenticatorId is automatically changed (below the framework) whenever a new biometric
* enrollment occurs.
*
* For multi-biometric devices, this will be done the following way:
* 1) New enrollment added for Sensor1. Sensor1's HAL/TEE updates its authenticatorId automatically
* when enrollment completes
* 2) Framework marks Sensor1 as "invalidationInProgress". See
* {@link BiometricUtils#setInvalidationInProgress(Context, int, boolean)}
* 3) After all other sensors have finished invalidation, the framework will clear the invalidation
* flag for Sensor1.
* 4) New keys that are generated will include all new authenticatorIds
*
* The above is robust to incomplete invalidation. For example, when system boots or after user
* switches, the framework can check if any sensor has the "invalidationInProgress" flag set. If so,
* the framework should re-start the invalidation process described above.
*/
public abstract class InvalidationRequesterClient<T> extends ClientMonitor<T> {
private final BiometricManager mBiometricManager;
public InvalidationRequesterClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
int userId, int sensorId) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId,
context.getOpPackageName(), 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricManager = context.getSystemService(BiometricManager.class);
}
@Override
public void start(@NonNull Callback callback) {
super.start(callback);
// TODO(b/159667191): Request BiometricManager/BiometricService to invalidate
// authenticatorIds. Be sure to invoke BiometricUtils#setInvalidationInProgress(true)
}
@Override
public void unableToStart() {
}
@Override
protected void startHalOperation() {
// No HAL operations necessary
}
}

View File

@@ -38,7 +38,7 @@ public abstract class LoggableMonitor {
private final int mStatsAction;
private final int mStatsClient;
private long mFirstAcquireTimeMs;
private boolean mShouldLogMetrics;
private boolean mShouldLogMetrics = true;
/**
* Only valid for AuthenticationClient.
@@ -52,14 +52,15 @@ public abstract class LoggableMonitor {
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants.
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants.
* @param shouldLogMetrics If set to false, metrics will not be reported to statsd.
*/
public LoggableMonitor(int statsModality, int statsAction, int statsClient,
boolean shouldLogMetrics) {
public LoggableMonitor(int statsModality, int statsAction, int statsClient) {
mStatsModality = statsModality;
mStatsAction = statsAction;
mStatsClient = statsClient;
mShouldLogMetrics = shouldLogMetrics;
}
protected void setShouldLog(boolean shouldLog) {
mShouldLogMetrics = shouldLog;
}
public int getStatsClient() {

View File

@@ -45,7 +45,7 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier,
int sensorId, @NonNull Map<Integer, Long> authenticatorIds, int statsModality) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
statsModality, BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN, true /* shouldLogMetrics */);
BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricId = biometricId;
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;

View File

@@ -27,8 +27,7 @@ public abstract class RevokeChallengeClient<T> extends ClientMonitor<T> {
@NonNull IBinder token, @NonNull String owner, int sensorId) {
super(context, lazyDaemon, token, null /* listener */, 0 /* userId */, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
}
@Override

View File

@@ -16,23 +16,18 @@
package com.android.server.biometrics.sensors.face;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.face.Face;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.server.biometrics.sensors.BiometricUserState;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -75,46 +70,26 @@ public class FaceUserState extends BiometricUserState<Face> {
}
@Override
protected void doWriteState() {
AtomicFile destination = new AtomicFile(mFile);
ArrayList<Face> faces;
protected void doWriteState(@NonNull TypedXmlSerializer serializer) throws Exception {
final ArrayList<Face> faces;
synchronized (this) {
faces = getCopy(mBiometrics);
}
FileOutputStream out = null;
try {
out = destination.startWrite();
serializer.startTag(null, TAG_FACES);
TypedXmlSerializer serializer = Xml.resolveSerializer(out);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
serializer.startTag(null, TAG_FACES);
final int count = faces.size();
for (int i = 0; i < count; i++) {
Face f = faces.get(i);
serializer.startTag(null, TAG_FACE);
serializer.attributeInt(null, ATTR_FACE_ID, f.getBiometricId());
serializer.attribute(null, ATTR_NAME, f.getName().toString());
serializer.attributeLong(null, ATTR_DEVICE_ID, f.getDeviceId());
serializer.endTag(null, TAG_FACE);
}
serializer.endTag(null, TAG_FACES);
serializer.endDocument();
destination.finishWrite(out);
// Any error while writing is fatal.
} catch (Throwable t) {
Slog.wtf(TAG, "Failed to write settings, restoring backup", t);
destination.failWrite(out);
throw new IllegalStateException("Failed to write faces", t);
} finally {
IoUtils.closeQuietly(out);
final int count = faces.size();
for (int i = 0; i < count; i++) {
Face f = faces.get(i);
serializer.startTag(null, TAG_FACE);
serializer.attributeInt(null, ATTR_FACE_ID, f.getBiometricId());
serializer.attribute(null, ATTR_NAME, f.getName().toString());
serializer.attributeLong(null, ATTR_DEVICE_ID, f.getDeviceId());
serializer.endTag(null, TAG_FACE);
}
serializer.endTag(null, TAG_FACES);
}
@GuardedBy("this")

View File

@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.face.Face;
import android.text.TextUtils;
import android.util.SparseArray;
@@ -115,6 +114,16 @@ public class FaceUtils implements BiometricUtils<Face> {
return getStateForUser(context, userId).getUniqueName();
}
@Override
public void setInvalidationInProgress(Context context, int userId, boolean inProgress) {
getStateForUser(context, userId).setInvalidationInProgress(inProgress);
}
@Override
public boolean isInvalidationInProgress(Context context, int userId) {
return getStateForUser(context, userId).isInvalidationInProgress();
}
private FaceUserState getStateForUser(Context ctx, int userId) {
synchronized (this) {
FaceUserState state = mUserStates.get(userId);

View File

@@ -62,7 +62,7 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
@Nullable NativeHandle previewSurface, int sensorId, int maxTemplatesPerUser) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */, true /* shouldLogMetrics */);
false /* shouldVibrate */);
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
mEnrollIgnoreListVendor = getContext().getResources()

View File

@@ -38,8 +38,7 @@ class FaceGetAuthenticatorIdClient extends ClientMonitor<ISession> {
Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, opPackageName,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FACE,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mAuthenticatorIds = authenticatorIds;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face.aidl;
import android.content.Context;
import android.hardware.biometrics.face.ISession;
import android.annotation.NonNull;
import android.hardware.face.Face;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.InvalidationClient;
import com.android.server.biometrics.sensors.face.FaceUtils;
public class FaceInvalidationClient extends InvalidationClient<Face, ISession> {
private static final String TAG = "FaceInvalidationClient";
public FaceInvalidationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, int sensorId,
@NonNull FaceUtils utils) {
super(context, lazyDaemon, userId, sensorId, utils);
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().invalidateAuthenticatorId(mSequentialId);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
mCallback.onClientFinished(this, false /* success */);
}
}
}

View File

@@ -50,8 +50,7 @@ public class FaceResetLockoutClient extends ClientMonitor<ISession> {
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
mLockoutCache = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;

View File

@@ -59,7 +59,7 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
@Nullable NativeHandle surfaceHandle, int sensorId) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */, true /* shouldLogMetrics */);
false /* shouldVibrate */);
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
mSurfaceHandle = surfaceHandle;
mEnrollIgnoreList = getContext().getResources()

View File

@@ -47,7 +47,7 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
@NonNull String owner, int sensorId, int feature, int faceId) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN, true /* shouldLogMetrics */);
BiometricsProtoEnums.CLIENT_UNKNOWN);
mFeature = feature;
mFaceId = faceId;

View File

@@ -42,8 +42,7 @@ public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> {
@NonNull byte[] hardwareAuthToken) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mHardwareAuthToken = new ArrayList<>();
for (byte b : hardwareAuthToken) {

View File

@@ -49,7 +49,7 @@ public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> {
byte[] hardwareAuthToken, int faceId) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN, true /* shouldLogMetrics */);
BiometricsProtoEnums.CLIENT_UNKNOWN);
mFeature = feature;
mEnabled = enabled;
mFaceId = faceId;

View File

@@ -43,8 +43,7 @@ public class FaceUpdateActiveUserClient extends ClientMonitor<IBiometricsFace> {
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mCurrentUserId = currentUserId;
mHasEnrolledBiometrics = hasEnrolledBIometrics;
mAuthenticatorIds = authenticatorIds;

View File

@@ -16,23 +16,18 @@
package com.android.server.biometrics.sensors.fingerprint;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.fingerprint.Fingerprint;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.server.biometrics.sensors.BiometricUserState;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -76,47 +71,27 @@ public class FingerprintUserState extends BiometricUserState<Fingerprint> {
}
@Override
protected void doWriteState() {
AtomicFile destination = new AtomicFile(mFile);
ArrayList<Fingerprint> fingerprints;
protected void doWriteState(@NonNull TypedXmlSerializer serializer) throws Exception {
final ArrayList<Fingerprint> fingerprints;
synchronized (this) {
fingerprints = getCopy(mBiometrics);
}
FileOutputStream out = null;
try {
out = destination.startWrite();
serializer.startTag(null, TAG_FINGERPRINTS);
TypedXmlSerializer serializer = Xml.resolveSerializer(out);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
serializer.startTag(null, TAG_FINGERPRINTS);
final int count = fingerprints.size();
for (int i = 0; i < count; i++) {
Fingerprint fp = fingerprints.get(i);
serializer.startTag(null, TAG_FINGERPRINT);
serializer.attributeInt(null, ATTR_FINGER_ID, fp.getBiometricId());
serializer.attribute(null, ATTR_NAME, fp.getName().toString());
serializer.attributeInt(null, ATTR_GROUP_ID, fp.getGroupId());
serializer.attributeLong(null, ATTR_DEVICE_ID, fp.getDeviceId());
serializer.endTag(null, TAG_FINGERPRINT);
}
serializer.endTag(null, TAG_FINGERPRINTS);
serializer.endDocument();
destination.finishWrite(out);
// Any error while writing is fatal.
} catch (Throwable t) {
Slog.wtf(TAG, "Failed to write settings, restoring backup", t);
destination.failWrite(out);
throw new IllegalStateException("Failed to write fingerprints", t);
} finally {
IoUtils.closeQuietly(out);
final int count = fingerprints.size();
for (int i = 0; i < count; i++) {
Fingerprint fp = fingerprints.get(i);
serializer.startTag(null, TAG_FINGERPRINT);
serializer.attributeInt(null, ATTR_FINGER_ID, fp.getBiometricId());
serializer.attribute(null, ATTR_NAME, fp.getName().toString());
serializer.attributeInt(null, ATTR_GROUP_ID, fp.getGroupId());
serializer.attributeLong(null, ATTR_DEVICE_ID, fp.getDeviceId());
serializer.endTag(null, TAG_FINGERPRINT);
}
serializer.endTag(null, TAG_FINGERPRINTS);
}
@GuardedBy("this")

View File

@@ -118,6 +118,16 @@ public class FingerprintUtils implements BiometricUtils<Fingerprint> {
return getStateForUser(context, userId).getUniqueName();
}
@Override
public void setInvalidationInProgress(Context context, int userId, boolean inProgress) {
getStateForUser(context, userId).setInvalidationInProgress(inProgress);
}
@Override
public boolean isInvalidationInProgress(Context context, int userId) {
return getStateForUser(context, userId).isInvalidationInProgress();
}
private FingerprintUserState getStateForUser(Context ctx, int userId) {
synchronized (this) {
FingerprintUserState state = mUserStates.get(userId);

View File

@@ -51,7 +51,7 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE,
statsClient, true /* shouldLogMetrics */);
statsClient);
mIsStrongBiometric = isStrongBiometric;
mUdfpsOverlayController = udfpsOverlayController;
}

View File

@@ -55,9 +55,10 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
boolean shouldLogMetrics) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
true /* shouldVibrate */, shouldLogMetrics);
true /* shouldVibrate */);
mUdfpsOverlayController = udfpsOvelayController;
mMaxTemplatesPerUser = maxTemplatesPerUser;
setShouldLog(shouldLogMetrics);
}
@Override

View File

@@ -38,8 +38,7 @@ class FingerprintGetAuthenticatorIdClient extends ClientMonitor<ISession> {
int sensorId, Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FINGERPRINT,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mAuthenticatorIds = authenticatorIds;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.fingerprint.Fingerprint;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.InvalidationClient;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
public class FingerprintInvalidationClient extends InvalidationClient<Fingerprint, ISession> {
private static final String TAG = "FingerprintInvalidationClient";
public FingerprintInvalidationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, int sensorId,
@NonNull FingerprintUtils utils) {
super(context, lazyDaemon, userId, sensorId, utils);
}
@Override
protected void startHalOperation() {
try {
getFreshDaemon().invalidateAuthenticatorId(mSequentialId);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
mCallback.onClientFinished(this, false /* success */);
}
}
}

View File

@@ -50,8 +50,7 @@ class FingerprintResetLockoutClient extends ClientMonitor<ISession> {
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
mLockoutCache = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;

View File

@@ -56,7 +56,7 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
boolean isStrongBiometric, int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_FINGERPRINT, BiometricsProtoEnums.ACTION_AUTHENTICATE,
statsClient, true /* shouldLogMetrics */);
statsClient);
mUdfpsOverlayController = udfpsOverlayController;
mIsStrongBiometric = isStrongBiometric;
}

View File

@@ -56,8 +56,9 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
boolean shouldLogMetrics) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
true /* shouldVibrate */, shouldLogMetrics);
true /* shouldVibrate */);
mUdfpsOverlayController = udfpsOverlayController;
setShouldLog(shouldLogMetrics);
}
@Override

View File

@@ -50,8 +50,7 @@ public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometrics
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN,
true /* shouldLogMetrics */);
BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
mCurrentUserId = currentUserId;
mHasEnrolledBiometrics = hasEnrolledBiometrics;
mAuthenticatorIds = authenticatorIds;

View File

@@ -218,7 +218,7 @@ public class BiometricSchedulerTest {
@NonNull LazyDaemon<Object> lazyDaemon, int cookie) {
super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */,
TAG, cookie, TEST_SENSOR_ID, 0 /* statsModality */,
0 /* statsAction */, 0 /* statsClient */, true /* shouldLogMetrics */);
0 /* statsAction */, 0 /* statsClient */);
}