| /* |
| * 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; |
| } |
| } |
| } |
| |