Merge "Implement enumerate in FingerprintService" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c2f8949b32
@@ -58,7 +58,7 @@ public abstract class EnumerateClient extends ClientMonitor {
|
|||||||
public int stop(boolean initiatedByClient) {
|
public int stop(boolean initiatedByClient) {
|
||||||
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
||||||
if (daemon == null) {
|
if (daemon == null) {
|
||||||
Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
|
Slog.w(TAG, "stopEnumeration: no fingerprint HAL!");
|
||||||
return ERROR_ESRCH;
|
return ERROR_ESRCH;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -102,12 +102,12 @@ public abstract class EnumerateClient extends ClientMonitor {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onEnrollResult(int fingerId, int groupId, int rem) {
|
public boolean onEnrollResult(int fingerId, int groupId, int rem) {
|
||||||
if (DEBUG) Slog.w(TAG, "onEnrollResult() called for enumerate!");
|
if (DEBUG) Slog.w(TAG, "onEnrollResult() called for enumerate!");
|
||||||
return true; // Invalid for Remove
|
return true; // Invalid for Enumerate.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onRemoved(int fingerId, int groupId, int remaining) {
|
public boolean onRemoved(int fingerId, int groupId, int remaining) {
|
||||||
if (DEBUG) Slog.w(TAG, "onRemoved() called for enumerate!");
|
if (DEBUG) Slog.w(TAG, "onRemoved() called for enumerate!");
|
||||||
return true; // Invalid for Authenticate
|
return true; // Invalid for Enumerate.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service to manage multiple clients that want to access the fingerprint HAL API.
|
* A service to manage multiple clients that want to access the fingerprint HAL API.
|
||||||
@@ -96,6 +97,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
|
public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
|
||||||
static final String TAG = "FingerprintService";
|
static final String TAG = "FingerprintService";
|
||||||
static final boolean DEBUG = true;
|
static final boolean DEBUG = true;
|
||||||
|
private static final boolean CLEANUP_UNUSED_FP = false;
|
||||||
private static final String FP_DATA_DIR = "fpdata";
|
private static final String FP_DATA_DIR = "fpdata";
|
||||||
private static final int MSG_USER_SWITCHING = 10;
|
private static final int MSG_USER_SWITCHING = 10;
|
||||||
private static final String ACTION_LOCKOUT_RESET =
|
private static final String ACTION_LOCKOUT_RESET =
|
||||||
@@ -134,6 +136,20 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
private ClientMonitor mPendingClient;
|
private ClientMonitor mPendingClient;
|
||||||
private PerformanceStats mPerformanceStats;
|
private PerformanceStats mPerformanceStats;
|
||||||
|
|
||||||
|
|
||||||
|
private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
|
||||||
|
private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>();
|
||||||
|
private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints
|
||||||
|
|
||||||
|
private class UserFingerprint {
|
||||||
|
Fingerprint f;
|
||||||
|
int userId;
|
||||||
|
public UserFingerprint(Fingerprint f, int userId) {
|
||||||
|
this.f = f;
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normal fingerprint authentications are tracked by mPerformanceMap.
|
// Normal fingerprint authentications are tracked by mPerformanceMap.
|
||||||
private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
|
private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
|
||||||
|
|
||||||
@@ -185,6 +201,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
+ (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
|
+ (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
|
||||||
+ " failed to respond to cancel, starting client "
|
+ " failed to respond to cancel, starting client "
|
||||||
+ (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
|
+ (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
|
||||||
|
|
||||||
mCurrentClient = null;
|
mCurrentClient = null;
|
||||||
startClient(mPendingClient, false);
|
startClient(mPendingClient, false);
|
||||||
}
|
}
|
||||||
@@ -239,6 +256,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
if (mHalDeviceId != 0) {
|
if (mHalDeviceId != 0) {
|
||||||
loadAuthenticatorIds();
|
loadAuthenticatorIds();
|
||||||
updateActiveGroup(ActivityManager.getCurrentUser(), null);
|
updateActiveGroup(ActivityManager.getCurrentUser(), null);
|
||||||
|
doFingerprintCleanup(ActivityManager.getCurrentUser());
|
||||||
} else {
|
} else {
|
||||||
Slog.w(TAG, "Failed to open Fingerprint HAL!");
|
Slog.w(TAG, "Failed to open Fingerprint HAL!");
|
||||||
MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
|
MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
|
||||||
@@ -253,7 +271,6 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
// This operation can be expensive, so keep track of the elapsed time. Might need to move to
|
// This operation can be expensive, so keep track of the elapsed time. Might need to move to
|
||||||
// background if it takes too long.
|
// background if it takes too long.
|
||||||
long t = System.currentTimeMillis();
|
long t = System.currentTimeMillis();
|
||||||
|
|
||||||
mAuthenticatorIds.clear();
|
mAuthenticatorIds.clear();
|
||||||
for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
|
for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
|
||||||
int userId = getUserOrWorkProfileId(null, user.id);
|
int userId = getUserOrWorkProfileId(null, user.id);
|
||||||
@@ -268,14 +285,88 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doFingerprintCleanup(int userId) {
|
||||||
|
if (CLEANUP_UNUSED_FP) {
|
||||||
|
resetEnumerateState();
|
||||||
|
mEnumeratingUserIds.push(userId);
|
||||||
|
enumerateNextUser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetEnumerateState() {
|
||||||
|
if (DEBUG) Slog.v(TAG, "Enumerate cleaning up");
|
||||||
|
mEnumeratingUserIds.clear();
|
||||||
|
mUnknownFingerprints.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enumerateNextUser() {
|
||||||
|
int nextUser = mEnumeratingUserIds.getFirst();
|
||||||
|
updateActiveGroup(nextUser, null);
|
||||||
|
boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
|
||||||
|
|
||||||
|
if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of "
|
||||||
|
+ mEnumeratingUserIds.size() + " remaining users");
|
||||||
|
|
||||||
|
startEnumerate(mToken, nextUser, null, restricted, true /* internal */);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove unknown fingerprints from hardware
|
||||||
|
private void cleanupUnknownFingerprints() {
|
||||||
|
if (!mUnknownFingerprints.isEmpty()) {
|
||||||
|
Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size());
|
||||||
|
UserFingerprint uf = mUnknownFingerprints.get(0);
|
||||||
|
mUnknownFingerprints.remove(uf);
|
||||||
|
boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
|
||||||
|
updateActiveGroup(uf.userId, null);
|
||||||
|
startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
|
||||||
|
restricted, true /* internal */);
|
||||||
|
} else {
|
||||||
|
resetEnumerateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
|
protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
|
||||||
if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
|
if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId
|
||||||
+ groupId + "rem=" + remaining);
|
+ ", gid=" + groupId
|
||||||
// TODO: coordinate names with framework
|
+ ", dev=" + deviceId
|
||||||
|
+ ", rem=" + remaining);
|
||||||
|
|
||||||
|
ClientMonitor client = mCurrentClient;
|
||||||
|
|
||||||
|
if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.onEnumerationResult(fingerId, groupId, remaining);
|
||||||
|
|
||||||
|
// All fingerprints in hardware for this user were enumerated
|
||||||
|
if (remaining == 0) {
|
||||||
|
mEnumeratingUserIds.poll();
|
||||||
|
|
||||||
|
if (client instanceof InternalEnumerateClient) {
|
||||||
|
List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList();
|
||||||
|
Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion");
|
||||||
|
for (Fingerprint f : enrolled) {
|
||||||
|
mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeClient(client);
|
||||||
|
|
||||||
|
if (!mEnumeratingUserIds.isEmpty()) {
|
||||||
|
enumerateNextUser();
|
||||||
|
} else if (client instanceof InternalEnumerateClient) {
|
||||||
|
if (DEBUG) Slog.v(TAG, "Finished enumerating all users");
|
||||||
|
// This will start a chain of InternalRemovalClients
|
||||||
|
cleanupUnknownFingerprints();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleError(long deviceId, int error, int vendorCode) {
|
protected void handleError(long deviceId, int error, int vendorCode) {
|
||||||
ClientMonitor client = mCurrentClient;
|
ClientMonitor client = mCurrentClient;
|
||||||
|
if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
|
||||||
|
resetEnumerateState();
|
||||||
|
}
|
||||||
if (client != null && client.onError(error, vendorCode)) {
|
if (client != null && client.onError(error, vendorCode)) {
|
||||||
removeClient(client);
|
removeClient(client);
|
||||||
}
|
}
|
||||||
@@ -301,10 +392,20 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
|
protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
|
||||||
|
if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
|
||||||
|
+ ", gid=" + groupId
|
||||||
|
+ ", dev=" + deviceId
|
||||||
|
+ ", rem=" + remaining);
|
||||||
|
|
||||||
ClientMonitor client = mCurrentClient;
|
ClientMonitor client = mCurrentClient;
|
||||||
if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
|
if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
|
||||||
removeClient(client);
|
removeClient(client);
|
||||||
}
|
}
|
||||||
|
if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
|
||||||
|
cleanupUnknownFingerprints();
|
||||||
|
} else if (client instanceof InternalRemovalClient){
|
||||||
|
resetEnumerateState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
|
protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
|
||||||
@@ -355,6 +456,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
|
|
||||||
void handleUserSwitching(int userId) {
|
void handleUserSwitching(int userId) {
|
||||||
updateActiveGroup(userId, null);
|
updateActiveGroup(userId, null);
|
||||||
|
doFingerprintCleanup(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeClient(ClientMonitor client) {
|
private void removeClient(ClientMonitor client) {
|
||||||
@@ -431,7 +533,15 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
ClientMonitor currentClient = mCurrentClient;
|
ClientMonitor currentClient = mCurrentClient;
|
||||||
if (currentClient != null) {
|
if (currentClient != null) {
|
||||||
if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
|
if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
|
||||||
currentClient.stop(initiatedByClient);
|
if (currentClient instanceof InternalEnumerateClient ||
|
||||||
|
currentClient instanceof InternalRemovalClient) {
|
||||||
|
// This condition means we're currently running internal diagnostics to
|
||||||
|
// remove extra fingerprints in the hardware and/or the software
|
||||||
|
// TODO: design an escape hatch in case client never finishes
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentClient.stop(initiatedByClient);
|
||||||
|
}
|
||||||
mPendingClient = newClient;
|
mPendingClient = newClient;
|
||||||
mHandler.removeCallbacks(mResetClientState);
|
mHandler.removeCallbacks(mResetClientState);
|
||||||
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
|
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
|
||||||
@@ -448,47 +558,86 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
}
|
}
|
||||||
|
|
||||||
void startRemove(IBinder token, int fingerId, int groupId, int userId,
|
void startRemove(IBinder token, int fingerId, int groupId, int userId,
|
||||||
IFingerprintServiceReceiver receiver, boolean restricted) {
|
IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
|
||||||
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
||||||
if (daemon == null) {
|
if (daemon == null) {
|
||||||
Slog.w(TAG, "startRemove: no fingerprint HAL!");
|
Slog.w(TAG, "startRemove: no fingerprint HAL!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
|
|
||||||
receiver, fingerId, groupId, userId, restricted, token.toString()) {
|
|
||||||
@Override
|
|
||||||
public void notifyUserActivity() {
|
|
||||||
FingerprintService.this.userActivity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (internal) {
|
||||||
public IBiometricsFingerprint getFingerprintDaemon() {
|
Context context = getContext();
|
||||||
return FingerprintService.this.getFingerprintDaemon();
|
InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
|
||||||
}
|
token, receiver, fingerId, groupId, userId, restricted,
|
||||||
};
|
context.getOpPackageName()) {
|
||||||
startClient(client, true);
|
@Override
|
||||||
|
public void notifyUserActivity() {
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public IBiometricsFingerprint getFingerprintDaemon() {
|
||||||
|
return FingerprintService.this.getFingerprintDaemon();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
startClient(client, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
|
||||||
|
receiver, fingerId, groupId, userId, restricted, token.toString()) {
|
||||||
|
@Override
|
||||||
|
public void notifyUserActivity() {
|
||||||
|
FingerprintService.this.userActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBiometricsFingerprint getFingerprintDaemon() {
|
||||||
|
return FingerprintService.this.getFingerprintDaemon();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
startClient(client, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void startEnumerate(IBinder token, int userId,
|
void startEnumerate(IBinder token, int userId,
|
||||||
IFingerprintServiceReceiver receiver, boolean restricted) {
|
IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
|
||||||
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
||||||
if (daemon == null) {
|
if (daemon == null) {
|
||||||
Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
|
Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
|
if (internal) {
|
||||||
receiver, userId, userId, restricted, token.toString()) {
|
List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
|
||||||
@Override
|
Context context = getContext();
|
||||||
public void notifyUserActivity() {
|
InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
|
||||||
FingerprintService.this.userActivity();
|
token, receiver, userId, userId, restricted, context.getOpPackageName(),
|
||||||
}
|
enrolledList) {
|
||||||
|
@Override
|
||||||
|
public void notifyUserActivity() {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public IBiometricsFingerprint getFingerprintDaemon() {
|
|
||||||
return FingerprintService.this.getFingerprintDaemon();
|
@Override
|
||||||
}
|
public IBiometricsFingerprint getFingerprintDaemon() {
|
||||||
};
|
return FingerprintService.this.getFingerprintDaemon();
|
||||||
startClient(client, true);
|
}
|
||||||
|
};
|
||||||
|
startClient(client, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
|
||||||
|
receiver, userId, userId, restricted, token.toString()) {
|
||||||
|
@Override
|
||||||
|
public void notifyUserActivity() {
|
||||||
|
FingerprintService.this.userActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBiometricsFingerprint getFingerprintDaemon() {
|
||||||
|
return FingerprintService.this.getFingerprintDaemon();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
startClient(client, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Fingerprint> getEnrolledFingerprints(int userId) {
|
public List<Fingerprint> getEnrolledFingerprints(int userId) {
|
||||||
@@ -978,11 +1127,13 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
startRemove(token, fingerId, groupId, userId, receiver, restricted);
|
startRemove(token, fingerId, groupId, userId, receiver,
|
||||||
|
restricted, false /* internal */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // Binder call
|
||||||
public void enumerate(final IBinder token, final int userId,
|
public void enumerate(final IBinder token, final int userId,
|
||||||
final IFingerprintServiceReceiver receiver) {
|
final IFingerprintServiceReceiver receiver) {
|
||||||
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
|
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
|
||||||
@@ -990,7 +1141,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death
|
|||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
startEnumerate(token, userId, receiver, restricted);
|
startEnumerate(token, userId, receiver, restricted, false /* internal */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.fingerprint;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.fingerprint.Fingerprint;
|
||||||
|
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Slog;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal class to help clean up unknown fingerprints in the hardware and software
|
||||||
|
*/
|
||||||
|
public abstract class InternalEnumerateClient extends EnumerateClient {
|
||||||
|
|
||||||
|
private List<Fingerprint> mEnrolledList;
|
||||||
|
private List<Fingerprint> mEnumeratedList = new ArrayList<>(); // list of fp to delete
|
||||||
|
|
||||||
|
public InternalEnumerateClient(Context context, long halDeviceId, IBinder token,
|
||||||
|
IFingerprintServiceReceiver receiver, int groupId, int userId,
|
||||||
|
boolean restricted, String owner, List<Fingerprint> enrolledList) {
|
||||||
|
|
||||||
|
super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
|
||||||
|
mEnrolledList = enrolledList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleEnumeratedFingerprint(int fingerId, int groupId, int remaining) {
|
||||||
|
|
||||||
|
boolean matched = false;
|
||||||
|
for (int i=0; i<mEnrolledList.size(); i++) {
|
||||||
|
if (mEnrolledList.get(i).getFingerId() == fingerId) {
|
||||||
|
mEnrolledList.remove(i);
|
||||||
|
matched = true;
|
||||||
|
Slog.e(TAG, "Matched fingerprint fid=" + fingerId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fingerId 0 means no fingerprints are in hardware
|
||||||
|
if (!matched && fingerId != 0) {
|
||||||
|
Fingerprint fingerprint = new Fingerprint("", groupId, fingerId, getHalDeviceId());
|
||||||
|
mEnumeratedList.add(fingerprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doFingerprintCleanup() {
|
||||||
|
|
||||||
|
if (mEnrolledList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Fingerprint f : mEnrolledList) {
|
||||||
|
Slog.e(TAG, "Internal Enumerate: Removing dangling enrolled fingerprint: "
|
||||||
|
+ f.getName() + " " + f.getFingerId() + " " + f.getGroupId()
|
||||||
|
+ " " + f.getDeviceId());
|
||||||
|
|
||||||
|
FingerprintUtils.getInstance().removeFingerprintIdForUser(getContext(),
|
||||||
|
f.getFingerId(), getTargetUserId());
|
||||||
|
}
|
||||||
|
mEnrolledList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Fingerprint> getEnumeratedList() {
|
||||||
|
return mEnumeratedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onEnumerationResult(int fingerId, int groupId, int remaining) {
|
||||||
|
|
||||||
|
handleEnumeratedFingerprint(fingerId, groupId, remaining);
|
||||||
|
if (remaining == 0) {
|
||||||
|
doFingerprintCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fingerId == 0; // done when id hits 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.fingerprint;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.hardware.fingerprint.IFingerprintServiceReceiver;
|
||||||
|
import com.android.server.fingerprint.RemovalClient;
|
||||||
|
|
||||||
|
public abstract class InternalRemovalClient extends RemovalClient {
|
||||||
|
|
||||||
|
public InternalRemovalClient(Context context, long halDeviceId, IBinder token,
|
||||||
|
IFingerprintServiceReceiver receiver, int fingerId, int groupId, int userId,
|
||||||
|
boolean restricted, String owner) {
|
||||||
|
|
||||||
|
super(context, halDeviceId, token, receiver, fingerId, groupId, userId, restricted, owner);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,12 +59,23 @@ public abstract class RemovalClient extends ClientMonitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int stop(boolean initiatedByClient) {
|
public int stop(boolean initiatedByClient) {
|
||||||
// We don't actually stop remove, but inform the client that the cancel operation succeeded
|
IBiometricsFingerprint daemon = getFingerprintDaemon();
|
||||||
// so we can start the next operation.
|
if (daemon == null) {
|
||||||
if (initiatedByClient) {
|
Slog.w(TAG, "stopRemoval: no fingerprint HAL!");
|
||||||
onError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, 0 /* vendorCode */);
|
return ERROR_ESRCH;
|
||||||
}
|
}
|
||||||
return 0;
|
try {
|
||||||
|
final int result = daemon.cancel();
|
||||||
|
if (result != 0) {
|
||||||
|
Slog.w(TAG, "stopRemoval failed, result=" + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is no longer removing");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "stopRemoval failed", e);
|
||||||
|
return ERROR_ESRCH;
|
||||||
|
}
|
||||||
|
return 0; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user