HCE: Fix potential crash and handle Android AID.

For new "default route" CTS test. Also, fix
a potential crash for starting off-host services
and check that HCE services have declared the
NFC permission.

Bug: 10681671
Change-Id: If86d9820d6eef5a0661be92be67168d5f81ddc64
diff --git a/src/com/android/nfc/cardemulation/HostEmulationManager.java b/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 0dc75b5..a4e7f75 100644
--- a/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -60,6 +60,9 @@
 
     static final byte INSTR_SELECT = (byte)0xA4;
 
+    static final String ANDROID_HCE_AID = "A000000476416E64726F6964484345";
+    static final byte[] ANDROID_HCE_RESPONSE = {0x14, (byte)0x81, 0x00, 0x00, (byte)0x90, 0x00};
+
     static final byte[] AID_NOT_FOUND = {0x6A, (byte)0x82};
     static final byte[] UNKNOWN_ERROR = {0x6F, 0x00};
 
@@ -161,6 +164,10 @@
                 return;
             }
             if (selectAid != null) {
+                if (selectAid.equals(ANDROID_HCE_AID)) {
+                    NfcService.getInstance().sendData(ANDROID_HCE_RESPONSE);
+                    return;
+                }
                 AidResolveInfo resolveInfo = mAidCache.resolveAidPrefix(selectAid);
                 if (resolveInfo == null || resolveInfo.services.size() == 0) {
                     // Tell the remote we don't handle this AID
@@ -179,6 +186,14 @@
                         launchTapAgain(resolveInfo.defaultService, category);
                         return;
                     }
+                    // In no circumstance should this be an OffHostService -
+                    // we should never get this AID on the host in the first place
+                    if (!resolveInfo.defaultService.isOnHost()) {
+                        Log.e(TAG, "AID that was meant to go off-host was routed to host." +
+                                " Check routing table configuration.");
+                        NfcService.getInstance().sendData(AID_NOT_FOUND);
+                        return;
+                    }
                     resolvedService = resolveInfo.defaultService.getComponent();
                 } else if (mActiveServiceName != null) {
                     for (ApduServiceInfo service : resolveInfo.services) {
diff --git a/src/com/android/nfc/cardemulation/RegisteredServicesCache.java b/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
index 2e037d2..0cfc0e0 100644
--- a/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
+++ b/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
@@ -207,6 +207,14 @@
                 boolean onHost = !resolvedOffHostServices.contains(resolvedService);
                 ServiceInfo si = resolvedService.serviceInfo;
                 ComponentName componentName = new ComponentName(si.packageName, si.name);
+                // Check if the package holds the NFC permission
+                if (pm.checkPermission(android.Manifest.permission.NFC, si.packageName) !=
+                        PackageManager.PERMISSION_GRANTED) {
+                    Log.e(TAG, "Skipping APDU service " + componentName +
+                            ": it does not require the permission " +
+                            android.Manifest.permission.NFC);
+                    continue;
+                }
                 if (!android.Manifest.permission.BIND_NFC_SERVICE.equals(
                         si.permission)) {
                     Log.e(TAG, "Skipping APDU service " + componentName +