summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorim Jaggi <jjaggi@google.com>2015-05-13 20:32:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-13 20:32:31 +0000
commit131a19ee6f55d95d747d3d1ed62537b1db5a2e69 (patch)
tree163fcc18f15a89eaf9596d92f97559080d54ea31
parentd90bf46264615159e1e16ee69e78a8651e126d6e (diff)
parentee77cebc1a54a0bee1a1d538db0abed00aa9cb4e (diff)
downloadframeworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.zip
frameworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.tar.gz
frameworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.tar.bz2
Merge "Persist fingerprint names" into mnc-dev
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintUtils.java126
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/res/res/values/strings.xml3
-rwxr-xr-xcore/res/res/values/symbols.xml1
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java12
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java38
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintUtils.java95
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintsUserState.java247
8 files changed, 358 insertions, 170 deletions
diff --git a/core/java/android/hardware/fingerprint/FingerprintUtils.java b/core/java/android/hardware/fingerprint/FingerprintUtils.java
deleted file mode 100644
index 525f254..0000000
--- a/core/java/android/hardware/fingerprint/FingerprintUtils.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * 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;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utility class for dealing with fingerprints and fingerprint settings.
- * @hide
- */
-public
-class FingerprintUtils {
- private static final boolean DEBUG = true;
- private static final String TAG = "FingerprintUtils";
- private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
- private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
-
- private static int[] toIntArray(List<Integer> list) {
- if (list == null) {
- return null;
- }
- int[] arr = new int[list.size()];
- int i = 0;
- for (int elem : list) {
- arr[i] = elem;
- i++;
- }
- return arr;
- }
-
- public static int[] getFingerprintIdsForUser(ContentResolver res, int userId) {
- String fingerIdsRaw = Settings.Secure.getStringForUser(res,
- Settings.Secure.USER_FINGERPRINT_IDS, userId);
- ArrayList<Integer> tmp = new ArrayList<Integer>();
- if (!TextUtils.isEmpty(fingerIdsRaw)) {
- String[] fingerStringIds = fingerIdsRaw.replace("[","").replace("]","").split(", ");
- int length = fingerStringIds.length;
- for (int i = 0; i < length; i++) {
- try {
- tmp.add(Integer.decode(fingerStringIds[i]));
- } catch (NumberFormatException e) {
- if (DEBUG) Log.w(TAG, "Error parsing finger id: '" + fingerStringIds[i] + "'");
- }
- }
- }
- return toIntArray(tmp);
- }
-
- public static void addFingerprintIdForUser(ContentResolver res, int fingerId, int userId) {
- // FingerId 0 has special meaning.
- if (fingerId == 0) {
- Log.w(TAG, "Tried to add fingerId 0");
- return;
- }
-
- int[] fingerIds = getFingerprintIdsForUser(res, userId);
-
- // Don't allow dups
- if (ArrayUtils.contains(fingerIds, fingerId)) {
- Log.w(TAG, "finger already added " + fingerId);
- return;
- }
- int[] newList = Arrays.copyOf(fingerIds, fingerIds.length + 1);
- newList[fingerIds.length] = fingerId;
- Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
- Arrays.toString(newList), userId);
- }
-
- public static boolean removeFingerprintIdForUser(int fingerId, ContentResolver res, int userId)
- {
- // FingerId 0 has special meaning. The HAL layer is supposed to remove each finger one
- // at a time and invoke notify() for each fingerId. If we get called with 0 here, it means
- // something bad has happened.
- if (fingerId == 0) throw new IllegalArgumentException("fingerId can't be 0");
-
- final int[] fingerIds = getFingerprintIdsForUser(res, userId);
- if (ArrayUtils.contains(fingerIds, fingerId)) {
- final int[] result = ArrayUtils.removeInt(fingerIds, fingerId);
- Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
- Arrays.toString(result), userId);
- return true;
- }
- return false;
- }
-
- public static void vibrateFingerprintError(Context context) {
- Vibrator vibrator = context.getSystemService(Vibrator.class);
- if (vibrator != null) {
- vibrator.vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
- }
- }
-
- public static void vibrateFingerprintSuccess(Context context) {
- Vibrator vibrator = context.getSystemService(Vibrator.class);
- if (vibrator != null) {
- vibrator.vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
- }
- }
-
-};
-
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d3a5561..c514180 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4363,12 +4363,6 @@ public final class Settings {
"lock_screen_appwidget_ids";
/**
- * List of enrolled fingerprint identifiers (comma-delimited).
- * @hide
- */
- public static final String USER_FINGERPRINT_IDS = "user_fingerprint_ids";
-
- /**
* Id of the appwidget shown on the lock screen when appwidgets are disabled.
* @hide
*/
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 47ff16b..bd4d73d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1255,6 +1255,9 @@
<!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
<string name="fingerprint_error_unable_to_process">Try again.</string>
+ <!-- Template to be used to name enrolled fingerprints by default. -->
+ <string name="fingerprint_name_template">Finger <xliff:g id="fingerId" example="1">%d</xliff:g></string>
+
<!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings -->
<string-array name="fingerprint_error_vendor">
</string-array>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1f6e861..8292e23 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2112,6 +2112,7 @@
<java-symbol type="array" name="fingerprint_acquired_vendor" />
<java-symbol type="string" name="fingerprint_error_canceled" />
<java-symbol type="string" name="fingerprint_error_lockout" />
+ <java-symbol type="string" name="fingerprint_name_template" />
<!-- From various Material changes -->
<java-symbol type="attr" name="titleTextAppearance" />
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d13d71c..1cee642 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -24,7 +24,6 @@ import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -56,7 +55,6 @@ import com.android.internal.telephony.TelephonyIntents;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
-import android.hardware.fingerprint.FingerprintUtils;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -367,14 +365,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
return;
}
- final ContentResolver res = mContext.getContentResolver();
- final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
- for (int i = 0; i < ids.length; i++) {
- // TODO: fix once HAL supports storing group id
- final boolean isCorrectUser = true || (groupId == userId);
- if (ids[i] == fingerId && isCorrectUser) {
- onFingerprintAuthenticated(userId);
- }
+ if (groupId == userId) {
+ onFingerprintAuthenticated(groupId);
}
} finally {
setFingerprintRunningDetectionRunning(false);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 0faccc6..aa143e4 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -31,7 +31,6 @@ import android.util.Slog;
import com.android.server.SystemService;
-import android.hardware.fingerprint.FingerprintUtils;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintService;
@@ -93,6 +92,7 @@ public class FingerprintService extends SystemService {
private Context mContext;
private int mHalDeviceId;
private int mFailedAttempts;
+ private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
private final Runnable mLockoutReset = new Runnable() {
@Override
public void run() {
@@ -172,7 +172,6 @@ public class FingerprintService extends SystemService {
* @return true if the operation is done, i.e. authentication completed
*/
boolean dispatchNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
- ContentResolver contentResolver = mContext.getContentResolver();
boolean operationCompleted = false;
int fpId;
int groupId;
@@ -198,7 +197,7 @@ public class FingerprintService extends SystemService {
remaining = arg3;
operationCompleted = clientMonitor.sendEnrollResult(fpId, groupId, remaining);
if (remaining == 0) {
- addTemplateForUser(clientMonitor, contentResolver, fpId);
+ addTemplateForUser(clientMonitor, fpId);
operationCompleted = true; // enroll completed
}
break;
@@ -207,7 +206,7 @@ public class FingerprintService extends SystemService {
groupId = arg2;
operationCompleted = clientMonitor.sendRemoved(fpId, groupId);
if (fpId != 0) {
- removeTemplateForUser(clientMonitor, contentResolver, fpId);
+ removeTemplateForUser(clientMonitor, fpId);
}
break;
}
@@ -252,16 +251,12 @@ public class FingerprintService extends SystemService {
return false;
}
- private void removeTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
- final int fingerId) {
- FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
- clientMonitor.userId);
+ private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
+ mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId);
}
- private void addTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
- final int fingerId) {
- FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
- clientMonitor.userId);
+ private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
+ mFingerprintUtils.addFingerprintForUser(mContext, fingerId, clientMonitor.userId);
}
void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
@@ -345,24 +340,11 @@ public class FingerprintService extends SystemService {
}
public List<Fingerprint> getEnrolledFingerprints(int groupId) {
- ContentResolver resolver = mContext.getContentResolver();
- int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
- List<Fingerprint> result = new ArrayList<Fingerprint>();
- for (int i = 0; i < ids.length; i++) {
- // TODO: persist names in Settings
- CharSequence name = "Finger" + ids[i];
- final int group = 0; // TODO
- final int fingerId = ids[i];
- final long deviceId = 0; // TODO
- Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
- result.add(item);
- }
- return result;
+ return mFingerprintUtils.getFingerprintsForUser(mContext, groupId);
}
public boolean hasEnrolledFingerprints(int groupId) {
- ContentResolver resolver = mContext.getContentResolver();
- return FingerprintUtils.getFingerprintIdsForUser(resolver, groupId).length > 0;
+ return mFingerprintUtils.getFingerprintsForUser(mContext, groupId).size() > 0;
}
void checkPermission(String permission) {
@@ -596,7 +578,7 @@ public class FingerprintService extends SystemService {
mHandler.post(new Runnable() {
@Override
public void run() {
- Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
+ mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, groupId, name);
}
});
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintUtils.java b/services/core/java/com/android/server/fingerprint/FingerprintUtils.java
new file mode 100644
index 0000000..1e6e105
--- /dev/null
+++ b/services/core/java/com/android/server/fingerprint/FingerprintUtils.java
@@ -0,0 +1,95 @@
+/**
+ * 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 com.android.server.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.Fingerprint;
+import android.os.Vibrator;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.List;
+
+/**
+ * Utility class for dealing with fingerprints and fingerprint settings.
+ */
+public class FingerprintUtils {
+
+ private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
+ private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
+
+ private static final Object sInstanceLock = new Object();
+ private static FingerprintUtils sInstance;
+
+ @GuardedBy("this")
+ private final SparseArray<FingerprintsUserState> mUsers = new SparseArray<>();
+
+ public static FingerprintUtils getInstance() {
+ synchronized (sInstanceLock) {
+ if (sInstance == null) {
+ sInstance = new FingerprintUtils();
+ }
+ }
+ return sInstance;
+ }
+
+ private FingerprintUtils() {
+ }
+
+ public List<Fingerprint> getFingerprintsForUser(Context ctx, int userId) {
+ return getStateForUser(ctx, userId).getFingerprints();
+ }
+
+ public void addFingerprintForUser(Context ctx, int fingerId, int userId) {
+ getStateForUser(ctx, userId).addFingerprint(fingerId);
+ }
+
+ public void removeFingerprintIdForUser(Context ctx, int fingerId, int userId) {
+ getStateForUser(ctx, userId).removeFingerprint(fingerId);
+ }
+
+ public void renameFingerprintForUser(Context ctx, int fingerId, int userId, CharSequence name) {
+ getStateForUser(ctx, userId).renameFingerprint(fingerId, name);
+ }
+
+ public static void vibrateFingerprintError(Context context) {
+ Vibrator vibrator = context.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
+ }
+ }
+
+ public static void vibrateFingerprintSuccess(Context context) {
+ Vibrator vibrator = context.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
+ }
+ }
+
+ private FingerprintsUserState getStateForUser(Context ctx, int userId) {
+ synchronized (this) {
+ FingerprintsUserState state = mUsers.get(userId);
+ if (state == null) {
+ state = new FingerprintsUserState(ctx, userId);
+ mUsers.put(userId, state);
+ }
+ return state;
+ }
+ }
+}
+
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
new file mode 100644
index 0000000..33177b4
--- /dev/null
+++ b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java
@@ -0,0 +1,247 @@
+/*
+ * 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 com.android.server.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.Fingerprint;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class managing the set of fingerprint per user across device reboots.
+ */
+class FingerprintsUserState {
+
+ private static final String TAG = "FingerprintState";
+ private static final String FINGERPRINT_FILE = "settings_fingerprint.xml";
+
+ private static final String TAG_FINGERPRINTS = "fingerprints";
+ private static final String TAG_FINGERPRINT = "fingerprint";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_GROUP_ID = "groupId";
+ private static final String ATTR_FINGER_ID = "fingerId";
+ private static final String ATTR_DEVICE_ID = "deviceId";
+
+ private final File mFile;
+
+ @GuardedBy("this")
+ private final ArrayList<Fingerprint> mFingerprints = new ArrayList<>();
+ private final Context mCtx;
+
+ public FingerprintsUserState(Context ctx, int userId) {
+ mFile = getFileForUser(userId);
+ mCtx = ctx;
+ synchronized (this) {
+ readStateSyncLocked();
+ }
+ }
+
+ public void addFingerprint(int fingerId) {
+ synchronized (this) {
+ mFingerprints.add(new Fingerprint(getDefaultFingerprintName(fingerId), 0, fingerId, 0));
+ scheduleWriteStateLocked();
+ }
+ }
+
+ public void removeFingerprint(int fingerId) {
+ synchronized (this) {
+ for (int i = 0; i < mFingerprints.size(); i++) {
+ if (mFingerprints.get(i).getFingerId() == fingerId) {
+ mFingerprints.remove(i);
+ scheduleWriteStateLocked();
+ break;
+ }
+ }
+ }
+ }
+
+ public void renameFingerprint(int fingerId, CharSequence name) {
+ synchronized (this) {
+ for (int i = 0; i < mFingerprints.size(); i++) {
+ if (mFingerprints.get(i).getFingerId() == fingerId) {
+ Fingerprint old = mFingerprints.get(i);
+ mFingerprints.set(i, new Fingerprint(name, old.getGroupId(), old.getFingerId(),
+ old.getDeviceId()));
+ scheduleWriteStateLocked();
+ break;
+ }
+ }
+ }
+ }
+
+ public List<Fingerprint> getFingerprints() {
+ synchronized (this) {
+ return getCopy(mFingerprints);
+ }
+ }
+
+ private String getDefaultFingerprintName(int fingerId) {
+ return mCtx.getString(com.android.internal.R.string.fingerprint_name_template, fingerId);
+ }
+
+ private static File getFileForUser(int userId) {
+ return new File(Environment.getUserSystemDirectory(userId), FINGERPRINT_FILE);
+ }
+
+ private final Runnable mWriteStateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ doWriteState();
+ }
+ };
+
+ private void scheduleWriteStateLocked() {
+ AsyncTask.execute(mWriteStateRunnable);
+ }
+
+ private ArrayList<Fingerprint> getCopy(ArrayList<Fingerprint> array) {
+ ArrayList<Fingerprint> result = new ArrayList<>(array.size());
+ for (int i = 0; i < array.size(); i++) {
+ Fingerprint fp = array.get(i);
+ result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getFingerId(),
+ fp.getDeviceId()));
+ }
+ return result;
+ }
+
+ private void doWriteState() {
+ AtomicFile destination = new AtomicFile(mFile);
+
+ ArrayList<Fingerprint> fingerprints;
+
+ synchronized (this) {
+ fingerprints = getCopy(mFingerprints);
+ }
+
+ FileOutputStream out = null;
+ try {
+ out = destination.startWrite();
+
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(out, "utf-8");
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_FINGERPRINTS);
+
+ final int count = fingerprints.size();
+ for (int i = 0; i < count; i++) {
+ Fingerprint fp = fingerprints.get(i);
+ serializer.startTag(null, TAG_FINGERPRINT);
+ serializer.attribute(null, ATTR_FINGER_ID, Integer.toString(fp.getFingerId()));
+ serializer.attribute(null, ATTR_NAME, fp.getName().toString());
+ serializer.attribute(null, ATTR_GROUP_ID, Integer.toString(fp.getGroupId()));
+ serializer.attribute(null, ATTR_DEVICE_ID, Long.toString(fp.getDeviceId()));
+ serializer.endTag(null, TAG_FINGERPRINT);
+ }
+
+ serializer.endTag(null, TAG_FINGERPRINTS);
+ serializer.endDocument();
+ destination.finishWrite(out);
+
+ // Any error while writing is fatal.
+ } catch (Throwable t) {
+ Slog.wtf(TAG, "Failed to write settings, restoring backup", t);
+ destination.failWrite(out);
+ throw new IllegalStateException("Failed to write fingerprints", t);
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+
+ private void readStateSyncLocked() {
+ FileInputStream in;
+ if (!mFile.exists()) {
+ return;
+ }
+ try {
+ in = new FileInputStream(mFile);
+ } catch (FileNotFoundException fnfe) {
+ Slog.i(TAG, "No fingerprint state");
+ return;
+ }
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseStateLocked(parser);
+
+ } catch (XmlPullParserException | IOException e) {
+ throw new IllegalStateException("Failed parsing settings file: "
+ + mFile , e);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ private void parseStateLocked(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_FINGERPRINTS)) {
+ parseFingerprintsLocked(parser);
+ }
+ }
+ }
+
+ private void parseFingerprintsLocked(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_FINGERPRINT)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ String groupId = parser.getAttributeValue(null, ATTR_GROUP_ID);
+ String fingerId = parser.getAttributeValue(null, ATTR_FINGER_ID);
+ String deviceId = parser.getAttributeValue(null, ATTR_DEVICE_ID);
+ mFingerprints.add(new Fingerprint(name, Integer.parseInt(groupId),
+ Integer.parseInt(fingerId), Integer.parseInt(deviceId)));
+ }
+ }
+ }
+
+}