blob: c5744780cd71eff29740574c7e83ba39811f52e3 [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.face;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.face.Face;
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 faces and face settings.
*/
public class FaceUtils implements BiometricUtils<Face> {
private static final Object sInstanceLock = new Object();
// Map<SensorId, FaceUtils>
private static SparseArray<FaceUtils> sInstances;
private static final String LEGACY_FACE_FILE = "settings_face.xml";
@GuardedBy("this")
private final SparseArray<FaceUserState> mUserStates;
private final String mFileName;
public static FaceUtils 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_face_<sensorId>.xml will be generated.
*
* Specifying an explicit fileName allows for backward compatibility with legacy devices,
* where everything is stored in settings_face.xml.
*/
private static FaceUtils getInstance(int sensorId, @Nullable String fileName) {
final FaceUtils utils;
synchronized (sInstanceLock) {
if (sInstances == null) {
sInstances = new SparseArray<>();
}
if (sInstances.get(sensorId) == null) {
if (fileName == null) {
fileName = "settings_face_" + sensorId + ".xml";
}
sInstances.put(sensorId, new FaceUtils(fileName));
}
utils = sInstances.get(sensorId);
}
return utils;
}
/**
* Legacy getter for {@link android.hardware.biometrics.face.V1_0} and its extended subclasses.
* Framework-side cache is always stored in the same file, regardless of sensorId.
*/
public static FaceUtils 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_FACE_FILE);
}
private FaceUtils(String fileName) {
mUserStates = new SparseArray<>();
mFileName = fileName;
}
@Override
public List<Face> getBiometricsForUser(Context ctx, int userId) {
return getStateForUser(ctx, userId).getBiometrics();
}
@Override
public void addBiometricForUser(Context ctx, int userId, Face face) {
getStateForUser(ctx, userId).addBiometric(face);
}
@Override
public void removeBiometricForUser(Context ctx, int userId, int faceId) {
getStateForUser(ctx, userId).removeBiometric(faceId);
}
@Override
public void renameBiometricForUser(Context ctx, int userId, int faceId, CharSequence name) {
if (TextUtils.isEmpty(name)) {
// Don't do the rename if it's empty
return;
}
getStateForUser(ctx, userId).renameBiometric(faceId, 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 FaceUserState getStateForUser(Context ctx, int userId) {
synchronized (this) {
FaceUserState state = mUserStates.get(userId);
if (state == null) {
state = new FaceUserState(ctx, userId, mFileName);
mUserStates.put(userId, state);
}
return state;
}
}
}