Move the face HIDL code under the hidl package

Bug: 171335732
Test: atest com.android.server.biometrics
Test: face unlock works on device
Change-Id: I485d728583562a64987a876f2f8e058e53c30c73
This commit is contained in:
Ilya Matyukhin
2020-11-05 14:11:58 -08:00
parent 54c1598b59
commit 92de384c71
15 changed files with 182 additions and 168 deletions

View File

@@ -66,7 +66,7 @@ public class FaceService extends SystemService {
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final LockPatternUtils mLockPatternUtils;
@NonNull
private List<ServiceProvider> mServiceProviders;
private final List<ServiceProvider> mServiceProviders;
@Nullable
private ServiceProvider getProviderForSensor(int sensorId) {
@@ -498,7 +498,8 @@ public class FaceService extends SystemService {
@BiometricManager.Authenticators.Types int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
mServiceProviders.add(
new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher));
new com.android.server.biometrics.sensors.face.hidl.Face10(getContext(),
sensorId, strength, mLockoutResetDispatcher));
}
}

View File

@@ -28,7 +28,7 @@ import java.util.ArrayDeque;
* Keep a short historical buffer of stats, with an aggregated usage time.
*/
class UsageStats {
public class UsageStats {
private static final int EVENT_LOG_SIZE = 100;
/**
@@ -44,7 +44,7 @@ class UsageStats {
private int mVendorError;
private int mUser;
AuthenticationEvent(long startTime, long latency, boolean authenticated, int error,
public AuthenticationEvent(long startTime, long latency, boolean authenticated, int error,
int vendorError, int user) {
mStartTime = startTime;
mLatency = latency;
@@ -76,14 +76,14 @@ class UsageStats {
private long mRejectLatency;
private SparseLongArray mErrorLatency;
UsageStats(Context context) {
public UsageStats(Context context) {
mAuthenticationEvents = new ArrayDeque<>();
mErrorCount = new SparseIntArray();
mErrorLatency = new SparseLongArray();
mContext = context;
}
void addEvent(AuthenticationEvent event) {
public void addEvent(AuthenticationEvent event) {
if (mAuthenticationEvents.size() >= EVENT_LOG_SIZE) {
mAuthenticationEvents.removeFirst();
}
@@ -101,7 +101,7 @@ class UsageStats {
}
}
void print(PrintWriter pw) {
public void print(PrintWriter pw) {
pw.println("Events since last reboot: " + mAuthenticationEvents.size());
for (AuthenticationEvent event : mAuthenticationEvents) {
pw.println(event.toString(mContext));

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -63,6 +63,10 @@ import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.RemovalConsumer;
import com.android.server.biometrics.sensors.face.FaceUtils;
import com.android.server.biometrics.sensors.face.LockoutHalImpl;
import com.android.server.biometrics.sensors.face.ServiceProvider;
import com.android.server.biometrics.sensors.face.UsageStats;
import org.json.JSONArray;
import org.json.JSONException;
@@ -82,7 +86,7 @@ import java.util.Map;
* Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or
* its extended minor versions.
*/
class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
private static final String TAG = "Face10";
private static final int ENROLL_TIMEOUT_SEC = 75;
@@ -120,166 +124,175 @@ class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
private final IBiometricsFaceClientCallback mDaemonCallback =
new IBiometricsFaceClientCallback.Stub() {
@Override
public void onEnrollResult(long deviceId, int faceId, int userId, int remaining) {
mHandler.post(() -> {
final CharSequence name = FaceUtils.getInstance()
.getUniqueName(mContext, userId);
final Face face = new Face(name, faceId, deviceId);
@Override
public void onEnrollResult(long deviceId, int faceId, int userId, int remaining) {
mHandler.post(() -> {
final CharSequence name = FaceUtils.getInstance()
.getUniqueName(mContext, userId);
final Face face = new Face(name, faceId, deviceId);
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof FaceEnrollClient)) {
Slog.e(TAG, "onEnrollResult for non-enroll client: "
+ Utils.getClientName(client));
return;
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof FaceEnrollClient)) {
Slog.e(TAG, "onEnrollResult for non-enroll client: "
+ Utils.getClientName(client));
return;
}
final FaceEnrollClient enrollClient = (FaceEnrollClient) client;
enrollClient.onEnrollResult(face, remaining);
});
}
final FaceEnrollClient enrollClient = (FaceEnrollClient) client;
enrollClient.onEnrollResult(face, remaining);
});
}
@Override
public void onAuthenticated(long deviceId, int faceId, int userId,
ArrayList<Byte> token) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
return;
}
@Override
public void onAuthenticated(long deviceId, int faceId, int userId, ArrayList<Byte> token) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
return;
final AuthenticationConsumer authenticationConsumer =
(AuthenticationConsumer) client;
final boolean authenticated = faceId != 0;
final Face face = new Face("", faceId, deviceId);
authenticationConsumer.onAuthenticated(face, authenticated, token);
});
}
final AuthenticationConsumer authenticationConsumer =
(AuthenticationConsumer) client;
final boolean authenticated = faceId != 0;
final Face face = new Face("", faceId, deviceId);
authenticationConsumer.onAuthenticated(face, authenticated, token);
});
}
@Override
public void onAcquired(long deviceId, int userId, int acquiredInfo,
int vendorCode) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(TAG, "onAcquired for non-acquire client: "
+ Utils.getClientName(client));
return;
}
@Override
public void onAcquired(long deviceId, int userId, int acquiredInfo, int vendorCode) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(TAG, "onAcquired for non-acquire client: "
+ Utils.getClientName(client));
return;
final AcquisitionClient<?> acquisitionClient =
(AcquisitionClient<?>) client;
acquisitionClient.onAcquired(acquiredInfo, vendorCode);
});
}
final AcquisitionClient<?> acquisitionClient = (AcquisitionClient<?>) client;
acquisitionClient.onAcquired(acquiredInfo, vendorCode);
});
}
@Override
public void onError(long deviceId, int userId, int error, int vendorCode) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
+ ", client: " + (client != null ? client.getOwnerString() : null)
+ ", error: " + error
+ ", vendorCode: " + vendorCode);
if (!(client instanceof Interruptable)) {
Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(
client));
return;
}
@Override
public void onError(long deviceId, int userId, int error, int vendorCode) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
+ ", client: " + (client != null ? client.getOwnerString() : null)
+ ", error: " + error
+ ", vendorCode: " + vendorCode);
if (!(client instanceof Interruptable)) {
Slog.e(TAG, "onError for non-error consumer: " + Utils.getClientName(client));
return;
final Interruptable interruptable = (Interruptable) client;
interruptable.onError(error, vendorCode);
if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE");
mDaemon = null;
mCurrentUserId = UserHandle.USER_NULL;
}
});
}
final Interruptable interruptable = (Interruptable) client;
interruptable.onError(error, vendorCode);
@Override
public void onRemoved(long deviceId, ArrayList<Integer> removed, int userId) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(TAG, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
return;
}
if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE) {
Slog.e(TAG, "Got ERROR_HW_UNAVAILABLE");
mDaemon = null;
mCurrentUserId = UserHandle.USER_NULL;
}
});
}
final RemovalConsumer removalConsumer = (RemovalConsumer) client;
@Override
public void onRemoved(long deviceId, ArrayList<Integer> removed, int userId) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(TAG, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
return;
if (!removed.isEmpty()) {
// Convert to old fingerprint-like behavior, where remove() receives
// one removal
// at a time. This way, remove can share some more common code.
for (int i = 0; i < removed.size(); i++) {
final int id = removed.get(i);
final Face face = new Face("", id, deviceId);
final int remaining = removed.size() - i - 1;
Slog.d(TAG, "Removed, faceId: " + id + ", remaining: " + remaining);
removalConsumer.onRemoved(face, remaining);
}
} else {
removalConsumer.onRemoved(null, 0 /* remaining */);
}
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0, UserHandle.USER_CURRENT);
});
}
final RemovalConsumer removalConsumer = (RemovalConsumer) client;
@Override
public void onEnumerate(long deviceId, ArrayList<Integer> faceIds, int userId) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
+ Utils.getClientName(client));
return;
}
if (!removed.isEmpty()) {
// Convert to old fingerprint-like behavior, where remove() receives one removal
// at a time. This way, remove can share some more common code.
for (int i = 0; i < removed.size(); i++) {
final int id = removed.get(i);
final Face face = new Face("", id, deviceId);
final int remaining = removed.size() - i - 1;
Slog.d(TAG, "Removed, faceId: " + id + ", remaining: " + remaining);
removalConsumer.onRemoved(face, remaining);
}
} else {
removalConsumer.onRemoved(null, 0 /* remaining */);
final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
if (!faceIds.isEmpty()) {
// Convert to old fingerprint-like behavior, where enumerate()
// receives one
// template at a time. This way, enumerate can share some more common
// code.
for (int i = 0; i < faceIds.size(); i++) {
final Face face = new Face("", faceIds.get(i), deviceId);
enumerateConsumer.onEnumerationResult(face, faceIds.size() - i - 1);
}
} else {
// For face, the HIDL contract is to receive an empty list when there
// are no
// templates enrolled. Send a null identifier since we don't consume
// them
// anywhere, and send remaining == 0 so this code can be shared with
// Fingerprint@2.1
enumerateConsumer.onEnumerationResult(null /* identifier */, 0);
}
});
}
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_RE_ENROLL, 0, UserHandle.USER_CURRENT);
});
}
@Override
public void onLockoutChanged(long duration) {
mHandler.post(() -> {
Slog.d(TAG, "onLockoutChanged: " + duration);
final @LockoutTracker.LockoutMode int lockoutMode;
if (duration == 0) {
lockoutMode = LockoutTracker.LOCKOUT_NONE;
} else if (duration == -1 || duration == Long.MAX_VALUE) {
lockoutMode = LockoutTracker.LOCKOUT_PERMANENT;
} else {
lockoutMode = LockoutTracker.LOCKOUT_TIMED;
}
@Override
public void onEnumerate(long deviceId, ArrayList<Integer> faceIds, int userId) {
mHandler.post(() -> {
final ClientMonitor<?> client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
+ Utils.getClientName(client));
return;
mLockoutTracker.setCurrentUserLockoutMode(lockoutMode);
if (duration == 0) {
mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorId);
}
});
}
final EnumerateConsumer enumerateConsumer = (EnumerateConsumer) client;
if (!faceIds.isEmpty()) {
// Convert to old fingerprint-like behavior, where enumerate() receives one
// template at a time. This way, enumerate can share some more common code.
for (int i = 0; i < faceIds.size(); i++) {
final Face face = new Face("", faceIds.get(i), deviceId);
enumerateConsumer.onEnumerationResult(face, faceIds.size() - i - 1);
}
} else {
// For face, the HIDL contract is to receive an empty list when there are no
// templates enrolled. Send a null identifier since we don't consume them
// anywhere, and send remaining == 0 so this code can be shared with
// Fingerprint@2.1
enumerateConsumer.onEnumerationResult(null /* identifier */, 0);
}
});
}
@Override
public void onLockoutChanged(long duration) {
mHandler.post(() -> {
Slog.d(TAG, "onLockoutChanged: " + duration);
final @LockoutTracker.LockoutMode int lockoutMode;
if (duration == 0) {
lockoutMode = LockoutTracker.LOCKOUT_NONE;
} else if (duration == -1 || duration == Long.MAX_VALUE) {
lockoutMode = LockoutTracker.LOCKOUT_PERMANENT;
} else {
lockoutMode = LockoutTracker.LOCKOUT_TIMED;
}
mLockoutTracker.setCurrentUserLockoutMode(lockoutMode);
if (duration == 0) {
mLockoutResetDispatcher.notifyLockoutResetCallbacks(mSensorId);
}
});
}
};
};
@VisibleForTesting
Face10(@NonNull Context context, int sensorId,
public Face10(@NonNull Context context, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
boolean supportsSelfIllumination, int maxTemplatesAllowed) {
@@ -304,7 +317,7 @@ class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
}
Face10(@NonNull Context context, int sensorId,
public Face10(@NonNull Context context, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
this(context, sensorId, strength, lockoutResetDispatcher,
@@ -479,8 +492,8 @@ class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
@NonNull String opPackageName, long challenge) {
mHandler.post(() -> {
if (mCurrentChallengeOwner != null &&
!mCurrentChallengeOwner.getOwnerString().contentEquals(opPackageName)) {
if (mCurrentChallengeOwner != null
&& !mCurrentChallengeOwner.getOwnerString().contentEquals(opPackageName)) {
Slog.e(TAG, "scheduleRevokeChallenge, package: " + opPackageName
+ " attempting to revoke challenge owned by: "
+ mCurrentChallengeOwner.getOwnerString());
@@ -717,10 +730,10 @@ class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
JSONArray sets = new JSONArray();
for (UserInfo user : UserManager.get(mContext).getUsers()) {
final int userId = user.getUserHandle().getIdentifier();
final int N = FaceUtils.getInstance().getBiometricsForUser(mContext, userId).size();
final int c = FaceUtils.getInstance().getBiometricsForUser(mContext, userId).size();
JSONObject set = new JSONObject();
set.put("id", userId);
set.put("count", N);
set.put("count", c);
set.put("accept", performanceTracker.getAcceptForUser(userId));
set.put("reject", performanceTracker.getRejectForUser(userId));
set.put("acquire", performanceTracker.getAcquireForUser(userId));
@@ -816,7 +829,7 @@ class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
try {
devnull = new FileOutputStream("/dev/null");
final NativeHandle handle = new NativeHandle(
new FileDescriptor[] { devnull.getFD(), fd },
new FileDescriptor[]{devnull.getFD(), fd},
new int[0], false);
daemon.debug(handle, new ArrayList<String>(Arrays.asList(args)));
} catch (IOException | RemoteException ex) {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.app.Notification;
@@ -40,6 +40,7 @@ import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.face.UsageStats;
import java.util.ArrayList;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.annotation.Nullable;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -24,7 +24,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.annotation.Nullable;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.biometrics.sensors.face;
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;

View File

@@ -43,7 +43,7 @@ public class Face10Test {
private Context mContext;
private LockoutResetDispatcher mLockoutResetDispatcher;
private Face10 mFace10;
private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10;
private IBinder mBinder;
private static void waitForIdle() {
@@ -55,9 +55,9 @@ public class Face10Test {
MockitoAnnotations.initMocks(this);
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG,
mLockoutResetDispatcher, false /* supportsSelfIllumination */,
1 /* maxTemplatesAllowed */);
mFace10 = new com.android.server.biometrics.sensors.face.hidl.Face10(mContext, SENSOR_ID,
BiometricManager.Authenticators.BIOMETRIC_STRONG, mLockoutResetDispatcher,
false /* supportsSelfIllumination */, 1 /* maxTemplatesAllowed */);
mBinder = new Binder();
}