diff options
author | Martijn Coenen <maco@google.com> | 2012-10-11 16:01:48 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-10-11 16:01:48 -0700 |
commit | 59f43aefee220afd41baa97ce2043017c171be73 (patch) | |
tree | 0c74968c6af7ff7ec96c50fa708b801dfbabdfb9 /nci | |
parent | 1b4047043526e88bcecb32f640d83e0d9a851128 (diff) | |
parent | a949c74321b17f8ef1c93692064969f60815c7e4 (diff) | |
download | packages_apps_nfc-59f43aefee220afd41baa97ce2043017c171be73.zip packages_apps_nfc-59f43aefee220afd41baa97ce2043017c171be73.tar.gz packages_apps_nfc-59f43aefee220afd41baa97ce2043017c171be73.tar.bz2 |
am a949c743: Fast-fail SE open if it\'s activated in listen mode.
* commit 'a949c74321b17f8ef1c93692064969f60815c7e4':
Fast-fail SE open if it's activated in listen mode.
Diffstat (limited to 'nci')
-rw-r--r-- | nci/jni/JavaClassConstants.h | 2 | ||||
-rwxr-xr-x | nci/jni/NativeNfcManager.cpp | 47 | ||||
-rwxr-xr-x | nci/jni/NativeSecureElement.cpp | 20 | ||||
-rwxr-xr-x | nci/jni/SecureElement.cpp | 127 | ||||
-rwxr-xr-x | nci/jni/SecureElement.h | 40 | ||||
-rwxr-xr-x | nci/src/com/android/nfc/dhimpl/NativeNfcManager.java | 8 |
6 files changed, 227 insertions, 17 deletions
diff --git a/nci/jni/JavaClassConstants.h b/nci/jni/JavaClassConstants.h index 64244c3..30deca9 100644 --- a/nci/jni/JavaClassConstants.h +++ b/nci/jni/JavaClassConstants.h @@ -24,6 +24,8 @@ namespace android extern jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated; extern jmethodID gCachedNfcManagerNotifySeFieldActivated; extern jmethodID gCachedNfcManagerNotifySeFieldDeactivated; + extern jmethodID gCachedNfcManagerNotifySeListenActivated; + extern jmethodID gCachedNfcManagerNotifySeListenDeactivated; extern const char* gNativeP2pDeviceClassName; extern const char* gNativeLlcpServiceSocketClassName; diff --git a/nci/jni/NativeNfcManager.cpp b/nci/jni/NativeNfcManager.cpp index eadca87..81bb6b2 100755 --- a/nci/jni/NativeNfcManager.cpp +++ b/nci/jni/NativeNfcManager.cpp @@ -78,6 +78,8 @@ namespace android jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated; jmethodID gCachedNfcManagerNotifySeFieldActivated; jmethodID gCachedNfcManagerNotifySeFieldDeactivated; + jmethodID gCachedNfcManagerNotifySeListenActivated; + jmethodID gCachedNfcManagerNotifySeListenDeactivated; const char* gNativeP2pDeviceClassName = "com/android/nfc/dhimpl/NativeP2pDevice"; const char* gNativeLlcpServiceSocketClassName = "com/android/nfc/dhimpl/NativeLlcpServiceSocket"; const char* gNativeLlcpConnectionlessSocketClassName = "com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket"; @@ -112,6 +114,7 @@ static bool sDiscoveryEnabled = false; //is polling for tag? static bool sIsDisabling = false; static bool sRfEnabled = false; // whether RF discovery is enabled static bool sSeRfActive = false; // whether RF with SE is likely active +static bool sP2pActive = false; // whether p2p was last active static int sConnlessSap = 0; static int sConnlessLinkMiu = 0; static bool sAbortConnlessWait = false; @@ -304,7 +307,18 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat nativeNfcTag_resetPresenceCheck(); if (isPeerToPeer(eventData->activated)) { + sP2pActive = true; ALOGD("%s: NFA_ACTIVATED_EVT; is p2p", __FUNCTION__); + // Disable RF field events in case of p2p + UINT8 nfa_disable_rf_events[] = { 0x00 }; + ALOGD ("%s: Disabling RF field events", __FUNCTION__); + 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", __FUNCTION__); + } else { + ALOGE ("%s: Failed to disable RF field events", __FUNCTION__); + } } else if (pn544InteropIsBusy() == false) { @@ -316,7 +330,7 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat if (isListenMode(eventData->activated)) { sSeRfActive = true; - SecureElement::getInstance().notifyRfFieldEvent (true); + SecureElement::getInstance().notifyListenModeState (true); } } @@ -338,13 +352,30 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat // If RF is activated for what we think is a Secure Element transaction // and it is deactivated to either IDLE or DISCOVERY mode, notify w/event. - if (sSeRfActive - && ((eventData->deactivated.type == NFA_DEACTIVATE_TYPE_IDLE) - || (eventData->deactivated.type == NFA_DEACTIVATE_TYPE_DISCOVERY))) + if ((eventData->deactivated.type == NFA_DEACTIVATE_TYPE_IDLE) + || (eventData->deactivated.type == NFA_DEACTIVATE_TYPE_DISCOVERY)) { - sSeRfActive = false; - SecureElement::getInstance().notifyRfFieldEvent (false); + if (sSeRfActive) { + sSeRfActive = false; + SecureElement::getInstance().notifyListenModeState (false); + } else if (sP2pActive) { + sP2pActive = false; + // Make sure RF field events are re-enabled + ALOGD("%s: NFA_ACTIVATED_EVT; is p2p", __FUNCTION__); + // Disable RF field events in case of p2p + UINT8 nfa_enable_rf_events[] = { 0x01 }; + + ALOGD ("%s: Enabling RF field events", __FUNCTION__); + 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", __FUNCTION__); + } else { + ALOGE ("%s: Failed to enable RF field events", __FUNCTION__); + } + } } + break; case NFA_TLV_DETECT_EVT: // TLV Detection complete @@ -513,6 +544,10 @@ static jboolean nfcManager_initNativeStruc (JNIEnv* e, jobject o) "notifySeFieldActivated", "()V"); gCachedNfcManagerNotifySeFieldDeactivated = e->GetMethodID (cls, "notifySeFieldDeactivated", "()V"); + gCachedNfcManagerNotifySeListenActivated = e->GetMethodID (cls, + "notifySeListenActivated", "()V"); + gCachedNfcManagerNotifySeListenDeactivated = e->GetMethodID (cls, + "notifySeListenDeactivated", "()V"); sCachedNfcManagerNotifySeApduReceived = e->GetMethodID(cls, "notifySeApduReceived", "([B)V"); diff --git a/nci/jni/NativeSecureElement.cpp b/nci/jni/NativeSecureElement.cpp index 104d4ea..1a2a73a 100755 --- a/nci/jni/NativeSecureElement.cpp +++ b/nci/jni/NativeSecureElement.cpp @@ -44,24 +44,34 @@ static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv* e, job ALOGD("%s: enter", __FUNCTION__); bool stat = true; jint secElemHandle = 0; + SecureElement &se = SecureElement::getInstance(); + if (se.isActivatedInListenMode()) { + ALOGD("Denying SE open due to SE listen mode active"); + goto TheEnd; + } + + if (se.isRfFieldOn()) { + ALOGD("Denying SE open due to SE in active RF field"); + goto TheEnd; + } //tell the controller to power up to get ready for sec elem operations PowerSwitch::getInstance ().setLevel (PowerSwitch::FULL_POWER); PowerSwitch::getInstance ().setModeOn (PowerSwitch::SE_CONNECTED); //if controller is not routing AND there is no pipe connected, //then turn on the sec elem - if (! SecureElement::getInstance().isBusy()) - stat = SecureElement::getInstance().activate(0); + if (! se.isBusy()) + stat = se.activate(0); if (stat) { //establish a pipe to sec elem - stat = SecureElement::getInstance().connectEE(); + stat = se.connectEE(); if (stat) - secElemHandle = SecureElement::getInstance().mActiveEeHandle; + secElemHandle = se.mActiveEeHandle; else - SecureElement::getInstance().deactivate (0); + se.deactivate (0); } //if code fails to connect to the secure element, and nothing is active, then diff --git a/nci/jni/SecureElement.cpp b/nci/jni/SecureElement.cpp index 1004bb4..f6b2721 100755 --- a/nci/jni/SecureElement.cpp +++ b/nci/jni/SecureElement.cpp @@ -76,13 +76,16 @@ SecureElement::SecureElement () mCurrentRouteSelection (NoRoute), mActualResponseSize(0), mUseOberthurWarmReset (false), - mOberthurWarmResetCommand (3) + mActivatedInListenMode (false), + mOberthurWarmResetCommand (3), + mRfFieldIsOn(false) { memset (&mEeInfo, 0, sizeof(mEeInfo)); memset (&mUiccInfo, 0, sizeof(mUiccInfo)); memset (&mHciCfg, 0, sizeof(mHciCfg)); memset (mResponseData, 0, sizeof(mResponseData)); memset (mAidForEmptySelect, 0, sizeof(mAidForEmptySelect)); + memset (&mLastRfFieldToggle, 0, sizeof(mLastRfFieldToggle)); } @@ -323,6 +326,70 @@ bool SecureElement::getEeInfo() /******************************************************************************* ** +** Function TimeDiff +** +** Description Computes time difference in milliseconds. +** +** Returns Time difference in milliseconds +** +*******************************************************************************/ +static UINT32 TimeDiff(timespec start, timespec end) +{ + end.tv_sec -= start.tv_sec; + end.tv_nsec -= start.tv_nsec; + + if (end.tv_nsec < 0) { + end.tv_nsec += 10e8; + end.tv_sec -=1; + } + + return (end.tv_sec * 1000) + (end.tv_nsec / 10e5); +} + +/******************************************************************************* +** +** Function: isRfFieldOn +** +** Description: Can be used to determine if the SE is in an RF field +** +** Returns: True if the SE is activated in an RF field +** +*******************************************************************************/ +bool SecureElement::isRfFieldOn() { + AutoMutex mutex(mMutex); + if (mRfFieldIsOn) { + return true; + } + struct timespec now; + int ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret == -1) { + ALOGE("isRfFieldOn(): clock_gettime failed"); + return false; + } + if (TimeDiff(mLastRfFieldToggle, now) < 50) { + // If it was less than 50ms ago that RF field + // was turned off, still return ON. + return true; + } else { + return false; + } +} + +/******************************************************************************* +** +** Function: isActivatedInListenMode +** +** Description: Can be used to determine if the SE is activated in listen mode +** +** Returns: True if the SE is activated in listen mode +** +*******************************************************************************/ +bool SecureElement::isActivatedInListenMode() { + return mActivatedInListenMode; +} + +/******************************************************************************* +** ** Function: getListOfEeHandles ** ** Description: Get the list of handles of all execution environments. @@ -939,6 +1006,48 @@ TheEnd: /******************************************************************************* ** +** Function: notifyListenModeState +** +** Description: Notify the NFC service about whether the SE was activated +** in listen mode. +** isActive: Whether the secure element is activated. +** +** Returns: None +** +*******************************************************************************/ +void SecureElement::notifyListenModeState (bool isActivated) { + static const char fn [] = "SecureElement::notifyListenMode"; + JNIEnv *e = NULL; + + ALOGD ("%s: enter; listen mode active=%u", fn, isActivated); + mNativeData->vm->AttachCurrentThread (&e, NULL); + + if (e == NULL) + { + ALOGE ("%s: jni env is null", fn); + return; + } + + mActivatedInListenMode = isActivated; + if (isActivated) { + e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifySeListenActivated); + } + else { + e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifySeListenDeactivated); + } + + if (e->ExceptionCheck()) + { + e->ExceptionClear(); + ALOGE ("%s: fail notify", fn); + } + + mNativeData->vm->DetachCurrentThread (); + ALOGD ("%s: exit", fn); +} + +/******************************************************************************* +** ** Function: notifyRfFieldEvent ** ** Description: Notify the NFC service about RF field events from the stack. @@ -961,17 +1070,27 @@ void SecureElement::notifyRfFieldEvent (bool isActive) return; } - if (isActive) + mMutex.lock(); + int ret = clock_gettime (CLOCK_MONOTONIC, &mLastRfFieldToggle); + if (ret == -1) { + ALOGE("%s: clock_gettime failed", fn); + // There is no good choice here... + } + if (isActive) { + mRfFieldIsOn = true; e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifySeFieldActivated); - else + } + else { + mRfFieldIsOn = false; e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifySeFieldDeactivated); + } + mMutex.unlock(); if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: fail notify", fn); } - mNativeData->vm->DetachCurrentThread (); ALOGD ("%s: exit", fn); } diff --git a/nci/jni/SecureElement.h b/nci/jni/SecureElement.h index 8339a29..1758590 100755 --- a/nci/jni/SecureElement.h +++ b/nci/jni/SecureElement.h @@ -157,6 +157,18 @@ public: bool transceive (UINT8* xmitBuffer, INT32 xmitBufferSize, UINT8* recvBuffer, INT32 recvBufferMaxSize, INT32& recvBufferActualSize, INT32 timeoutMillisec); + /******************************************************************************* + ** + ** Function: notifyListenModeState + ** + ** Description: Notify the NFC service about whether the SE was activated + ** in listen mode. + ** isActive: Whether the secure element is activated. + ** + ** Returns: None + ** + *******************************************************************************/ + void notifyListenModeState (bool isActivated); /******************************************************************************* ** @@ -346,6 +358,28 @@ public: bool getSeVerInfo(int seIndex, char * verInfo, int verInfoSz, UINT8 * seid); + /******************************************************************************* + ** + ** Function: isActivatedInListenMode + ** + ** Description: Can be used to determine if the SE is activated in listen mode + ** + ** Returns: True if the SE is activated in listen mode + ** + *******************************************************************************/ + bool isActivatedInListenMode(); + + /******************************************************************************* + ** + ** Function: isRfFieldOn + ** + ** Description: Can be used to determine if the SE is in an RF field + ** + ** Returns: True if the SE is activated in an RF field + ** + *******************************************************************************/ + bool isRfFieldOn(); + private: static const unsigned int MAX_RESPONSE_SIZE = 1024; enum RouteSelection {NoRoute, DefaultRoute, SecElemRoute}; @@ -373,6 +407,7 @@ private: RouteSelection mCurrentRouteSelection; int mActualResponseSize; //number of bytes in the response received from secure element bool mUseOberthurWarmReset; //whether to use warm-reset command + bool mActivatedInListenMode; // whether we're activated in listen mode UINT8 mOberthurWarmResetCommand; //warm-reset command byte tNFA_EE_INFO mEeInfo [MAX_NUM_EE]; //actual size stored in mActualNumEe tNFA_EE_DISCOVER_REQ mUiccInfo; @@ -397,7 +432,9 @@ private: RouteDataSet mRouteDataSet; //routing data std::vector<std::string> mUsedAids; //AID's that are used in current routes UINT8 mAidForEmptySelect[NCI_MAX_AID_LEN+1]; - + Mutex mMutex; // protects fields below + bool mRfFieldIsOn; // last known RF field state + struct timespec mLastRfFieldToggle; // last time RF field went off /******************************************************************************* ** ** Function: SecureElement @@ -538,7 +575,6 @@ private: *******************************************************************************/ bool getEeInfo (); - /******************************************************************************* ** ** Function: eeStatusToString diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java index cc485a5..1437e5d 100755 --- a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java +++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java @@ -355,6 +355,14 @@ public class NativeNfcManager implements DeviceHost { mListener.onRemoteFieldDeactivated(); } + private void notifySeListenActivated() { + mListener.onSeListenActivated(); + } + + private void notifySeListenDeactivated() { + mListener.onSeListenDeactivated(); + } + private void notifySeApduReceived(byte[] apdu) { mListener.onSeApduReceived(apdu); } |