diff options
author | Jorim Jaggi <jjaggi@google.com> | 2015-05-13 20:32:30 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-05-13 20:32:31 +0000 |
commit | 131a19ee6f55d95d747d3d1ed62537b1db5a2e69 (patch) | |
tree | 163fcc18f15a89eaf9596d92f97559080d54ea31 | |
parent | d90bf46264615159e1e16ee69e78a8651e126d6e (diff) | |
parent | ee77cebc1a54a0bee1a1d538db0abed00aa9cb4e (diff) | |
download | frameworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.zip frameworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.tar.gz frameworks_base-131a19ee6f55d95d747d3d1ed62537b1db5a2e69.tar.bz2 |
Merge "Persist fingerprint names" into mnc-dev
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))); + } + } + } + +} |