diff options
author | Jorim Jaggi <jjaggi@google.com> | 2015-09-04 14:17:58 -0700 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2015-09-09 20:41:11 +0000 |
commit | 5e354223d817477efac9a6a2e3ce3d9161e046a4 (patch) | |
tree | d60fd7f5d402b7f0d7bd97e8693979dc060b9b48 | |
parent | ebd1465885af2a1de5a885dac791ee6184f85d7f (diff) | |
download | frameworks_base-5e354223d817477efac9a6a2e3ce3d9161e046a4.zip frameworks_base-5e354223d817477efac9a6a2e3ce3d9161e046a4.tar.gz frameworks_base-5e354223d817477efac9a6a2e3ce3d9161e046a4.tar.bz2 |
Use AlarmManager for lockout reset
So the lockout reset exactly fires after 30 seconds, independent
of whether the device was in deep sleep.
Bug: 23668918
Change-Id: Idea1a877c395897c1fd075cf98edf41c8b1f4082
3 files changed, 56 insertions, 12 deletions
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 1f23c0a..7fef5e1 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -27,6 +27,7 @@ import android.os.CancellationSignal.OnCancelListener; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; import android.security.keystore.AndroidKeyStoreProvider; @@ -705,15 +706,23 @@ public class FingerprintManager { public void addLockoutResetCallback(final LockoutResetCallback callback) { if (mService != null) { try { + final PowerManager powerManager = mContext.getSystemService(PowerManager.class); mService.addLockoutResetCallback( new IFingerprintServiceLockoutResetCallback.Stub() { @Override public void onLockoutReset(long deviceId) throws RemoteException { + final PowerManager.WakeLock wakeLock = powerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback"); + wakeLock.acquire(); mHandler.post(new Runnable() { @Override public void run() { - callback.onLockoutReset(); + try { + callback.onLockoutReset(); + } finally { + wakeLock.release(); + } } }); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl index c9a5d59..e027a2b 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl @@ -23,6 +23,8 @@ import android.os.UserHandle; * Callback when lockout period expired and clients are allowed to authenticate again. * @hide */ -oneway interface IFingerprintServiceLockoutResetCallback { +interface IFingerprintServiceLockoutResetCallback { + + /** Method is synchronous so wakelock is held when this is called from a WAKEUP alarm. */ void onLockoutReset(long deviceId); } diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 0023258..ea7d85e 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -21,10 +21,15 @@ import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManagerNative; +import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.IUserSwitchObserver; +import android.app.PendingIntent; import android.content.ComponentName; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback; @@ -85,6 +90,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe 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 static final String ACTION_LOCKOUT_RESET = + "com.android.server.fingerprint.ACTION_LOCKOUT_RESET"; private ClientMonitor mAuthClient = null; private ClientMonitor mEnrollClient = null; @@ -118,9 +125,19 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private long mHalDeviceId; private int mFailedAttempts; private IFingerprintDaemon mDaemon; - private PowerManager mPowerManager; + private final PowerManager mPowerManager; + private final AlarmManager mAlarmManager; - private final Runnable mLockoutReset = new Runnable() { + private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) { + resetFailedAttempts(); + } + } + }; + + private final Runnable mResetFailedAttemptsRunnable = new Runnable() { @Override public void run() { resetFailedAttempts(); @@ -133,7 +150,10 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( com.android.internal.R.string.config_keyguardComponent)).getPackageName(); mAppOps = context.getSystemService(AppOpsManager.class); - mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mPowerManager = mContext.getSystemService(PowerManager.class); + mAlarmManager = mContext.getSystemService(AlarmManager.class); + mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET), + RESET_FINGERPRINT_LOCKOUT, null /* handler */); } @Override @@ -262,14 +282,28 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return mFailedAttempts >= MAX_FAILED_ATTEMPTS; } + private void scheduleLockoutReset() { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, getLockoutResetIntent()); + } + + private void cancelLockoutReset() { + mAlarmManager.cancel(getLockoutResetIntent()); + } + + private PendingIntent getLockoutResetIntent() { + return PendingIntent.getBroadcast(mContext, 0, + new Intent(ACTION_LOCKOUT_RESET), PendingIntent.FLAG_UPDATE_CURRENT); + } + private void resetFailedAttempts() { if (DEBUG && inLockoutMode()) { Slog.v(TAG, "Reset fingerprint lockout"); } mFailedAttempts = 0; - // 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); + // If we're asked to reset failed attempts externally (i.e. from Keyguard), the alarm might + // still be pending; remove it. + cancelLockoutReset(); notifyLockoutResetMonitors(); } @@ -277,8 +311,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mFailedAttempts++; if (inLockoutMode()) { // Failing multiple times will continue to push out the lockout time. - mHandler.removeCallbacks(mLockoutReset); - mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS); + scheduleLockoutReset(); if (clientMonitor != null && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { Slog.w(TAG, "Cannot send lockout message to client"); @@ -683,7 +716,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe FingerprintUtils.vibrateFingerprintSuccess(getContext()); } result |= true; // we have a valid fingerprint - mHandler.post(mLockoutReset); + resetFailedAttempts(); } return result; } @@ -1016,7 +1049,7 @@ 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. - mHandler.post(mLockoutReset); + mHandler.post(mResetFailedAttemptsRunnable); } @Override |