Merge "Move from native FingerprintService implementation to fingerprintd" into mnc-dev

This commit is contained in:
Jim Miller
2015-05-21 00:57:26 +00:00
committed by Android (Google) Code Review
8 changed files with 348 additions and 189 deletions

View File

@@ -156,6 +156,8 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/display/IDisplayManager.aidl \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \ core/java/android/hardware/display/IDisplayManagerCallback.aidl \
core/java/android/hardware/display/IVirtualDisplayCallback.aidl \ core/java/android/hardware/display/IVirtualDisplayCallback.aidl \
core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl \
core/java/android/hardware/fingerprint/IFingerprintDaemonCallback.aidl \
core/java/android/hardware/fingerprint/IFingerprintService.aidl \ core/java/android/hardware/fingerprint/IFingerprintService.aidl \
core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \ core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \ core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \

View File

@@ -729,12 +729,6 @@ public class FingerprintManager {
} }
} }
private void clearCallbacks() {
mAuthenticationCallback = null;
mEnrollmentCallback = null;
mRemovalCallback = null;
}
private void cancelEnrollment() { private void cancelEnrollment() {
if (mService != null) try { if (mService != null) try {
mService.cancelEnrollment(mToken); mService.cancelEnrollment(mToken);

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2015 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 android.hardware.fingerprint;
import android.hardware.fingerprint.IFingerprintDaemonCallback;
/**
* Communication channel from FingerprintService to FingerprintDaemon (fingerprintd)
* @hide
*/
interface IFingerprintDaemon {
int authenticate(long sessionId, int groupId);
int cancelAuthentication();
int enroll(in byte [] token, int groupId, int timeout);
int cancelEnrollment();
long preEnroll();
int remove(int fingerId, int groupId);
long getAuthenticatorId();
int setActiveGroup(int groupId, in byte[] path);
long openHal();
int closeHal();
void init(IFingerprintDaemonCallback callback);
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2014 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 android.hardware.fingerprint;
/**
* Communication channel from the fingerprintd back to FingerprintService.
* @hide
*/
interface IFingerprintDaemonCallback {
void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
void onAcquired(long deviceId, int acquiredInfo);
void onAuthenticated(long deviceId, int fingerId, int groupId);
void onError(long deviceId, int error);
void onRemoved(long deviceId, int fingerId, int groupId);
void onEnumerate(long deviceId, in int [] fingerIds, in int [] groupIds);
}

View File

@@ -361,9 +361,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
return; return;
} }
if (groupId == userId) { onFingerprintAuthenticated(userId);
onFingerprintAuthenticated(groupId);
}
} finally { } finally {
setFingerprintRunningDetectionRunning(false); setFingerprintRunningDetectionRunning(false);
} }

View File

@@ -30,6 +30,7 @@ import android.os.IRemoteCallback;
import android.os.Looper; import android.os.Looper;
import android.os.MessageQueue; import android.os.MessageQueue;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog; import android.util.Slog;
import com.android.server.SystemService; import com.android.server.SystemService;
@@ -37,6 +38,8 @@ import com.android.server.SystemService;
import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintService; import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintDaemon;
import android.hardware.fingerprint.IFingerprintDaemonCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IFingerprintServiceReceiver;
import static android.Manifest.permission.MANAGE_FINGERPRINT; import static android.Manifest.permission.MANAGE_FINGERPRINT;
@@ -55,20 +58,19 @@ import java.util.List;
* *
* @hide * @hide
*/ */
public class FingerprintService extends SystemService { public class FingerprintService extends SystemService implements IBinder.DeathRecipient {
private static final String TAG = "FingerprintService"; private static final String TAG = "FingerprintService";
private static final boolean DEBUG = true; private static final boolean DEBUG = true;
private static final String FP_DATA_DIR = "fpdata";
private static final String FINGERPRINTD = "android.hardware.fingerprint.IFingerprintDaemon";
private static final int MSG_USER_SWITCHING = 10;
private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
private ClientMonitor mAuthClient = null; private ClientMonitor mAuthClient = null;
private ClientMonitor mEnrollClient = null; private ClientMonitor mEnrollClient = null;
private ClientMonitor mRemoveClient = null; private ClientMonitor mRemoveClient = null;
private final AppOpsManager mAppOps; private final AppOpsManager mAppOps;
private static final int MSG_NOTIFY = 10;
private static final int MSG_USER_SWITCHING = 11;
private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
// Message types. Used internally to dispatch messages to the correct callback. // Message types. Used internally to dispatch messages to the correct callback.
// Must agree with the list in fingerprint.h // Must agree with the list in fingerprint.h
private static final int FINGERPRINT_ERROR = -1; private static final int FINGERPRINT_ERROR = -1;
@@ -83,11 +85,6 @@ public class FingerprintService extends SystemService {
Handler mHandler = new Handler() { Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) { public void handleMessage(android.os.Message msg) {
switch (msg.what) { switch (msg.what) {
case MSG_NOTIFY:
FpHalMsg m = (FpHalMsg) msg.obj;
handleNotify(m.type, m.arg1, m.arg2, m.arg3);
break;
case MSG_USER_SWITCHING: case MSG_USER_SWITCHING:
handleUserSwitching(msg.arg1); handleUserSwitching(msg.arg1);
break; break;
@@ -97,10 +94,13 @@ public class FingerprintService extends SystemService {
} }
} }
}; };
private Context mContext;
private int mHalDeviceId;
private int mFailedAttempts;
private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance(); private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
private Context mContext;
private long mHalDeviceId;
private int mFailedAttempts;
private IFingerprintDaemon mDaemon;
private final Runnable mLockoutReset = new Runnable() { private final Runnable mLockoutReset = new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -112,127 +112,115 @@ public class FingerprintService extends SystemService {
super(context); super(context);
mContext = context; mContext = context;
mAppOps = context.getSystemService(AppOpsManager.class); mAppOps = context.getSystemService(AppOpsManager.class);
nativeInit(Looper.getMainLooper().getQueue(), this);
} }
// TODO: Move these into separate process @Override
// JNI methods to communicate from FingerprintService to HAL public void binderDied() {
static native int nativeEnroll(byte [] token, int groupId, int timeout); Slog.v(TAG, "fingerprintd died");
static native long nativePreEnroll(); mDaemon = null;
static native int nativeStopEnrollment();
static native int nativeAuthenticate(long sessionId, int groupId);
static native int nativeStopAuthentication();
static native int nativeRemove(int fingerId, int groupId);
static native int nativeOpenHal();
static native int nativeCloseHal();
static native void nativeInit(MessageQueue queue, FingerprintService service);
static native long nativeGetAuthenticatorId();
static native int nativeSetActiveGroup(int gid, byte[] storePath);
static final class FpHalMsg {
int type; // Type of the message. One of the constants in fingerprint.h
int arg1; // optional arguments
int arg2;
int arg3;
FpHalMsg(int type, int arg1, int arg2, int arg3) {
this.type = type;
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
} }
/** public IFingerprintDaemon getFingerprintDaemon() {
* Called from JNI to communicate messages from fingerprint HAL. if (mDaemon == null) {
*/ mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
void notify(int type, int arg1, int arg2, int arg3) { if (mDaemon == null) {
mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget(); Slog.w(TAG, "fingerprind service not available");
} } else {
try {
void handleNotify(int type, int arg1, int arg2, int arg3) { mDaemon.asBinder().linkToDeath(this, 0);
Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")" } catch (RemoteException e) {
+ ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient); Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
if (mEnrollClient != null) { mDaemon = null; // try again!
final IBinder token = mEnrollClient.token; }
if (dispatchNotify(mEnrollClient, type, arg1, arg2, arg3)) {
stopEnrollment(token, false);
removeClient(mEnrollClient);
} }
} }
return mDaemon;
}
protected void dispatchEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {
if (fingerIds.length != groupIds.length) {
Slog.w(TAG, "fingerIds and groupIds differ in length: f[]="
+ fingerIds + ", g[]=" + groupIds);
return;
}
if (DEBUG) Slog.w(TAG, "Enumerate: f[]=" + fingerIds + ", g[]=" + groupIds);
// TODO: update fingerprint/name pairs
}
protected void dispatchRemoved(long deviceId, int fingerId, int groupId) {
final ClientMonitor client = mRemoveClient;
if (fingerId != 0) {
ContentResolver res = mContext.getContentResolver();
removeTemplateForUser(mRemoveClient, fingerId);
}
if (client != null && client.sendRemoved(fingerId, groupId)) {
removeClient(mRemoveClient);
}
}
protected void dispatchError(long deviceId, int error) {
if (mEnrollClient != null) {
final IBinder token = mEnrollClient.token;
if (mEnrollClient.sendError(error)) {
stopEnrollment(token, false);
}
} else if (mAuthClient != null) {
final IBinder token = mAuthClient.token;
if (mAuthClient.sendError(error)) {
stopAuthentication(token, false);
}
} else if (mRemoveClient != null) {
if (mRemoveClient.sendError(error)) removeClient(mRemoveClient);
}
}
protected void dispatchAuthenticated(long deviceId, int fingerId, int groupId) {
if (mAuthClient != null) { if (mAuthClient != null) {
final IBinder token = mAuthClient.token; final IBinder token = mAuthClient.token;
if (dispatchNotify(mAuthClient, type, arg1, arg2, arg3)) { if (mAuthClient.sendAuthenticated(fingerId, groupId)) {
stopAuthentication(token, false); stopAuthentication(token, false);
removeClient(mAuthClient); removeClient(mAuthClient);
} }
} }
if (mRemoveClient != null) { }
if (dispatchNotify(mRemoveClient, type, arg1, arg2, arg3)) {
removeClient(mRemoveClient); protected void dispatchAcquired(long deviceId, int acquiredInfo) {
if (mEnrollClient != null) {
if (mEnrollClient.sendAcquired(acquiredInfo)) {
removeClient(mEnrollClient);
}
} else if (mAuthClient != null) {
if (mAuthClient.sendAcquired(acquiredInfo)) {
removeClient(mAuthClient);
} }
} }
} }
void handleUserSwitching(int userId) { void handleUserSwitching(int userId) {
updateActiveGroup(userId); updateActiveGroup(userId);
} }
/* protected void dispatchEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
* Dispatch notify events to clients. if (mEnrollClient != null) {
* if (mEnrollClient.sendEnrollResult(fingerId, groupId, remaining)) {
* @return true if the operation is done, i.e. authentication completed
*/
boolean dispatchNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
boolean operationCompleted = false;
int fpId;
int groupId;
int remaining;
int acquireInfo;
switch (type) {
case FINGERPRINT_ERROR:
fpId = arg1;
operationCompleted = clientMonitor.sendError(fpId);
break;
case FINGERPRINT_ACQUIRED:
acquireInfo = arg1;
operationCompleted = clientMonitor.sendAcquired(acquireInfo);
break;
case FINGERPRINT_AUTHENTICATED:
fpId = arg1;
groupId = arg2;
operationCompleted = clientMonitor.sendAuthenticated(fpId, groupId);
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
fpId = arg1;
groupId = arg2;
remaining = arg3;
operationCompleted = clientMonitor.sendEnrollResult(fpId, groupId, remaining);
if (remaining == 0) { if (remaining == 0) {
addTemplateForUser(clientMonitor, fpId); ContentResolver res = mContext.getContentResolver();
operationCompleted = true; // enroll completed addTemplateForUser(mEnrollClient, fingerId);
removeClient(mEnrollClient);
} }
break; }
case FINGERPRINT_TEMPLATE_REMOVED:
fpId = arg1;
groupId = arg2;
operationCompleted = clientMonitor.sendRemoved(fpId, groupId);
if (fpId != 0) {
removeTemplateForUser(clientMonitor, fpId);
}
break;
} }
return operationCompleted;
} }
private void removeClient(ClientMonitor clientMonitor) { private void removeClient(ClientMonitor client) {
if (clientMonitor == null) return; if (client == null) return;
clientMonitor.destroy(); client.destroy();
if (clientMonitor == mAuthClient) { if (client == mAuthClient) {
mAuthClient = null; mAuthClient = null;
} else if (clientMonitor == mEnrollClient) { } else if (client == mEnrollClient) {
mEnrollClient = null; mEnrollClient = null;
} else if (clientMonitor == mRemoveClient) { } else if (client == mRemoveClient) {
mRemoveClient = null; mRemoveClient = null;
} }
} }
@@ -273,17 +261,36 @@ public class FingerprintService extends SystemService {
void startEnrollment(IBinder token, byte[] cryptoToken, int groupId, void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
IFingerprintServiceReceiver receiver, int flags) { IFingerprintServiceReceiver receiver, int flags) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "enroll: no fingeprintd!");
return;
}
stopPendingOperations(); stopPendingOperations();
mEnrollClient = new ClientMonitor(token, receiver, groupId); mEnrollClient = new ClientMonitor(token, receiver, groupId);
final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
final int result = nativeEnroll(cryptoToken, groupId, timeout); try {
if (result != 0) { final int result = daemon.enroll(cryptoToken, groupId, timeout);
Slog.w(TAG, "startEnroll failed, result=" + result); if (result != 0) {
Slog.w(TAG, "startEnroll failed, result=" + result);
}
} catch (RemoteException e) {
Slog.e(TAG, "startEnroll failed", e);
} }
} }
public long startPreEnroll(IBinder token) { public long startPreEnroll(IBinder token) {
return nativePreEnroll(); IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startPreEnroll: no fingeprintd!");
return 0;
}
try {
return daemon.preEnroll();
} catch (RemoteException e) {
Slog.e(TAG, "startPreEnroll failed", e);
}
return 0;
} }
private void stopPendingOperations() { private void stopPendingOperations() {
@@ -297,20 +304,34 @@ public class FingerprintService extends SystemService {
} }
void stopEnrollment(IBinder token, boolean notify) { void stopEnrollment(IBinder token, boolean notify) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "stopEnrollment: no fingeprintd!");
return;
}
final ClientMonitor client = mEnrollClient; final ClientMonitor client = mEnrollClient;
if (client == null || client.token != token) return; if (client == null || client.token != token) return;
int result = nativeStopEnrollment(); try {
int result = daemon.cancelEnrollment();
if (result != 0) {
Slog.w(TAG, "startEnrollCancel failed, result = " + result);
}
} catch (RemoteException e) {
Slog.e(TAG, "stopEnrollment failed", e);
}
if (notify) { if (notify) {
client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
} }
removeClient(mEnrollClient); removeClient(mEnrollClient);
if (result != 0) {
Slog.w(TAG, "startEnrollCancel failed, result=" + result);
}
} }
void startAuthentication(IBinder token, long opId, int groupId, void startAuthentication(IBinder token, long opId, int groupId,
IFingerprintServiceReceiver receiver, int flags) { IFingerprintServiceReceiver receiver, int flags) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startAuthentication: no fingeprintd!");
return;
}
stopPendingOperations(); stopPendingOperations();
mAuthClient = new ClientMonitor(token, receiver, groupId); mAuthClient = new ClientMonitor(token, receiver, groupId);
if (inLockoutMode()) { if (inLockoutMode()) {
@@ -322,32 +343,54 @@ public class FingerprintService extends SystemService {
return; return;
} }
final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
final int result = nativeAuthenticate(opId, groupId); try {
if (result != 0) { final int result = daemon.authenticate(opId, groupId);
Slog.w(TAG, "startAuthentication failed, result=" + result); if (result != 0) {
Slog.w(TAG, "startAuthentication failed, result=" + result);
}
} catch (RemoteException e) {
Slog.e(TAG, "startAuthentication failed", e);
} }
} }
void stopAuthentication(IBinder token, boolean notify) { void stopAuthentication(IBinder token, boolean notify) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "stopAuthentication: no fingeprintd!");
return;
}
final ClientMonitor client = mAuthClient; final ClientMonitor client = mAuthClient;
if (client == null || client.token != token) return; if (client == null || client.token != token) return;
int result = nativeStopAuthentication(); try {
int result = daemon.cancelAuthentication();
if (result != 0) {
Slog.w(TAG, "stopAuthentication failed, result=" + result);
}
} catch (RemoteException e) {
Slog.e(TAG, "stopAuthentication failed", e);
}
if (notify) { if (notify) {
client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
} }
removeClient(mAuthClient); removeClient(mAuthClient);
if (result != 0) {
Slog.w(TAG, "stopAuthentication failed, result=" + result);
}
} }
void startRemove(IBinder token, int fingerId, int userId, void startRemove(IBinder token, int fingerId, int userId,
IFingerprintServiceReceiver receiver) { IFingerprintServiceReceiver receiver) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startRemove: no fingeprintd!");
return;
}
mRemoveClient = new ClientMonitor(token, receiver, userId); mRemoveClient = new ClientMonitor(token, receiver, userId);
// The fingerprint template ids will be removed when we get confirmation from the HAL // The fingerprint template ids will be removed when we get confirmation from the HAL
final int result = nativeRemove(fingerId, userId); try {
if (result != 0) { final int result = daemon.remove(fingerId, userId);
Slog.w(TAG, "startRemove with id = " + fingerId + " failed with result=" + result); if (result != 0) {
Slog.w(TAG, "startRemove with id = " + fingerId + " failed, result=" + result);
}
} catch (RemoteException e) {
Slog.e(TAG, "startRemove failed", e);
} }
} }
@@ -364,7 +407,7 @@ public class FingerprintService extends SystemService {
"Must have " + permission + " permission."); "Must have " + permission + " permission.");
} }
private boolean canUserFingerPrint(String opPackageName) { private boolean canUseFingerprint(String opPackageName) {
checkPermission(USE_FINGERPRINT); checkPermission(USE_FINGERPRINT);
return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(), return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(),
@@ -496,15 +539,48 @@ public class FingerprintService extends SystemService {
} }
} }
private final class FingerprintServiceWrapper extends IFingerprintService.Stub { private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
@Override @Override
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
dispatchEnrollResult(deviceId, fingerId, groupId, remaining);
}
@Override
public void onAcquired(long deviceId, int acquiredInfo) {
dispatchAcquired(deviceId, acquiredInfo);
}
@Override
public void onAuthenticated(long deviceId, int fingerId, int groupId) {
dispatchAuthenticated(deviceId, fingerId, groupId);
}
@Override
public void onError(long deviceId, int error) {
dispatchError(deviceId, error);
}
@Override
public void onRemoved(long deviceId, int fingerId, int groupId) {
dispatchRemoved(deviceId, fingerId, groupId);
}
@Override
public void onEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {
dispatchEnumerate(deviceId, fingerIds, groupIds);
}
};
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
@Override // Binder call
public long preEnroll(IBinder token) { public long preEnroll(IBinder token) {
checkPermission(MANAGE_FINGERPRINT); checkPermission(MANAGE_FINGERPRINT);
return startPreEnroll(token); return startPreEnroll(token);
} }
@Override @Override // Binder call
// Binder call
public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId, public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags) { final IFingerprintServiceReceiver receiver, final int flags) {
checkPermission(MANAGE_FINGERPRINT); checkPermission(MANAGE_FINGERPRINT);
@@ -517,8 +593,7 @@ public class FingerprintService extends SystemService {
}); });
} }
@Override @Override // Binder call
// Binder call
public void cancelEnrollment(final IBinder token) { public void cancelEnrollment(final IBinder token) {
checkPermission(MANAGE_FINGERPRINT); checkPermission(MANAGE_FINGERPRINT);
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@@ -529,12 +604,11 @@ public class FingerprintService extends SystemService {
}); });
} }
@Override @Override // Binder call
// Binder call
public void authenticate(final IBinder token, final long opId, final int groupId, public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) { final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) {
checkPermission(USE_FINGERPRINT); checkPermission(USE_FINGERPRINT);
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return; return;
} }
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@@ -545,11 +619,9 @@ public class FingerprintService extends SystemService {
}); });
} }
@Override @Override // Binder call
// Binder call
public void cancelAuthentication(final IBinder token, String opPackageName) { public void cancelAuthentication(final IBinder token, String opPackageName) {
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return; return;
} }
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@@ -560,8 +632,7 @@ public class FingerprintService extends SystemService {
}); });
} }
@Override @Override // Binder call
// Binder call
public void remove(final IBinder token, final int fingerId, final int groupId, public void remove(final IBinder token, final int fingerId, final int groupId,
final IFingerprintServiceReceiver receiver) { final IFingerprintServiceReceiver receiver) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
@@ -574,17 +645,15 @@ public class FingerprintService extends SystemService {
} }
@Override @Override // Binder call
// Binder call
public boolean isHardwareDetected(long deviceId, String opPackageName) { public boolean isHardwareDetected(long deviceId, String opPackageName) {
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return false; return false;
} }
return mHalDeviceId != 0; // TODO return mHalDeviceId != 0;
} }
@Override @Override // Binder call
// Binder call
public void rename(final int fingerId, final int groupId, final String name) { public void rename(final int fingerId, final int groupId, final String name) {
checkPermission(MANAGE_FINGERPRINT); checkPermission(MANAGE_FINGERPRINT);
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@@ -595,69 +664,102 @@ public class FingerprintService extends SystemService {
}); });
} }
@Override @Override // Binder call
// Binder call
public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) { public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) {
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return Collections.emptyList(); return Collections.emptyList();
} }
return FingerprintService.this.getEnrolledFingerprints(groupId); return FingerprintService.this.getEnrolledFingerprints(groupId);
} }
@Override @Override // Binder call
// Binder call
public boolean hasEnrolledFingerprints(int groupId, String opPackageName) { public boolean hasEnrolledFingerprints(int groupId, String opPackageName) {
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return false; return false;
} }
return FingerprintService.this.hasEnrolledFingerprints(groupId); return FingerprintService.this.hasEnrolledFingerprints(groupId);
} }
@Override @Override // Binder call
public long getAuthenticatorId(String opPackageName) { public long getAuthenticatorId(String opPackageName) {
if (!canUserFingerPrint(opPackageName)) { if (!canUseFingerprint(opPackageName)) {
return 0; return 0;
} }
return nativeGetAuthenticatorId(); return FingerprintService.this.getAuthenticatorId();
} }
} }
@Override @Override
public void onStart() { public void onStart() {
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
mHalDeviceId = nativeOpenHal(); IFingerprintDaemon daemon = getFingerprintDaemon();
updateActiveGroup(ActivityManager.getCurrentUser()); if (daemon != null) {
try {
daemon.init(mDaemonCallback);
mHalDeviceId = daemon.openHal();
updateActiveGroup(ActivityManager.getCurrentUser());
} catch (RemoteException e) {
Slog.e(TAG, "Failed to open fingeprintd HAL", e);
}
}
if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
listenForUserSwitches(); listenForUserSwitches();
} }
private void updateActiveGroup(int userId) { private void updateActiveGroup(int userId) {
if (mHalDeviceId != 0) { IFingerprintDaemon daemon = getFingerprintDaemon();
File path = Environment.getUserSystemDirectory(userId); if (daemon != null) {
nativeSetActiveGroup(userId, path.getAbsolutePath().getBytes()); try {
// TODO: if this is a managed profile, use the profile parent's directory for
// storage.
final File systemDir = Environment.getUserSystemDirectory(userId);
final File fpDir = new File(systemDir, FP_DATA_DIR);
if (!fpDir.exists()) {
if (!fpDir.mkdir()) {
Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());
return;
}
}
daemon.setActiveGroup(userId, fpDir.getAbsolutePath().getBytes());
} catch (RemoteException e) {
Slog.e(TAG, "Failed to setActiveGroup():", e);
}
} }
} }
private void listenForUserSwitches() { private void listenForUserSwitches() {
try { try {
ActivityManagerNative.getDefault().registerUserSwitchObserver( ActivityManagerNative.getDefault().registerUserSwitchObserver(
new IUserSwitchObserver.Stub() { new IUserSwitchObserver.Stub() {
@Override @Override
public void onUserSwitching(int newUserId, IRemoteCallback reply) { public void onUserSwitching(int newUserId, IRemoteCallback reply) {
mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
.sendToTarget(); .sendToTarget();
} }
@Override @Override
public void onUserSwitchComplete(int newUserId) throws RemoteException { public void onUserSwitchComplete(int newUserId) throws RemoteException {
// Ignore. // Ignore.
} }
@Override @Override
public void onForegroundProfileSwitch(int newProfileId) { public void onForegroundProfileSwitch(int newProfileId) {
// Ignore. // Ignore.
} }
}); });
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.w(TAG, "Failed to listen for user switching event" ,e); Slog.w(TAG, "Failed to listen for user switching event" ,e);
} }
} }
public long getAuthenticatorId() {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon != null) {
try {
return daemon.getAuthenticatorId();
} catch (RemoteException e) {
Slog.e(TAG, "getAuthenticatorId failed", e);
}
}
return 0;
}
} }

View File

@@ -10,7 +10,6 @@ LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \ $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
$(LOCAL_REL_DIR)/com_android_server_fingerprint_FingerprintService.cpp \
$(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \

View File

@@ -41,7 +41,6 @@ int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_hdmi_HdmiCecController(JNIEnv* env); int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
int register_android_server_tv_TvInputHal(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env);
int register_android_server_PersistentDataBlockService(JNIEnv* env); int register_android_server_PersistentDataBlockService(JNIEnv* env);
int register_android_server_fingerprint_FingerprintService(JNIEnv* env);
int register_android_server_Watchdog(JNIEnv* env); int register_android_server_Watchdog(JNIEnv* env);
}; };
@@ -79,7 +78,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_hdmi_HdmiCecController(env); register_android_server_hdmi_HdmiCecController(env);
register_android_server_tv_TvInputHal(env); register_android_server_tv_TvInputHal(env);
register_android_server_PersistentDataBlockService(env); register_android_server_PersistentDataBlockService(env);
register_android_server_fingerprint_FingerprintService(env);
register_android_server_Watchdog(env); register_android_server_Watchdog(env);
return JNI_VERSION_1_4; return JNI_VERSION_1_4;