summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xAndroidManifest.xml2
-rw-r--r--etc/sample_nfcee_access.xml45
-rwxr-xr-xres/values/strings.xml7
-rwxr-xr-xsrc/com/android/nfc/NfcService.java85
-rw-r--r--src/com/android/nfc/NfceeAccessControl.java289
5 files changed, 393 insertions, 35 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 38dd575..6177da4 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -23,7 +23,7 @@
<permission android:name="com.android.nfc.permission.NFCEE_ADMIN"
android:label="@string/permlab_nfcAdmin"
android:description="@string/permdesc_nfcAdmin"
- android:protectionLevel="signature"
+ android:protectionLevel="dangerous"
/>
<application android:name="com.android.nfc.NfcService"
diff --git a/etc/sample_nfcee_access.xml b/etc/sample_nfcee_access.xml
new file mode 100644
index 0000000..d6c8707
--- /dev/null
+++ b/etc/sample_nfcee_access.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The built in list of signatures and package names that are allowed
+ access to the NFCEE (Secure Element).
+
+ Format:
+ <signer android:signature="SIGNATURE">
+ <package android:name="PACKAGE_NAME" />
+ ...
+ </signer>
+ ...
+
+ Rules:
+ SIGNATURE is a hex encoded X.509 certificate
+ See Debug section to generate hex encoded certificates.
+ PACKAGE_NAME is a Android package name
+ Zero or more signer tags are allowed.
+ Each signer tag must have one android:signature.
+ Zero or more package tags are allowed per signer.
+ Each package tag must have one android:name.
+ If a signer has zero package tags, then ANY application with the
+ specified certificate is granted NFCEE access.
+ If a signer has one or more package tags, then an application signed
+ with the specified certificate must have a package name that is an
+ exact match of one of the specified package names to be granted
+ NFCEE access.
+ Duplicate signer tags are not allowed.
+ Duplicate package tags for a single signer are not allowed.
+
+ Example:
+ In this example, any application from the first signer is granted
+ access, but only applications with the specified package names
+ are granted access for the second signer.
+ <signer android:signature="308201c53082012ea00302010202044ebb27cc300d06092a864886f70d01010505003026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c793020170d3131313131303031323432385a180f32313131313031373031323432385a3026310f300d060355040a1306476f6f676c65311330110603550403130a4e69636b2050656c6c7930819f300d06092a864886f70d010101050003818d00308189028181008d43e546b3f5572707a095ced120d8f06781fa162bcf0ffa0ed0ecb48eb90ed009f65a5a1afd69fb4d38cf24e931b69b061741b8c7ca9f785ba59509e883f5a308f5e2da3c496bb362a2229da8f95f08a92f7f94c829c56e78a34e5147d138d0be0671cb5b7caceaffae6199ba544496a7645e7df3c9f02c5ac156eb0501584f0203010001300d06092a864886f70d0101050500038181003511bcb73651a7927db71ad76e4f6dc5ba121c941ae0fd4dfe519aae8775520b204a5e3cdad2c61ad41aff2c510dbe3376a7578d8aba00f35633e1ae72c91ec83d80eac6f5f081fb8361c6c30c47b0a17932d859d7e991e02cba410a82b35234b2b1bc859e50fe308bf9b64b71a8046777300c07ead159287c187b8865e23f23" />
+ <signer android:signature="3082044c30820334a003020102020900de7695041d7650c0300d06092a864886f70d01010505003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643301e170d3131303332343031303332345a170d3338303830393031303332345a3077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e464330820120300d06092a864886f70d01010105000382010d00308201080282010100e6ff3defe92aa10d71eb0fa6408bc036b7e243eeed68a6a4763dc7a52a31757cdac61fe510bb73c716e4000104265b347fcecef4c42bf1e1379dd0a876f028227fbbc1f9bdd5d713b2f6a935a379d2cba9c96f92d2d0787c11f1eb19548008a6a072b34b91836cfa0ae1276780e9007530166986a11c9cef46cef7c704806dde9431fb60284d120ab0e7de1d633f07687d468c51139afffdc6bc9a207ca904b8be1da0aa7b4e97756f43606488be5cae3c68e8bb7942cdf51607c930a2fcda655b75d0759cba89ad06e739bd0ba29b1f404296c2c0a85a847f5ab0d067c6c3ec9c49212042ac63a7e53b546c65b46080b4e3e680e23e1f77cfe7f6de744b1a65020103a381dc3081d9301d0603551d0e04160414a2e89064b05d08865c34db930a9d840050117aec3081a90603551d230481a130819e8014a2e89064b05d08865c34db930a9d840050117aeca17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f6964311330110603550403130a476f6f676c65204e4643820900de7695041d7650c0300c0603551d13040530030101ff300d06092a864886f70d010105050003820101003771870ce87c3c52ea84899230c6e962d94b4d5f1293c25d88261541fd90b5555d1285cef3b8312c3f5df691a8aae04cb981b305e427fd1d2d9e1987e1d29078f13c8452990f1821980263d8d4bd36519348d8d8ba26d8b99fbf09f5fd3ebb0ea3c2f0c9376f1e1fca76f3a6a405429d081b752a7a90b756e9ab44da41abc8e1e8f88ac2758da743fb73e650719a57840ccb6b7add21b99fc681e456e1872c223d5c074adf55f6abda268c2d8b64ea0a8845eecd968f92b493127e75c753c3ff30cbc678b51c9f52961472f17da20a0dc6274aa2463434c1a9b614df697d8ff5ca8101e7a25c7db3fb055d65569c04b01d389cabba57b3a1703ec2e74a88d334">
+ <package android:name="com.foo.my.awesome.wallet" />
+ <package android:name="com.foo.my.awesome.wallet.tests" />
+ </signer>
+
+ Debug:
+ Including the tag <debug /> will print to logcat the
+ hex encoded signature of applications that are denied NFCEE
+ access, for easy cut-and-paste into this file.
+ -->
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 42b76e2..903103a 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2,13 +2,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Nfc Service</string>
<string name="nfcUserLabel">Nfc</string>
-
- <!-- The label for the NFC admin permission -->
- <string name="permlab_nfcAdmin">control NFC secure hardware</string>
-
- <!-- The description for the NFC admin permission -->
- <string name="permdesc_nfcAdmin">Allows the app to control the secure hardware used with NFC,
- for example, to modify payment credentials.</string>
<!-- A notification description string informing the user that contact details were received over NFC [CHAR-LIMIT=64] -->
<string name="inbound_me_profile_title">Contact received over NFC</string>
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 68e7598..4325183 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -35,7 +35,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
@@ -71,22 +73,24 @@ import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.concurrent.ExecutionException;
public class NfcService extends Application implements DeviceHostListener {
private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
- static final boolean DBG = true;
+ static final boolean DBG = false;
static final String TAG = "NfcService";
public static final String SERVICE_NAME = "nfc";
+ /** Regular NFC permission */
private static final String NFC_PERM = android.Manifest.permission.NFC;
private static final String NFC_PERM_ERROR = "NFC permission required";
+
+ /** NFC ADMIN permission - only for system apps */
private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
- private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
- private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
public static final String PREF = "NfcServicePrefs";
@@ -194,6 +198,7 @@ public class NfcService extends Application implements DeviceHostListener {
NfcAdapterExtrasService mExtrasService;
boolean mIsAirplaneSensitive;
boolean mIsAirplaneToggleable;
+ NfceeAccessControl mNfceeAccessControl;
private NfcDispatcher mNfcDispatcher;
private KeyguardManager mKeyguard;
@@ -201,16 +206,18 @@ public class NfcService extends Application implements DeviceHostListener {
private static NfcService sService;
public static void enforceAdminPerm(Context context) {
- int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
- int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
- if (admin != PackageManager.PERMISSION_GRANTED
- && nfcee != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(ADMIN_PERM_ERROR);
- }
+ context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
}
- public static void enforceNfceeAdminPerm(Context context) {
- context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
+ public void enforceNfceeAdminPerm(String pkg) {
+ if (pkg == null) {
+ throw new SecurityException("caller must pass a package name");
+ }
+ mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
+ if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) {
+ throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
+ " denies NFCEE access to " + pkg);
+ }
}
public static NfcService getInstance() {
@@ -300,6 +307,8 @@ public class NfcService extends Application implements DeviceHostListener {
mSecureElement = new NativeNfcSecureElement();
mEeRoutingState = ROUTE_OFF;
+ mNfceeAccessControl = new NfceeAccessControl(this);
+
mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
mPrefsEditor = mPrefs.edit();
@@ -725,8 +734,8 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
- public INfcAdapterExtras getNfcAdapterExtrasInterface() {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
return mExtrasService;
}
@@ -1150,8 +1159,8 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
- public Bundle open(IBinder b) throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public Bundle open(String pkg, IBinder b) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
Bundle result;
try {
@@ -1194,8 +1203,10 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
- public Bundle close() throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public Bundle close(String pkg, IBinder b) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ b.unlinkToDeath(mOpenEe, 0);
Bundle result;
try {
@@ -1208,8 +1219,8 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
- public Bundle transceive(byte[] in) throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public Bundle transceive(String pkg, byte[] in) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
Bundle result;
byte[] out;
@@ -1240,21 +1251,21 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
- public int getCardEmulationRoute() throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public int getCardEmulationRoute(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
return mEeRoutingState;
}
@Override
- public void setCardEmulationRoute(int route) throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public void setCardEmulationRoute(String pkg, int route) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
mEeRoutingState = route;
applyRouting();
}
@Override
- public void authenticate(byte[] token) throws RemoteException {
- NfcService.enforceNfceeAdminPerm(mContext);
+ public void authenticate(String pkg, byte[] token) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
}
};
@@ -1565,9 +1576,24 @@ public class NfcService extends Application implements DeviceHostListener {
}
private void sendSeBroadcast(Intent intent) {
- mNfcDispatcher.resumeAppSwitches();
+ PackageManager pm = getPackageManager();
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- mContext.sendBroadcast(intent, NFCEE_ADMIN_PERM);
+
+ // Resume app switches so the receivers can start activites without delay
+ mNfcDispatcher.resumeAppSwitches();
+
+ // Find the matching receivers and check each one for access permissions
+ List<ResolveInfo> receivers = pm.queryBroadcastReceivers(intent, 0);
+ for (ResolveInfo receiver : receivers) {
+ ActivityInfo activityInfo = receiver.activityInfo;
+ if (activityInfo != null) {
+ if (mNfceeAccessControl.check(activityInfo.applicationInfo)) {
+ intent.setComponent(new ComponentName(receiver.activityInfo.packageName,
+ receiver.activityInfo.name));
+ mContext.sendBroadcast(intent);
+ }
+ }
+ }
}
private boolean llcpActivated(NfcDepEndpoint device) {
@@ -1730,6 +1756,9 @@ public class NfcService extends Application implements DeviceHostListener {
Log.w(TAG, "failed to wipe NFC-EE");
}
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
+ // Clear the NFCEE access cache in case a UID gets recycled
+ mNfceeAccessControl.invalidateCache();
+
boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
if (dataRemoved) {
Uri data = intent.getData();
@@ -1800,7 +1829,9 @@ public class NfcService extends Application implements DeviceHostListener {
pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive);
pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable);
mP2pLinkManager.dump(fd, pw, args);
+ mNfceeAccessControl.dump(fd, pw, args);
pw.println(mDeviceHost.dump());
+
}
}
}
diff --git a/src/com/android/nfc/NfceeAccessControl.java b/src/com/android/nfc/NfceeAccessControl.java
new file mode 100644
index 0000000..9056b99
--- /dev/null
+++ b/src/com/android/nfc/NfceeAccessControl.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2011 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.nfc;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Environment;
+import android.util.Log;
+
+public class NfceeAccessControl {
+ static final String TAG = "NfceeAccess";
+ static final boolean DBG = true;
+
+ public static final String NFCEE_ACCESS_PATH = "/etc/nfcee_access.xml";
+
+ /**
+ * Map of signatures to valid packages names, as read from nfcee_access.xml.
+ * An empty list of package names indicates that any package
+ * with this signature is allowed.
+ */
+ final HashMap<Signature, String[]> mNfceeAccess; // contents final after onCreate()
+
+ /**
+ * Map from UID to NFCEE access, used as a cache.
+ * Note: if a UID contains multiple packages they must all be
+ * signed with the same certificate so in effect UID == certificate
+ * used to sign the package.
+ */
+ final HashMap<Integer, Boolean> mUidCache; // contents guarded by this
+
+ final Context mContext;
+ final boolean mDebugPrintSignature;
+
+ NfceeAccessControl(Context context) {
+ mContext = context;
+ mNfceeAccess = new HashMap<Signature, String[]>();
+ mUidCache = new HashMap<Integer, Boolean>();
+ mDebugPrintSignature = parseNfceeAccess();
+ }
+
+ /**
+ * Check if the {uid, pkg} combination may use NFCEE.
+ * Also verify with package manager that this {uid, pkg} combination
+ * is valid if it is not cached.
+ */
+ public boolean check(int uid, String pkg) {
+ synchronized (this) {
+ Boolean cached = mUidCache.get(uid);
+ if (cached != null) {
+ return cached;
+ }
+
+ boolean access = false;
+
+ // Ensure the claimed package is present in the calling UID
+ PackageManager pm = mContext.getPackageManager();
+ String[] pkgs = pm.getPackagesForUid(uid);
+ for (String uidPkg : pkgs) {
+ if (uidPkg.equals(pkg)) {
+ // Ensure the package has access permissions
+ if (checkPackageNfceeAccess(pkg)) {
+ access = true;
+ }
+ break;
+ }
+ }
+
+ mUidCache.put(uid, access);
+ return access;
+ }
+ }
+
+ /**
+ * Check if the given ApplicationInfo may use the NFCEE.
+ * Assumes ApplicationInfo came from package manager,
+ * so no need to confirm {uid, pkg} is valid.
+ */
+ public boolean check(ApplicationInfo info) {
+ synchronized (this) {
+ Boolean access = mUidCache.get(info.uid);
+ if (access == null) {
+ access = checkPackageNfceeAccess(info.packageName);
+ mUidCache.put(info.uid, access);
+ }
+ return access;
+ }
+ }
+
+ public void invalidateCache() {
+ synchronized (this) {
+ mUidCache.clear();
+ }
+ }
+
+ /**
+ * Check with package manager if the pkg may use NFCEE.
+ * Does not use cache.
+ */
+ boolean checkPackageNfceeAccess(String pkg) {
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+ if (info.signatures == null) {
+ return false;
+ }
+
+ for (Signature s : info.signatures){
+ if (s == null) {
+ continue;
+ }
+ String[] packages = mNfceeAccess.get(s);
+ if (packages == null) {
+ continue;
+ }
+ if (packages.length == 0) {
+ // wildcard access
+ if (DBG) Log.d(TAG, "Granted NFCEE access to " + pkg + " (wildcard)");
+ return true;
+ }
+ for (String p : packages) {
+ if (pkg.equals(p)) {
+ // explicit package access
+ if (DBG) Log.d(TAG, "Granted access to " + pkg + " (explicit)");
+ return true;
+ }
+ }
+ }
+
+ if (mDebugPrintSignature) {
+ Log.w(TAG, "denied NFCEE access for " + pkg + " with signature:");
+ for (Signature s : info.signatures) {
+ if (s != null) {
+ Log.w(TAG, s.toCharsString());
+ }
+ }
+ }
+ } catch (NameNotFoundException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ /**
+ * Parse nfcee_access.xml, populate mNfceeAccess
+ * Policy is to ignore unexpected XML elements and continue processing,
+ * except for obvious errors within a <signer> group since they might cause
+ * package names to by ignored and therefore wildcard access granted
+ * by mistake. Those errors invalidate the entire <signer> group.
+ */
+ boolean parseNfceeAccess() {
+ File file = new File(Environment.getRootDirectory(), NFCEE_ACCESS_PATH);
+ FileReader reader = null;
+ boolean debug = false;
+ try {
+ reader = new FileReader(file);
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ XmlPullParser parser = factory.newPullParser();
+ parser.setInput(reader);
+
+ int event;
+ ArrayList<String> packages = new ArrayList<String>();
+ Signature signature = null;
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
+ while (true) {
+ event = parser.next();
+ String tag = parser.getName();
+ if (event == XmlPullParser.START_TAG && "signer".equals(tag)) {
+ signature = null;
+ packages.clear();
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ if ("android:signature".equals(parser.getAttributeName(i))) {
+ signature = new Signature(parser.getAttributeValue(i));
+ break;
+ }
+ }
+ if (signature == null) {
+ Log.w(TAG, "signer tag is missing android:signature attribute, igorning");
+ continue;
+ }
+ if (mNfceeAccess.containsKey(signature)) {
+ Log.w(TAG, "duplicate signature, ignoring");
+ signature = null;
+ continue;
+ }
+ } else if (event == XmlPullParser.END_TAG && "signer".equals(tag)) {
+ if (signature == null) {
+ Log.w(TAG, "mis-matched signer tag");
+ continue;
+ }
+ mNfceeAccess.put(signature, (String[])packages.toArray(new String[0]));
+ packages.clear();
+ } else if (event == XmlPullParser.START_TAG && "package".equals(tag)) {
+ if (signature == null) {
+ Log.w(TAG, "ignoring unnested packge tag");
+ continue;
+ }
+ String name = null;
+ for (int i = 0; i < parser.getAttributeCount(); i++) {
+ if ("android:name".equals(parser.getAttributeName(i))) {
+ name = parser.getAttributeValue(i);
+ break;
+ }
+ }
+ if (name == null) {
+ Log.w(TAG, "package missing android:name, ignoring signer group");
+ signature = null; // invalidate signer
+ continue;
+ }
+ // check for duplicate package names
+ if (packages.contains(name)) {
+ Log.w(TAG, "duplicate package name in signer group, ignoring");
+ continue;
+ }
+ packages.add(name);
+ } else if (event == XmlPullParser.START_TAG && "debug".equals(tag)) {
+ debug = true;
+ } else if (event == XmlPullParser.END_DOCUMENT) {
+ break;
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "failed to load NFCEE access list", e);
+ mNfceeAccess.clear(); // invalidate entire access list
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "could not find " + NFCEE_ACCESS_PATH + ", no NFCEE access allowed");
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to load NFCEE access list", e);
+ mNfceeAccess.clear(); // invalidate entire access list
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e2) { }
+ }
+ }
+ Log.i(TAG, "read " + mNfceeAccess.size() + " signature(s) for NFCEE access");
+ return debug;
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("mNfceeAccess=");
+ for (Signature s : mNfceeAccess.keySet()) {
+ pw.printf("\t%s [", s.toCharsString());
+ String[] ps = mNfceeAccess.get(s);
+ for (String p : ps) {
+ pw.printf("%s, ", p);
+ }
+ pw.println("]");
+ }
+ synchronized (this) {
+ pw.println("mNfceeUidCache=");
+ for (Integer uid : mUidCache.keySet()) {
+ Boolean b = mUidCache.get(uid);
+ pw.printf("\t%d %s\n", uid, b);
+ }
+ }
+ }
+}