summaryrefslogtreecommitdiffstats
path: root/packages/Keyguard/src/com/android/keyguard
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2015-08-20 18:20:02 -0700
committerJorim Jaggi <jjaggi@google.com>2015-08-21 19:29:05 +0000
commit86bed40605e407459496ee2bfdf6b8af1ae1a581 (patch)
treebb55ec35000b1e43a95f3b4985fb4313f1887123 /packages/Keyguard/src/com/android/keyguard
parent446c00a2919da5b4ea0bdf08f72ac4f95125ea45 (diff)
downloadframeworks_base-86bed40605e407459496ee2bfdf6b8af1ae1a581.zip
frameworks_base-86bed40605e407459496ee2bfdf6b8af1ae1a581.tar.gz
frameworks_base-86bed40605e407459496ee2bfdf6b8af1ae1a581.tar.bz2
Fix fingerprint listening state race conditions
When calling cancel() on the cancellation signal, it doesn't happen immediately. Now, because of a state messup during boot, we go through the sequence startListeningForFingerprint stopListeningForFingerprint startListeningForFingerprint However, the cancellation callback from stopListeningForFingeprint happened AFTER the second startListeningForFingerprint, so we assumed that fingerprint detection was not running anymore but in reality it was - leading to weird states and all kinds of small state messups. Introduce a state machine to track when we we called cancel but waiting for the confirmation of FingerprintService in order to track this properly. Bug: 23380500 Change-Id: I403479fb749cf7c22b73611b69698e8b771777d0
Diffstat (limited to 'packages/Keyguard/src/com/android/keyguard')
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java103
1 files changed, 68 insertions, 35 deletions
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 40dcd0d..afa5ae2 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,36 +29,19 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Bitmap;
-
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_STATUS;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
-
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.media.AudioManager;
import android.os.BatteryManager;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.Message;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
-import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -71,6 +54,11 @@ import android.util.SparseIntArray;
import com.google.android.collect.Lists;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -79,6 +67,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_STATUS;
+
/**
* Watches for updates that may be interesting to the keyguard, and provides
* the up to date information as well as a registration for callbacks that care
@@ -138,6 +135,24 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final int MSG_SCREEN_TURNED_ON = 331;
private static final int MSG_SCREEN_TURNED_OFF = 332;
+ /** Fingerprint state: Not listening to fingerprint. */
+ private static final int FINGERPRINT_STATE_STOPPED = 0;
+
+ /** Fingerprint state: Listening. */
+ private static final int FINGERPRINT_STATE_RUNNING = 1;
+
+ /**
+ * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to
+ * send us the confirmation that cancellation has happened.
+ */
+ private static final int FINGERPRINT_STATE_CANCELLING = 2;
+
+ /**
+ * Fingerprint state: During cancelling we got another request to start listening, so when we
+ * receive the cancellation done signal, we should start listening again.
+ */
+ private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3;
+
private static KeyguardUpdateMonitor sInstance;
private final Context mContext;
@@ -180,8 +195,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private SubscriptionManager mSubscriptionManager;
private AlarmManager mAlarmManager;
private List<SubscriptionInfo> mSubscriptionInfo;
- private boolean mFingerprintDetectionRunning;
private TrustManager mTrustManager;
+ private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
private final Handler mHandler = new Handler() {
@Override
@@ -275,8 +290,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static int sCurrentUser;
- private int mFpWakeMode;
-
public synchronized static void setCurrentUser(int currentUser) {
sCurrentUser = currentUser;
}
@@ -429,7 +442,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
onFingerprintAuthenticated(userId);
} finally {
- setFingerprintRunningDetectionRunning(false);
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
}
}
@@ -443,7 +456,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void handleFingerprintError(int msgId, String errString) {
- setFingerprintRunningDetectionRunning(false);
+ if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
+ && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+ startListeningForFingerprint();
+ } else {
+ setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -452,9 +471,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
- private void setFingerprintRunningDetectionRunning(boolean running) {
- if (running != mFingerprintDetectionRunning) {
- mFingerprintDetectionRunning = running;
+ private void setFingerprintRunningState(int fingerprintRunningState) {
+ boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+ boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
+ mFingerprintRunningState = fingerprintRunningState;
+
+ // Clients of KeyguardUpdateMonitor don't care about the internal state about the
+ // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // has changed.
+ if (wasRunning != isRunning) {
notifyFingerprintRunningStateChanged();
}
}
@@ -463,7 +488,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onFingerprintRunningStateChanged(mFingerprintDetectionRunning);
+ cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning());
}
}
}
@@ -482,7 +507,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
public boolean isFingerprintDetectionRunning() {
- return mFingerprintDetectionRunning;
+ return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
}
private boolean isTrustDisabled(int userId) {
@@ -955,9 +980,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void updateFingerprintListeningState() {
boolean shouldListenForFingerprint = shouldListenForFingerprint();
- if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
stopListeningForFingerprint();
- } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
+ } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
+ && shouldListenForFingerprint) {
startListeningForFingerprint();
}
}
@@ -968,6 +994,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void startListeningForFingerprint() {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
+ return;
+ }
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
if (isUnlockWithFingerprintPossible(userId)) {
@@ -978,7 +1008,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
- setFingerprintRunningDetectionRunning(true);
+ setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
}
}
@@ -989,11 +1019,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void stopListeningForFingerprint() {
if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
- if (isFingerprintDetectionRunning()) {
+ if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) {
mFingerprintCancelSignal.cancel();
mFingerprintCancelSignal = null;
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
+ }
+ if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) {
+ setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING);
}
- setFingerprintRunningDetectionRunning(false);
}
private boolean isDeviceProvisionedInSettingsDb() {