blob: 0062d31962a9fd724439ad92990caa79e0ae480d [file] [log] [blame]
/*
* Copyright (C) 2020 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;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMAGER_DIRTY;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_INSUFFICIENT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_PARTIAL;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_BRIGHT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_FAST;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_SLOW;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.fingerprint.V2_1.FingerprintError;
import android.hardware.fingerprint.Fingerprint;
import android.text.TextUtils;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.biometrics.sensors.BiometricUtils;
import java.util.List;
/**
* Utility class for dealing with fingerprints and fingerprint settings.
*/
public class FingerprintUtils implements BiometricUtils<Fingerprint> {
private static final Object sInstanceLock = new Object();
// Map<SensorId, FingerprintUtils>
private static SparseArray<FingerprintUtils> sInstances;
private static final String LEGACY_FINGERPRINT_FILE = "settings_fingerprint.xml";
@GuardedBy("this")
private final SparseArray<FingerprintUserState> mUserStates;
private final String mFileName;
/**
* Retrieves an instance for the specified sensorId.
*/
public static FingerprintUtils getInstance(int sensorId) {
// Specify a null fileName to use an auto-generated sensorId-specific filename.
return getInstance(sensorId, null /* fileName */);
}
/**
* Retrieves an instance for the specified sensorId. If the fileName is null, a default
* filename (e.g. settings_fingerprint_<sensorId>.xml will be generated.
*
* Specifying an explicit fileName allows for backward compatibility with legacy devices,
* where everything is stored in settings_fingerprint.xml.
*/
private static FingerprintUtils getInstance(int sensorId, @Nullable String fileName) {
final FingerprintUtils utils;
synchronized (sInstanceLock) {
if (sInstances == null) {
sInstances = new SparseArray<>();
}
if (sInstances.get(sensorId) == null) {
if (fileName == null) {
fileName = "settings_fingerprint_" + sensorId + ".xml";
}
sInstances.put(sensorId, new FingerprintUtils(fileName));
}
utils = sInstances.get(sensorId);
}
return utils;
}
/**
* Legacy getter for {@link android.hardware.biometrics.fingerprint.V2_1} ands its extended
* subclasses. Framework-side cache is always stored in the same file, regardless of sensorId.
*/
public static FingerprintUtils getLegacyInstance(int sensorId) {
// Note that sensorId for legacy services can be hard-coded to 0 since it's only used
// to index into the sensor states map.
return getInstance(sensorId, LEGACY_FINGERPRINT_FILE);
}
private FingerprintUtils(String fileName) {
mUserStates = new SparseArray<>();
mFileName = fileName;
}
@Override
public List<Fingerprint> getBiometricsForUser(Context ctx, int userId) {
return getStateForUser(ctx, userId).getBiometrics();
}
@Override
public void addBiometricForUser(Context context, int userId, Fingerprint fingerprint) {
getStateForUser(context, userId).addBiometric(fingerprint);
}
@Override
public void removeBiometricForUser(Context context, int userId, int fingerId) {
getStateForUser(context, userId).removeBiometric(fingerId);
}
@Override
public void renameBiometricForUser(Context context, int userId, int fingerId,
CharSequence name) {
if (TextUtils.isEmpty(name)) {
// Don't do the rename if it's empty
return;
}
getStateForUser(context, userId).renameBiometric(fingerId, name);
}
@Override
public CharSequence getUniqueName(Context context, int userId) {
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);
if (state == null) {
state = new FingerprintUserState(ctx, userId, mFileName);
mUserStates.put(userId, state);
}
return state;
}
}
/**
* Checks if the given error code corresponds to a known fingerprint error.
*
* @param errorCode The error code to be checked.
* @return Whether the error code corresponds to a known error.
*/
public static boolean isKnownErrorCode(int errorCode) {
switch (errorCode) {
case FingerprintError.ERROR_HW_UNAVAILABLE:
case FingerprintError.ERROR_UNABLE_TO_PROCESS:
case FingerprintError.ERROR_TIMEOUT:
case FingerprintError.ERROR_NO_SPACE:
case FingerprintError.ERROR_CANCELED:
case FingerprintError.ERROR_UNABLE_TO_REMOVE:
case FingerprintError.ERROR_LOCKOUT:
case FingerprintError.ERROR_VENDOR:
return true;
default:
return false;
}
}
/**
* Checks if the given acquired code corresponds to a known fingerprint error.
*
* @param acquiredCode The acquired code to be checked.
* @return Whether the acquired code corresponds to a known error.
*/
public static boolean isKnownAcquiredCode(int acquiredCode) {
switch (acquiredCode) {
case FINGERPRINT_ACQUIRED_GOOD:
case FINGERPRINT_ACQUIRED_PARTIAL:
case FINGERPRINT_ACQUIRED_INSUFFICIENT:
case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
case FINGERPRINT_ACQUIRED_TOO_SLOW:
case FINGERPRINT_ACQUIRED_TOO_FAST:
case FINGERPRINT_ACQUIRED_VENDOR:
case FINGERPRINT_ACQUIRED_START:
case FINGERPRINT_ACQUIRED_TOO_BRIGHT:
case FINGERPRINT_ACQUIRED_IMMOBILE:
return true;
default:
return false;
}
}
}