summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-07-09 07:33:07 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-07-09 07:33:07 +0000
commit084ad222eaf0fd53ecd4c4efaf79b8afd31d841d (patch)
tree459b84aa4539c6bdc5271452a4cb3af6175631cc
parented38674449cf922e3fa4808e1a2c43106790e599 (diff)
parent8ee2015a9c4639d465a390af93df3fdcd983cac8 (diff)
downloadandroid_packages_apps_Nfc-084ad222eaf0fd53ecd4c4efaf79b8afd31d841d.tar.gz
android_packages_apps_Nfc-084ad222eaf0fd53ecd4c4efaf79b8afd31d841d.tar.bz2
android_packages_apps_Nfc-084ad222eaf0fd53ecd4c4efaf79b8afd31d841d.zip
release-request-bf3460d4-15ec-4b2b-816a-b106ef372c4b-for-git_oc-dr1-release-4164433 snap-temp-L62100000080728136
Change-Id: If8148f85ae083524dfdc1953de4f887f833af6c7
-rwxr-xr-xnci/jni/NativeNfcManager.cpp156
-rw-r--r--nci/jni/NativeNfcTag.cpp4
-rwxr-xr-xnci/jni/NfcJniUtil.h2
-rwxr-xr-xnci/jni/NfcTag.cpp16
-rwxr-xr-xnci/jni/RoutingManager.cpp10
-rwxr-xr-xnci/jni/RoutingManager.h2
-rwxr-xr-xnci/src/com/android/nfc/dhimpl/NativeNfcManager.java8
-rw-r--r--src/com/android/nfc/DeviceHost.java6
-rwxr-xr-xsrc/com/android/nfc/NfcService.java78
-rw-r--r--src/com/android/nfc/ScreenStateHelper.java26
-rw-r--r--src/com/android/nfc/cardemulation/AidRoutingManager.java75
-rw-r--r--src/com/android/nfc/cardemulation/EnabledNfcFServices.java3
-rw-r--r--src/com/android/nfc/cardemulation/RegisteredAidCache.java344
-rw-r--r--src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java6
-rw-r--r--src/com/android/nfc/cardemulation/SystemCodeRoutingManager.java9
15 files changed, 611 insertions, 134 deletions
diff --git a/nci/jni/NativeNfcManager.cpp b/nci/jni/NativeNfcManager.cpp
index 146b61e6..b79954e6 100755
--- a/nci/jni/NativeNfcManager.cpp
+++ b/nci/jni/NativeNfcManager.cpp
@@ -75,6 +75,7 @@ namespace android
*****************************************************************************/
bool gActivated = false;
SyncEvent gDeactivatedEvent;
+SyncEvent sNfaSetPowerSubState;
namespace android
{
@@ -130,7 +131,7 @@ static jint sLfT3tMax = 0;
#define DEFAULT_TECH_MASK (NFA_TECHNOLOGY_MASK_A \
| NFA_TECHNOLOGY_MASK_B \
| NFA_TECHNOLOGY_MASK_F \
- | NFA_TECHNOLOGY_MASK_ISO15693 \
+ | NFA_TECHNOLOGY_MASK_V \
| NFA_TECHNOLOGY_MASK_B_PRIME \
| NFA_TECHNOLOGY_MASK_A_ACTIVE \
| NFA_TECHNOLOGY_MASK_F_ACTIVE \
@@ -145,10 +146,12 @@ static bool isListenMode(tNFA_ACTIVATED& activated);
static void enableDisableLptd (bool enable);
static tNFA_STATUS stopPolling_rfDiscoveryDisabled();
static tNFA_STATUS startPolling_rfDiscoveryDisabled(tNFA_TECHNOLOGY_MASK tech_mask);
+static void nfcManager_doSetScreenState(JNIEnv* e, jobject o, jint screen_state_mask);
static uint16_t sCurrentConfigLen;
static uint8_t sConfig[256];
-
+static int prevScreenState = NFA_SCREEN_STATE_OFF_LOCKED;
+static int NFA_SCREEN_POLLING_TAG_MASK = 0x10;
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
@@ -329,16 +332,19 @@ static void nfaConnectionCallback (uint8_t connEvent, tNFA_CONN_EVT_DATA* eventD
break;
}
sP2pActive = true;
- ALOGV("%s: NFA_ACTIVATED_EVT; is p2p", __func__);
- // Disable RF field events in case of p2p
- uint8_t nfa_disable_rf_events[] = { 0x00 };
- ALOGV("%s: Disabling RF field events", __func__);
- status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO, sizeof(nfa_disable_rf_events),
- &nfa_disable_rf_events[0]);
- if (status == NFA_STATUS_OK) {
- ALOGV("%s: Disabled RF field events", __func__);
- } else {
- ALOGE("%s: Failed to disable RF field events", __func__);
+ ALOGD("%s: NFA_ACTIVATED_EVT; is p2p", __func__);
+ if (NFC_GetNCIVersion() == NCI_VERSION_1_0)
+ {
+ // Disable RF field events in case of p2p
+ uint8_t nfa_disable_rf_events[] = { 0x00 };
+ ALOGD ("%s: Disabling RF field events", __func__);
+ status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO, sizeof(nfa_disable_rf_events),
+ &nfa_disable_rf_events[0]);
+ if (status == NFA_STATUS_OK) {
+ ALOGD ("%s: Disabled RF field events", __func__);
+ } else {
+ ALOGE ("%s: Failed to disable RF field events", __func__);
+ }
}
}
else if (pn544InteropIsBusy() == false)
@@ -391,19 +397,22 @@ static void nfaConnectionCallback (uint8_t connEvent, tNFA_CONN_EVT_DATA* eventD
} else if (sP2pActive) {
sP2pActive = false;
// Make sure RF field events are re-enabled
- ALOGV("%s: NFA_DEACTIVATED_EVT; is p2p", __func__);
- // Disable RF field events in case of p2p
- uint8_t nfa_enable_rf_events[] = { 0x01 };
-
- if (!sIsDisabling && sIsNfaEnabled)
+ ALOGD("%s: NFA_DEACTIVATED_EVT; is p2p", __func__);
+ if (NFC_GetNCIVersion() == NCI_VERSION_1_0)
{
- ALOGV("%s: Enabling RF field events", __func__);
- status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO, sizeof(nfa_enable_rf_events),
- &nfa_enable_rf_events[0]);
- if (status == NFA_STATUS_OK) {
- ALOGV("%s: Enabled RF field events", __func__);
- } else {
- ALOGE("%s: Failed to enable RF field events", __func__);
+ // Disable RF field events in case of p2p
+ uint8_t nfa_enable_rf_events[] = { 0x01 };
+
+ if (!sIsDisabling && sIsNfaEnabled)
+ {
+ ALOGD ("%s: Enabling RF field events", __func__);
+ status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO, sizeof(nfa_enable_rf_events),
+ &nfa_enable_rf_events[0]);
+ if (status == NFA_STATUS_OK) {
+ ALOGD ("%s: Enabled RF field events", __func__);
+ } else {
+ ALOGE ("%s: Failed to enable RF field events", __func__);
+ }
}
}
}
@@ -743,6 +752,14 @@ void nfaDeviceManagementCallback (uint8_t dmEvent, tNFA_DM_CBACK_DATA* eventData
PowerSwitch::getInstance ().deviceManagementCallback (dmEvent, eventData);
break;
+ case NFA_DM_SET_POWER_SUB_STATE_EVT:
+ {
+ ALOGD("%s: NFA_DM_SET_POWER_SUB_STATE_EVT; status=0x%X",
+ __FUNCTION__, eventData->power_sub_state.status);
+ SyncEventGuard guard (sNfaSetPowerSubState);
+ sNfaSetPowerSubState.notifyOne();
+ }
+ break;
default:
ALOGV("%s: unhandled event", __func__);
break;
@@ -776,18 +793,19 @@ static jboolean nfcManager_sendRawFrame (JNIEnv* e, jobject, jbyteArray data)
**
** Description: Route an AID to an EE
** e: JVM environment.
-** o: Java object.
+** aid: aid to be added to routing table.
+** route: aid route location. i.e. DH/eSE/UICC
+** aidInfo: prefix or suffix aid.
**
-** Returns: True if ok.
+** Returns: True if aid is accpted by NFA Layer.
**
*******************************************************************************/
-static jboolean nfcManager_routeAid (JNIEnv* e, jobject, jbyteArray aid, jint route)
+static jboolean nfcManager_routeAid (JNIEnv* e, jobject, jbyteArray aid, jint route, jint aidInfo)
{
ScopedByteArrayRO bytes(e, aid);
uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
size_t bufLen = bytes.size();
- bool result = RoutingManager::getInstance().addAidRouting(buf, bufLen, route);
- return result;
+ return RoutingManager::getInstance().addAidRouting(buf, bufLen, route, aidInfo);
}
/*******************************************************************************
@@ -1634,7 +1652,79 @@ static jstring nfcManager_doDump(JNIEnv* e, jobject)
return e->NewStringUTF(buffer);
}
+static jint nfcManager_doGetNciVersion(JNIEnv* , jobject)
+{
+ return NFC_GetNCIVersion();
+}
+static void nfcManager_doSetScreenState (JNIEnv* e, jobject o, jint screen_state_mask)
+{
+ tNFA_STATUS status = NFA_STATUS_OK;
+ uint8_t state = (screen_state_mask & NFA_SCREEN_STATE_MASK);
+ uint8_t discovry_param = NFA_LISTEN_DH_NFCEE_ENABLE_MASK | NFA_POLLING_DH_ENABLE_MASK;
+
+ ALOGD ("%s: state = %d discovry_param = %d", __FUNCTION__, state, discovry_param);
+
+ if (sIsDisabling || !sIsNfaEnabled ||(NFC_GetNCIVersion() != NCI_VERSION_2_0))
+ return;
+ if (prevScreenState == NFA_SCREEN_STATE_OFF_LOCKED || prevScreenState == NFA_SCREEN_STATE_OFF_UNLOCKED)
+ {
+ SyncEventGuard guard (sNfaSetPowerSubState);
+ status = NFA_SetPowerSubStateForScreenState(state);
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: fail enable SetScreenState; error=0x%X", __FUNCTION__, status);
+ return;
+ }
+ else
+ {
+ sNfaSetPowerSubState.wait();
+ }
+ }
+
+ if (state == NFA_SCREEN_STATE_OFF_LOCKED || state == NFA_SCREEN_STATE_OFF_UNLOCKED)
+ {
+ // disable both poll and listen on DH 0x02
+ discovry_param = NFA_POLLING_DH_DISABLE_MASK | NFA_LISTEN_DH_NFCEE_DISABLE_MASK;
+ }
+
+ if (state == NFA_SCREEN_STATE_ON_LOCKED)
+ {
+ // disable poll and enable listen on DH 0x00
+ discovry_param = (screen_state_mask & NFA_SCREEN_POLLING_TAG_MASK) ?
+ (NFA_LISTEN_DH_NFCEE_ENABLE_MASK | NFA_POLLING_DH_ENABLE_MASK):
+ (NFA_POLLING_DH_DISABLE_MASK | NFA_LISTEN_DH_NFCEE_ENABLE_MASK);
+ }
+
+ if (state == NFA_SCREEN_STATE_ON_UNLOCKED)
+ {
+ // enable both poll and listen on DH 0x01
+ discovry_param = NFA_LISTEN_DH_NFCEE_ENABLE_MASK | NFA_POLLING_DH_ENABLE_MASK;
+ }
+
+ SyncEventGuard guard (sNfaSetConfigEvent);
+ status = NFA_SetConfig(NFC_PMID_CON_DISCOVERY_PARAM, NCI_PARAM_LEN_CON_DISCOVERY_PARAM, &discovry_param);
+ if (status == NFA_STATUS_OK)
+ {
+ sNfaSetConfigEvent.wait ();
+ } else {
+ ALOGE ("%s: Failed to update CON_DISCOVER_PARAM", __FUNCTION__);
+ return;
+ }
+
+ if (prevScreenState == NFA_SCREEN_STATE_ON_LOCKED || prevScreenState == NFA_SCREEN_STATE_ON_UNLOCKED)
+ {
+ SyncEventGuard guard (sNfaSetPowerSubState);
+ status = NFA_SetPowerSubStateForScreenState(state);
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: fail enable SetScreenState; error=0x%X", __FUNCTION__, status);
+ } else {
+ sNfaSetPowerSubState.wait();
+ }
+ }
+ prevScreenState = state;
+}
/*******************************************************************************
**
** Function: nfcManager_doSetP2pInitiatorModes
@@ -1722,7 +1812,7 @@ static JNINativeMethod gMethods[] =
{"sendRawFrame", "([B)Z",
(void*) nfcManager_sendRawFrame},
- {"routeAid", "([BI)Z",
+ {"routeAid", "([BII)Z",
(void*) nfcManager_routeAid},
{"unrouteAid", "([B)Z",
@@ -1785,11 +1875,17 @@ static JNINativeMethod gMethods[] =
{"doEnableScreenOffSuspend", "()V",
(void *)nfcManager_doEnableScreenOffSuspend},
+ {"doSetScreenState", "(I)V",
+ (void*)nfcManager_doSetScreenState},
+
{"doDisableScreenOffSuspend", "()V",
(void *)nfcManager_doDisableScreenOffSuspend},
{"doDump", "()Ljava/lang/String;",
(void *)nfcManager_doDump},
+
+ {"getNciVersion","()I",
+ (void *)nfcManager_doGetNciVersion},
};
diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp
index 6361bc96..ece0ce5b 100644
--- a/nci/jni/NativeNfcTag.cpp
+++ b/nci/jni/NativeNfcTag.cpp
@@ -1102,7 +1102,7 @@ static jint nativeNfcTag_doGetNdefType (JNIEnv*, jobject, jint libnfcType, jint
}
else
{
- /* NFA_PROTOCOL_ISO15693, NFA_PROTOCOL_INVALID and others */
+ /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */
ndefType = NDEF_UNKNOWN_TYPE;
}
ALOGV("%s: exit; ndef type=%d", __func__, ndefType);
@@ -1455,7 +1455,7 @@ static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv* e,
{
jboolean isFormattable = JNI_FALSE;
tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol();
- if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_ISO15693 == protocol
+ if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_T5T == protocol
|| NFA_PROTOCOL_MIFARE == protocol)
{
isFormattable = JNI_TRUE;
diff --git a/nci/jni/NfcJniUtil.h b/nci/jni/NfcJniUtil.h
index c52e93ef..f5368c90 100755
--- a/nci/jni/NfcJniUtil.h
+++ b/nci/jni/NfcJniUtil.h
@@ -78,7 +78,7 @@
#define TARGET_TYPE_ISO14443_3B 2
#define TARGET_TYPE_ISO14443_4 3
#define TARGET_TYPE_FELICA 4
-#define TARGET_TYPE_ISO15693 5
+#define TARGET_TYPE_V 5
#define TARGET_TYPE_NDEF 6
#define TARGET_TYPE_NDEF_FORMATABLE 7
#define TARGET_TYPE_MIFARE_CLASSIC 8
diff --git a/nci/jni/NfcTag.cpp b/nci/jni/NfcTag.cpp
index 3246f6fa..0b8ec85e 100755
--- a/nci/jni/NfcTag.cpp
+++ b/nci/jni/NfcTag.cpp
@@ -384,10 +384,10 @@ void NfcTag::discoverTechnologies (tNFA_ACTIVATED& activationData)
memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
}
}
- else if (NFC_PROTOCOL_15693 == rfDetail.protocol)
+ else if (NFC_PROTOCOL_T5T == rfDetail.protocol)
{
//is TagTechnology.NFC_V by Java API
- mTechList [mNumTechList] = TARGET_TYPE_ISO15693;
+ mTechList [mNumTechList] = TARGET_TYPE_V;
}
else if (NFC_PROTOCOL_KOVIO == rfDetail.protocol)
{
@@ -510,10 +510,10 @@ void NfcTag::discoverTechnologies (tNFA_DISC_RESULT& discoveryData)
}
}
}
- else if (NFC_PROTOCOL_15693 == discovery_ntf.protocol)
+ else if (NFC_PROTOCOL_T5T == discovery_ntf.protocol)
{
//is TagTechnology.NFC_V by Java API
- mTechList [mNumTechList] = TARGET_TYPE_ISO15693;
+ mTechList [mNumTechList] = TARGET_TYPE_V;
}
else if (NFC_PROTOCOL_MIFARE == discovery_ntf.protocol)
{
@@ -784,7 +784,7 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t
pollBytes.reset(e->NewByteArray(len));
e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*) result);
}
- else if (NFC_DISCOVERY_TYPE_POLL_ISO15693 == mTechParams [i].mode
+ else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams [i].mode
|| NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams [i].mode)
{
ALOGV("%s: tech iso 15693", fn);
@@ -916,7 +916,7 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t
actBytes.reset(e->NewByteArray(0));
}
} //case NFC_PROTOCOL_ISO_DEP: //t4t
- else if (NFC_PROTOCOL_15693 == mTechLibNfcTypes[i])
+ else if (NFC_PROTOCOL_T5T == mTechLibNfcTypes[i])
{
ALOGV("%s: tech iso 15693", fn);
//iso 15693 response flags: 1 octet
@@ -1004,7 +1004,7 @@ void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, t
(jbyte*) &mTechParams [0].param.pf.nfcid2);
ALOGV("%s: tech F", fn);
}
- else if (NFC_DISCOVERY_TYPE_POLL_ISO15693 == mTechParams [0].mode
+ else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams [0].mode
|| NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams [0].mode)
{
ALOGV("%s: tech iso 15693", fn);
@@ -1487,7 +1487,7 @@ void NfcTag::resetAllTransceiveTimeouts ()
mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_3B] = 1000; //NfcB
mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_4] = 618; //ISO-DEP
mTechnologyTimeoutsTable [TARGET_TYPE_FELICA] = 255; //Felica
- mTechnologyTimeoutsTable [TARGET_TYPE_ISO15693] = 1000;//NfcV
+ mTechnologyTimeoutsTable [TARGET_TYPE_V] = 1000;//NfcV
mTechnologyTimeoutsTable [TARGET_TYPE_NDEF] = 1000;
mTechnologyTimeoutsTable [TARGET_TYPE_NDEF_FORMATABLE] = 1000;
mTechnologyTimeoutsTable [TARGET_TYPE_MIFARE_CLASSIC] = 618; //MifareClassic
diff --git a/nci/jni/RoutingManager.cpp b/nci/jni/RoutingManager.cpp
index 101dc0c0..bf6489c3 100755
--- a/nci/jni/RoutingManager.cpp
+++ b/nci/jni/RoutingManager.cpp
@@ -326,11 +326,11 @@ void RoutingManager::disableRoutingToHost()
}
}
-bool RoutingManager::addAidRouting(const uint8_t* aid, uint8_t aidLen, int route)
+bool RoutingManager::addAidRouting(const uint8_t* aid, uint8_t aidLen, int route, int aidInfo)
{
static const char fn [] = "RoutingManager::addAidRouting";
ALOGV("%s: enter", fn);
- tNFA_STATUS nfaStat = NFA_EeAddAidRouting(route, aidLen, (uint8_t*) aid, 0x01);
+ tNFA_STATUS nfaStat = NFA_EeAddAidRouting(route, aidLen, (uint8_t*) aid, 0x01, aidInfo);
if (nfaStat == NFA_STATUS_OK)
{
ALOGV("%s: routed AID", fn);
@@ -688,7 +688,7 @@ int RoutingManager::registerT3tIdentifier(uint8_t* t3tId, uint8_t t3tIdLen)
ALOGV("%s: Start to register NFC-F system on DH", fn);
- if (t3tIdLen != (2 + NCI_RF_F_UID_LEN))
+ if (t3tIdLen != (2 + NCI_RF_F_UID_LEN + NCI_T3T_PMM_LEN))
{
ALOGE("%s: Invalid length of T3T Identifier", fn);
return NFA_HANDLE_INVALID;
@@ -699,11 +699,13 @@ int RoutingManager::registerT3tIdentifier(uint8_t* t3tId, uint8_t t3tIdLen)
int systemCode;
uint8_t nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t t3tPmm[NCI_T3T_PMM_LEN];
systemCode = (((int)t3tId[0] << 8) | ((int)t3tId[1] << 0));
memcpy(nfcid2, t3tId + 2, NCI_RF_F_UID_LEN);
+ memcpy(t3tPmm, t3tId + 10, NCI_T3T_PMM_LEN);
- tNFA_STATUS nfaStat = NFA_CeRegisterFelicaSystemCodeOnDH (systemCode, nfcid2, nfcFCeCallback);
+ tNFA_STATUS nfaStat = NFA_CeRegisterFelicaSystemCodeOnDH (systemCode, nfcid2, t3tPmm, nfcFCeCallback);
if (nfaStat == NFA_STATUS_OK)
{
mRoutingEvent.wait ();
diff --git a/nci/jni/RoutingManager.h b/nci/jni/RoutingManager.h
index ee9211fc..62d569fe 100755
--- a/nci/jni/RoutingManager.h
+++ b/nci/jni/RoutingManager.h
@@ -35,7 +35,7 @@ public:
bool initialize(nfc_jni_native_data* native);
void enableRoutingToHost();
void disableRoutingToHost();
- bool addAidRouting(const uint8_t* aid, uint8_t aidLen, int route);
+ bool addAidRouting(const uint8_t* aid, uint8_t aidLen, int route, int aidInfo);
bool removeAidRouting(const uint8_t* aid, uint8_t aidLen);
bool commitRouting();
int registerT3tIdentifier(uint8_t* t3tId, uint8_t t3tIdLen);
diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
index ecd8e6d3..35f2cb33 100755
--- a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
+++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
@@ -95,7 +95,7 @@ public class NativeNfcManager implements DeviceHost {
public native boolean sendRawFrame(byte[] data);
@Override
- public native boolean routeAid(byte[] aid, int route);
+ public native boolean routeAid(byte[] aid, int route, int aidInfo);
@Override
public native boolean unrouteAid(byte[] aid);
@@ -143,6 +143,12 @@ public class NativeNfcManager implements DeviceHost {
@Override
public native int getLfT3tMax();
+ @Override
+ public native void doSetScreenState(int screen_state_mask);
+
+ @Override
+ public native int getNciVersion();
+
private native void doEnableDiscovery(int techMask,
boolean enableLowPowerPolling,
boolean enableReaderMode,
diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java
index 621478c8..8b622206 100644
--- a/src/com/android/nfc/DeviceHost.java
+++ b/src/com/android/nfc/DeviceHost.java
@@ -183,7 +183,7 @@ public interface DeviceHost {
public boolean sendRawFrame(byte[] data);
- public boolean routeAid(byte[] aid, int route);
+ public boolean routeAid(byte[] aid, int route, int aidInfo);
public boolean unrouteAid(byte[] aid);
@@ -237,4 +237,8 @@ public interface DeviceHost {
boolean enableScreenOffSuspend();
boolean disableScreenOffSuspend();
+
+ public void doSetScreenState(int screen_state_mask);
+
+ public int getNciVersion();
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 4eff56ec..d52ca834 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -131,6 +131,7 @@ public class NfcService implements DeviceHostListener {
static final int MSG_DEREGISTER_T3T_IDENTIFIER = 13;
static final int MSG_TAG_DEBOUNCE = 14;
static final int MSG_UPDATE_STATS = 15;
+ static final int MSG_APPLY_SCREEN_STATE = 16;
// Update stats every 4 hours
static final long STATS_UPDATE_INTERVAL_MS = 4 * 60 * 60 * 1000;
@@ -144,7 +145,7 @@ public class NfcService implements DeviceHostListener {
static final int NFC_POLL_A = 0x01;
static final int NFC_POLL_B = 0x02;
static final int NFC_POLL_F = 0x04;
- static final int NFC_POLL_ISO15693 = 0x08;
+ static final int NFC_POLL_V = 0x08;
static final int NFC_POLL_B_PRIME = 0x10;
static final int NFC_POLL_KOVIO = 0x20;
@@ -178,6 +179,10 @@ public class NfcService implements DeviceHostListener {
public static final int SOUND_END = 1;
public static final int SOUND_ERROR = 2;
+ public static final int NCI_VERSION_2_0 = 0x20;
+
+ public static final int NCI_VERSION_1_0 = 0x10;
+
public static final String ACTION_LLCP_UP =
"com.android.nfc.action.LLCP_UP";
@@ -189,6 +194,7 @@ public class NfcService implements DeviceHostListener {
private final UserManager mUserManager;
+ private static int nci_version = NCI_VERSION_1_0;
// NFC Execution Environment
// fields below are protected by this
private final ReaderModeDeathRecipient mReaderModeDeathRecipient =
@@ -384,7 +390,7 @@ public class NfcService implements DeviceHostListener {
} else if (liveCaseTechList[i].equals("TypeF")) {
mLiveCaseTechnology |= NFC_POLL_F;
} else if (liveCaseTechList[i].equals("TypeV")) {
- mLiveCaseTechnology |= NFC_POLL_ISO15693;
+ mLiveCaseTechnology |= NFC_POLL_V;
}
}
} catch (NotFoundException e) {
@@ -620,6 +626,8 @@ public class NfcService implements DeviceHostListener {
mCardEmulationManager.onNfcEnabled();
}
+ nci_version = getNciVersion();
+
synchronized (NfcService.this) {
mObjectMap.clear();
mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
@@ -628,6 +636,15 @@ public class NfcService implements DeviceHostListener {
initSoundPool();
+ mScreenState = mScreenStateHelper.checkScreenState();
+ int screen_state_mask = (mNfcUnlockManager.isLockscreenPollingEnabled()) ?
+ (ScreenStateHelper.SCREEN_POLLING_TAG_MASK | mScreenState) : mScreenState;
+
+ if(mNfcUnlockManager.isLockscreenPollingEnabled())
+ applyRouting(false);
+
+ mDeviceHost.doSetScreenState(screen_state_mask);
+
/* Start polling loop */
applyRouting(true);
@@ -1115,7 +1132,7 @@ public class NfcService implements DeviceHostListener {
techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A);
techCodeToMask.put(TagTechnology.NFC_B, NfcService.NFC_POLL_B);
- techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693);
+ techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_V);
techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F);
techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO);
@@ -1596,7 +1613,7 @@ public class NfcService implements DeviceHostListener {
if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0)
techMask |= NFC_POLL_F;
if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0)
- techMask |= NFC_POLL_ISO15693;
+ techMask |= NFC_POLL_V;
if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0)
techMask |= NFC_POLL_KOVIO;
@@ -1736,11 +1753,12 @@ public class NfcService implements DeviceHostListener {
sendMessage(MSG_MOCK_NDEF, msg);
}
- public void routeAids(String aid, int route) {
+ public void routeAids(String aid, int route, int aidInfo) {
Message msg = mHandler.obtainMessage();
msg.what = MSG_ROUTE_AID;
msg.arg1 = route;
msg.obj = aid;
+ msg.arg2 = aidInfo;
mHandler.sendMessage(msg);
}
@@ -1748,11 +1766,15 @@ public class NfcService implements DeviceHostListener {
sendMessage(MSG_UNROUTE_AID, aid);
}
- private byte[] getT3tIdentifierBytes(String systemCode, String nfcId2) {
- ByteBuffer buffer = ByteBuffer.allocate(2 + 8);
+ public int getNciVersion() {
+ return mDeviceHost.getNciVersion();
+ }
+
+ private byte[] getT3tIdentifierBytes(String systemCode, String nfcId2, String t3tPmm) {
+ ByteBuffer buffer = ByteBuffer.allocate(2 + 8 + 8); /* systemcode + nfcid2 + t3tpmm */
buffer.put(hexStringToBytes(systemCode));
buffer.put(hexStringToBytes(nfcId2));
-
+ buffer.put(hexStringToBytes(t3tPmm));
byte[] t3tIdBytes = new byte[buffer.position()];
buffer.position(0);
buffer.get(t3tIdBytes);
@@ -1760,17 +1782,17 @@ public class NfcService implements DeviceHostListener {
return t3tIdBytes;
}
- public void registerT3tIdentifier(String systemCode, String nfcId2) {
+ public void registerT3tIdentifier(String systemCode, String nfcId2, String t3tPmm) {
Log.d(TAG, "request to register LF_T3T_IDENTIFIER");
- byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2);
+ byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2, t3tPmm);
sendMessage(MSG_REGISTER_T3T_IDENTIFIER, t3tIdentifier);
}
- public void deregisterT3tIdentifier(String systemCode, String nfcId2) {
+ public void deregisterT3tIdentifier(String systemCode, String nfcId2, String t3tPmm) {
Log.d(TAG, "request to deregister LF_T3T_IDENTIFIER");
- byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2);
+ byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2, t3tPmm);
sendMessage(MSG_DEREGISTER_T3T_IDENTIFIER, t3tIdentifier);
}
@@ -1804,8 +1826,9 @@ public class NfcService implements DeviceHostListener {
switch (msg.what) {
case MSG_ROUTE_AID: {
int route = msg.arg1;
+ int aidInfo = msg.arg2;
String aid = (String) msg.obj;
- mDeviceHost.routeAid(hexStringToBytes(aid), route);
+ mDeviceHost.routeAid(hexStringToBytes(aid), route, aidInfo);
// Restart polling config
break;
}
@@ -2041,6 +2064,22 @@ public class NfcService implements DeviceHostListener {
removeMessages(MSG_UPDATE_STATS);
sendEmptyMessageDelayed(MSG_UPDATE_STATS, STATS_UPDATE_INTERVAL_MS);
break;
+
+ case MSG_APPLY_SCREEN_STATE:
+ mScreenState = (Integer)msg.obj;
+
+ if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
+ applyRouting(false);
+ }
+ int screen_state_mask = (mNfcUnlockManager.isLockscreenPollingEnabled()) ?
+ (ScreenStateHelper.SCREEN_POLLING_TAG_MASK | mScreenState) : mScreenState;
+
+ if (mNfcUnlockManager.isLockscreenPollingEnabled())
+ applyRouting(false);
+
+ mDeviceHost.doSetScreenState(screen_state_mask);
+ break;
+
default:
Log.e(TAG, "Unknown message received");
break;
@@ -2203,9 +2242,12 @@ public class NfcService implements DeviceHostListener {
|| action.equals(Intent.ACTION_SCREEN_OFF)
|| action.equals(Intent.ACTION_USER_PRESENT)) {
// Perform applyRouting() in AsyncTask to serialize blocking calls
- int screenState = ScreenStateHelper.SCREEN_STATE_OFF;
+ int screenState = mScreenStateHelper.checkScreenState();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- screenState = ScreenStateHelper.SCREEN_STATE_OFF;
+ if (mScreenState != ScreenStateHelper.SCREEN_STATE_OFF_LOCKED) {
+ screenState = mKeyguard.isKeyguardLocked() ?
+ ScreenStateHelper.SCREEN_STATE_OFF_LOCKED : ScreenStateHelper.SCREEN_STATE_OFF_UNLOCKED;
+ }
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
screenState = mKeyguard.isKeyguardLocked()
? ScreenStateHelper.SCREEN_STATE_ON_LOCKED
@@ -2213,8 +2255,10 @@ public class NfcService implements DeviceHostListener {
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
}
-
- new ApplyRoutingTask().execute(Integer.valueOf(screenState));
+ if (nci_version != NCI_VERSION_2_0) {
+ new ApplyRoutingTask().execute(Integer.valueOf(screenState));
+ }
+ sendMessage(NfcService.MSG_APPLY_SCREEN_STATE, screenState);
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
synchronized (this) {
diff --git a/src/com/android/nfc/ScreenStateHelper.java b/src/com/android/nfc/ScreenStateHelper.java
index b044c287..92ba1687 100644
--- a/src/com/android/nfc/ScreenStateHelper.java
+++ b/src/com/android/nfc/ScreenStateHelper.java
@@ -9,10 +9,16 @@ import android.os.PowerManager;
*/
class ScreenStateHelper {
- static final int SCREEN_STATE_UNKNOWN = 0;
- static final int SCREEN_STATE_OFF = 1;
- static final int SCREEN_STATE_ON_LOCKED = 2;
- static final int SCREEN_STATE_ON_UNLOCKED = 3;
+ static final int SCREEN_STATE_UNKNOWN = 0x00;
+ static final int SCREEN_STATE_OFF_UNLOCKED = 0x01;
+ static final int SCREEN_STATE_OFF_LOCKED = 0x02;
+ static final int SCREEN_STATE_ON_LOCKED = 0x04;
+ static final int SCREEN_STATE_ON_UNLOCKED = 0x08;
+
+ //Polling mask
+ static final int SCREEN_POLLING_TAG_MASK = 0x10;
+ static final int SCREEN_POLLING_P2P_MASK = 0x20;
+ static final int SCREEN_POLLING_READER_MASK = 0x40;
private final PowerManager mPowerManager;
private final KeyguardManager mKeyguardManager;
@@ -26,7 +32,11 @@ class ScreenStateHelper {
int checkScreenState() {
//TODO: fix deprecated api
if (!mPowerManager.isScreenOn()) {
- return SCREEN_STATE_OFF;
+ if(mKeyguardManager.isKeyguardLocked()) {
+ return SCREEN_STATE_OFF_LOCKED;
+ } else {
+ return SCREEN_STATE_OFF_UNLOCKED;
+ }
} else if (mKeyguardManager.isKeyguardLocked()) {
return SCREEN_STATE_ON_LOCKED;
} else {
@@ -39,12 +49,14 @@ class ScreenStateHelper {
*/
static String screenStateToString(int screenState) {
switch (screenState) {
- case SCREEN_STATE_OFF:
- return "OFF";
+ case SCREEN_STATE_OFF_LOCKED:
+ return "OFF_LOCKED";
case SCREEN_STATE_ON_LOCKED:
return "ON_LOCKED";
case SCREEN_STATE_ON_UNLOCKED:
return "ON_UNLOCKED";
+ case SCREEN_STATE_OFF_UNLOCKED:
+ return "OFF_UNLOCKED";
default:
return "UNKNOWN";
}
diff --git a/src/com/android/nfc/cardemulation/AidRoutingManager.java b/src/com/android/nfc/cardemulation/AidRoutingManager.java
index 96225b71..b21b9e79 100644
--- a/src/com/android/nfc/cardemulation/AidRoutingManager.java
+++ b/src/com/android/nfc/cardemulation/AidRoutingManager.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
public class AidRoutingManager {
+
static final String TAG = "AidRoutingManager";
static final boolean DBG = false;
@@ -40,7 +41,8 @@ public class AidRoutingManager {
static final int AID_MATCHING_EXACT_OR_PREFIX = 0x01;
// Every routing table entry is matched as a prefix
static final int AID_MATCHING_PREFIX_ONLY = 0x02;
-
+ // Every routing table entry can be matched either exact or prefix or subset only
+ static final int AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX = 0x03;
// This is the default IsoDep protocol route; it means
// that for any AID that needs to be routed to this
// destination, we won't need to add a rule to the routing
@@ -72,6 +74,11 @@ public class AidRoutingManager {
private native int doGetDefaultOffHostRouteDestination();
private native int doGetAidMatchingMode();
+ final class AidEntry {
+ boolean isOnHost;
+ int aidInfo;
+ }
+
public AidRoutingManager() {
mDefaultRoute = doGetDefaultRouteDestination();
if (DBG) Log.d(TAG, "mDefaultRoute=0x" + Integer.toHexString(mDefaultRoute));
@@ -83,7 +90,12 @@ public class AidRoutingManager {
public boolean supportsAidPrefixRouting() {
return mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
- mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY;
+ mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX;
+ }
+
+ public boolean supportsAidSubsetRouting() {
+ return mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX;
}
void clearNfcRoutingTableLocked() {
@@ -97,9 +109,23 @@ public class AidRoutingManager {
if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
// Cut off '*' since controller anyway treats all AIDs as a prefix
aid = aid.substring(0, aid.length() - 1);
- } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
+ aid = aid.substring(0, aid.length() - 1);
if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
}
+ } else if (aid.endsWith("#")) {
+ if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
+ if (DBG) Log.d(TAG, "Unrouting subset AID " + aid);
+ aid = aid.substring(0, aid.length() - 1);
+ }
} else {
if (DBG) Log.d(TAG, "Unrouting exact AID " + aid);
}
@@ -108,17 +134,20 @@ public class AidRoutingManager {
}
}
- public boolean configureRouting(HashMap<String, Boolean> aidMap) {
+ public boolean configureRouting(HashMap<String, AidEntry> aidMap) {
SparseArray<Set<String>> aidRoutingTable = new SparseArray<Set<String>>(aidMap.size());
HashMap<String, Integer> routeForAid = new HashMap<String, Integer>(aidMap.size());
+ HashMap<String, Integer> infoForAid = new HashMap<String, Integer>(aidMap.size());
// Then, populate internal data structures first
- for (Map.Entry<String, Boolean> aidEntry : aidMap.entrySet()) {
- int route = aidEntry.getValue() ? ROUTE_HOST : mDefaultOffHostRoute;
+ for (Map.Entry<String, AidEntry> aidEntry : aidMap.entrySet()) {
+ int route = aidEntry.getValue().isOnHost ? ROUTE_HOST : mDefaultOffHostRoute;
+ int aidType = aidEntry.getValue().aidInfo;
String aid = aidEntry.getKey();
Set<String> entries = aidRoutingTable.get(route, new HashSet<String>());
entries.add(aid);
aidRoutingTable.put(route, entries);
routeForAid.put(aid, route);
+ infoForAid.put(aid, aidType);
}
synchronized (mLock) {
@@ -155,11 +184,11 @@ public class AidRoutingManager {
String aid = aidEntry.getKey();
int route = aidEntry.getValue();
if (defaultRouteAid.startsWith(aid) && route != mDefaultRoute) {
- if (DBG)
- Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
- "route, because a conflicting shorter AID will be " +
- "added to the routing table");
- NfcService.getInstance().routeAids(defaultRouteAid, mDefaultRoute);
+ if (DBG) Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
+ "route, because a conflicting shorter AID will be " +
+ "added to the routing table");
+ NfcService.getInstance().routeAids(defaultRouteAid, mDefaultRoute,
+ infoForAid.get(defaultRouteAid));
}
}
}
@@ -180,16 +209,32 @@ public class AidRoutingManager {
+ Integer.toString(route));
// Cut off '*' since controller anyway treats all AIDs as a prefix
NfcService.getInstance().routeAids(aid.substring(0,
- aid.length() - 1), route);
- } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
+ aid.length() - 1), route, infoForAid.get(aid));
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
+ Integer.toString(route));
- NfcService.getInstance().routeAids(aid, route);
+ NfcService.getInstance().routeAids(aid.substring(0,aid.length() - 1),
+ route, infoForAid.get(aid));
+ }
+ } else if (aid.endsWith("#")) {
+ if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
+ if (DBG) Log.d(TAG, "Routing subset AID " + aid + " to route "
+ + Integer.toString(route));
+ NfcService.getInstance().routeAids(aid.substring(0,aid.length() - 1),
+ route, infoForAid.get(aid));
}
} else {
if (DBG) Log.d(TAG, "Routing exact AID " + aid + " to route "
+ Integer.toString(route));
- NfcService.getInstance().routeAids(aid, route);
+ NfcService.getInstance().routeAids(aid, route, infoForAid.get(aid));
}
}
}
diff --git a/src/com/android/nfc/cardemulation/EnabledNfcFServices.java b/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
index 1d2acb58..c06ca26b 100644
--- a/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
+++ b/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
@@ -117,7 +117,8 @@ public class EnabledNfcFServices implements com.android.nfc.ForegroundUtils.Call
return false;
} else {
if (serviceInfo.getSystemCode().equalsIgnoreCase("NULL") ||
- serviceInfo.getNfcid2().equalsIgnoreCase("NULL")) {
+ serviceInfo.getNfcid2().equalsIgnoreCase("NULL") ||
+ serviceInfo.getT3tPmm().equalsIgnoreCase("NULL")) {
return false;
}
}
diff --git a/src/com/android/nfc/cardemulation/RegisteredAidCache.java b/src/com/android/nfc/cardemulation/RegisteredAidCache.java
index 0ac04b71..402d7936 100644
--- a/src/com/android/nfc/cardemulation/RegisteredAidCache.java
+++ b/src/com/android/nfc/cardemulation/RegisteredAidCache.java
@@ -24,7 +24,7 @@ import android.nfc.cardemulation.CardEmulation;
import android.util.Log;
import com.google.android.collect.Maps;
-
+import java.util.Collections;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -42,14 +42,17 @@ public class RegisteredAidCache {
static final boolean DBG = false;
+ static final int AID_ROUTE_QUAL_SUBSET = 0x20;
+ static final int AID_ROUTE_QUAL_PREFIX = 0x10;
+
// mAidServices maps AIDs to services that have registered them.
// It's a TreeMap in order to be able to quickly select subsets
// of AIDs that conflict with each other.
final TreeMap<String, ArrayList<ServiceAidInfo>> mAidServices =
new TreeMap<String, ArrayList<ServiceAidInfo>>();
- // mAidCache is a lookup table for quickly mapping an exact or prefix AID to one or
- // more handling services. It differs from mAidServices in the sense that it
+ // mAidCache is a lookup table for quickly mapping an exact or prefix or subset AID
+ // to one or more handling services. It differs from mAidServices in the sense that it
// has already accounted for defaults, and hence its return value
// is authoritative for the current set of services and defaults.
// It is only valid for the current user.
@@ -100,7 +103,7 @@ public class RegisteredAidCache {
ApduServiceInfo defaultService = null;
String category = null;
boolean mustRoute = true; // Whether this AID should be routed at all
-
+ ReslovedPrefixConflictAid prefixInfo = null;
@Override
public String toString() {
return "AidResolveInfo{" +
@@ -124,6 +127,7 @@ public class RegisteredAidCache {
boolean mNfcEnabled = false;
boolean mSupportsPrefixes = false;
+ boolean mSupportsSubset = false;
public RegisteredAidCache(Context context) {
mContext = context;
@@ -131,9 +135,13 @@ public class RegisteredAidCache {
mPreferredPaymentService = null;
mPreferredForegroundService = null;
mSupportsPrefixes = mRoutingManager.supportsAidPrefixRouting();
+ mSupportsSubset = mRoutingManager.supportsAidSubsetRouting();
if (mSupportsPrefixes) {
if (DBG) Log.d(TAG, "Controller supports AID prefix routing");
}
+ if (mSupportsSubset) {
+ if (DBG) Log.d(TAG, "Controller supports AID subset routing");
+ }
}
public AidResolveInfo resolveAid(String aid) {
@@ -144,12 +152,13 @@ public class RegisteredAidCache {
return EMPTY_RESOLVE_INFO;
}
AidResolveInfo resolveInfo = new AidResolveInfo();
- if (mSupportsPrefixes) {
- // Our AID cache may contain prefixes which also match this AID,
- // so we must find all potential prefixes and merge the ResolveInfo
+ if (mSupportsPrefixes || mSupportsSubset) {
+ // Our AID cache may contain prefixes/subset which also match this AID,
+ // so we must find all potential prefixes or suffixes and merge the ResolveInfo
// of those prefixes plus any exact match in a single result.
String shortestAidMatch = aid.substring(0, 10); // Minimum AID length is 5 bytes
- String longestAidMatch = aid + "*"; // Longest potential matching AID
+ String longestAidMatch = String.format("%-32s", aid).replace(' ', 'F');
+
if (DBG) Log.d(TAG, "Finding AID registrations in range [" + shortestAidMatch +
" - " + longestAidMatch + "]");
@@ -159,9 +168,11 @@ public class RegisteredAidCache {
resolveInfo.category = CardEmulation.CATEGORY_OTHER;
for (Map.Entry<String, AidResolveInfo> entry : matchingAids.entrySet()) {
boolean isPrefix = isPrefix(entry.getKey());
- String entryAid = isPrefix ? entry.getKey().substring(0,
- entry.getKey().length() - 1) : entry.getKey(); // Cut off '*' if prefix
- if (entryAid.equalsIgnoreCase(aid) || (isPrefix && aid.startsWith(entryAid))) {
+ boolean isSubset = isSubset(entry.getKey());
+ String entryAid = (isPrefix || isSubset) ? entry.getKey().substring(0,
+ entry.getKey().length() - 1):entry.getKey(); // Cut off '*' if prefix
+ if (entryAid.equalsIgnoreCase(aid) || (isPrefix && aid.startsWith(entryAid))
+ || (isSubset && entryAid.startsWith(aid))) {
if (DBG) Log.d(TAG, "resolveAid: AID " + entry.getKey() + " matches.");
AidResolveInfo entryResolveInfo = entry.getValue();
if (entryResolveInfo.defaultService != null) {
@@ -192,6 +203,10 @@ public class RegisteredAidCache {
return mSupportsPrefixes;
}
+ public boolean supportsAidSubsetRegistration() {
+ return mSupportsSubset;
+ }
+
public boolean isDefaultServiceForAid(int userId, ComponentName service, String aid) {
AidResolveInfo resolveInfo = resolveAid(aid);
if (resolveInfo == null || resolveInfo.services == null ||
@@ -305,27 +320,33 @@ public class RegisteredAidCache {
return defaultServiceInfo;
}
- AidResolveInfo resolvePrefixAidConflictLocked(ArrayList<ServiceAidInfo> prefixServices,
+ AidResolveInfo resolveAidConflictLocked(ArrayList<ServiceAidInfo> aidServices,
ArrayList<ServiceAidInfo> conflictingServices) {
- // Find defaults among the prefix services themselves
- DefaultServiceInfo prefixDefaultInfo = findDefaultServices(prefixServices);
+ // Find defaults among the root AID services themselves
+ DefaultServiceInfo aidDefaultInfo = findDefaultServices(aidServices);
// Find any defaults among the children
DefaultServiceInfo conflictingDefaultInfo = findDefaultServices(conflictingServices);
-
- // Three conditions under which the prefix root AID gets to be the default
- // 1. A service registering the prefix root AID is the current foreground preferred
- // 2. A service registering the prefix root AID is the current tap & pay default AND
+ AidResolveInfo resolveinfo;
+ // Three conditions under which the root AID gets to be the default
+ // 1. A service registering the root AID is the current foreground preferred
+ // 2. A service registering the root AID is the current tap & pay default AND
// no child is the current foreground preferred
- // 3. There is only one service for the prefix root AID, and there are no children
- if (prefixDefaultInfo.foregroundDefault != null) {
+ // 3. There is only one service for the root AID, and there are no children
+ if (aidDefaultInfo.foregroundDefault != null) {
if (DBG) Log.d(TAG, "Prefix AID service " +
- prefixDefaultInfo.foregroundDefault.service.getComponent() + " has foreground" +
+ aidDefaultInfo.foregroundDefault.service.getComponent() + " has foreground" +
" preference, ignoring conflicting AIDs.");
// Foreground default trumps any conflicting services, treat as normal AID conflict
// and ignore children
- return resolveAidConflictLocked(prefixServices, true);
- } else if (prefixDefaultInfo.paymentDefault != null) {
+ resolveinfo = resolveAidConflictLocked(aidServices, true);
+ //If the AID is subsetAID check for prefix in same service.
+ if (isSubset(aidServices.get(0).aid)) {
+ resolveinfo.prefixInfo = findPrefixConflictForSubsetAid(aidServices.get(0).aid ,
+ new ArrayList<ApduServiceInfo>(){{add(resolveinfo.defaultService);}},true);
+ }
+ return resolveinfo;
+ } else if (aidDefaultInfo.paymentDefault != null) {
// Check if any of the conflicting services is foreground default
if (conflictingDefaultInfo.foregroundDefault != null) {
// Conflicting AID registration is in foreground, trumps prefix tap&pay default
@@ -335,9 +356,15 @@ public class RegisteredAidCache {
} else {
// Prefix service is tap&pay default, treat as normal AID conflict for just prefix
if (DBG) Log.d(TAG, "Prefix AID service " +
- prefixDefaultInfo.paymentDefault.service.getComponent() + " is payment" +
+ aidDefaultInfo.paymentDefault.service.getComponent() + " is payment" +
" default, ignoring conflicting AIDs.");
- return resolveAidConflictLocked(prefixServices, true);
+ resolveinfo = resolveAidConflictLocked(aidServices, true);
+ //If the AID is subsetAID check for prefix in same service.
+ if (isSubset(aidServices.get(0).aid)) {
+ resolveinfo.prefixInfo = findPrefixConflictForSubsetAid(aidServices.get(0).aid ,
+ new ArrayList<ApduServiceInfo>(){{add(resolveinfo.defaultService);}},true);
+ }
+ return resolveinfo;
}
} else {
if (conflictingDefaultInfo.foregroundDefault != null ||
@@ -349,7 +376,19 @@ public class RegisteredAidCache {
// No children that are preferred; add all services of the root
// make single service default if no children are present
if (DBG) Log.d(TAG, "No service has preference, adding all.");
- return resolveAidConflictLocked(prefixServices, conflictingServices.isEmpty());
+ resolveinfo = resolveAidConflictLocked(aidServices, conflictingServices.isEmpty());
+ //If the AID is subsetAID check for conflicting prefix in all
+ //conflciting services and root services.
+ if (isSubset(aidServices.get(0).aid)) {
+ ArrayList <ApduServiceInfo> apduServiceList = new ArrayList <ApduServiceInfo>();
+ for (ServiceAidInfo serviceInfo : conflictingServices)
+ apduServiceList.add(serviceInfo.service);
+ for (ServiceAidInfo serviceInfo : aidServices)
+ apduServiceList.add(serviceInfo.service);
+ resolveinfo.prefixInfo =
+ findPrefixConflictForSubsetAid(aidServices.get(0).aid ,apduServiceList,false);
+ }
+ return resolveinfo;
}
}
}
@@ -360,6 +399,8 @@ public class RegisteredAidCache {
for (ApduServiceInfo service : services) {
if (DBG) Log.d(TAG, "generateServiceMap component: " + service.getComponent());
List<String> prefixAids = service.getPrefixAids();
+ List<String> subSetAids = service.getSubsetAids();
+
for (String aid : service.getAids()) {
if (!CardEmulation.isValidAid(aid)) {
Log.e(TAG, "Aid " + aid + " is not valid.");
@@ -368,7 +409,7 @@ public class RegisteredAidCache {
if (aid.endsWith("*") && !supportsAidPrefixRegistration()) {
Log.e(TAG, "Prefix AID " + aid + " ignored on device that doesn't support it.");
continue;
- } else if (supportsAidPrefixRegistration() && prefixAids.size() > 0 && !isPrefix(aid)) {
+ } else if (supportsAidPrefixRegistration() && prefixAids.size() > 0 && isExact(aid)) {
// Check if we already have an overlapping prefix registered for this AID
boolean foundPrefix = false;
for (String prefixAid : prefixAids) {
@@ -383,7 +424,26 @@ public class RegisteredAidCache {
if (foundPrefix) {
continue;
}
+ } else if (aid.endsWith("#") && !supportsAidSubsetRegistration()) {
+ Log.e(TAG, "Subset AID " + aid + " ignored on device that doesn't support it.");
+ continue;
+ } else if (supportsAidSubsetRegistration() && subSetAids.size() > 0 && isExact(aid)) {
+ // Check if we already have an overlapping subset registered for this AID
+ boolean foundSubset = false;
+ for (String subsetAid : subSetAids) {
+ String plainSubset = subsetAid.substring(0, subsetAid.length() - 1);
+ if (plainSubset.startsWith(aid)) {
+ Log.e(TAG, "Ignoring exact AID " + aid + " because subset AID " + plainSubset +
+ " is already registered");
+ foundSubset = true;
+ break;
+ }
+ }
+ if (foundSubset) {
+ continue;
+ }
}
+
ServiceAidInfo serviceAidInfo = new ServiceAidInfo();
serviceAidInfo.aid = aid.toUpperCase();
serviceAidInfo.service = service;
@@ -403,18 +463,67 @@ public class RegisteredAidCache {
}
}
+ static boolean isExact(String aid) {
+ return (!((aid.endsWith("*") || (aid.endsWith("#")))));
+ }
+
static boolean isPrefix(String aid) {
return aid.endsWith("*");
}
- final class PrefixConflicts {
+ static boolean isSubset(String aid) {
+ return aid.endsWith("#");
+ }
+
+ final class ReslovedPrefixConflictAid {
+ String prefixAid = null;
+ boolean matchingSubset = false;
+ }
+
+ final class AidConflicts {
NavigableMap<String, ArrayList<ServiceAidInfo>> conflictMap;
final ArrayList<ServiceAidInfo> services = new ArrayList<ServiceAidInfo>();
final HashSet<String> aids = new HashSet<String>();
}
- PrefixConflicts findConflictsForPrefixLocked(String prefixAid) {
- PrefixConflicts prefixConflicts = new PrefixConflicts();
+ ReslovedPrefixConflictAid findPrefixConflictForSubsetAid(String subsetAid ,
+ ArrayList<ApduServiceInfo> prefixServices, boolean priorityRootAid){
+ ArrayList<String> prefixAids = new ArrayList<String>();
+ String minPrefix = null;
+ //This functions checks whether there is a prefix AID matching to subset AID
+ //Because both the subset AID and matching smaller perfix are to be added to routing table.
+ //1.Finds the prefix matching AID in the services sent.
+ //2.Find the smallest prefix among matching prefix and add it only if it is not same as susbet AID.
+ //3..If the subset AID and prefix AID are same add only one AID with both prefix , subset bits set.
+ // Cut off "#"
+ String plainSubsetAid = subsetAid.substring(0, subsetAid.length() - 1);
+ for (ApduServiceInfo service : prefixServices) {
+ for (String prefixAid : service.getPrefixAids()) {
+ // Cut off "#"
+ String plainPrefix= prefixAid.substring(0, prefixAid.length() - 1);
+ if( plainSubsetAid.startsWith(plainPrefix)) {
+ if (priorityRootAid) {
+ if (CardEmulation.CATEGORY_PAYMENT.equals(service.getCategoryForAid(prefixAid)) ||
+ (service.getComponent().equals(mPreferredForegroundService)))
+ prefixAids.add(prefixAid);
+ } else {
+ prefixAids.add(prefixAid);
+ }
+ }
+ }
+ }
+ if (prefixAids.size() > 0)
+ minPrefix = Collections.min(prefixAids);
+ ReslovedPrefixConflictAid resolvedPrefix = new ReslovedPrefixConflictAid();
+ resolvedPrefix.prefixAid = minPrefix;
+ if ((minPrefix != null ) &&
+ plainSubsetAid.equalsIgnoreCase(minPrefix.substring(0, minPrefix.length() - 1)))
+ resolvedPrefix.matchingSubset = true;
+ return resolvedPrefix;
+ }
+
+ AidConflicts findConflictsForPrefixLocked(String prefixAid) {
+ AidConflicts prefixConflicts = new AidConflicts();
String plainAid = prefixAid.substring(0, prefixAid.length() - 1); // Cut off "*"
String lastAidWithPrefix = String.format("%-32s", plainAid).replace(' ', 'F');
if (DBG) Log.d(TAG, "Finding AIDs in range [" + plainAid + " - " +
@@ -434,11 +543,46 @@ public class RegisteredAidCache {
return prefixConflicts;
}
+ AidConflicts findConflictsForSubsetAidLocked(String subsetAid) {
+ AidConflicts subsetConflicts = new AidConflicts();
+ // Cut off "@"
+ String lastPlainAid = subsetAid.substring(0, subsetAid.length() - 1);
+ // Cut off "@"
+ String plainSubsetAid = subsetAid.substring(0, subsetAid.length() - 1);
+ String firstAid = subsetAid.substring(0, 10);
+ if (DBG) Log.d(TAG, "Finding AIDs in range [" + firstAid + " - " +
+ lastPlainAid + "]");
+ subsetConflicts.conflictMap = new TreeMap();
+ for (Map.Entry<String, ArrayList<ServiceAidInfo>> entry :
+ mAidServices.entrySet()) {
+ String aid = entry.getKey();
+ String plainAid = aid;
+ if (isSubset(aid) || isPrefix(aid))
+ plainAid = aid.substring(0, aid.length() - 1);
+ if (plainSubsetAid.startsWith(plainAid))
+ subsetConflicts.conflictMap.put(entry.getKey(),entry.getValue());
+ }
+ for (Map.Entry<String, ArrayList<ServiceAidInfo>> entry :
+ subsetConflicts.conflictMap.entrySet()) {
+ if (!entry.getKey().equalsIgnoreCase(subsetAid)) {
+ if (DBG)
+ Log.d(TAG, "AID " + entry.getKey() + " conflicts with subset AID; " +
+ " adding handling services for conflict resolution.");
+ subsetConflicts.services.addAll(entry.getValue());
+ subsetConflicts.aids.add(entry.getKey());
+ }
+ }
+ return subsetConflicts;
+ }
+
void generateAidCacheLocked() {
mAidCache.clear();
// Get all exact and prefix AIDs in an ordered list
- PriorityQueue<String> aidsToResolve = new PriorityQueue<String>(mAidServices.keySet());
+ final TreeMap<String, AidResolveInfo> aidCache = new TreeMap<String, AidResolveInfo>();
+ //aidCache is temproary cache for geenrating the first prefix based lookup table.
+ PriorityQueue<String> aidsToResolve = new PriorityQueue<String>(mAidServices.keySet());
+ aidCache.clear();
while (!aidsToResolve.isEmpty()) {
final ArrayList<String> resolvedAids = new ArrayList<String>();
@@ -448,6 +592,7 @@ public class RegisteredAidCache {
// A special case is if another service registered the same AID as a prefix, in
// which case we want to start with that AID, since it conflicts with this one
+ // All exact and suffix and prefix AID must be checked for conflicting cases
if (aidsToResolve.contains(aidToResolve + "*")) {
aidToResolve = aidToResolve + "*";
}
@@ -462,17 +607,28 @@ public class RegisteredAidCache {
mAidServices.get(aidToResolve));
// Find all conflicting children services
- PrefixConflicts prefixConflicts = findConflictsForPrefixLocked(aidToResolve);
+ AidConflicts prefixConflicts = findConflictsForPrefixLocked(aidToResolve);
// Resolve conflicts
- AidResolveInfo resolveInfo = resolvePrefixAidConflictLocked(prefixServices,
+ AidResolveInfo resolveInfo = resolveAidConflictLocked(prefixServices,
prefixConflicts.services);
- mAidCache.put(aidToResolve, resolveInfo);
+ aidCache.put(aidToResolve, resolveInfo);
resolvedAids.add(aidToResolve);
if (resolveInfo.defaultService != null) {
// This prefix is the default; therefore, AIDs of all conflicting children
// will no longer be evaluated.
resolvedAids.addAll(prefixConflicts.aids);
+ for (String aid : resolveInfo.defaultService.getSubsetAids()) {
+ if (prefixConflicts.aids.contains(aid)) {
+ if ((CardEmulation.CATEGORY_PAYMENT.equals(resolveInfo.defaultService.getCategoryForAid(aid))) ||
+ (resolveInfo.defaultService.getComponent().equals(mPreferredForegroundService))) {
+ AidResolveInfo childResolveInfo = resolveAidConflictLocked(mAidServices.get(aid), false);
+ aidCache.put(aid,childResolveInfo);
+ Log.d(TAG, "AID " + aid+ " shared with prefix; " +
+ "adding subset .");
+ }
+ }
+ }
} else if (resolveInfo.services.size() > 0) {
// This means we don't have a default for this prefix and all its
// conflicting children. So, for all conflicting AIDs, just add
@@ -491,7 +647,7 @@ public class RegisteredAidCache {
// Since these are all "children" of the prefix, they don't need
// to be routed, since the prefix will already get routed to the host
childResolveInfo.mustRoute = false;
- mAidCache.put(entry.getKey(),childResolveInfo);
+ aidCache.put(entry.getKey(),childResolveInfo);
resolvedAids.add(entry.getKey());
foundChildService |= !childResolveInfo.services.isEmpty();
}
@@ -512,7 +668,7 @@ public class RegisteredAidCache {
if (DBG) Log.d(TAG, "Exact AID, resolving.");
final ArrayList<ServiceAidInfo> conflictingServiceInfos =
new ArrayList<ServiceAidInfo>(mAidServices.get(aidToResolve));
- mAidCache.put(aidToResolve, resolveAidConflictLocked(conflictingServiceInfos, true));
+ aidCache.put(aidToResolve, resolveAidConflictLocked(conflictingServiceInfos, true));
resolvedAids.add(aidToResolve);
}
@@ -521,6 +677,103 @@ public class RegisteredAidCache {
aidsToResolve.removeAll(resolvedAids);
resolvedAids.clear();
}
+ PriorityQueue<String> reversedQueue = new PriorityQueue<String>(1, Collections.reverseOrder());
+ reversedQueue.addAll(aidCache.keySet());
+ while (!reversedQueue.isEmpty()) {
+ final ArrayList<String> resolvedAids = new ArrayList<String>();
+
+ String aidToResolve = reversedQueue.peek();
+ if (isPrefix(aidToResolve)) {
+ String matchingSubset = aidToResolve.substring(0,aidToResolve.length()-1 ) + "#";
+ if (DBG) Log.d(TAG, "matching subset"+matchingSubset);
+ if (reversedQueue.contains(matchingSubset))
+ aidToResolve = aidToResolve.substring(0,aidToResolve.length()-1) + "#";
+ }
+ if (isSubset(aidToResolve)) {
+ if (DBG) Log.d(TAG, "subset resolving aidToResolve "+aidToResolve);
+ final ArrayList<ServiceAidInfo> subsetServices = new ArrayList<ServiceAidInfo>(
+ mAidServices.get(aidToResolve));
+
+ // Find all conflicting children services
+ AidConflicts aidConflicts = findConflictsForSubsetAidLocked(aidToResolve);
+
+ // Resolve conflicts
+ AidResolveInfo resolveInfo = resolveAidConflictLocked(subsetServices,
+ aidConflicts.services);
+ mAidCache.put(aidToResolve, resolveInfo);
+ resolvedAids.add(aidToResolve);
+ if (resolveInfo.defaultService != null) {
+ // This subset is the default; therefore, AIDs of all conflicting children
+ // will no longer be evaluated.Check for any prefix matching in the same service
+ if (resolveInfo.prefixInfo != null && resolveInfo.prefixInfo.prefixAid != null &&
+ !resolveInfo.prefixInfo.matchingSubset) {
+ if (DBG)
+ Log.d(TAG, "AID default " + resolveInfo.prefixInfo.prefixAid +
+ " prefix AID shared with dsubset root; " +
+ " adding prefix aid");
+ AidResolveInfo childResolveInfo = resolveAidConflictLocked(
+ mAidServices.get(resolveInfo.prefixInfo.prefixAid), false);
+ mAidCache.put(resolveInfo.prefixInfo.prefixAid, childResolveInfo);
+ }
+ resolvedAids.addAll(aidConflicts.aids);
+ } else if (resolveInfo.services.size() > 0) {
+ // This means we don't have a default for this subset and all its
+ // conflicting children. So, for all conflicting AIDs, just add
+ // all handling services without setting a default
+ boolean foundChildService = false;
+ for (Map.Entry<String, ArrayList<ServiceAidInfo>> entry :
+ aidConflicts.conflictMap.entrySet()) {
+ // We need to add shortest prefix among them.
+ if (!entry.getKey().equalsIgnoreCase(aidToResolve)) {
+ if (DBG)
+ Log.d(TAG, "AID " + entry.getKey() + " shared with subset root; " +
+ " adding all handling services.");
+ AidResolveInfo childResolveInfo = resolveAidConflictLocked(
+ entry.getValue(), false);
+ // Special case: in this case all children AIDs must be routed to the
+ // host, so we can ask the user which service is preferred.
+ // Since these are all "children" of the subset, they don't need
+ // to be routed, since the subset will already get routed to the host
+ childResolveInfo.mustRoute = false;
+ mAidCache.put(entry.getKey(),childResolveInfo);
+ resolvedAids.add(entry.getKey());
+ foundChildService |= !childResolveInfo.services.isEmpty();
+ }
+ }
+ if(resolveInfo.prefixInfo != null &&
+ resolveInfo.prefixInfo.prefixAid != null &&
+ !resolveInfo.prefixInfo.matchingSubset) {
+ AidResolveInfo childResolveInfo = resolveAidConflictLocked(
+ mAidServices.get(resolveInfo.prefixInfo.prefixAid), false);
+ mAidCache.put(resolveInfo.prefixInfo.prefixAid, childResolveInfo);
+ if (DBG)
+ Log.d(TAG, "AID " + resolveInfo.prefixInfo.prefixAid +
+ " prefix AID shared with subset root; " +
+ " adding prefix aid");
+ }
+ // Special case: if in the end we didn't add any children services,
+ // and the subset has only one service, make that default
+ if (!foundChildService && resolveInfo.services.size() == 1) {
+ resolveInfo.defaultService = resolveInfo.services.get(0);
+ }
+ } else {
+ // This subset is not handled at all; we will evaluate
+ // the children separately in next passes.
+ }
+ } else {
+ // Exact AID and no other conflicting AID registrations present. This is
+ // true because reversedQueue is lexicographically ordered in revrese, and
+ // so by necessity all other AIDs are different than this AID or shorter.
+ if (DBG) Log.d(TAG, "Exact or Prefix AID."+aidToResolve);
+ mAidCache.put(aidToResolve, aidCache.get(aidToResolve));
+ resolvedAids.add(aidToResolve);
+ }
+
+ // Remove the AIDs we resolved from the list of AIDs to resolve
+ if (DBG) Log.d(TAG, "AIDs: " + resolvedAids + " were resolved.");
+ reversedQueue.removeAll(resolvedAids);
+ resolvedAids.clear();
+ }
updateRoutingLocked();
}
@@ -530,7 +783,7 @@ public class RegisteredAidCache {
if (DBG) Log.d(TAG, "Not updating routing table because NFC is off.");
return;
}
- final HashMap<String, Boolean> routingEntries = Maps.newHashMap();
+ final HashMap<String, AidRoutingManager.AidEntry> routingEntries = Maps.newHashMap();
// For each AID, find interested services
for (Map.Entry<String, AidResolveInfo> aidEntry:
mAidCache.entrySet()) {
@@ -540,19 +793,30 @@ public class RegisteredAidCache {
if (DBG) Log.d(TAG, "Not routing AID " + aid + " on request.");
continue;
}
+ AidRoutingManager.AidEntry aidType = mRoutingManager.new AidEntry();
+ if (aid.endsWith("#")) {
+ aidType.aidInfo |= AID_ROUTE_QUAL_SUBSET;
+ }
+ if(aid.endsWith("*") || (resolveInfo.prefixInfo != null &&
+ resolveInfo.prefixInfo.matchingSubset)) {
+ aidType.aidInfo |= AID_ROUTE_QUAL_PREFIX;
+ }
if (resolveInfo.services.size() == 0) {
// No interested services
} else if (resolveInfo.defaultService != null) {
// There is a default service set, route to where that service resides -
// either on the host (HCE) or on an SE.
- routingEntries.put(aid, resolveInfo.defaultService.isOnHost());
+ aidType.isOnHost = resolveInfo.defaultService.isOnHost();
+ routingEntries.put(aid, aidType);
} else if (resolveInfo.services.size() == 1) {
// Only one service, but not the default, must route to host
// to ask the user to choose one.
- routingEntries.put(aid, true);
+ aidType.isOnHost = true;
+ routingEntries.put(aid, aidType);
} else if (resolveInfo.services.size() > 1) {
// Multiple services, need to route to host to ask
- routingEntries.put(aid, true);
+ aidType.isOnHost = true;
+ routingEntries.put(aid, aidType);
}
}
mRoutingManager.configureRouting(routingEntries);
diff --git a/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java b/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
index de7ef8f4..6391a51f 100644
--- a/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
+++ b/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
@@ -46,10 +46,12 @@ public class RegisteredT3tIdentifiersCache {
final class T3tIdentifier {
public final String systemCode;
public final String nfcid2;
+ public final String t3tPmm;
- T3tIdentifier(String systemCode, String nfcid2) {
+ T3tIdentifier(String systemCode, String nfcid2, String t3tPmm) {
this.systemCode = systemCode;
this.nfcid2 = nfcid2;
+ this.t3tPmm = t3tPmm;
}
@Override
@@ -138,7 +140,7 @@ public class RegisteredT3tIdentifiersCache {
Map.Entry<String, NfcFServiceInfo> entry =
(Map.Entry<String, NfcFServiceInfo>) it.next();
t3tIdentifiers.add(new T3tIdentifier(
- entry.getValue().getSystemCode(), entry.getValue().getNfcid2()));
+ entry.getValue().getSystemCode(), entry.getValue().getNfcid2(), entry.getValue().getT3tPmm()));
}
mRoutingManager.configureRouting(t3tIdentifiers);
}
diff --git a/src/com/android/nfc/cardemulation/SystemCodeRoutingManager.java b/src/com/android/nfc/cardemulation/SystemCodeRoutingManager.java
index 70195255..a2d2a777 100644
--- a/src/com/android/nfc/cardemulation/SystemCodeRoutingManager.java
+++ b/src/com/android/nfc/cardemulation/SystemCodeRoutingManager.java
@@ -59,25 +59,26 @@ public class SystemCodeRoutingManager {
for (T3tIdentifier t3tIdentifier : toBeRemoved) {
if (DBG) Log.d(TAG, "deregisterNfcFSystemCodeonDh:");
NfcService.getInstance().deregisterT3tIdentifier(
- t3tIdentifier.systemCode, t3tIdentifier.nfcid2);
+ t3tIdentifier.systemCode, t3tIdentifier.nfcid2, t3tIdentifier.t3tPmm);
}
for (T3tIdentifier t3tIdentifier : toBeAdded) {
if (DBG) Log.d(TAG, "registerNfcFSystemCodeonDh:");
NfcService.getInstance().registerT3tIdentifier(
- t3tIdentifier.systemCode, t3tIdentifier.nfcid2);
+ t3tIdentifier.systemCode, t3tIdentifier.nfcid2 , t3tIdentifier.t3tPmm);
}
if (DBG) {
Log.d(TAG, "(Before) mConfiguredT3tIdentifiers: size=" +
mConfiguredT3tIdentifiers.size());
for (T3tIdentifier t3tIdentifier : mConfiguredT3tIdentifiers) {
Log.d(TAG, " " + t3tIdentifier.systemCode +
- "/" + t3tIdentifier.nfcid2);
+ "/" + t3tIdentifier.t3tPmm);
}
Log.d(TAG, "(After) mConfiguredT3tIdentifiers: size=" +
t3tIdentifiers.size());
for (T3tIdentifier t3tIdentifier : t3tIdentifiers) {
Log.d(TAG, " " + t3tIdentifier.systemCode +
- "/" + t3tIdentifier.nfcid2);
+ "/" + t3tIdentifier.nfcid2 +
+ "/" + t3tIdentifier.t3tPmm);
}
}
mConfiguredT3tIdentifiers = t3tIdentifiers;