am 4a306fd7: am 3a464785: Add a private API to get notified about lockout resets

* commit '4a306fd744bc2f6f434cb7032580b063b704a9c5':
  Add a private API to get notified about lockout resets
This commit is contained in:
Jorim Jaggi
2015-09-01 00:58:31 +00:00
committed by Android Git Automerger
6 changed files with 157 additions and 5 deletions

View File

@@ -160,6 +160,7 @@ LOCAL_SRC_FILES += \
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/IFingerprintServiceLockoutResetCallback.aidl \
core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
core/java/android/hardware/hdmi/IHdmiControlService.aidl \

View File

@@ -391,6 +391,18 @@ public class FingerprintManager {
public void onRemovalSucceeded(Fingerprint fingerprint) { }
};
/**
* @hide
*/
public static abstract class LockoutResetCallback {
/**
* Called when lockout period expired and clients are allowed to listen for fingerprint
* again.
*/
public void onLockoutReset() { }
};
/**
* Request authentication of a crypto object. This call warms up the fingerprint hardware
* and starts scanning for a fingerprint. It terminates when
@@ -680,10 +692,37 @@ public class FingerprintManager {
try {
mService.resetTimeout(token);
} catch (RemoteException e) {
Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
Log.v(TAG, "Remote exception in resetTimeout(): ", e);
}
} else {
Log.w(TAG, "getAuthenticatorId(): Service not connected!");
Log.w(TAG, "resetTimeout(): Service not connected!");
}
}
/**
* @hide
*/
public void addLockoutResetCallback(final LockoutResetCallback callback) {
if (mService != null) {
try {
mService.addLockoutResetCallback(
new IFingerprintServiceLockoutResetCallback.Stub() {
@Override
public void onLockoutReset(long deviceId) throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onLockoutReset();
}
});
}
});
} catch (RemoteException e) {
Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
}
} else {
Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
}
}

View File

@@ -17,6 +17,7 @@ package android.hardware.fingerprint;
import android.os.Bundle;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.hardware.fingerprint.Fingerprint;
import java.util.List;
@@ -71,4 +72,7 @@ interface IFingerprintService {
// Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
void resetTimeout(in byte [] cryptoToken);
// Add a callback which gets notified when the fingerprint lockout period expired.
void addLockoutResetCallback(IFingerprintServiceLockoutResetCallback callback);
}

View File

@@ -0,0 +1,28 @@
/*
* 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.Fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
/**
* Callback when lockout period expired and clients are allowed to authenticate again.
* @hide
*/
oneway interface IFingerprintServiceLockoutResetCallback {
void onLockoutReset(long deviceId);
}

View File

@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -472,6 +473,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
private void handleFingerprintLockoutReset() {
updateFingerprintListeningState();
}
private void setFingerprintRunningState(int fingerprintRunningState) {
boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
@@ -681,6 +686,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
};
private final FingerprintManager.LockoutResetCallback mLockoutResetCallback
= new FingerprintManager.LockoutResetCallback() {
@Override
public void onLockoutReset() {
handleFingerprintLockoutReset();
}
};
private FingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@@ -1003,6 +1016,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
updateFingerprintListeningState();
if (mFpm != null) {
mFpm.addLockoutResetCallback(mLockoutResetCallback);
}
}
private void updateFingerprintListeningState() {

View File

@@ -24,7 +24,9 @@ import android.app.IUserSwitchObserver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.os.Binder;
import android.os.DeadObjectException;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -51,7 +53,6 @@ import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintDaemon;
import android.hardware.fingerprint.IFingerprintDaemonCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.view.Display;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
@@ -60,6 +61,7 @@ import static android.Manifest.permission.USE_FINGERPRINT;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -83,6 +85,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
private ClientMonitor mAuthClient = null;
private ClientMonitor mEnrollClient = null;
private ClientMonitor mRemoveClient = null;
private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
new ArrayList<>();
private final AppOpsManager mAppOps;
private static final long MS_PER_SEC = 1000;
@@ -259,6 +263,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
// If we're asked to reset failed attempts externally (i.e. from Keyguard), the runnable
// may still be in the queue; remove it.
mHandler.removeCallbacks(mLockoutReset);
notifyLockoutResetMonitors();
}
private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
@@ -499,6 +504,23 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
opPackageName) == AppOpsManager.MODE_ALLOWED;
}
private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
if (!mLockoutMonitors.contains(monitor)) {
mLockoutMonitors.add(monitor);
}
}
private void removeLockoutResetCallback(
FingerprintServiceLockoutResetMonitor monitor) {
mLockoutMonitors.remove(monitor);
}
private void notifyLockoutResetMonitors() {
for (int i = 0; i < mLockoutMonitors.size(); i++) {
mLockoutMonitors.get(i).sendLockoutReset();
}
}
private class ClientMonitor implements IBinder.DeathRecipient {
IBinder token;
IFingerprintServiceReceiver receiver;
@@ -614,7 +636,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
FingerprintUtils.vibrateFingerprintSuccess(getContext());
}
result |= true; // we have a valid fingerprint
mLockoutReset.run();
mHandler.post(mLockoutReset);
}
return result;
}
@@ -654,6 +676,36 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
}
private class FingerprintServiceLockoutResetMonitor {
private final IFingerprintServiceLockoutResetCallback mCallback;
public FingerprintServiceLockoutResetMonitor(
IFingerprintServiceLockoutResetCallback callback) {
mCallback = callback;
}
public void sendLockoutReset() {
if (mCallback != null) {
try {
mCallback.onLockoutReset(mHalDeviceId);
} catch (DeadObjectException e) {
Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
mHandler.post(mRemoveCallbackRunnable);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
}
}
}
private final Runnable mRemoveCallbackRunnable = new Runnable() {
@Override
public void run() {
removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
}
};
}
private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
@Override
@@ -922,7 +974,19 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
public void resetTimeout(byte [] token) {
checkPermission(RESET_FINGERPRINT_LOCKOUT);
// TODO: confirm security token when we move timeout management into the HAL layer.
mLockoutReset.run();
mHandler.post(mLockoutReset);
}
@Override
public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
throws RemoteException {
mHandler.post(new Runnable() {
@Override
public void run() {
addLockoutResetMonitor(
new FingerprintServiceLockoutResetMonitor(callback));
}
});
}
}