summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartijn Coenen <maco@google.com>2012-10-11 16:01:48 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-10-11 16:01:48 -0700
commit59f43aefee220afd41baa97ce2043017c171be73 (patch)
tree0c74968c6af7ff7ec96c50fa708b801dfbabdfb9
parent1b4047043526e88bcecb32f640d83e0d9a851128 (diff)
parenta949c74321b17f8ef1c93692064969f60815c7e4 (diff)
downloadpackages_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.
-rw-r--r--nci/jni/JavaClassConstants.h2
-rwxr-xr-xnci/jni/NativeNfcManager.cpp47
-rwxr-xr-xnci/jni/NativeSecureElement.cpp20
-rwxr-xr-xnci/jni/SecureElement.cpp127
-rwxr-xr-xnci/jni/SecureElement.h40
-rwxr-xr-xnci/src/com/android/nfc/dhimpl/NativeNfcManager.java8
-rw-r--r--src/com/android/nfc/DeviceHost.java10
-rwxr-xr-xsrc/com/android/nfc/NfcService.java34
8 files changed, 271 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);
}
diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java
index 487d2ad..e514bb6 100644
--- a/src/com/android/nfc/DeviceHost.java
+++ b/src/com/android/nfc/DeviceHost.java
@@ -49,6 +49,16 @@ public interface DeviceHost {
public void onRemoteFieldDeactivated();
+ /**
+ * Notifies that the SE has been activated in listen mode
+ */
+ public void onSeListenActivated();
+
+ /**
+ * Notifies that the SE has been deactivated
+ */
+ public void onSeListenDeactivated();
+
public void onSeApduReceived(byte[] apdu);
public void onSeEmvCardRemoval();
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index c344b49..0514160 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -113,6 +113,8 @@ public class NfcService implements DeviceHostListener {
static final int MSG_SE_APDU_RECEIVED = 10;
static final int MSG_SE_EMV_CARD_REMOVAL = 11;
static final int MSG_SE_MIFARE_ACCESS = 12;
+ static final int MSG_SE_LISTEN_ACTIVATED = 13;
+ static final int MSG_SE_LISTEN_DEACTIVATED = 14;
static final int TASK_ENABLE = 1;
static final int TASK_DISABLE = 2;
@@ -159,6 +161,11 @@ public class NfcService implements DeviceHostListener {
public static final String EXTRA_MIFARE_BLOCK =
"com.android.nfc_extras.extra.MIFARE_BLOCK";
+ public static final String ACTION_SE_LISTEN_ACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED";
+ public static final String ACTION_SE_LISTEN_DEACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED";
+
// NFC Execution Environment
// fields below are protected by this
private NativeNfcSecureElement mSecureElement;
@@ -280,6 +287,17 @@ public class NfcService implements DeviceHostListener {
}
@Override
+ public void onSeListenActivated() {
+ sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null);
+ }
+
+ @Override
+ public void onSeListenDeactivated() {
+ sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null);
+ }
+
+
+ @Override
public void onSeApduReceived(byte[] apdu) {
sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
}
@@ -1745,6 +1763,22 @@ public class NfcService implements DeviceHostListener {
break;
}
+ case MSG_SE_LISTEN_ACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED");
+ Intent listenModeActivated = new Intent();
+ listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED);
+ sendSeBroadcast(listenModeActivated);
+ break;
+ }
+
+ case MSG_SE_LISTEN_DEACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED");
+ Intent listenModeDeactivated = new Intent();
+ listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED);
+ sendSeBroadcast(listenModeDeactivated);
+ break;
+ }
+
default:
Log.e(TAG, "Unknown message received");
break;