diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-07-25 00:31:49 +0100 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-07-25 00:31:49 +0100 |
commit | 2179fd368b019e2f0f419fd0eada5e2b693c18bb (patch) | |
tree | 0c217a7c8c5c4221e7883d714b8dd2ff5729a7fc | |
parent | 43c1153e4b31194a32b9be7febd5aa4a542cef3c (diff) | |
parent | 36cf13f6279056792e154c3222041dc295d2f405 (diff) | |
download | android_packages_apps_Nfc-2179fd368b019e2f0f419fd0eada5e2b693c18bb.tar.gz android_packages_apps_Nfc-2179fd368b019e2f0f419fd0eada5e2b693c18bb.tar.bz2 android_packages_apps_Nfc-2179fd368b019e2f0f419fd0eada5e2b693c18bb.zip |
Merge tag 'android-4.3_r2.1' into cm-10.2
Android 4.3 release 2.1
Conflicts:
nxp/jni/com_android_nfc_NativeNfcManager.cpp
nxp/jni/com_android_nfc_NativeNfcTag.cpp
res/values-nl/strings.xml
Change-Id: I2e53f288cd65fc179d5c385971e703f6eda0c232
94 files changed, 2301 insertions, 1254 deletions
@@ -18,7 +18,7 @@ LOCAL_CERTIFICATE := platform LOCAL_STATIC_JAVA_LIBRARIES := NfcLogTags -LOCAL_JNI_SHARED_LIBRARIES := libnfc_jni +LOCAL_REQUIRED_MODULES := libnfc_jni LOCAL_PROGUARD_ENABLED := disabled @@ -43,7 +43,7 @@ LOCAL_CERTIFICATE := platform LOCAL_STATIC_JAVA_LIBRARIES := NfcLogTags -LOCAL_JNI_SHARED_LIBRARIES := libnfc_nci_jni +LOCAL_REQUIRED_MODULES := libnfc_nci_jni LOCAL_PROGUARD_ENABLED := disabled diff --git a/nci/jni/Android.mk b/nci/jni/Android.mk index 39832fdb..c84ca1a5 100644 --- a/nci/jni/Android.mk +++ b/nci/jni/Android.mk @@ -10,6 +10,8 @@ ifneq ($(NCI_VERSION),) LOCAL_CFLAGS += -DNCI_VERSION=$(NCI_VERSION) -O0 -g endif +LOCAL_CFLAGS += -Wall -Wextra + define all-cpp-files-under $(patsubst ./%,%, \ $(shell cd $(LOCAL_PATH) ; \ @@ -26,6 +28,7 @@ LOCAL_C_INCLUDES += \ external/libxml2/include \ external/icu4c/common \ frameworks/native/include \ + libcore/include \ $(NFA)/include \ $(NFA)/brcm \ $(NFC)/include \ @@ -42,6 +45,7 @@ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libcutils \ libutils \ + liblog \ libnfc-nci \ libstlport @@ -51,4 +55,3 @@ LOCAL_MODULE := libnfc_nci_jni LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) - diff --git a/nci/jni/IntervalTimer.cpp b/nci/jni/IntervalTimer.cpp index f71ca8e9..9453451d 100644 --- a/nci/jni/IntervalTimer.cpp +++ b/nci/jni/IntervalTimer.cpp @@ -24,14 +24,14 @@ IntervalTimer::IntervalTimer() { - mTimerId = NULL; + mTimerId = 0; mCb = NULL; } bool IntervalTimer::set(int ms, TIMER_FUNC cb) { - if (mTimerId == NULL) + if (mTimerId == 0) { if (cb == NULL) return false; @@ -69,11 +69,11 @@ IntervalTimer::~IntervalTimer() void IntervalTimer::kill() { - if (mTimerId == NULL) + if (mTimerId == 0) return; timer_delete(mTimerId); - mTimerId = NULL; + mTimerId = 0; mCb = NULL; } diff --git a/nci/jni/JavaClassConstants.h b/nci/jni/JavaClassConstants.h index 30deca94..4b54db8a 100644 --- a/nci/jni/JavaClassConstants.h +++ b/nci/jni/JavaClassConstants.h @@ -22,6 +22,7 @@ namespace android extern jmethodID gCachedNfcManagerNotifyTransactionListeners; extern jmethodID gCachedNfcManagerNotifyLlcpLinkActivation; extern jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated; + extern jmethodID gCachedNfcManagerNotifyLlcpFirstPacketReceived; extern jmethodID gCachedNfcManagerNotifySeFieldActivated; extern jmethodID gCachedNfcManagerNotifySeFieldDeactivated; extern jmethodID gCachedNfcManagerNotifySeListenActivated; diff --git a/nci/jni/NativeLlcpConnectionlessSocket.cpp b/nci/jni/NativeLlcpConnectionlessSocket.cpp index ecc57e3a..99a4b227 100644 --- a/nci/jni/NativeLlcpConnectionlessSocket.cpp +++ b/nci/jni/NativeLlcpConnectionlessSocket.cpp @@ -19,6 +19,8 @@ #include "OverrideLog.h" #include "NfcJniUtil.h" #include "JavaClassConstants.h" +#include <ScopedLocalRef.h> +#include <ScopedPrimitiveArray.h> extern "C" { #include "nfa_api.h" @@ -57,29 +59,25 @@ static uint32_t sConnlessRecvRemoteSap = 0; *******************************************************************************/ static jboolean nativeLlcpConnectionlessSocket_doSendTo (JNIEnv *e, jobject o, jint nsap, jbyteArray data) { - tNFA_STATUS status = NFA_STATUS_FAILED; - jint handle = 0; - uint8_t* buf = NULL; - uint32_t len = 0; - jclass c = NULL; - jfieldID f = NULL; - ALOGD ("%s: nsap = %d", __FUNCTION__, nsap); - c = e->GetObjectClass (o); - f = e->GetFieldID (c, "mHandle", "I"); - handle = e->GetIntField (o, f); + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mHandle", "I"); + jint handle = e->GetIntField(o, f); - buf = (uint8_t*) e->GetByteArrayElements (data, NULL); - len = (uint32_t) e->GetArrayLength (data); + ScopedByteArrayRO bytes(e, data); + if (bytes.get() == NULL) { + return JNI_FALSE; + } + size_t byte_count = bytes.size(); - ALOGD ("NFA_P2pSendUI: len = %d", len); - status = NFA_P2pSendUI ((tNFA_HANDLE) handle, nsap, len, buf); + ALOGD("NFA_P2pSendUI: len = %d", byte_count); + UINT8* raw_ptr = const_cast<UINT8*>(reinterpret_cast<const UINT8*>(&bytes[0])); // TODO: API bug; NFA_P2pSendUI should take const*! + tNFA_STATUS status = NFA_P2pSendUI((tNFA_HANDLE) handle, nsap, byte_count, raw_ptr); - ALOGD ("%s: NFA_P2pSendUI done, status = %d", __FUNCTION__, status); - if (status != NFA_STATUS_OK) - { - ALOGE ("%s: NFA_P2pSendUI failed, status = %d", __FUNCTION__, status); + ALOGD("%s: NFA_P2pSendUI done, status = %d", __FUNCTION__, status); + if (status != NFA_STATUS_OK) { + ALOGE("%s: NFA_P2pSendUI failed, status = %d", __FUNCTION__, status); return JNI_FALSE; } return JNI_TRUE; @@ -169,14 +167,11 @@ void nativeLlcpConnectionlessSocket_abortWait () ** Returns: LlcpPacket Java object. ** *******************************************************************************/ -static jobject nativeLlcpConnectionlessSocket_doReceiveFrom (JNIEnv *e, jobject o, jint linkMiu) +static jobject nativeLlcpConnectionlessSocket_doReceiveFrom (JNIEnv* e, jobject, jint linkMiu) { - jbyteArray receivedData = NULL; - jobject llcpPacket = NULL; - jclass clsLlcpPacket = NULL; - jfieldID f = NULL; - ALOGD ("%s: linkMiu = %d", __FUNCTION__, linkMiu); + jobject llcpPacket = NULL; + ScopedLocalRef<jclass> clsLlcpPacket(e, NULL); if (sConnlessRecvWaitingForData != JNI_FALSE) { @@ -216,8 +211,8 @@ static jobject nativeLlcpConnectionlessSocket_doReceiveFrom (JNIEnv *e, jobject } // Get NativeConnectionless class object - clsLlcpPacket = e->GetObjectClass (llcpPacket); - if (e->ExceptionCheck ()) + clsLlcpPacket.reset(e->GetObjectClass(llcpPacket)); + if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: Get Object class error", __FUNCTION__); @@ -225,17 +220,21 @@ static jobject nativeLlcpConnectionlessSocket_doReceiveFrom (JNIEnv *e, jobject } // Set Llcp Packet remote SAP - f = e->GetFieldID (clsLlcpPacket, "mRemoteSap", "I"); - e->SetIntField (llcpPacket, f, (jbyte) sConnlessRecvRemoteSap); + jfieldID f; + f = e->GetFieldID(clsLlcpPacket.get(), "mRemoteSap", "I"); + e->SetIntField(llcpPacket, f, (jbyte) sConnlessRecvRemoteSap); // Set Llcp Packet Buffer ALOGD ("%s: Received Llcp packet buffer size = %d\n", __FUNCTION__, sConnlessRecvLen); - f = e->GetFieldID (clsLlcpPacket, "mDataBuffer", "[B"); - receivedData = e->NewByteArray (sConnlessRecvLen); - e->SetByteArrayRegion (receivedData, 0, sConnlessRecvLen, (jbyte*) sConnlessRecvBuf); - e->SetObjectField (llcpPacket, f, receivedData); + f = e->GetFieldID(clsLlcpPacket.get(), "mDataBuffer", "[B"); + + { + ScopedLocalRef<jbyteArray> receivedData(e, e->NewByteArray(sConnlessRecvLen)); + e->SetByteArrayRegion(receivedData.get(), 0, sConnlessRecvLen, (jbyte*) sConnlessRecvBuf); + e->SetObjectField(llcpPacket, f, receivedData.get()); + } -TheEnd: +TheEnd: // TODO: should all the "return connectionlessCleanup()"s in this function jump here instead? connectionlessCleanup (); if (sem_destroy (&sConnlessRecvSem)) { @@ -258,20 +257,14 @@ TheEnd: *******************************************************************************/ static jboolean nativeLlcpConnectionlessSocket_doClose (JNIEnv *e, jobject o) { - tNFA_STATUS status = NFA_STATUS_FAILED; - jint handle = 0; - jclass c = NULL; - jfieldID f = NULL; - ALOGD ("%s", __FUNCTION__); - c = e->GetObjectClass (o); - f = e->GetFieldID (c, "mHandle", "I"); - handle = e->GetIntField (o, f); + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mHandle", "I"); + jint handle = e->GetIntField(o, f); - status = NFA_P2pDisconnect ((tNFA_HANDLE) handle, FALSE); - if (status != NFA_STATUS_OK) - { + tNFA_STATUS status = NFA_P2pDisconnect((tNFA_HANDLE) handle, FALSE); + if (status != NFA_STATUS_OK) { ALOGE ("%s: disconnect failed, status = %d", __FUNCTION__, status); return JNI_FALSE; } diff --git a/nci/jni/NativeLlcpServiceSocket.cpp b/nci/jni/NativeLlcpServiceSocket.cpp index e1c2bb5d..17145efa 100644 --- a/nci/jni/NativeLlcpServiceSocket.cpp +++ b/nci/jni/NativeLlcpServiceSocket.cpp @@ -44,7 +44,7 @@ namespace android ** Returns: LlcpSocket Java object. ** *******************************************************************************/ -static jobject nativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint miu, jint rw, jint linearBufferLength) +static jobject nativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint miu, jint rw, jint /*linearBufferLength*/) { jobject clientSocket = NULL; jclass clsNativeLlcpSocket = NULL; @@ -155,4 +155,3 @@ int register_com_android_nfc_NativeLlcpServiceSocket (JNIEnv* e) } //namespace android - diff --git a/nci/jni/NativeLlcpSocket.cpp b/nci/jni/NativeLlcpSocket.cpp index 74a59b9f..ad03506b 100644 --- a/nci/jni/NativeLlcpSocket.cpp +++ b/nci/jni/NativeLlcpSocket.cpp @@ -16,6 +16,8 @@ #include "OverrideLog.h" #include "PeerToPeer.h" #include "JavaClassConstants.h" +#include <ScopedPrimitiveArray.h> +#include <ScopedUtfChars.h> namespace android @@ -36,20 +38,13 @@ namespace android *******************************************************************************/ static jboolean nativeLlcpSocket_doConnect (JNIEnv* e, jobject o, jint nSap) { - bool stat = false; - jboolean retVal = JNI_FALSE; - ALOGD ("%s: enter; sap=%d", __FUNCTION__, nSap); - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); - - stat = PeerToPeer::getInstance().connectConnOriented (jniHandle, nSap); - - if (stat) - retVal = JNI_TRUE; + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + bool stat = PeerToPeer::getInstance().connectConnOriented (jniHandle, nSap); ALOGD ("%s: exit", __FUNCTION__); - return retVal; + return stat ? JNI_TRUE : JNI_FALSE; } @@ -68,22 +63,17 @@ static jboolean nativeLlcpSocket_doConnect (JNIEnv* e, jobject o, jint nSap) static jboolean nativeLlcpSocket_doConnectBy (JNIEnv* e, jobject o, jstring sn) { ALOGD ("%s: enter", __FUNCTION__); - bool stat = false; - jboolean retVal = JNI_FALSE; - - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); - const char* serviceName = e->GetStringUTFChars (sn, JNI_FALSE); //convert jstring, which is unicode, into char* + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); - stat = PeerToPeer::getInstance().connectConnOriented (jniHandle, serviceName); - - e->ReleaseStringUTFChars (sn, serviceName); //free the string - - if (stat) - retVal = JNI_TRUE; + ScopedUtfChars serviceName(e, sn); + if (serviceName.c_str() == NULL) { + return JNI_FALSE; + } + bool stat = PeerToPeer::getInstance().connectConnOriented(jniHandle, serviceName.c_str()); ALOGD ("%s: exit", __FUNCTION__); - return retVal; + return stat ? JNI_TRUE : JNI_FALSE; } @@ -101,16 +91,12 @@ static jboolean nativeLlcpSocket_doConnectBy (JNIEnv* e, jobject o, jstring sn) static jboolean nativeLlcpSocket_doClose(JNIEnv *e, jobject o) { ALOGD ("%s: enter", __FUNCTION__); - bool stat = false; - jboolean retVal = JNI_FALSE; - - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); - stat = PeerToPeer::getInstance().disconnectConnOriented (jniHandle); + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + bool stat = PeerToPeer::getInstance().disconnectConnOriented (jniHandle); - retVal = JNI_TRUE; ALOGD ("%s: exit", __FUNCTION__); - return retVal; + return JNI_TRUE; // TODO: stat? } @@ -129,15 +115,12 @@ static jboolean nativeLlcpSocket_doClose(JNIEnv *e, jobject o) static jboolean nativeLlcpSocket_doSend (JNIEnv* e, jobject o, jbyteArray data) { ALOGD_IF ((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: enter", __FUNCTION__); - uint8_t* dataBuffer = (uint8_t*) e->GetByteArrayElements (data, NULL); - uint32_t dataBufferLen = (uint32_t) e->GetArrayLength (data); - bool stat = false; - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); + ScopedByteArrayRO bytes(e, data); - stat = PeerToPeer::getInstance().send (jniHandle, dataBuffer, dataBufferLen); - - e->ReleaseByteArrayElements (data, (jbyte*) dataBuffer, JNI_ABORT); + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + UINT8* raw_ptr = const_cast<UINT8*>(reinterpret_cast<const UINT8*>(&bytes[0])); // TODO: API bug: send should take const*! + bool stat = PeerToPeer::getInstance().send(jniHandle, raw_ptr, bytes.size()); ALOGD_IF ((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: exit", __FUNCTION__); return stat ? JNI_TRUE : JNI_FALSE; @@ -159,24 +142,20 @@ static jboolean nativeLlcpSocket_doSend (JNIEnv* e, jobject o, jbyteArray data) static jint nativeLlcpSocket_doReceive(JNIEnv *e, jobject o, jbyteArray origBuffer) { ALOGD_IF ((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: enter", __FUNCTION__); - uint8_t* dataBuffer = (uint8_t*) e->GetByteArrayElements (origBuffer, NULL); - uint32_t dataBufferLen = (uint32_t) e->GetArrayLength (origBuffer); - uint16_t actualLen = 0; - bool stat = false; - jint retval = 0; - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); + ScopedByteArrayRW bytes(e, origBuffer); - stat = PeerToPeer::getInstance().receive (jniHandle, dataBuffer, dataBufferLen, actualLen); + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + uint16_t actualLen = 0; + bool stat = PeerToPeer::getInstance().receive(jniHandle, reinterpret_cast<UINT8*>(&bytes[0]), bytes.size(), actualLen); - if (stat && (actualLen>0)) - { + jint retval = 0; + if (stat && (actualLen>0)) { retval = actualLen; - } - else + } else { retval = -1; + } - e->ReleaseByteArrayElements (origBuffer, (jbyte*) dataBuffer, 0); ALOGD_IF ((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: exit; actual len=%d", __FUNCTION__, retval); return retval; } @@ -196,12 +175,9 @@ static jint nativeLlcpSocket_doReceive(JNIEnv *e, jobject o, jbyteArray origBuff static jint nativeLlcpSocket_doGetRemoteSocketMIU (JNIEnv* e, jobject o) { ALOGD ("%s: enter", __FUNCTION__); - bool stat = false; - - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); - jint miu = 0; - miu = PeerToPeer::getInstance().getRemoteMaxInfoUnit (jniHandle); + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + jint miu = PeerToPeer::getInstance().getRemoteMaxInfoUnit(jniHandle); ALOGD ("%s: exit", __FUNCTION__); return miu; @@ -222,12 +198,9 @@ static jint nativeLlcpSocket_doGetRemoteSocketMIU (JNIEnv* e, jobject o) static jint nativeLlcpSocket_doGetRemoteSocketRW (JNIEnv* e, jobject o) { ALOGD ("%s: enter", __FUNCTION__); - bool stat = false; - jint rw = 0; - PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle (e,o); - - rw = PeerToPeer::getInstance().getRemoteRecvWindow (jniHandle); + PeerToPeer::tJNI_HANDLE jniHandle = (PeerToPeer::tJNI_HANDLE) nfc_jni_get_nfc_socket_handle(e, o); + jint rw = PeerToPeer::getInstance().getRemoteRecvWindow (jniHandle); ALOGD ("%s: exit", __FUNCTION__); return rw; @@ -268,4 +241,3 @@ int register_com_android_nfc_NativeLlcpSocket (JNIEnv* e) } //namespace android - diff --git a/nci/jni/NativeNfcManager.cpp b/nci/jni/NativeNfcManager.cpp index 61fc0520..e4ea20e2 100755 --- a/nci/jni/NativeNfcManager.cpp +++ b/nci/jni/NativeNfcManager.cpp @@ -27,6 +27,8 @@ #include "PowerSwitch.h" #include "JavaClassConstants.h" #include "Pn544Interop.h" +#include <ScopedLocalRef.h> +#include <ScopedUtfChars.h> extern "C" { @@ -35,11 +37,9 @@ extern "C" #include "rw_api.h" #include "nfa_ee_api.h" #include "nfc_brcm_defs.h" - #include "nfa_cho_api.h" #include "ce_api.h" } -extern UINT8 *p_nfa_dm_lptd_cfg; extern UINT8 *p_nfa_dm_start_up_cfg; extern const UINT8 nfca_version_string []; namespace android @@ -76,6 +76,7 @@ namespace android jmethodID gCachedNfcManagerNotifyTransactionListeners; jmethodID gCachedNfcManagerNotifyLlcpLinkActivation; jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated; + jmethodID gCachedNfcManagerNotifyLlcpFirstPacketReceived; jmethodID gCachedNfcManagerNotifySeFieldActivated; jmethodID gCachedNfcManagerNotifySeFieldDeactivated; jmethodID gCachedNfcManagerNotifySeListenActivated; @@ -90,6 +91,7 @@ namespace android void doStartupConfig (); void startStopPolling (bool isStartPolling); void startRfDiscovery (bool isStart); + void setUiccIdleTimeout (bool enable); } @@ -109,20 +111,15 @@ static SyncEvent sNfaEnableEvent; //event for NFA_Enable() static SyncEvent sNfaDisableEvent; //event for NFA_Disable() static SyncEvent sNfaEnableDisablePollingEvent; //event for NFA_EnablePolling(), NFA_DisablePolling() static SyncEvent sNfaSetConfigEvent; // event for Set_Config.... +static SyncEvent sNfaGetConfigEvent; // event for Get_Config.... static bool sIsNfaEnabled = false; 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; static bool sIsSecElemSelected = false; //has NFC service selected a sec elem -static UINT8 * sOriginalLptdCfg = NULL; -static UINT8 sNewLptdCfg[LPTD_PARAM_LEN]; -static UINT32 sConfigUpdated = 0; -#define CONFIG_UPDATE_LPTD (1 << 0) #define CONFIG_UPDATE_TECH_MASK (1 << 1) #define DEFAULT_TECH_MASK (NFA_TECHNOLOGY_MASK_A \ | NFA_TECHNOLOGY_MASK_B \ @@ -130,7 +127,8 @@ static UINT32 sConfigUpdated = 0; | NFA_TECHNOLOGY_MASK_ISO15693 \ | NFA_TECHNOLOGY_MASK_B_PRIME \ | NFA_TECHNOLOGY_MASK_A_ACTIVE \ - | NFA_TECHNOLOGY_MASK_F_ACTIVE) + | NFA_TECHNOLOGY_MASK_F_ACTIVE \ + | NFA_TECHNOLOGY_MASK_KOVIO) static void nfaConnectionCallback (UINT8 event, tNFA_CONN_EVT_DATA *eventData); @@ -138,6 +136,8 @@ static void nfaDeviceManagementCallback (UINT8 event, tNFA_DM_CBACK_DATA *eventD static bool isPeerToPeer (tNFA_ACTIVATED& activated); static bool isListenMode(tNFA_ACTIVATED& activated); +static UINT16 sCurrentConfigLen; +static UINT8 sConfig[256]; ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// @@ -210,7 +210,13 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat tNFA_STATUS status = NFA_STATUS_FAILED; ALOGD("%s: event= %u", __FUNCTION__, connEvent); - if (gIsTagDeactivating && connEvent != NFA_DEACTIVATED_EVT && connEvent != NFA_PRESENCE_CHECK_EVT && connEvent != NFA_DATA_EVT) + // TODO this if can probably be completely removed. It's unclear why this + // was present in the initial code drop - either to work around NFCC, + // stack or certain NFC tags bugs. Until we verify removing it doesn't + // break things, leave it be. + if (gIsTagDeactivating && connEvent != NFA_DEACTIVATED_EVT && + connEvent != NFA_PRESENCE_CHECK_EVT && connEvent != NFA_DATA_EVT && + connEvent != NFA_RW_INTF_ERROR_EVT) { // special case to switching frame interface for ISO_DEP tags gIsTagDeactivating = false; @@ -294,7 +300,7 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat case NFA_ACTIVATED_EVT: // NFC link/protocol activated ALOGD("%s: NFA_ACTIVATED_EVT: gIsSelectingRfInterface=%d, sIsDisabling=%d", __FUNCTION__, gIsSelectingRfInterface, sIsDisabling); - if (sIsDisabling) + if (sIsDisabling || !sIsNfaEnabled) break; NfcTag::getInstance().setActivationState (); @@ -319,13 +325,15 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat } else { ALOGE ("%s: Failed to disable RF field events", __FUNCTION__); } + // For the SE, consider the field to be on while p2p is active. + SecureElement::getInstance().notifyRfFieldEvent (true); } else if (pn544InteropIsBusy() == false) { NfcTag::getInstance().connectionEventHandler (connEvent, eventData); // We know it is not activating for P2P. If it activated in - // listen mode then it is likely for and SE transaction. + // listen mode then it is likely for an SE transaction. // Send the RF Event. if (isListenMode(eventData->activated)) { @@ -358,21 +366,27 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat { if (sSeRfActive) { sSeRfActive = false; - SecureElement::getInstance().notifyListenModeState (false); + if (!sIsDisabling && sIsNfaEnabled) + 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__); + ALOGD("%s: NFA_DEACTIVATED_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__); + if (!sIsDisabling && sIsNfaEnabled) + { + 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__); + } + // Consider the field to be off at this point + SecureElement::getInstance().notifyRfFieldEvent (false); } } } @@ -462,12 +476,14 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat ALOGD("%s: NFA_LLCP_DEACTIVATED_EVT", __FUNCTION__); PeerToPeer::getInstance().llcpDeactivatedHandler (getNative(0, 0), eventData->llcp_deactivated); break; - + case NFA_LLCP_FIRST_PACKET_RECEIVED_EVT: // Received first packet over llcp + ALOGD("%s: NFA_LLCP_FIRST_PACKET_RECEIVED_EVT", __FUNCTION__); + PeerToPeer::getInstance().llcpFirstPacketHandler (getNative(0, 0)); + break; case NFA_PRESENCE_CHECK_EVT: ALOGD("%s: NFA_PRESENCE_CHECK_EVT", __FUNCTION__); nativeNfcTag_doPresenceCheckResult (eventData->status); break; - case NFA_FORMAT_CPLT_EVT: ALOGD("%s: NFA_FORMAT_CPLT_EVT: status=0x%X", __FUNCTION__, eventData->status); nativeNfcTag_formatStatus (eventData->status == NFA_STATUS_OK); @@ -507,14 +523,9 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat *******************************************************************************/ static jboolean nfcManager_initNativeStruc (JNIEnv* e, jobject o) { - nfc_jni_native_data* nat = NULL; - jclass cls = NULL; - jobject obj = NULL; - jfieldID f = 0; - ALOGD ("%s: enter", __FUNCTION__); - nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data)); + nfc_jni_native_data* nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data)); if (nat == NULL) { ALOGE ("%s: fail allocate native data", __FUNCTION__); @@ -522,50 +533,52 @@ static jboolean nfcManager_initNativeStruc (JNIEnv* e, jobject o) } memset (nat, 0, sizeof(*nat)); - e->GetJavaVM (&(nat->vm)); - nat->env_version = e->GetVersion (); - nat->manager = e->NewGlobalRef (o); + e->GetJavaVM(&(nat->vm)); + nat->env_version = e->GetVersion(); + nat->manager = e->NewGlobalRef(o); - cls = e->GetObjectClass (o); - f = e->GetFieldID (cls, "mNative", "I"); - e->SetIntField (o, f, (jint)nat); + ScopedLocalRef<jclass> cls(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(cls.get(), "mNative", "I"); + e->SetIntField(o, f, (jint)nat); /* Initialize native cached references */ - gCachedNfcManagerNotifyNdefMessageListeners = e->GetMethodID (cls, + gCachedNfcManagerNotifyNdefMessageListeners = e->GetMethodID(cls.get(), "notifyNdefMessageListeners", "(Lcom/android/nfc/dhimpl/NativeNfcTag;)V"); - gCachedNfcManagerNotifyTransactionListeners = e->GetMethodID (cls, + gCachedNfcManagerNotifyTransactionListeners = e->GetMethodID(cls.get(), "notifyTransactionListeners", "([B)V"); - gCachedNfcManagerNotifyLlcpLinkActivation = e->GetMethodID (cls, + gCachedNfcManagerNotifyLlcpLinkActivation = e->GetMethodID(cls.get(), "notifyLlcpLinkActivation", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V"); - gCachedNfcManagerNotifyLlcpLinkDeactivated = e->GetMethodID (cls, + gCachedNfcManagerNotifyLlcpLinkDeactivated = e->GetMethodID(cls.get(), "notifyLlcpLinkDeactivated", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V"); - sCachedNfcManagerNotifyTargetDeselected = e->GetMethodID (cls, + gCachedNfcManagerNotifyLlcpFirstPacketReceived = e->GetMethodID(cls.get(), + "notifyLlcpLinkFirstPacketReceived", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V"); + sCachedNfcManagerNotifyTargetDeselected = e->GetMethodID(cls.get(), "notifyTargetDeselected","()V"); - gCachedNfcManagerNotifySeFieldActivated = e->GetMethodID (cls, + gCachedNfcManagerNotifySeFieldActivated = e->GetMethodID(cls.get(), "notifySeFieldActivated", "()V"); - gCachedNfcManagerNotifySeFieldDeactivated = e->GetMethodID (cls, + gCachedNfcManagerNotifySeFieldDeactivated = e->GetMethodID(cls.get(), "notifySeFieldDeactivated", "()V"); - gCachedNfcManagerNotifySeListenActivated = e->GetMethodID (cls, + gCachedNfcManagerNotifySeListenActivated = e->GetMethodID(cls.get(), "notifySeListenActivated", "()V"); - gCachedNfcManagerNotifySeListenDeactivated = e->GetMethodID (cls, + gCachedNfcManagerNotifySeListenDeactivated = e->GetMethodID(cls.get(), "notifySeListenDeactivated", "()V"); - sCachedNfcManagerNotifySeApduReceived = e->GetMethodID(cls, + sCachedNfcManagerNotifySeApduReceived = e->GetMethodID(cls.get(), "notifySeApduReceived", "([B)V"); - sCachedNfcManagerNotifySeMifareAccess = e->GetMethodID(cls, + sCachedNfcManagerNotifySeMifareAccess = e->GetMethodID(cls.get(), "notifySeMifareAccess", "([B)V"); - sCachedNfcManagerNotifySeEmvCardRemoval = e->GetMethodID(cls, + sCachedNfcManagerNotifySeEmvCardRemoval = e->GetMethodID(cls.get(), "notifySeEmvCardRemoval", "()V"); - if (nfc_jni_cache_object(e,gNativeNfcTagClassName, &(nat->cached_NfcTag)) == -1) + if (nfc_jni_cache_object(e, gNativeNfcTagClassName, &(nat->cached_NfcTag)) == -1) { ALOGE ("%s: fail cache NativeNfcTag", __FUNCTION__); return JNI_FALSE; } - if (nfc_jni_cache_object(e,gNativeP2pDeviceClassName, &(nat->cached_P2pDevice)) == -1) + if (nfc_jni_cache_object(e, gNativeP2pDeviceClassName, &(nat->cached_P2pDevice)) == -1) { ALOGE ("%s: fail cache NativeP2pDevice", __FUNCTION__); return JNI_FALSE; @@ -624,14 +637,32 @@ void nfaDeviceManagementCallback (UINT8 dmEvent, tNFA_DM_CBACK_DATA* eventData) case NFA_DM_GET_CONFIG_EVT: /* Result of NFA_GetConfig */ ALOGD ("%s: NFA_DM_GET_CONFIG_EVT", __FUNCTION__); + { + SyncEventGuard guard (sNfaGetConfigEvent); + if (eventData->status == NFA_STATUS_OK && + eventData->get_config.tlv_size <= sizeof(sConfig)) + { + sCurrentConfigLen = eventData->get_config.tlv_size; + memcpy(sConfig, eventData->get_config.param_tlvs, eventData->get_config.tlv_size); + } + else + { + ALOGE("%s: NFA_DM_GET_CONFIG failed", __FUNCTION__); + sCurrentConfigLen = 0; + } + sNfaGetConfigEvent.notifyOne(); + } break; case NFA_DM_RF_FIELD_EVT: ALOGD ("%s: NFA_DM_RF_FIELD_EVT; status=0x%X; field status=%u", __FUNCTION__, eventData->rf_field.status, eventData->rf_field.rf_field_status); + if (sIsDisabling || !sIsNfaEnabled) + break; - if (!sIsDisabling && eventData->rf_field.status == NFA_STATUS_OK) - SecureElement::getInstance().notifyRfFieldEvent (eventData->rf_field.rf_field_status == NFA_DM_RF_FIELD_ON); + if (!sP2pActive && eventData->rf_field.status == NFA_STATUS_OK) + SecureElement::getInstance().notifyRfFieldEvent ( + eventData->rf_field.rf_field_status == NFA_DM_RF_FIELD_ON); break; case NFA_DM_NFCC_TRANSPORT_ERR_EVT: @@ -735,9 +766,7 @@ static jboolean nfcManager_doInitialize (JNIEnv* e, jobject o) NFC_SetTraceLevel (num); RW_SetTraceLevel (num); NFA_SetTraceLevel (num); - NFA_ChoSetTraceLevel (num); NFA_P2pSetTraceLevel (num); - NFA_SnepSetTraceLevel (num); sNfaEnableEvent.wait(); //wait for NFA command to finish } } @@ -768,10 +797,6 @@ static jboolean nfcManager_doInitialize (JNIEnv* e, jobject o) ALOGD ("%s: tag polling tech mask=0x%X", __FUNCTION__, nat->tech_mask); } - // Always restore LPTD Configuration to the stack default. - if (sOriginalLptdCfg != NULL) - p_nfa_dm_lptd_cfg = sOriginalLptdCfg; - // if this value exists, set polling interval. if (GetNumValue(NAME_NFA_DM_DISC_DURATION_POLL, &num, sizeof(num))) NFA_SetRfDiscoveryDuration(num); @@ -884,7 +909,7 @@ static void nfcManager_enableDiscovery (JNIEnv* e, jobject o) ** Returns: None ** *******************************************************************************/ -void nfcManager_disableDiscovery (JNIEnv* e, jobject o) +void nfcManager_disableDiscovery (JNIEnv*, jobject) { tNFA_STATUS status = NFA_STATUS_OK; ALOGD ("%s: enter;", __FUNCTION__); @@ -918,10 +943,52 @@ void nfcManager_disableDiscovery (JNIEnv* e, jobject o) if (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::DISCOVERY)) PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER); + // We may have had RF field notifications that did not cause + // any activate/deactive events. For example, caused by wireless + // charging orbs. Those may cause us to go to sleep while the last + // field event was indicating a field. To prevent sticking in that + // state, always reset the rf field status when we disable discovery. + SecureElement::getInstance().resetRfFieldStatus(); TheEnd: ALOGD ("%s: exit", __FUNCTION__); } +void setUiccIdleTimeout (bool enable) +{ + // This method is *NOT* thread-safe. Right now + // it is only called from the same thread so it's + // not an issue. + tNFA_STATUS stat = NFA_STATUS_OK; + UINT8 swp_cfg_byte0 = 0x00; + { + SyncEventGuard guard (sNfaGetConfigEvent); + stat = NFA_GetConfig(1, new tNFA_PMID[1] {0xC2}); + if (stat != NFA_STATUS_OK) + { + ALOGE("%s: NFA_GetConfig failed", __FUNCTION__); + return; + } + sNfaGetConfigEvent.wait (); + if (sCurrentConfigLen < 4 || sConfig[1] != 0xC2) { + ALOGE("%s: Config TLV length %d returned is too short", __FUNCTION__, + sCurrentConfigLen); + return; + } + swp_cfg_byte0 = sConfig[3]; + } + SyncEventGuard guard(sNfaSetConfigEvent); + if (enable) + swp_cfg_byte0 |= 0x01; + else + swp_cfg_byte0 &= ~0x01; + + stat = NFA_SetConfig(0xC2, 1, &swp_cfg_byte0); + if (stat == NFA_STATUS_OK) + sNfaSetConfigEvent.wait (); + else + ALOGE("%s: Could not configure UICC idle timeout feature", __FUNCTION__); + return; +} /******************************************************************************* ** ** Function nfc_jni_cache_object_local @@ -931,35 +998,26 @@ TheEnd: ** Returns -1 on failure, 0 on success ** *******************************************************************************/ -int nfc_jni_cache_object_local (JNIEnv *e, const char *className, jobject *cachedObj) +static int nfc_jni_cache_object_local (JNIEnv *e, const char *className, jobject *cachedObj) { - jclass cls = NULL; - jobject obj = NULL; - jmethodID ctor = 0; - - cls = e->FindClass (className); - if(cls == NULL) - { + ScopedLocalRef<jclass> cls(e, e->FindClass(className)); + if(cls.get() == NULL) { ALOGE ("%s: find class error", __FUNCTION__); return -1; } - ctor = e->GetMethodID (cls, "<init>", "()V"); - obj = e->NewObject (cls, ctor); - if (obj == NULL) - { + jmethodID ctor = e->GetMethodID(cls.get(), "<init>", "()V"); + jobject obj = e->NewObject(cls.get(), ctor); + if (obj == NULL) { ALOGE ("%s: create object error", __FUNCTION__); return -1; } - *cachedObj = e->NewLocalRef (obj); - if (*cachedObj == NULL) - { - e->DeleteLocalRef (obj); + *cachedObj = obj; + if (*cachedObj == NULL) { ALOGE ("%s: global ref error", __FUNCTION__); return -1; } - e->DeleteLocalRef (obj); return 0; } @@ -980,20 +1038,16 @@ int nfc_jni_cache_object_local (JNIEnv *e, const char *className, jobject *cache ** Returns: NativeLlcpServiceSocket Java object. ** *******************************************************************************/ -static jobject nfcManager_doCreateLlcpServiceSocket (JNIEnv* e, jobject o, jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength) +static jobject nfcManager_doCreateLlcpServiceSocket (JNIEnv* e, jobject, jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength) { - bool stat = false; - jobject serviceSocket = NULL; - jclass clsNativeLlcpServiceSocket = NULL; - jfieldID f = 0; PeerToPeer::tJNI_HANDLE jniHandle = PeerToPeer::getInstance().getNewJniHandle (); - const char* serviceName = e->GetStringUTFChars (sn, JNI_FALSE); //convert jstring, which is unicode, into char* - std::string serviceName2 (serviceName); - e->ReleaseStringUTFChars (sn, serviceName); //free the string - ALOGD ("%s: enter: sap=%i; name=%s; miu=%i; rw=%i; buffLen=%i", __FUNCTION__, nSap, serviceName2.c_str(), miu, rw, linearBufferLength); + ScopedUtfChars serviceName(e, sn); + + ALOGD ("%s: enter: sap=%i; name=%s; miu=%i; rw=%i; buffLen=%i", __FUNCTION__, nSap, serviceName.c_str(), miu, rw, linearBufferLength); /* Create new NativeLlcpServiceSocket object */ + jobject serviceSocket = NULL; if (nfc_jni_cache_object(e, gNativeLlcpServiceSocketClassName, &(serviceSocket)) == -1) { ALOGE ("%s: Llcp socket object creation error", __FUNCTION__); @@ -1001,7 +1055,7 @@ static jobject nfcManager_doCreateLlcpServiceSocket (JNIEnv* e, jobject o, jint } /* Get NativeLlcpServiceSocket class object */ - clsNativeLlcpServiceSocket = e->GetObjectClass (serviceSocket); + ScopedLocalRef<jclass> clsNativeLlcpServiceSocket(e, e->GetObjectClass(serviceSocket)); if (e->ExceptionCheck()) { e->ExceptionClear(); @@ -1009,30 +1063,32 @@ static jobject nfcManager_doCreateLlcpServiceSocket (JNIEnv* e, jobject o, jint return NULL; } - if (!PeerToPeer::getInstance().registerServer (jniHandle, serviceName2.c_str())) + if (!PeerToPeer::getInstance().registerServer (jniHandle, serviceName.c_str())) { ALOGE("%s: RegisterServer error", __FUNCTION__); return NULL; } + jfieldID f; + /* Set socket handle to be the same as the NfaHandle*/ - f = e->GetFieldID (clsNativeLlcpServiceSocket, "mHandle", "I"); - e->SetIntField (serviceSocket, f, (jint) jniHandle); + f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mHandle", "I"); + e->SetIntField(serviceSocket, f, (jint) jniHandle); ALOGD ("%s: socket Handle = 0x%X", __FUNCTION__, jniHandle); /* Set socket linear buffer length */ - f = e->GetFieldID (clsNativeLlcpServiceSocket, "mLocalLinearBufferLength", "I"); - e->SetIntField (serviceSocket, f,(jint)linearBufferLength); + f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mLocalLinearBufferLength", "I"); + e->SetIntField(serviceSocket, f,(jint)linearBufferLength); ALOGD ("%s: buffer length = %d", __FUNCTION__, linearBufferLength); /* Set socket MIU */ - f = e->GetFieldID (clsNativeLlcpServiceSocket, "mLocalMiu", "I"); - e->SetIntField (serviceSocket, f,(jint)miu); + f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mLocalMiu", "I"); + e->SetIntField(serviceSocket, f,(jint)miu); ALOGD ("%s: MIU = %d", __FUNCTION__, miu); /* Set socket RW */ - f = e->GetFieldID (clsNativeLlcpServiceSocket, "mLocalRw", "I"); - e->SetIntField (serviceSocket, f,(jint)rw); + f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mLocalRw", "I"); + e->SetIntField(serviceSocket, f,(jint)rw); ALOGD ("%s: RW = %d", __FUNCTION__, rw); sLastError = 0; @@ -1052,7 +1108,7 @@ static jobject nfcManager_doCreateLlcpServiceSocket (JNIEnv* e, jobject o, jint ** Returns: Last error code. ** *******************************************************************************/ -static jint nfcManager_doGetLastError(JNIEnv* e, jobject o) +static jint nfcManager_doGetLastError(JNIEnv*, jobject) { ALOGD ("%s: last error=%i", __FUNCTION__, sLastError); return sLastError; @@ -1070,7 +1126,7 @@ static jint nfcManager_doGetLastError(JNIEnv* e, jobject o) ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nfcManager_doDeinitialize (JNIEnv* e, jobject o) +static jboolean nfcManager_doDeinitialize (JNIEnv*, jobject) { ALOGD ("%s: enter", __FUNCTION__); @@ -1131,50 +1187,48 @@ static jboolean nfcManager_doDeinitialize (JNIEnv* e, jobject o) ** Returns: NativeLlcpSocket Java object. ** *******************************************************************************/ -static jobject nfcManager_doCreateLlcpSocket (JNIEnv* e, jobject o, jint nSap, jint miu, jint rw, jint linearBufferLength) +static jobject nfcManager_doCreateLlcpSocket (JNIEnv* e, jobject, jint nSap, jint miu, jint rw, jint linearBufferLength) { ALOGD ("%s: enter; sap=%d; miu=%d; rw=%d; buffer len=%d", __FUNCTION__, nSap, miu, rw, linearBufferLength); - jobject clientSocket = NULL; - jclass clsNativeLlcpSocket; - jfieldID f; - PeerToPeer::tJNI_HANDLE jniHandle = PeerToPeer::getInstance().getNewJniHandle (); - bool stat = false; - stat = PeerToPeer::getInstance().createClient (jniHandle, miu, rw); + PeerToPeer::tJNI_HANDLE jniHandle = PeerToPeer::getInstance().getNewJniHandle (); + bool stat = PeerToPeer::getInstance().createClient (jniHandle, miu, rw); /* Create new NativeLlcpSocket object */ + jobject clientSocket = NULL; if (nfc_jni_cache_object_local(e, gNativeLlcpSocketClassName, &(clientSocket)) == -1) { ALOGE ("%s: fail Llcp socket creation", __FUNCTION__); - goto TheEnd; + return clientSocket; } /* Get NativeConnectionless class object */ - clsNativeLlcpSocket = e->GetObjectClass (clientSocket); + ScopedLocalRef<jclass> clsNativeLlcpSocket(e, e->GetObjectClass(clientSocket)); if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: fail get class object", __FUNCTION__); - goto TheEnd; + return clientSocket; } + jfieldID f; + /* Set socket SAP */ - f = e->GetFieldID (clsNativeLlcpSocket, "mSap", "I"); + f = e->GetFieldID (clsNativeLlcpSocket.get(), "mSap", "I"); e->SetIntField (clientSocket, f, (jint) nSap); /* Set socket handle */ - f = e->GetFieldID (clsNativeLlcpSocket, "mHandle", "I"); + f = e->GetFieldID (clsNativeLlcpSocket.get(), "mHandle", "I"); e->SetIntField (clientSocket, f, (jint) jniHandle); /* Set socket MIU */ - f = e->GetFieldID (clsNativeLlcpSocket, "mLocalMiu", "I"); + f = e->GetFieldID (clsNativeLlcpSocket.get(), "mLocalMiu", "I"); e->SetIntField (clientSocket, f, (jint) miu); /* Set socket RW */ - f = e->GetFieldID (clsNativeLlcpSocket, "mLocalRw", "I"); + f = e->GetFieldID (clsNativeLlcpSocket.get(), "mLocalRw", "I"); e->SetIntField (clientSocket, f, (jint) rw); -TheEnd: ALOGD ("%s: exit", __FUNCTION__); return clientSocket; } @@ -1193,7 +1247,7 @@ TheEnd: ** Returns: NativeLlcpConnectionlessSocket Java object. ** *******************************************************************************/ -static jobject nfcManager_doCreateLlcpConnectionlessSocket (JNIEnv *e, jobject o, jint nSap, jstring sn) +static jobject nfcManager_doCreateLlcpConnectionlessSocket (JNIEnv *, jobject, jint nSap, jstring /*sn*/) { ALOGD ("%s: nSap=0x%X", __FUNCTION__, nSap); return NULL; @@ -1211,7 +1265,7 @@ static jobject nfcManager_doCreateLlcpConnectionlessSocket (JNIEnv *e, jobject o ** Returns: List of secure element handles. ** *******************************************************************************/ -static jintArray nfcManager_doGetSecureElementList(JNIEnv *e, jobject o) +static jintArray nfcManager_doGetSecureElementList(JNIEnv* e, jobject) { ALOGD ("%s", __FUNCTION__); return SecureElement::getInstance().getListOfEeHandles (e); @@ -1229,11 +1283,17 @@ static jintArray nfcManager_doGetSecureElementList(JNIEnv *e, jobject o) ** Returns: None ** *******************************************************************************/ -static void nfcManager_doSelectSecureElement(JNIEnv *e, jobject o) +static void nfcManager_doSelectSecureElement(JNIEnv*, jobject) { ALOGD ("%s: enter", __FUNCTION__); bool stat = true; + if (sIsSecElemSelected) + { + ALOGD ("%s: already selected", __FUNCTION__); + goto TheEnd; + } + PowerSwitch::getInstance ().setLevel (PowerSwitch::FULL_POWER); if (sRfEnabled) { @@ -1241,22 +1301,14 @@ static void nfcManager_doSelectSecureElement(JNIEnv *e, jobject o) startRfDiscovery (false); } - if (sIsSecElemSelected) - { - ALOGD ("%s: already selected", __FUNCTION__); - goto TheEnd; - } - stat = SecureElement::getInstance().activate (0xABCDEF); if (stat) SecureElement::getInstance().routeToSecureElement (); sIsSecElemSelected = true; -TheEnd: startRfDiscovery (true); - PowerSwitch::getInstance ().setModeOn (PowerSwitch::SE_ROUTING); - +TheEnd: ALOGD ("%s: exit", __FUNCTION__); } @@ -1272,7 +1324,7 @@ TheEnd: ** Returns: None ** *******************************************************************************/ -static void nfcManager_doDeselectSecureElement(JNIEnv *e, jobject o) +static void nfcManager_doDeselectSecureElement(JNIEnv*, jobject) { ALOGD ("%s: enter", __FUNCTION__); bool stat = false; @@ -1362,7 +1414,7 @@ static bool isListenMode(tNFA_ACTIVATED& activated) ** Returns: True ** *******************************************************************************/ -static jboolean nfcManager_doCheckLlcp(JNIEnv *e, jobject o) +static jboolean nfcManager_doCheckLlcp(JNIEnv*, jobject) { ALOGD("%s", __FUNCTION__); return JNI_TRUE; @@ -1378,7 +1430,7 @@ static jboolean nfcManager_doCheckLlcp(JNIEnv *e, jobject o) ** Returns: True ** *******************************************************************************/ -static jboolean nfcManager_doActivateLlcp(JNIEnv *e, jobject o) +static jboolean nfcManager_doActivateLlcp(JNIEnv*, jobject) { ALOGD("%s", __FUNCTION__); return JNI_TRUE; @@ -1394,7 +1446,7 @@ static jboolean nfcManager_doActivateLlcp(JNIEnv *e, jobject o) ** Returns: None ** *******************************************************************************/ -static void nfcManager_doAbort(JNIEnv *e, jobject o) +static void nfcManager_doAbort(JNIEnv*, jobject) { ALOGE("%s: abort()", __FUNCTION__); abort(); @@ -1410,7 +1462,7 @@ static void nfcManager_doAbort(JNIEnv *e, jobject o) ** Returns: True ** *******************************************************************************/ -static jboolean nfcManager_doDownload(JNIEnv *e, jobject o) +static jboolean nfcManager_doDownload(JNIEnv*, jobject) { ALOGD("%s", __FUNCTION__); return JNI_TRUE; @@ -1426,7 +1478,7 @@ static jboolean nfcManager_doDownload(JNIEnv *e, jobject o) ** Returns: None ** *******************************************************************************/ -static void nfcManager_doResetTimeouts(JNIEnv *e, jobject o) +static void nfcManager_doResetTimeouts(JNIEnv*, jobject) { ALOGD ("%s: %d millisec", __FUNCTION__, DEFAULT_GENERAL_TRANS_TIMEOUT); gGeneralTransceiveTimeout = DEFAULT_GENERAL_TRANS_TIMEOUT; @@ -1445,7 +1497,7 @@ static void nfcManager_doResetTimeouts(JNIEnv *e, jobject o) ** Returns: True if ok. ** *******************************************************************************/ -static bool nfcManager_doSetTimeout(JNIEnv *e, jobject o, jint tech, jint timeout) +static bool nfcManager_doSetTimeout(JNIEnv*, jobject, jint /*tech*/, jint timeout) { if (timeout <= 0) { @@ -1471,7 +1523,7 @@ static bool nfcManager_doSetTimeout(JNIEnv *e, jobject o, jint tech, jint timeou ** Returns: Timeout value. ** *******************************************************************************/ -static jint nfcManager_doGetTimeout(JNIEnv *e, jobject o, jint tech) +static jint nfcManager_doGetTimeout(JNIEnv*, jobject, jint /*tech*/) { ALOGD ("%s: timeout=%d", __FUNCTION__, gGeneralTransceiveTimeout); return gGeneralTransceiveTimeout; @@ -1489,7 +1541,7 @@ static jint nfcManager_doGetTimeout(JNIEnv *e, jobject o, jint tech) ** Returns: Text dump. ** *******************************************************************************/ -static jstring nfcManager_doDump(JNIEnv *e, jobject o) +static jstring nfcManager_doDump(JNIEnv* e, jobject) { char buffer[100]; snprintf(buffer, sizeof(buffer), "libnfc llc error_count=%u", /*libnfc_llc_error_count*/ 0); @@ -1541,7 +1593,7 @@ static void nfcManager_doSetP2pInitiatorModes (JNIEnv *e, jobject o, jint modes) ** Returns: None. ** *******************************************************************************/ -static void nfcManager_doSetP2pTargetModes (JNIEnv *e, jobject o, jint modes) +static void nfcManager_doSetP2pTargetModes (JNIEnv*, jobject, jint modes) { ALOGD ("%s: modes=0x%X", __FUNCTION__, modes); // Map in the right modes @@ -1693,23 +1745,6 @@ void doStartupConfig() struct nfc_jni_native_data *nat = getNative(0, 0); tNFA_STATUS stat = NFA_STATUS_FAILED; - // Enable the "RC workaround" to allow our stack/firmware to work with a retail - // Nexus S that causes IOP issues. Only enable if value exists and set to 1. - if (GetNumValue(NAME_USE_NXP_P2P_RC_WORKAROUND, &num, sizeof(num)) && (num == 1)) - { -#if (NCI_VERSION > NCI_VERSION_20791B0) - UINT8 nfa_dm_rc_workaround[] = { 0x03, 0x0f, 0xab }; -#else - UINT8 nfa_dm_rc_workaround[] = { 0x01, 0x0f, 0xab, 0x01 }; -#endif - - ALOGD ("%s: Configure RC work-around", __FUNCTION__); - SyncEventGuard guard (sNfaSetConfigEvent); - stat = NFA_SetConfig(NCI_PARAM_ID_FW_WORKAROUND, sizeof(nfa_dm_rc_workaround), &nfa_dm_rc_workaround[0]); - if (stat == NFA_STATUS_OK) - sNfaSetConfigEvent.wait (); - } - // If polling for Active mode, set the ordering so that we choose Active over Passive mode first. if (nat && (nat->tech_mask & (NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE))) { @@ -1719,41 +1754,6 @@ void doStartupConfig() if (stat == NFA_STATUS_OK) sNfaSetConfigEvent.wait (); } - - // Set configuration to allow UICC to Power off if there is no traffic. - if (GetNumValue(NAME_UICC_IDLE_TIMEOUT, &num, sizeof(num)) && (num != 0)) - { - // 61 => The least significant bit of this byte enables the power off when Idle mode. - // 00 87 93 03 == > These 4 bytes form a 4 byte value which decides the idle timeout(in us) - // value to trigger the uicc deactivation. - // e.g. in current example its value is 0x3938700 i.e. 60000000 is 60 seconds. - UINT8 swpcfg_param[] = { 0x61, 0x00, 0x82, 0x04, 0x20, 0xA1, 0x07, 0x00, - 0x90, 0xD0, 0x03, 0x00, 0x00, 0x87, 0x93, 0x03 }; - - ALOGD ("%s: Configure UICC idle-timeout to %lu ms", __FUNCTION__, num); - - // Set the timeout from the .conf file value. - num *= 1000; - UINT8 * p = &swpcfg_param[12]; - UINT32_TO_STREAM(p, num) - - SyncEventGuard guard (sNfaSetConfigEvent); - stat = NFA_SetConfig(NCI_PARAM_ID_SWPCFG, sizeof(swpcfg_param), &swpcfg_param[0]); - if (stat == NFA_STATUS_OK) - sNfaSetConfigEvent.wait (); - } - - // Set antenna tuning configuration if configured. -#define PREINIT_DSP_CFG_SIZE 30 - UINT8 preinit_dsp_param[PREINIT_DSP_CFG_SIZE]; - - if (GetStrValue(NAME_PREINIT_DSP_CFG, (char*)&preinit_dsp_param[0], sizeof(preinit_dsp_param))) - { - SyncEventGuard guard (sNfaSetConfigEvent); - stat = NFA_SetConfig(NCI_PARAM_ID_PREINIT_DSP_CFG, sizeof(preinit_dsp_param), &preinit_dsp_param[0]); - if (stat == NFA_STATUS_OK) - sNfaSetConfigEvent.wait (); - } } diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp index 0ba7b21a..86666683 100755 --- a/nci/jni/NativeNfcTag.cpp +++ b/nci/jni/NativeNfcTag.cpp @@ -26,6 +26,8 @@ #include "IntervalTimer.h" #include "JavaClassConstants.h" #include "Pn544Interop.h" +#include <ScopedLocalRef.h> +#include <ScopedPrimitiveArray.h> extern "C" { @@ -244,7 +246,7 @@ static void ndefHandlerCallback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *eventD ** Returns: NDEF message. ** *******************************************************************************/ -static jbyteArray nativeNfcTag_doRead (JNIEnv *e, jobject o) +static jbyteArray nativeNfcTag_doRead (JNIEnv* e, jobject) { ALOGD ("%s: enter", __FUNCTION__); tNFA_STATUS status = NFA_STATUS_FAILED; @@ -277,7 +279,6 @@ static jbyteArray nativeNfcTag_doRead (JNIEnv *e, jobject o) else { ALOGD ("%s: create emtpy buffer", __FUNCTION__); - static uint8_t* empty = (uint8_t*) ""; sReadDataLen = 0; sReadData = (uint8_t*) malloc (1); buf = e->NewByteArray (sReadDataLen); @@ -348,20 +349,18 @@ void nativeNfcTag_formatStatus (bool isOk) ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nativeNfcTag_doWrite (JNIEnv *e, jobject o, jbyteArray buf) +static jboolean nativeNfcTag_doWrite (JNIEnv* e, jobject, jbyteArray buf) { jboolean result = JNI_FALSE; tNFA_STATUS status = 0; - UINT32 len = 0; - UINT8* p_data = NULL; const int maxBufferSize = 1024; UINT8 buffer[maxBufferSize] = { 0 }; UINT32 curDataSize = 0; - len = (UINT32) e->GetArrayLength (buf); - p_data = (UINT8*) e->GetByteArrayElements (buf, NULL); + ScopedByteArrayRO bytes(e, buf); + UINT8* p_data = const_cast<UINT8*>(reinterpret_cast<const UINT8*>(&bytes[0])); // TODO: const-ness API bug in NFA_RwWriteNDef! - ALOGD ("%s: enter; len = %lu", __FUNCTION__, len); + ALOGD ("%s: enter; len = %zu", __FUNCTION__, bytes.size()); /* Create the write semaphore */ if (sem_init (&sWriteSem, 0, 0) == -1) @@ -387,9 +386,9 @@ static jboolean nativeNfcTag_doWrite (JNIEnv *e, jobject o, jbyteArray buf) goto TheEnd; } ALOGD ("%s: try write", __FUNCTION__); - status = NFA_RwWriteNDef (p_data, len); + status = NFA_RwWriteNDef (p_data, bytes.size()); } - else if (len == 0) + else if (bytes.size() == 0) { //if (NXP TagWriter wants to erase tag) then create and write an empty ndef message NDEF_MsgInit (buffer, maxBufferSize, &curDataSize); @@ -400,7 +399,7 @@ static jboolean nativeNfcTag_doWrite (JNIEnv *e, jobject o, jbyteArray buf) else { ALOGD ("%s: NFA_RwWriteNDef", __FUNCTION__); - status = NFA_RwWriteNDef (p_data, len); + status = NFA_RwWriteNDef (p_data, bytes.size()); } if (status != NFA_STATUS_OK) @@ -483,7 +482,7 @@ void nativeNfcTag_doDeactivateStatus (int status) ** Returns: Must return NXP status code, which NFC service expects. ** *******************************************************************************/ -static jint nativeNfcTag_doConnect (JNIEnv *e, jobject o, jint targetHandle) +static jint nativeNfcTag_doConnect (JNIEnv*, jobject, jint targetHandle) { ALOGD ("%s: targetHandle = %d", __FUNCTION__, targetHandle); int i = targetHandle; @@ -671,7 +670,7 @@ static bool switchRfInterface (tNFA_INTF_TYPE rfInterface) ** Returns: Status code. ** *******************************************************************************/ -static jint nativeNfcTag_doReconnect (JNIEnv *e, jobject o) +static jint nativeNfcTag_doReconnect (JNIEnv*, jobject) { ALOGD ("%s: enter", __FUNCTION__); int retCode = NFCSTATUS_SUCCESS; @@ -684,6 +683,13 @@ static jint nativeNfcTag_doReconnect (JNIEnv *e, jobject o) goto TheEnd; } + // special case for Kovio + if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE) + { + ALOGD ("%s: fake out reconnect for Kovio", __FUNCTION__); + goto TheEnd; + } + // this is only supported for type 2 or 4 (ISO_DEP) tags if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_ISO_DEP) retCode = reSelect(NFA_INTERFACE_ISO_DEP); @@ -726,7 +732,7 @@ static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHan ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nativeNfcTag_doDisconnect (JNIEnv *e, jobject o) +static jboolean nativeNfcTag_doDisconnect (JNIEnv*, jobject) { ALOGD ("%s: enter", __FUNCTION__); struct nfc_jni_native_data *nat = getNative (0, 0); @@ -800,15 +806,13 @@ void nativeNfcTag_doTransceiveStatus (uint8_t* buf, uint32_t bufLen) ** Returns: Response from tag. ** *******************************************************************************/ -static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost) +static jbyteArray nativeNfcTag_doTransceive (JNIEnv* e, jobject, jbyteArray data, jboolean raw, jintArray statusTargetLost) { ALOGD ("%s: enter; raw=%u; timeout = %d", __FUNCTION__, raw, gGeneralTransceiveTimeout); bool fNeedToSwitchBack = false; nfc_jni_native_data *nat = getNative (0, 0); bool waitOk = false; bool isNack = false; - uint8_t *buf = NULL; - uint32_t bufLen = 0; jint *targetLost = NULL; if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) @@ -827,8 +831,9 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da NfcTag& natTag = NfcTag::getInstance (); // get input buffer and length from java call - buf = (uint8_t *) e->GetByteArrayElements (data, NULL); - bufLen = (uint32_t) e->GetArrayLength (data); + ScopedByteArrayRO bytes(e, data); + uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0])); // TODO: API bug; NFA_SendRawFrame should take const*! + size_t bufLen = bytes.size(); if (statusTargetLost) { @@ -838,7 +843,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da } sSwitchBackTimer.kill (); - jbyteArray result = NULL; + ScopedLocalRef<jbyteArray> result(e, NULL); do { if (sNeedToSwitchRf) @@ -855,7 +860,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da sTransceiveDataLen = 0; { SyncEventGuard g (sTransceiveEvent); - tNFA_STATUS status = NFA_SendRawFrame (buf, bufLen); + tNFA_STATUS status = NFA_SendRawFrame (buf, bufLen, NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY); if (status != NFA_STATUS_OK) { ALOGE ("%s: fail send; error=%d", __FUNCTION__, status); @@ -892,10 +897,9 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da { if (!isNack) { // marshall data to java for return - result = e->NewByteArray (sTransceiveDataLen); - if (result != NULL) - { - e->SetByteArrayRegion (result, 0, sTransceiveDataLen, (jbyte *) sTransceiveData); + result.reset(e->NewByteArray(sTransceiveDataLen)); + if (result.get() != NULL) { + e->SetByteArrayRegion(result.get(), 0, sTransceiveDataLen, (jbyte *) sTransceiveData); } else ALOGE ("%s: Failed to allocate java byte array", __FUNCTION__); @@ -908,7 +912,6 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da } while (0); sWaitingForTransceive = false; - e->ReleaseByteArrayElements (data, (jbyte *) buf, JNI_ABORT); if (targetLost) e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0); @@ -919,7 +922,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da } ALOGD ("%s: exit", __FUNCTION__); - return result; + return result.release(); } @@ -936,7 +939,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da ** Returns: Type of tag represented by NFC Service. ** *******************************************************************************/ -static jint nativeNfcTag_doGetNdefType (JNIEnv *e, jobject o, jint libnfcType, jint javaType) +static jint nativeNfcTag_doGetNdefType (JNIEnv*, jobject, jint libnfcType, jint javaType) { ALOGD ("%s: enter; libnfc type=%d; java type=%d", __FUNCTION__, libnfcType, javaType); jint ndefType = NDEF_UNKNOWN_TYPE; @@ -1064,13 +1067,35 @@ void nativeNfcTag_doCheckNdefResult (tNFA_STATUS status, uint32_t maxSize, uint3 ** Returns: Status code; 0 is success. ** *******************************************************************************/ -static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo) +static jint nativeNfcTag_doCheckNdef (JNIEnv* e, jobject, jintArray ndefInfo) { tNFA_STATUS status = NFA_STATUS_FAILED; jint* ndef = NULL; ALOGD ("%s: enter", __FUNCTION__); + // special case for Kovio + if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE) + { + ALOGD ("%s: Kovio tag, no NDEF", __FUNCTION__); + ndef = e->GetIntArrayElements (ndefInfo, 0); + ndef[0] = 0; + ndef[1] = NDEF_MODE_READ_ONLY; + e->ReleaseIntArrayElements (ndefInfo, ndef, 0); + return NFA_STATUS_FAILED; + } + + // special case for Kovio + if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE) + { + ALOGD ("%s: Kovio tag, no NDEF", __FUNCTION__); + ndef = e->GetIntArrayElements (ndefInfo, 0); + ndef[0] = 0; + ndef[1] = NDEF_MODE_READ_ONLY; + e->ReleaseIntArrayElements (ndefInfo, ndef, 0); + return NFA_STATUS_FAILED; + } + /* Create the write semaphore */ if (sem_init (&sCheckNdefSem, 0, 0) == -1) { @@ -1202,12 +1227,29 @@ void nativeNfcTag_doPresenceCheckResult (tNFA_STATUS status) ** Returns: True if tag is in RF field. ** *******************************************************************************/ -static jboolean nativeNfcTag_doPresenceCheck (JNIEnv *e, jobject o) +static jboolean nativeNfcTag_doPresenceCheck (JNIEnv*, jobject) { ALOGD ("%s", __FUNCTION__); tNFA_STATUS status = NFA_STATUS_OK; jboolean isPresent = JNI_FALSE; + // Special case for Kovio. The deactivation would have already occurred + // but was ignored so that normal tag opertions could complete. Now we + // want to process as if the deactivate just happened. + if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE) + { + ALOGD ("%s: Kovio, force deactivate handling", __FUNCTION__); + tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE}; + + NfcTag::getInstance().setDeactivationState (deactivated); + nativeNfcTag_resetPresenceCheck(); + NfcTag::getInstance().connectionEventHandler (NFA_DEACTIVATED_EVT, NULL); + nativeNfcTag_abortWaits(); + NfcTag::getInstance().abort (); + + return JNI_FALSE; + } + if (nfcManager_isNfcActive() == false) { ALOGD ("%s: NFC is no longer active.", __FUNCTION__); @@ -1265,9 +1307,9 @@ static jboolean nativeNfcTag_doPresenceCheck (JNIEnv *e, jobject o) ** Returns: True if formattable. ** *******************************************************************************/ -static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv *e, - jobject o, jint libNfcType, jbyteArray uidBytes, jbyteArray pollBytes, - jbyteArray actBytes) +static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv*, + jobject, jint /*libNfcType*/, jbyteArray, jbyteArray, + jbyteArray) { jboolean isFormattable = JNI_FALSE; @@ -1321,7 +1363,7 @@ static jboolean nativeNfcTag_doIsIsoDepNdefFormatable (JNIEnv *e, jobject o, jby ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nativeNfcTag_doNdefFormat (JNIEnv *e, jobject o, jbyteArray key) +static jboolean nativeNfcTag_doNdefFormat (JNIEnv*, jobject, jbyteArray) { ALOGD ("%s: enter", __FUNCTION__); tNFA_STATUS status = NFA_STATUS_OK; @@ -1379,7 +1421,7 @@ void nativeNfcTag_doMakeReadonlyResult (tNFA_STATUS status) ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nativeNfcTag_doMakeReadonly (JNIEnv *e, jobject o, jbyteArray key) +static jboolean nativeNfcTag_doMakeReadonly (JNIEnv*, jobject, jbyteArray) { jboolean result = JNI_FALSE; tNFA_STATUS status; diff --git a/nci/jni/NativeP2pDevice.cpp b/nci/jni/NativeP2pDevice.cpp index 57f9dad0..fffa46b5 100644 --- a/nci/jni/NativeP2pDevice.cpp +++ b/nci/jni/NativeP2pDevice.cpp @@ -23,35 +23,35 @@ namespace android { -static jboolean nativeP2pDeviceDoConnect (JNIEnv* e, jobject o) +static jboolean nativeP2pDeviceDoConnect (JNIEnv*, jobject) { ALOGD ("%s", __FUNCTION__); return JNI_TRUE; } -static jboolean nativeP2pDeviceDoDisconnect (JNIEnv* e, jobject o) +static jboolean nativeP2pDeviceDoDisconnect (JNIEnv*, jobject) { ALOGD ("%s", __FUNCTION__); return JNI_TRUE; } -static jbyteArray nativeP2pDeviceDoTransceive (JNIEnv* e, jobject o, jbyteArray data) +static jbyteArray nativeP2pDeviceDoTransceive (JNIEnv*, jobject, jbyteArray) { ALOGD ("%s", __FUNCTION__); return NULL; } -static jbyteArray nativeP2pDeviceDoReceive (JNIEnv* e, jobject o) +static jbyteArray nativeP2pDeviceDoReceive (JNIEnv*, jobject) { ALOGD ("%s", __FUNCTION__); return NULL; } -static jboolean nativeP2pDeviceDoSend (JNIEnv* e, jobject o, jbyteArray buf) +static jboolean nativeP2pDeviceDoSend (JNIEnv*, jobject, jbyteArray) { ALOGD ("%s", __FUNCTION__); return JNI_TRUE; diff --git a/nci/jni/NativeSecureElement.cpp b/nci/jni/NativeSecureElement.cpp index 1a2a73a0..fea2e151 100755 --- a/nci/jni/NativeSecureElement.cpp +++ b/nci/jni/NativeSecureElement.cpp @@ -17,7 +17,7 @@ #include "SecureElement.h" #include "JavaClassConstants.h" #include "PowerSwitch.h" - +#include <ScopedPrimitiveArray.h> namespace android { @@ -27,6 +27,13 @@ extern void com_android_nfc_NfcManager_disableDiscovery (JNIEnv* e, jobject o); extern void com_android_nfc_NfcManager_enableDiscovery (JNIEnv* e, jobject o, jint mode); extern int gGeneralTransceiveTimeout; +// These must match the EE_ERROR_ types in NfcService.java +static const int EE_ERROR_IO = -1; +static const int EE_ERROR_ALREADY_OPEN = -2; +static const int EE_ERROR_INIT = -3; +static const int EE_ERROR_LISTEN_MODE = -4; +static const int EE_ERROR_EXT_FIELD = -5; +static const int EE_ERROR_NFC_DISABLED = -6; /******************************************************************************* ** @@ -36,23 +43,25 @@ extern int gGeneralTransceiveTimeout; ** e: JVM environment. ** o: Java object. ** -** Returns: Handle of secure element. 0 is failure. +** Returns: Handle of secure element. values < 0 represent failure. ** *******************************************************************************/ -static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv* e, jobject o) +static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv*, jobject) { ALOGD("%s: enter", __FUNCTION__); bool stat = true; - jint secElemHandle = 0; + jint secElemHandle = EE_ERROR_INIT; SecureElement &se = SecureElement::getInstance(); if (se.isActivatedInListenMode()) { ALOGD("Denying SE open due to SE listen mode active"); + secElemHandle = EE_ERROR_LISTEN_MODE; goto TheEnd; } if (se.isRfFieldOn()) { ALOGD("Denying SE open due to SE in active RF field"); + secElemHandle = EE_ERROR_EXT_FIELD; goto TheEnd; } //tell the controller to power up to get ready for sec elem operations @@ -69,9 +78,13 @@ static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv* e, job //establish a pipe to sec elem stat = se.connectEE(); if (stat) + { secElemHandle = se.mActiveEeHandle; + } else + { se.deactivate (0); + } } //if code fails to connect to the secure element, and nothing is active, then @@ -99,7 +112,7 @@ TheEnd: ** Returns: True if ok. ** *******************************************************************************/ -static jboolean nativeNfcSecureElement_doDisconnectSecureElementConnection (JNIEnv* e, jobject o, jint handle) +static jboolean nativeNfcSecureElement_doDisconnectSecureElementConnection (JNIEnv*, jobject, jint handle) { ALOGD("%s: enter; handle=0x%04x", __FUNCTION__, handle); bool stat = false; @@ -133,29 +146,23 @@ static jboolean nativeNfcSecureElement_doDisconnectSecureElementConnection (JNIE ** Returns: Buffer of received data. ** *******************************************************************************/ -static jbyteArray nativeNfcSecureElement_doTransceive (JNIEnv* e, jobject o, jint handle, jbyteArray data) +static jbyteArray nativeNfcSecureElement_doTransceive (JNIEnv* e, jobject, jint handle, jbyteArray data) { - UINT8* buf = NULL; - INT32 buflen = 0; const INT32 recvBufferMaxSize = 1024; UINT8 recvBuffer [recvBufferMaxSize]; INT32 recvBufferActualSize = 0; - jbyteArray result = NULL; - buf = (UINT8*) e->GetByteArrayElements (data, NULL); - buflen = e->GetArrayLength (data); + ScopedByteArrayRW bytes(e, data); - ALOGD("%s: enter; handle=0x%X; buf len=%ld", __FUNCTION__, handle, buflen); - SecureElement::getInstance().transceive (buf, buflen, recvBuffer, recvBufferMaxSize, recvBufferActualSize, gGeneralTransceiveTimeout); + ALOGD("%s: enter; handle=0x%X; buf len=%zu", __FUNCTION__, handle, bytes.size()); + SecureElement::getInstance().transceive(reinterpret_cast<UINT8*>(&bytes[0]), bytes.size(), recvBuffer, recvBufferMaxSize, recvBufferActualSize, gGeneralTransceiveTimeout); //copy results back to java - result = e->NewByteArray (recvBufferActualSize); - if (result != NULL) - { - e->SetByteArrayRegion (result, 0, recvBufferActualSize, (jbyte *) recvBuffer); + jbyteArray result = e->NewByteArray(recvBufferActualSize); + if (result != NULL) { + e->SetByteArrayRegion(result, 0, recvBufferActualSize, (jbyte *) recvBuffer); } - e->ReleaseByteArrayElements (data, (jbyte *) buf, JNI_ABORT); ALOGD("%s: exit: recv len=%ld", __FUNCTION__, recvBufferActualSize); return result; } @@ -173,7 +180,7 @@ static jbyteArray nativeNfcSecureElement_doTransceive (JNIEnv* e, jobject o, jin ** Returns: Secure element's unique ID. ** *******************************************************************************/ -static jbyteArray nativeNfcSecureElement_doGetUid (JNIEnv* e, jobject o, jint handle) +static jbyteArray nativeNfcSecureElement_doGetUid (JNIEnv*, jobject, jint handle) { ALOGD("%s: enter; handle=0x%X", __FUNCTION__, handle); jbyteArray secureElementUid = NULL; @@ -197,7 +204,7 @@ static jbyteArray nativeNfcSecureElement_doGetUid (JNIEnv* e, jobject o, jint ha ** Returns: Array of technologies. ** *******************************************************************************/ -static jintArray nativeNfcSecureElement_doGetTechList (JNIEnv* e, jobject o, jint handle) +static jintArray nativeNfcSecureElement_doGetTechList (JNIEnv*, jobject, jint handle) { ALOGD("%s: enter; handle=0x%X", __FUNCTION__, handle); jintArray techList = NULL; @@ -242,4 +249,3 @@ int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e) } // namespace android - diff --git a/nci/jni/NfcJniUtil.cpp b/nci/jni/NfcJniUtil.cpp index 9921caed..2bac97b0 100755 --- a/nci/jni/NfcJniUtil.cpp +++ b/nci/jni/NfcJniUtil.cpp @@ -15,6 +15,7 @@ */ #include "NfcJniUtil.h" #include <errno.h> +#include <ScopedLocalRef.h> /******************************************************************************* @@ -28,11 +29,13 @@ ** Returns: JNI version. ** *******************************************************************************/ -jint JNI_OnLoad (JavaVM *jvm, void *reserved) +jint JNI_OnLoad (JavaVM* jvm, void*) { ALOGD ("%s: enter", __FUNCTION__); JNIEnv *e = NULL; + ALOGI("NFC Service: loading nci JNI"); + // Check JNI version if (jvm->GetEnv ((void **) &e, JNI_VERSION_1_6)) return JNI_ERR; @@ -71,33 +74,24 @@ namespace android *******************************************************************************/ int nfc_jni_cache_object (JNIEnv *e, const char *className, jobject *cachedObj) { - jclass cls = NULL; - jobject obj = NULL; - jmethodID ctor = 0; - - cls = e->FindClass (className); - if(cls == NULL) - { - ALOGE ("%s: find class error", __FUNCTION__); + ScopedLocalRef<jclass> cls(e, e->FindClass(className)); + if (cls.get() == NULL) { + ALOGE("%s: find class error", __FUNCTION__); return -1; } - ctor = e->GetMethodID (cls, "<init>", "()V"); - obj = e->NewObject (cls, ctor); - if (obj == NULL) - { - ALOGE ("%s: create object error", __FUNCTION__); + jmethodID ctor = e->GetMethodID(cls.get(), "<init>", "()V"); + ScopedLocalRef<jobject> obj(e, e->NewObject(cls.get(), ctor)); + if (obj.get() == NULL) { + ALOGE("%s: create object error", __FUNCTION__); return -1; } - *cachedObj = e->NewGlobalRef (obj); - if (*cachedObj == NULL) - { - e->DeleteLocalRef (obj); - ALOGE ("%s: global ref error", __FUNCTION__); + *cachedObj = e->NewGlobalRef(obj.get()); + if (*cachedObj == NULL) { + ALOGE("%s: global ref error", __FUNCTION__); return -1; } - e->DeleteLocalRef (obj); return 0; } @@ -115,12 +109,9 @@ int nfc_jni_cache_object (JNIEnv *e, const char *className, jobject *cachedObj) *******************************************************************************/ int nfc_jni_get_nfc_socket_handle (JNIEnv *e, jobject o) { - jclass c = NULL; - jfieldID f = 0; - - c = e->GetObjectClass (o); - f = e->GetFieldID (c, "mHandle", "I"); - return e->GetIntField (o, f); + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mHandle", "I"); + return e->GetIntField(o, f); } @@ -137,13 +128,10 @@ int nfc_jni_get_nfc_socket_handle (JNIEnv *e, jobject o) *******************************************************************************/ struct nfc_jni_native_data* nfc_jni_get_nat(JNIEnv *e, jobject o) { - jclass c = NULL; - jfieldID f = 0; - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mNative", "I"); /* Retrieve native structure address */ - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mNative", "I"); - return (struct nfc_jni_native_data*)e->GetIntField(o, f); + return (struct nfc_jni_native_data*) e->GetIntField(o, f); } diff --git a/nci/jni/NfcJniUtil.h b/nci/jni/NfcJniUtil.h index 8caa0b88..a8b5faa4 100755 --- a/nci/jni/NfcJniUtil.h +++ b/nci/jni/NfcJniUtil.h @@ -15,6 +15,7 @@ */ #pragma once +#undef LOG_TAG #define LOG_TAG "BrcmNfcJni" #include <JNIHelp.h> #include <jni.h> @@ -83,6 +84,7 @@ #define TARGET_TYPE_NDEF_FORMATABLE 7 #define TARGET_TYPE_MIFARE_CLASSIC 8 #define TARGET_TYPE_MIFARE_UL 9 +#define TARGET_TYPE_KOVIO_BARCODE 10 //define a few NXP error codes that NFC service expects; @@ -131,6 +133,21 @@ struct nfc_jni_native_data }; +class ScopedAttach { + public: + ScopedAttach(JavaVM* vm, JNIEnv** env) : vm_(vm) { + vm_->AttachCurrentThread(env, NULL); + } + + ~ScopedAttach() { + vm_->DetachCurrentThread(); + } + + private: + JavaVM* vm_; +}; + + extern "C" { jint JNI_OnLoad(JavaVM *jvm, void *reserved); diff --git a/nci/jni/NfcTag.cpp b/nci/jni/NfcTag.cpp index b94355fb..de006565 100755 --- a/nci/jni/NfcTag.cpp +++ b/nci/jni/NfcTag.cpp @@ -20,6 +20,9 @@ #include "OverrideLog.h" #include "NfcTag.h" #include "JavaClassConstants.h" +#include <ScopedLocalRef.h> +#include <ScopedPrimitiveArray.h> + extern "C" { #include "rw_int.h" @@ -348,8 +351,8 @@ void NfcTag::discoverTechnologies (tNFA_ACTIVATED& activationData) break; case NFC_PROTOCOL_KOVIO: - ALOGE ("%s: Kovio", fn); - mNumTechList--; // no tech classes for Kovio + ALOGD ("%s: Kovio", fn); + mTechList [mNumTechList] = TARGET_TYPE_KOVIO_BARCODE; break; default: @@ -491,63 +494,53 @@ void NfcTag::createNativeNfcTag (tNFA_ACTIVATED& activationData) { static const char fn [] = "NfcTag::createNativeNfcTag"; ALOGD ("%s: enter", fn); - JNIEnv* e = NULL; - jclass tag_cls = NULL; - jmethodID ctor = NULL; - jobject tag = NULL; - //acquire a pointer to the Java virtual machine - mNativeData->vm->AttachCurrentThread (&e, NULL); - if (e == NULL) - { + JNIEnv* e = NULL; + ScopedAttach attach(mNativeData->vm, &e); + if (e == NULL) { ALOGE("%s: jni env is null", fn); - goto TheEnd; + return; } - tag_cls = e->GetObjectClass (mNativeData->cached_NfcTag); - if (e->ExceptionCheck()) - { + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(mNativeData->cached_NfcTag)); + if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE("%s: failed to get class", fn); - goto TheEnd; + return; } //create a new Java NativeNfcTag object - ctor = e->GetMethodID (tag_cls, "<init>", "()V"); - tag = e->NewObject (tag_cls, ctor); + jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); + ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor)); //fill NativeNfcTag's mProtocols, mTechList, mTechHandles, mTechLibNfcTypes - fillNativeNfcTagMembers1 (e, tag_cls, tag); + fillNativeNfcTagMembers1(e, tag_cls.get(), tag.get()); //fill NativeNfcTag's members: mHandle, mConnectedTechnology - fillNativeNfcTagMembers2 (e, tag_cls, tag, activationData); + fillNativeNfcTagMembers2(e, tag_cls.get(), tag.get(), activationData); //fill NativeNfcTag's members: mTechPollBytes - fillNativeNfcTagMembers3 (e, tag_cls, tag, activationData); + fillNativeNfcTagMembers3(e, tag_cls.get(), tag.get(), activationData); //fill NativeNfcTag's members: mTechActBytes - fillNativeNfcTagMembers4 (e, tag_cls, tag, activationData); + fillNativeNfcTagMembers4(e, tag_cls.get(), tag.get(), activationData); //fill NativeNfcTag's members: mUid - fillNativeNfcTagMembers5 (e, tag_cls, tag, activationData); + fillNativeNfcTagMembers5(e, tag_cls.get(), tag.get(), activationData); if (mNativeData->tag != NULL) { - e->DeleteGlobalRef (mNativeData->tag); + e->DeleteGlobalRef(mNativeData->tag); } - mNativeData->tag = e->NewGlobalRef (tag); + mNativeData->tag = e->NewGlobalRef(tag.get()); //notify NFC service about this new tag ALOGD ("%s: try notify nfc service", fn); - e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyNdefMessageListeners, tag); - if (e->ExceptionCheck()) - { + e->CallVoidMethod(mNativeData->manager, android::gCachedNfcManagerNotifyNdefMessageListeners, tag.get()); + if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: fail notify nfc service", fn); } - e->DeleteLocalRef (tag); -TheEnd: - mNativeData->vm->DetachCurrentThread (); ALOGD ("%s: exit", fn); } @@ -568,36 +561,35 @@ void NfcTag::fillNativeNfcTagMembers1 (JNIEnv* e, jclass tag_cls, jobject tag) { static const char fn [] = "NfcTag::fillNativeNfcTagMembers1"; ALOGD ("%s", fn); - jfieldID f = NULL; //create objects that represent NativeNfcTag's member variables - jintArray techList = e->NewIntArray (mNumTechList); - jintArray handleList = e->NewIntArray (mNumTechList); - jintArray typeList = e->NewIntArray (mNumTechList); + ScopedLocalRef<jintArray> techList(e, e->NewIntArray(mNumTechList)); + ScopedLocalRef<jintArray> handleList(e, e->NewIntArray(mNumTechList)); + ScopedLocalRef<jintArray> typeList(e, e->NewIntArray(mNumTechList)); - jint* technologies = e->GetIntArrayElements (techList, NULL); - jint* handles = e->GetIntArrayElements (handleList, NULL); - jint* types = e->GetIntArrayElements (typeList, NULL); - for (int i = 0; i < mNumTechList; i++) { - mNativeData->tProtocols [i] = mTechLibNfcTypes [i]; - mNativeData->handles [i] = mTechHandles [i]; - technologies [i] = mTechList [i]; - handles [i] = mTechHandles [i]; - types [i] = mTechLibNfcTypes [i]; + ScopedIntArrayRW technologies(e, techList.get()); + ScopedIntArrayRW handles(e, handleList.get()); + ScopedIntArrayRW types(e, typeList.get()); + for (int i = 0; i < mNumTechList; i++) { + mNativeData->tProtocols [i] = mTechLibNfcTypes [i]; + mNativeData->handles [i] = mTechHandles [i]; + technologies [i] = mTechList [i]; + handles [i] = mTechHandles [i]; + types [i] = mTechLibNfcTypes [i]; + } } - e->ReleaseIntArrayElements (techList, technologies, 0); - e->ReleaseIntArrayElements (handleList, handles, 0); - e->ReleaseIntArrayElements (typeList, types, 0); - f = e->GetFieldID (tag_cls, "mTechList", "[I"); - e->SetObjectField (tag, f, techList); + jfieldID f = NULL; + + f = e->GetFieldID(tag_cls, "mTechList", "[I"); + e->SetObjectField(tag, f, techList.get()); - f = e->GetFieldID (tag_cls, "mTechHandles", "[I"); - e->SetObjectField (tag, f, handleList); + f = e->GetFieldID(tag_cls, "mTechHandles", "[I"); + e->SetObjectField(tag, f, handleList.get()); - f = e->GetFieldID (tag_cls, "mTechLibNfcTypes", "[I"); - e->SetObjectField (tag, f, typeList); + f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I"); + e->SetObjectField(tag, f, typeList.get()); } @@ -617,14 +609,12 @@ void NfcTag::fillNativeNfcTagMembers1 (JNIEnv* e, jclass tag_cls, jobject tag) ** *******************************************************************************/ //fill NativeNfcTag's members: mHandle, mConnectedTechnology -void NfcTag::fillNativeNfcTagMembers2 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData) +void NfcTag::fillNativeNfcTagMembers2 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& /*activationData*/) { static const char fn [] = "NfcTag::fillNativeNfcTagMembers2"; ALOGD ("%s", fn); - jfieldID f = NULL; - - f = e->GetFieldID (tag_cls, "mConnectedTechIndex", "I"); - e->SetIntField (tag, f, (jint) 0); + jfieldID f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I"); + e->SetIntField(tag, f, (jint) 0); } @@ -646,9 +636,9 @@ void NfcTag::fillNativeNfcTagMembers2 (JNIEnv* e, jclass tag_cls, jobject tag, t void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData) { static const char fn [] = "NfcTag::fillNativeNfcTagMembers3"; - jfieldID f = NULL; - jbyteArray pollBytes = e->NewByteArray (0); - jobjectArray techPollBytes = e->NewObjectArray (mNumTechList, e->GetObjectClass(pollBytes), 0); + ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0)); + ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get())); + ScopedLocalRef<jobjectArray> techPollBytes(e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0)); int len = 0; for (int i = 0; i < mNumTechList; i++) @@ -661,9 +651,8 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t case NFC_DISCOVERY_TYPE_LISTEN_A: case NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE: ALOGD ("%s: tech A", fn); - pollBytes = e->NewByteArray (2); - e->SetByteArrayRegion (pollBytes, 0, 2, - (jbyte*) mTechParams [i].param.pa.sens_res); + pollBytes.reset(e->NewByteArray(2)); + e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*) mTechParams [i].param.pa.sens_res); break; case NFC_DISCOVERY_TYPE_POLL_B: @@ -680,11 +669,11 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t ALOGD ("%s: tech B; TARGET_TYPE_ISO14443_3B", fn); len = mTechParams [i].param.pb.sensb_res_len; len = len - 4; //subtract 4 bytes for NFCID0 at byte 2 through 5 - pollBytes = e->NewByteArray (len); - e->SetByteArrayRegion (pollBytes, 0, len, (jbyte*) (mTechParams [i].param.pb.sensb_res+4)); + pollBytes.reset(e->NewByteArray(len)); + e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*) (mTechParams [i].param.pb.sensb_res+4)); + } else { + pollBytes.reset(e->NewByteArray(0)); } - else - pollBytes = e->NewByteArray (0); break; case NFC_DISCOVERY_TYPE_POLL_F: @@ -718,9 +707,9 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t result [9] = (UINT8) systemCode; ALOGD ("%s: tech F; sys code=0x%X 0x%X", fn, result [8], result [9]); } - pollBytes = e->NewByteArray (len); - e->SetByteArrayRegion (pollBytes, 0, len, (jbyte*) result); - } + pollBytes.reset(e->NewByteArray(len)); + e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*) result); + } break; case NFC_DISCOVERY_TYPE_POLL_ISO15693: @@ -731,20 +720,20 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t //iso 15693 Data Structure Format Identifier (DSF ID): 1 octet //used by public API: NfcV.getDsfId(), NfcV.getResponseFlags(); uint8_t data [2]= {activationData.params.i93.afi, activationData.params.i93.dsfid}; - pollBytes = e->NewByteArray (2); - e->SetByteArrayRegion (pollBytes, 0, 2, (jbyte *) data); + pollBytes.reset(e->NewByteArray(2)); + e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte *) data); } break; default: ALOGE ("%s: tech unknown ????", fn); - pollBytes = e->NewByteArray(0); + pollBytes.reset(e->NewByteArray(0)); break; } //switch: every type of technology - e->SetObjectArrayElement (techPollBytes, i, pollBytes); + e->SetObjectArrayElement(techPollBytes.get(), i, pollBytes.get()); } //for: every technology in the array - f = e->GetFieldID (tag_cls, "mTechPollBytes", "[[B"); - e->SetObjectField (tag, f, techPollBytes); + jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B"); + e->SetObjectField(tag, f, techPollBytes.get()); } @@ -766,11 +755,9 @@ void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, t void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData) { static const char fn [] = "NfcTag::fillNativeNfcTagMembers4"; - jfieldID f = NULL; - jbyteArray actBytes = e->NewByteArray (0); - jobjectArray techActBytes = e->NewObjectArray (mNumTechList, e->GetObjectClass(actBytes), 0); - jbyteArray uid = NULL; - int len = 0; + ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0)); + ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get())); + ScopedLocalRef<jobjectArray> techActBytes(e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0)); for (int i = 0; i < mNumTechList; i++) { @@ -780,18 +767,16 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t case NFC_PROTOCOL_T1T: { ALOGD ("%s: T1T; tech A", fn); - actBytes = e->NewByteArray (1); - e->SetByteArrayRegion (actBytes, 0, 1, - (jbyte*) &mTechParams [i].param.pa.sel_rsp); + actBytes.reset(e->NewByteArray(1)); + e->SetByteArrayRegion(actBytes.get(), 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp); } break; - case NFC_PROTOCOL_T2T: + case NFC_PROTOCOL_T2T: // TODO: why is this code a duplicate of NFC_PROTOCOL_T1T? { ALOGD ("%s: T2T; tech A", fn); - actBytes = e->NewByteArray (1); - e->SetByteArrayRegion (actBytes, 0, 1, - (jbyte*) &mTechParams [i].param.pa.sel_rsp); + actBytes.reset(e->NewByteArray(1)); + e->SetByteArrayRegion(actBytes.get(), 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp); } break; @@ -799,7 +784,7 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t { ALOGD ("%s: T3T; felica; tech F", fn); //really, there is no data - actBytes = e->NewByteArray (0); + actBytes.reset(e->NewByteArray(0)); } break; @@ -819,14 +804,14 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t { tNFC_INTF_PA_ISO_DEP& pa_iso = activationData.activate_ntf.intf_param.intf_param.pa_iso; ALOGD ("%s: T4T; ISO_DEP for tech A; copy historical bytes; len=%u", fn, pa_iso.his_byte_len); - actBytes = e->NewByteArray (pa_iso.his_byte_len); + actBytes.reset(e->NewByteArray(pa_iso.his_byte_len)); if (pa_iso.his_byte_len > 0) - e->SetByteArrayRegion (actBytes, 0, pa_iso.his_byte_len, (jbyte*) (pa_iso.his_byte)); + e->SetByteArrayRegion(actBytes.get(), 0, pa_iso.his_byte_len, (jbyte*) (pa_iso.his_byte)); } else { ALOGE ("%s: T4T; ISO_DEP for tech A; wrong interface=%u", fn, activationData.activate_ntf.intf_param.type); - actBytes = e->NewByteArray (0); + actBytes.reset(e->NewByteArray(0)); } } else if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B) || @@ -841,26 +826,26 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t { tNFC_INTF_PB_ISO_DEP& pb_iso = activationData.activate_ntf.intf_param.intf_param.pb_iso; ALOGD ("%s: T4T; ISO_DEP for tech B; copy response bytes; len=%u", fn, pb_iso.hi_info_len); - actBytes = e->NewByteArray (pb_iso.hi_info_len); + actBytes.reset(e->NewByteArray(pb_iso.hi_info_len)); if (pb_iso.hi_info_len > 0) - e->SetByteArrayRegion (actBytes, 0, pb_iso.hi_info_len, (jbyte*) (pb_iso.hi_info)); + e->SetByteArrayRegion(actBytes.get(), 0, pb_iso.hi_info_len, (jbyte*) (pb_iso.hi_info)); } else { ALOGE ("%s: T4T; ISO_DEP for tech B; wrong interface=%u", fn, activationData.activate_ntf.intf_param.type); - actBytes = e->NewByteArray (0); + actBytes.reset(e->NewByteArray(0)); } } } else if (mTechList [i] == TARGET_TYPE_ISO14443_3A) //is TagTechnology.NFC_A by Java API { ALOGD ("%s: T4T; tech A", fn); - actBytes = e->NewByteArray (1); - e->SetByteArrayRegion (actBytes, 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp); + actBytes.reset(e->NewByteArray(1)); + e->SetByteArrayRegion(actBytes.get(), 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp); } else { - actBytes = e->NewByteArray (0); + actBytes.reset(e->NewByteArray(0)); } } //case NFC_PROTOCOL_ISO_DEP: //t4t break; @@ -872,20 +857,20 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t //iso 15693 Data Structure Format Identifier (DSF ID): 1 octet //used by public API: NfcV.getDsfId(), NfcV.getResponseFlags(); uint8_t data [2]= {activationData.params.i93.afi, activationData.params.i93.dsfid}; - actBytes = e->NewByteArray (2); - e->SetByteArrayRegion (actBytes, 0, 2, (jbyte *) data); + actBytes.reset(e->NewByteArray(2)); + e->SetByteArrayRegion(actBytes.get(), 0, 2, (jbyte *) data); } break; default: ALOGD ("%s: tech unknown ????", fn); - actBytes = e->NewByteArray (0); + actBytes.reset(e->NewByteArray(0)); break; }//switch - e->SetObjectArrayElement (techActBytes, i, actBytes); + e->SetObjectArrayElement(techActBytes.get(), i, actBytes.get()); } //for: every technology in the array - f = e->GetFieldID (tag_cls, "mTechActBytes", "[[B"); - e->SetObjectField (tag, f, techActBytes); + jfieldID f = e->GetFieldID (tag_cls, "mTechActBytes", "[[B"); + e->SetObjectField(tag, f, techActBytes.get()); } @@ -907,17 +892,16 @@ void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, t void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData) { static const char fn [] = "NfcTag::fillNativeNfcTagMembers5"; - jfieldID f = NULL; int len = 0; - jbyteArray uid = NULL; + ScopedLocalRef<jbyteArray> uid(e, NULL); switch (mTechParams [0].mode) { case NFC_DISCOVERY_TYPE_POLL_KOVIO: ALOGD ("%s: Kovio", fn); len = mTechParams [0].param.pk.uid_len; - uid = e->NewByteArray (len); - e->SetByteArrayRegion (uid, 0, len, + uid.reset(e->NewByteArray(len)); + e->SetByteArrayRegion(uid.get(), 0, len, (jbyte*) &mTechParams [0].param.pk.uid); break; @@ -927,8 +911,8 @@ void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, t case NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE: ALOGD ("%s: tech A", fn); len = mTechParams [0].param.pa.nfcid1_len; - uid = e->NewByteArray (len); - e->SetByteArrayRegion (uid, 0, len, + uid.reset(e->NewByteArray(len)); + e->SetByteArrayRegion(uid.get(), 0, len, (jbyte*) &mTechParams [0].param.pa.nfcid1); break; @@ -937,8 +921,8 @@ void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, t case NFC_DISCOVERY_TYPE_LISTEN_B: case NFC_DISCOVERY_TYPE_LISTEN_B_PRIME: ALOGD ("%s: tech B", fn); - uid = e->NewByteArray (NFC_NFCID0_MAX_LEN); - e->SetByteArrayRegion (uid, 0, NFC_NFCID0_MAX_LEN, + uid.reset(e->NewByteArray(NFC_NFCID0_MAX_LEN)); + e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID0_MAX_LEN, (jbyte*) &mTechParams [0].param.pb.nfcid0); break; @@ -947,8 +931,8 @@ void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, t case NFC_DISCOVERY_TYPE_LISTEN_F: case NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE: ALOGD ("%s: tech F", fn); - uid = e->NewByteArray (NFC_NFCID2_LEN); - e->SetByteArrayRegion (uid, 0, NFC_NFCID2_LEN, + uid.reset(e->NewByteArray(NFC_NFCID2_LEN)); + e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID2_LEN, (jbyte*) &mTechParams [0].param.pf.nfcid2); break; @@ -959,18 +943,18 @@ void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, t jbyte data [I93_UID_BYTE_LEN]; //8 bytes for (int i=0; i<I93_UID_BYTE_LEN; ++i) //reverse the ID data[i] = activationData.params.i93.uid [I93_UID_BYTE_LEN - i - 1]; - uid = e->NewByteArray (I93_UID_BYTE_LEN); - e->SetByteArrayRegion (uid, 0, I93_UID_BYTE_LEN, data); + uid.reset(e->NewByteArray(I93_UID_BYTE_LEN)); + e->SetByteArrayRegion(uid.get(), 0, I93_UID_BYTE_LEN, data); } break; default: ALOGE ("%s: tech unknown ????", fn); - uid = e->NewByteArray (0); + uid.reset(e->NewByteArray(0)); break; - } //if - f = e->GetFieldID(tag_cls, "mUid", "[B"); - e->SetObjectField(tag, f, uid); + } + jfieldID f = e->GetFieldID(tag_cls, "mUid", "[B"); + e->SetObjectField(tag, f, uid.get()); } @@ -1322,4 +1306,3 @@ void NfcTag::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* data) } } } - diff --git a/nci/jni/PeerToPeer.cpp b/nci/jni/PeerToPeer.cpp index b40e3663..087cd7ad 100644 --- a/nci/jni/PeerToPeer.cpp +++ b/nci/jni/PeerToPeer.cpp @@ -23,6 +23,16 @@ #include "llcp_defs.h" #include "config.h" #include "JavaClassConstants.h" +#include <ScopedLocalRef.h> + +/* Some older PN544-based solutions would only send the first SYMM back + * (as an initiator) after the full LTO (750ms). But our connect timer + * starts immediately, and hence we may timeout if the timer is set to + * 1000 ms. Worse, this causes us to immediately connect to the NPP + * socket, causing concurrency issues in that stack. Increase the default + * timeout to 2000 ms, giving us enough time to complete the first connect. + */ +#define LLCP_DATA_LINK_TIMEOUT 2000 using namespace android; @@ -55,7 +65,6 @@ PeerToPeer::PeerToPeer () | NFA_TECHNOLOGY_MASK_F_ACTIVE), mNextJniHandle (1) { - unsigned long num = 0; memset (mServers, 0, sizeof(mServers)); memset (mClients, 0, sizeof(mClients)); } @@ -202,9 +211,7 @@ bool PeerToPeer::registerServer (tJNI_HANDLE jniHandle, const char *serviceName) { static const char fn [] = "PeerToPeer::registerServer"; ALOGD ("%s: enter; service name: %s JNI handle: %u", fn, serviceName, jniHandle); - tNFA_STATUS stat = NFA_STATUS_OK; sp<P2pServer> pSrv = NULL; - UINT8 serverSap = NFA_P2P_ANY_SAP; mMutex.lock(); // Check if already registered @@ -293,18 +300,14 @@ void PeerToPeer::llcpActivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_ACTIV { static const char fn [] = "PeerToPeer::llcpActivatedHandler"; ALOGD ("%s: enter", fn); - JNIEnv* e = NULL; - jclass tag_cls = NULL; - jobject tag = NULL; - jmethodID ctor = 0; - jfieldID f = 0; //no longer need to receive NDEF message from a tag android::nativeNfcTag_deregisterNdefTypeHandler (); mRemoteWKS = activated.remote_wks; - nat->vm->AttachCurrentThread (&e, NULL); + JNIEnv* e = NULL; + ScopedAttach attach(nat->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -312,57 +315,47 @@ void PeerToPeer::llcpActivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_ACTIV } ALOGD ("%s: get object class", fn); - tag_cls = e->GetObjectClass (nat->cached_P2pDevice); - if (e->ExceptionCheck()) - { + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_P2pDevice)); + if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: fail get p2p device", fn); - goto TheEnd; + return; } ALOGD ("%s: instantiate", fn); /* New target instance */ - ctor = e->GetMethodID (tag_cls, "<init>", "()V"); - tag = e->NewObject (tag_cls, ctor); + jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); + ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor)); /* Set P2P Target mode */ - f = e->GetFieldID (tag_cls, "mMode", "I"); + jfieldID f = e->GetFieldID(tag_cls.get(), "mMode", "I"); - if (activated.is_initiator == TRUE) - { + if (activated.is_initiator == TRUE) { ALOGD ("%s: p2p initiator", fn); - e->SetIntField (tag, f, (jint) MODE_P2P_INITIATOR); - } - else - { + e->SetIntField(tag.get(), f, (jint) MODE_P2P_INITIATOR); + } else { ALOGD ("%s: p2p target", fn); - e->SetIntField (tag, f, (jint) MODE_P2P_TARGET); + e->SetIntField(tag.get(), f, (jint) MODE_P2P_TARGET); } /* Set tag handle */ - f = e->GetFieldID (tag_cls, "mHandle", "I"); - e->SetIntField (tag, f, (jint) 0x1234); // ?? This handle is not used for anything + f = e->GetFieldID(tag_cls.get(), "mHandle", "I"); + e->SetIntField(tag.get(), f, (jint) 0x1234); // ?? This handle is not used for anything - if (nat->tag != NULL) - { - e->DeleteGlobalRef (nat->tag); + if (nat->tag != NULL) { + e->DeleteGlobalRef(nat->tag); } - nat->tag = e->NewGlobalRef (tag); + nat->tag = e->NewGlobalRef(tag.get()); ALOGD ("%s: notify nfc service", fn); /* Notify manager that new a P2P device was found */ - e->CallVoidMethod (nat->manager, android::gCachedNfcManagerNotifyLlcpLinkActivation, tag); - if (e->ExceptionCheck()) - { + e->CallVoidMethod(nat->manager, android::gCachedNfcManagerNotifyLlcpLinkActivation, tag.get()); + if (e->ExceptionCheck()) { e->ExceptionClear(); ALOGE ("%s: fail notify", fn); } - e->DeleteLocalRef (tag); - -TheEnd: - nat->vm->DetachCurrentThread (); ALOGD ("%s: exit", fn); } @@ -378,13 +371,13 @@ TheEnd: ** Returns: None ** *******************************************************************************/ -void PeerToPeer::llcpDeactivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_DEACTIVATED& deactivated) +void PeerToPeer::llcpDeactivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_DEACTIVATED& /*deactivated*/) { static const char fn [] = "PeerToPeer::llcpDeactivatedHandler"; ALOGD ("%s: enter", fn); - JNIEnv* e = NULL; - nat->vm->AttachCurrentThread (&e, NULL); + JNIEnv* e = NULL; + ScopedAttach attach(nat->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -400,14 +393,36 @@ void PeerToPeer::llcpDeactivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_DEA ALOGE ("%s: fail notify", fn); } - nat->vm->DetachCurrentThread (); - //let the tag-reading code handle NDEF data event android::nativeNfcTag_registerNdefTypeHandler (); ALOGD ("%s: exit", fn); } +void PeerToPeer::llcpFirstPacketHandler (nfc_jni_native_data* nat) +{ + static const char fn [] = "PeerToPeer::llcpFirstPacketHandler"; + ALOGD ("%s: enter", fn); + JNIEnv* e = NULL; + ScopedAttach attach(nat->vm, &e); + if (e == NULL) + { + ALOGE ("%s: jni env is null", fn); + return; + } + + ALOGD ("%s: notify nfc service", fn); + /* Notify manager that the LLCP is lost or deactivated */ + e->CallVoidMethod (nat->manager, android::gCachedNfcManagerNotifyLlcpFirstPacketReceived, nat->tag); + if (e->ExceptionCheck()) + { + e->ExceptionClear(); + ALOGE ("%s: fail notify", fn); + } + + ALOGD ("%s: exit", fn); + +} /******************************************************************************* ** ** Function: accept @@ -424,10 +439,6 @@ void PeerToPeer::llcpDeactivatedHandler (nfc_jni_native_data* nat, tNFA_LLCP_DEA bool PeerToPeer::accept (tJNI_HANDLE serverJniHandle, tJNI_HANDLE connJniHandle, int maxInfoUnit, int recvWindow) { static const char fn [] = "PeerToPeer::accept"; - tNFA_STATUS nfaStat = NFA_STATUS_FAILED; - sp<NfaConn> *pConn = NULL; - bool stat = false; - int ii = 0; sp<P2pServer> pSrv = NULL; ALOGD ("%s: enter; server jni handle: %u; conn jni handle: %u; maxInfoUnit: %d; recvWindow: %d", fn, @@ -565,11 +576,10 @@ bool PeerToPeer::createClient (tJNI_HANDLE jniHandle, UINT16 miu, UINT8 rw) void PeerToPeer::removeConn(tJNI_HANDLE jniHandle) { static const char fn[] = "PeerToPeer::removeConn"; - int ii = 0, jj = 0; AutoMutex mutex(mMutex); // If the connection is a for a client, delete the client itself - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if ((mClients[ii] != NULL) && (mClients[ii]->mClientConn->mJniHandle == jniHandle)) { @@ -583,7 +593,7 @@ void PeerToPeer::removeConn(tJNI_HANDLE jniHandle) } // If the connection is for a server, just delete the connection - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if (mServers[ii] != NULL) { @@ -781,11 +791,9 @@ sp<P2pClient> PeerToPeer::findClientCon (tNFA_HANDLE nfaConnHandle) *******************************************************************************/ sp<NfaConn> PeerToPeer::findConnection (tNFA_HANDLE nfaConnHandle) { - int ii = 0, jj = 0; - AutoMutex mutex(mMutex); // First, look through all the client control blocks - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if ( (mClients[ii] != NULL) && (mClients[ii]->mClientConn->mNfaConnHandle == nfaConnHandle) ) { @@ -794,7 +802,7 @@ sp<NfaConn> PeerToPeer::findConnection (tNFA_HANDLE nfaConnHandle) } // Not found yet. Look through all the server control blocks - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if (mServers[ii] != NULL) { @@ -822,11 +830,9 @@ sp<NfaConn> PeerToPeer::findConnection (tNFA_HANDLE nfaConnHandle) *******************************************************************************/ sp<NfaConn> PeerToPeer::findConnection (tJNI_HANDLE jniHandle) { - int ii = 0, jj = 0; - AutoMutex mutex(mMutex); // First, look through all the client control blocks - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if ( (mClients[ii] != NULL) && (mClients[ii]->mClientConn->mJniHandle == jniHandle) ) { @@ -835,7 +841,7 @@ sp<NfaConn> PeerToPeer::findConnection (tJNI_HANDLE jniHandle) } // Not found yet. Look through all the server control blocks - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if (mServers[ii] != NULL) { @@ -1142,7 +1148,6 @@ void PeerToPeer::handleNfcOnOff (bool isOn) { static const char fn [] = "PeerToPeer::handleNfcOnOff"; ALOGD ("%s: enter; is on=%u", fn, isOn); - tNFA_STATUS stat = NFA_STATUS_FAILED; mIsP2pListening = false; // In both cases, P2P will not be listening @@ -1155,10 +1160,8 @@ void PeerToPeer::handleNfcOnOff (bool isOn) } else { - int ii = 0, jj = 0; - // Disconnect through all the clients - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if (mClients[ii] != NULL) { @@ -1183,7 +1186,7 @@ void PeerToPeer::handleNfcOnOff (bool isOn) } //loop // Now look through all the server control blocks - for (ii = 0; ii < sMax; ii++) + for (size_t ii = 0; ii < sMax; ii++) { if (mServers[ii] != NULL) { @@ -1515,7 +1518,7 @@ void PeerToPeer::nfaClientCallback (tNFA_P2P_EVT p2pEvent, tNFA_P2P_EVT_DATA* ev ** Returns: None ** *******************************************************************************/ -void PeerToPeer::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* eventData) +void PeerToPeer::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* /*eventData*/) { switch (event) { @@ -1597,7 +1600,7 @@ bool P2pServer::registerWithStack() 0, //use 0 for infinite timeout for symmetry procedure when acting as initiator 0, //use 0 for infinite timeout for symmetry procedure when acting as target LLCP_DELAY_RESP_TIME, - LLCP_DATA_LINK_CONNECTION_TOUT, + LLCP_DATA_LINK_TIMEOUT, LLCP_DELAY_TIME_TO_SEND_FIRST_PDU); if (stat != NFA_STATUS_OK) ALOGE ("%s: fail set LLCP config; error=0x%X", fn, stat); @@ -1837,4 +1840,3 @@ NfaConn::NfaConn() mRemoteRecvWindow (0) { } - diff --git a/nci/jni/PeerToPeer.h b/nci/jni/PeerToPeer.h index 3e8ffec0..11733f3e 100644 --- a/nci/jni/PeerToPeer.h +++ b/nci/jni/PeerToPeer.h @@ -26,7 +26,6 @@ extern "C" { #include "nfa_p2p_api.h" - #include "nfa_snep_api.h" } class P2pServer; @@ -121,6 +120,7 @@ public: *******************************************************************************/ void llcpDeactivatedHandler (nfc_jni_native_data* nativeData, tNFA_LLCP_DEACTIVATED& deactivated); + void llcpFirstPacketHandler(nfc_jni_native_data* nativeData); /******************************************************************************* ** @@ -393,19 +393,6 @@ private: Mutex mDisconnectMutex; // synchronize the disconnect operation Mutex mNewJniHandleMutex; // synchronize the creation of a new JNI handle - /******************************************************************************* - ** - ** Function: snepClientCallback - ** - ** Description: Receive SNEP-related events from the stack. - ** snepEvent: Event code. - ** eventData: Event data. - ** - ** Returns: None - ** - *******************************************************************************/ - static void snepClientCallback (tNFA_SNEP_EVT snepEvent, tNFA_SNEP_EVT_DATA *eventData); - /******************************************************************************* ** diff --git a/nci/jni/RouteDataSet.cpp b/nci/jni/RouteDataSet.cpp index 1458776b..e0a918f8 100644 --- a/nci/jni/RouteDataSet.cpp +++ b/nci/jni/RouteDataSet.cpp @@ -528,6 +528,7 @@ void RouteDataSet::printDiagnostic () ALOGD ("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol); } break; + // TODO: RouteData::TechnologyRoute isn't handled --- bug? } } diff --git a/nci/jni/SecureElement.cpp b/nci/jni/SecureElement.cpp index a4c4d57e..101bd38c 100755 --- a/nci/jni/SecureElement.cpp +++ b/nci/jni/SecureElement.cpp @@ -20,6 +20,7 @@ */ #include <semaphore.h> #include <errno.h> +#include <ScopedLocalRef.h> #include "OverrideLog.h" #include "SecureElement.h" #include "config.h" @@ -40,6 +41,7 @@ bool gUseStaticPipe = false; // if true, use gGatePipe as static pipe id. if namespace android { extern void startRfDiscovery (bool isStart); + extern void setUiccIdleTimeout (bool enable); } ////////////////////////////////////////////// @@ -149,7 +151,6 @@ bool SecureElement::initialize (nfc_jni_native_data* native) { static const char fn [] = "SecureElement::initialize"; tNFA_STATUS nfaStat; - UINT8 xx = 0, yy = 0; unsigned long num = 0; ALOGD ("%s: enter", fn); @@ -177,6 +178,8 @@ bool SecureElement::initialize (nfc_jni_native_data* native) mbNewEE = true; mNewPipeId = 0; mNewSourceGate = 0; + mRfFieldIsOn = false; + mActivatedInListenMode = false; mCurrentRouteSelection = NoRoute; memset (mEeInfo, 0, sizeof(mEeInfo)); memset (&mUiccInfo, 0, sizeof(mUiccInfo)); @@ -201,7 +204,7 @@ bool SecureElement::initialize (nfc_jni_native_data* native) } // If the controller has an HCI Network, register for that - for (xx = 0; xx < mActualNumEe; xx++) + for (size_t xx = 0; xx < mActualNumEe; xx++) { if ((mEeInfo[xx].num_interface > 0) && (mEeInfo[xx].ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS) ) { @@ -245,7 +248,6 @@ void SecureElement::finalize () { static const char fn [] = "SecureElement::finalize"; ALOGD ("%s: enter", fn); - tNFA_STATUS nfaStat = NFA_STATUS_FAILED; NFA_EeDeregister (nfaEeCallback); @@ -281,7 +283,6 @@ bool SecureElement::getEeInfo() static const char fn [] = "SecureElement::getEeInfo"; ALOGD ("%s: enter; mbNewEE=%d, mActualNumEe=%d", fn, mbNewEE, mActualNumEe); tNFA_STATUS nfaStat = NFA_STATUS_FAILED; - UINT8 xx = 0, yy = 0; // If mbNewEE is true then there is new EE info. if (mbNewEE) @@ -309,7 +310,7 @@ bool SecureElement::getEeInfo() fn, xx, mEeInfo[xx].ee_handle, eeStatusToString(mEeInfo[xx].ee_status), mEeInfo[xx].num_interface, mEeInfo[xx].ee_interface[0], mEeInfo[xx].ee_interface[1], mEeInfo[xx].num_tlvs); - for (yy = 0; yy < mEeInfo[xx].num_tlvs; yy++) + for (size_t yy = 0; yy < mEeInfo[xx].num_tlvs; yy++) { ALOGD ("%s: EE[%u] TLV[%u] Tag: 0x%02x Len: %u Values[]: 0x%02x 0x%02x 0x%02x ...", fn, xx, yy, mEeInfo[xx].ee_tlv[yy].tag, mEeInfo[xx].ee_tlv[yy].len, mEeInfo[xx].ee_tlv[yy].info[0], @@ -404,7 +405,6 @@ jintArray SecureElement::getListOfEeHandles (JNIEnv* e) ALOGD ("%s: enter", fn); if (mNumEePresent == 0) return NULL; - jintArray list = NULL; if (!mIsInit) { @@ -416,7 +416,7 @@ jintArray SecureElement::getListOfEeHandles (JNIEnv* e) if (! getEeInfo()) return (NULL); - list = e->NewIntArray (mNumEePresent); //allocate array + jintArray list = e->NewIntArray (mNumEePresent); //allocate array jint jj = 0; int cnt = 0; for (int ii = 0; ii < mActualNumEe && cnt < mNumEePresent; ii++) @@ -430,7 +430,6 @@ jintArray SecureElement::getListOfEeHandles (JNIEnv* e) jj = mEeInfo[ii].ee_handle & ~NFA_HANDLE_GROUP_EE; e->SetIntArrayRegion (list, cnt++, 1, &jj); } - //e->DeleteLocalRef (list); ALOGD("%s: exit", fn); return list; @@ -537,8 +536,6 @@ bool SecureElement::activate (jint seID) bool SecureElement::deactivate (jint seID) { static const char fn [] = "SecureElement::deactivate"; - tNFA_STATUS nfaStat = NFA_STATUS_FAILED; - int numDeactivatedEe = 0; bool retval = false; ALOGD ("%s: enter; seID=0x%X, mActiveEeHandle=0x%X", fn, seID, mActiveEeHandle); @@ -588,41 +585,37 @@ void SecureElement::notifyTransactionListenersOfAid (const UINT8* aidBuffer, UIN static const char fn [] = "SecureElement::notifyTransactionListenersOfAid"; ALOGD ("%s: enter; aid len=%u", fn, aidBufferLen); - if (aidBufferLen == 0) - return; + if (aidBufferLen == 0) { + return; + } - jobject tlvJavaArray = NULL; JNIEnv* e = NULL; - UINT8* tlv = 0; - const UINT16 tlvMaxLen = aidBufferLen + 10; - UINT16 tlvActualLen = 0; - bool stat = false; - - mNativeData->vm->AttachCurrentThread (&e, NULL); + ScopedAttach attach(mNativeData->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); return; } - tlv = new UINT8 [tlvMaxLen]; + const UINT16 tlvMaxLen = aidBufferLen + 10; + UINT8* tlv = new UINT8 [tlvMaxLen]; if (tlv == NULL) { ALOGE ("%s: fail allocate tlv", fn); - goto TheEnd; + return; } memcpy (tlv, aidBuffer, aidBufferLen); - tlvActualLen = aidBufferLen; + UINT16 tlvActualLen = aidBufferLen; - tlvJavaArray = e->NewByteArray (tlvActualLen); - if (tlvJavaArray == NULL) + ScopedLocalRef<jobject> tlvJavaArray(e, e->NewByteArray(tlvActualLen)); + if (tlvJavaArray.get() == NULL) { ALOGE ("%s: fail allocate array", fn); goto TheEnd; } - e->SetByteArrayRegion ((jbyteArray)tlvJavaArray, 0, tlvActualLen, (jbyte *)tlv); + e->SetByteArrayRegion ((jbyteArray)tlvJavaArray.get(), 0, tlvActualLen, (jbyte *)tlv); if (e->ExceptionCheck()) { e->ExceptionClear(); @@ -630,7 +623,7 @@ void SecureElement::notifyTransactionListenersOfAid (const UINT8* aidBuffer, UIN goto TheEnd; } - e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyTransactionListeners, tlvJavaArray); + e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyTransactionListeners, tlvJavaArray.get()); if (e->ExceptionCheck()) { e->ExceptionClear(); @@ -639,9 +632,6 @@ void SecureElement::notifyTransactionListenersOfAid (const UINT8* aidBuffer, UIN } TheEnd: - if (tlvJavaArray) - e->DeleteLocalRef (tlvJavaArray); - mNativeData->vm->DetachCurrentThread (); delete [] tlv; ALOGD ("%s: exit", fn); } @@ -698,6 +688,9 @@ bool SecureElement::connectEE () // Disable RF discovery completely while the DH is connected android::startRfDiscovery(false); + // Disable UICC idle timeout while the DH is connected + android::setUiccIdleTimeout (false); + mNewSourceGate = 0; if (gGatePipe == -1) @@ -878,12 +871,17 @@ bool SecureElement::disconnectEE (jint seID) else ALOGE ("%s: fail dealloc gate; error=0x%X", fn, nfaStat); } + mIsPiping = false; + + // Re-enable UICC low-power mode + android::setUiccIdleTimeout (true); // Re-enable RF discovery // Note that it only effactuates the current configuration, // so if polling/listening were configured OFF (forex because // the screen was off), they will stay OFF with this call. android::startRfDiscovery(true); + return true; } @@ -1007,11 +1005,11 @@ TheEnd: *******************************************************************************/ 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); + JNIEnv* e = NULL; + ScopedAttach attach(mNativeData->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -1032,7 +1030,6 @@ void SecureElement::notifyListenModeState (bool isActivated) { ALOGE ("%s: fail notify", fn); } - mNativeData->vm->DetachCurrentThread (); ALOGD ("%s: exit", fn); } @@ -1049,11 +1046,10 @@ void SecureElement::notifyListenModeState (bool isActivated) { void SecureElement::notifyRfFieldEvent (bool isActive) { static const char fn [] = "SecureElement::notifyRfFieldEvent"; - JNIEnv *e = NULL; - ALOGD ("%s: enter; is active=%u", fn, isActive); - mNativeData->vm->AttachCurrentThread (&e, NULL); + JNIEnv* e = NULL; + ScopedAttach attach(mNativeData->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -1081,7 +1077,33 @@ void SecureElement::notifyRfFieldEvent (bool isActive) e->ExceptionClear(); ALOGE ("%s: fail notify", fn); } - mNativeData->vm->DetachCurrentThread (); + ALOGD ("%s: exit", fn); +} + +/******************************************************************************* +** +** Function: resetRfFieldStatus +** +** Description: Resets the field status. +** isActive: Whether any secure element is activated. +** +** Returns: None +** +*******************************************************************************/ +void SecureElement::resetRfFieldStatus () +{ + static const char fn [] = "SecureElement::resetRfFieldStatus`"; + ALOGD ("%s: enter;"); + + mMutex.lock(); + mRfFieldIsOn = false; + int ret = clock_gettime (CLOCK_MONOTONIC, &mLastRfFieldToggle); + if (ret == -1) { + ALOGE("%s: clock_gettime failed", fn); + // There is no good choice here... + } + mMutex.unlock(); + ALOGD ("%s: exit", fn); } @@ -1134,9 +1156,9 @@ bool SecureElement::getUiccId (tNFA_HANDLE eeHandle, jbyteArray& uid) static const char fn [] = "SecureElement::getUiccId"; ALOGD ("%s: ee h=0x%X", fn, eeHandle); bool retval = false; - JNIEnv* e = NULL; - mNativeData->vm->AttachCurrentThread (&e, NULL); + JNIEnv* e = NULL; + ScopedAttach attach(mNativeData->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -1146,8 +1168,9 @@ bool SecureElement::getUiccId (tNFA_HANDLE eeHandle, jbyteArray& uid) findUiccByHandle (eeHandle); //cannot get UID from the stack; nothing to do -TheEnd: - mNativeData->vm->DetachCurrentThread (); + // TODO: uid is unused --- bug? + + // TODO: retval is always false --- bug? ALOGD ("%s: exit; ret=%u", fn, retval); return retval; } @@ -1169,10 +1192,9 @@ bool SecureElement::getTechnologyList (tNFA_HANDLE eeHandle, jintArray& techList static const char fn [] = "SecureElement::getTechnologyList"; ALOGD ("%s: ee h=0x%X", fn, eeHandle); bool retval = false; - JNIEnv* e = NULL; - jint theList = 0; - mNativeData->vm->AttachCurrentThread (&e, NULL); + JNIEnv* e = NULL; + ScopedAttach attach(mNativeData->vm, &e); if (e == NULL) { ALOGE ("%s: jni env is null", fn); @@ -1181,6 +1203,8 @@ bool SecureElement::getTechnologyList (tNFA_HANDLE eeHandle, jintArray& techList tNFA_EE_DISCOVER_INFO *pUICC = findUiccByHandle (eeHandle); + // TODO: theList is written but not set --- bug? + jint theList = 0; if (pUICC->la_protocol != 0) theList = TARGET_TYPE_ISO14443_3A; else if (pUICC->lb_protocol != 0) @@ -1192,8 +1216,9 @@ bool SecureElement::getTechnologyList (tNFA_HANDLE eeHandle, jintArray& techList else theList = TARGET_TYPE_UNKNOWN; -TheEnd: - mNativeData->vm->DetachCurrentThread (); + // TODO: techList is neither read nor written --- bug? + + // TODO: retval is always false --- bug? ALOGD ("%s: exit; ret=%u", fn, retval); return retval; } @@ -1213,7 +1238,6 @@ void SecureElement::adjustRoutes (RouteSelection selection) { static const char fn [] = "SecureElement::adjustRoutes"; ALOGD ("%s: enter; selection=%u", fn, selection); - tNFA_STATUS nfaStat = NFA_STATUS_FAILED; RouteDataSet::Database* db = mRouteDataSet.getDatabase (RouteDataSet::DefaultRouteDatabase); if (selection == SecElemRoute) @@ -2035,7 +2059,7 @@ const char* SecureElement::eeStatusToString (UINT8 status) ** Returns: None ** *******************************************************************************/ -void SecureElement::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* eventData) +void SecureElement::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* /*eventData*/) { switch (event) { @@ -2176,4 +2200,3 @@ bool SecureElement::isBusy () ALOGD ("SecureElement::isBusy: %u", retval); return retval; } - diff --git a/nci/jni/SecureElement.h b/nci/jni/SecureElement.h index 1758590c..c537b2bc 100755 --- a/nci/jni/SecureElement.h +++ b/nci/jni/SecureElement.h @@ -185,6 +185,17 @@ public: /******************************************************************************* ** + ** Function: resetRfFieldStatus (); + ** + ** Description: Resets the field status. + ** + ** Returns: None + ** + *******************************************************************************/ + void resetRfFieldStatus (); + + /******************************************************************************* + ** ** Function: storeUiccInfo ** ** Description: Store a copy of the execution environment information from the stack. diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java index d045ae2a..aea5f972 100755 --- a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java +++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java @@ -359,6 +359,13 @@ public class NativeNfcManager implements DeviceHost { mListener.onLlcpLinkDeactivated(device); } + /** + * Notifies first packet received from remote LLCP + */ + private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) { + mListener.onLlcpFirstPacketReceived(device); + } + private void notifySeFieldActivated() { mListener.onRemoteFieldActivated(); } diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcTag.java b/nci/src/com/android/nfc/dhimpl/NativeNfcTag.java index eb8410f9..d0fc6d9d 100755 --- a/nci/src/com/android/nfc/dhimpl/NativeNfcTag.java +++ b/nci/src/com/android/nfc/dhimpl/NativeNfcTag.java @@ -28,6 +28,7 @@ import android.nfc.tech.NfcA; import android.nfc.tech.NfcB; import android.nfc.tech.NfcF; import android.nfc.tech.NfcV; +import android.nfc.tech.NfcBarcode; import android.nfc.tech.TagTechnology; import android.os.Bundle; import android.util.Log; @@ -702,6 +703,12 @@ public class NativeNfcTag implements TagEndpoint { break; } + case TagTechnology.NFC_BARCODE: { + // hard code this for now, this is the only valid type + extras.putInt(NfcBarcode.EXTRA_BARCODE_TYPE, NfcBarcode.TYPE_KOVIO); + break; + } + default: { // Leave the entry in the array null continue; diff --git a/nxp/jni/Android.mk b/nxp/jni/Android.mk index 8ae792a2..53d17daa 100644 --- a/nxp/jni/Android.mk +++ b/nxp/jni/Android.mk @@ -18,12 +18,14 @@ LOCAL_SRC_FILES:= \ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ external/libnfc-nxp/src \ - external/libnfc-nxp/inc + external/libnfc-nxp/inc \ + libcore/include LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libcutils \ libutils \ + liblog \ libnfc \ libhardware diff --git a/nxp/jni/com_android_nfc.cpp b/nxp/jni/com_android_nfc.cpp index c0e19935..23828564 100755 --- a/nxp/jni/com_android_nfc.cpp +++ b/nxp/jni/com_android_nfc.cpp @@ -20,6 +20,7 @@ #include "com_android_nfc.h" #include "com_android_nfc_list.h" #include "phLibNfcStatus.h" +#include <ScopedLocalRef.h> /* * JNI Initialization @@ -28,7 +29,7 @@ jint JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *e; - ALOGD("NFC Service : loading JNI\n"); + ALOGI("NFC Service: loading nxp JNI"); // Check JNI version if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) @@ -128,50 +129,35 @@ void nfc_cb_data_releaseAll() int nfc_jni_cache_object(JNIEnv *e, const char *clsname, jobject *cached_obj) { - jclass cls; - jobject obj; - jmethodID ctor; - - cls = e->FindClass(clsname); - if(cls == NULL) - { - return -1; + ScopedLocalRef<jclass> cls(e, e->FindClass(clsname)); + if (cls.get() == NULL) { ALOGD("Find class error\n"); + return -1; } - - ctor = e->GetMethodID(cls, "<init>", "()V"); - - obj = e->NewObject(cls, ctor); - if(obj == NULL) - { - return -1; + jmethodID ctor = e->GetMethodID(cls.get(), "<init>", "()V"); + ScopedLocalRef<jobject> obj(e, e->NewObject(cls.get(), ctor)); + if (obj.get() == NULL) { ALOGD("Create object error\n"); + return -1; } - *cached_obj = e->NewGlobalRef(obj); - if(*cached_obj == NULL) - { - e->DeleteLocalRef(obj); + *cached_obj = e->NewGlobalRef(obj.get()); + if (*cached_obj == NULL) { ALOGD("Global ref error\n"); return -1; } - e->DeleteLocalRef(obj); - return 0; } struct nfc_jni_native_data* nfc_jni_get_nat(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - /* Retrieve native structure address */ - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mNative", "I"); - return (struct nfc_jni_native_data*)e->GetIntField(o, f); + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mNative", "I"); + return (struct nfc_jni_native_data*) e->GetIntField(o, f); } struct nfc_jni_native_data* nfc_jni_get_nat_ext(JNIEnv *e) @@ -233,54 +219,39 @@ nfc_jni_native_monitor_t* nfc_jni_init_monitor(void) } return nfc_jni_native_monitor; -} +} nfc_jni_native_monitor_t* nfc_jni_get_monitor(void) { return nfc_jni_native_monitor; } - + phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mHandle", "I"); - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mHandle", "I"); return e->GetIntField(o, f); } jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mMode", "S"); - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mMode", "S"); return e->GetShortField(o, f); } int nfc_jni_get_connected_tech_index(JNIEnv *e, jobject o) { - - jclass c; - jfieldID f; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mConnectedTechIndex", "I"); - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mConnectedTechIndex", "I"); return e->GetIntField(o, f); } jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; int connectedTech = -1; int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o); @@ -301,62 +272,43 @@ jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o) jint nfc_jni_get_connected_technology_libnfc_type(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; jint connectedLibNfcType = -1; int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o); - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mTechLibNfcTypes", "[I"); - jintArray libNfcTypes = (jintArray) e->GetObjectField(o, f); + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mTechLibNfcTypes", "[I"); + ScopedLocalRef<jintArray> libNfcTypes(e, (jintArray) e->GetObjectField(o, f)); - if ((connectedTechIndex != -1) && (libNfcTypes != NULL) && - (connectedTechIndex < e->GetArrayLength(libNfcTypes))) { - jint* types = e->GetIntArrayElements(libNfcTypes, 0); + if ((connectedTechIndex != -1) && (libNfcTypes.get() != NULL) && + (connectedTechIndex < e->GetArrayLength(libNfcTypes.get()))) { + jint* types = e->GetIntArrayElements(libNfcTypes.get(), 0); if (types != NULL) { connectedLibNfcType = types[connectedTechIndex]; - e->ReleaseIntArrayElements(libNfcTypes, types, JNI_ABORT); + e->ReleaseIntArrayElements(libNfcTypes.get(), types, JNI_ABORT); } } return connectedLibNfcType; - } phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mConnectedHandle", "I"); - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mConnectedHandle", "I"); return e->GetIntField(o, f); } phLibNfc_Handle nfc_jni_get_nfc_socket_handle(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mHandle", "I"); - + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mHandle", "I"); return e->GetIntField(o, f); } jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o) { - jclass c; - jfieldID f; - jintArray techtypes; - - c = e->GetObjectClass(o); - f = e->GetFieldID(c, "mTechList","[I"); - - /* Read the techtypes */ - techtypes = (jintArray) e->GetObjectField(o, f); - - return techtypes; + ScopedLocalRef<jclass> c(e, e->GetObjectClass(o)); + jfieldID f = e->GetFieldID(c.get(), "mTechList","[I"); + return (jintArray) e->GetObjectField(o, f); } @@ -365,7 +317,7 @@ jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o) const char* nfc_jni_get_status_name(NFCSTATUS status) { #define STATUS_ENTRY(status) { status, #status } - + struct status_entry { NFCSTATUS code; const char *name; @@ -414,7 +366,7 @@ const char* nfc_jni_get_status_name(NFCSTATUS status) }; int i = sizeof(sNameTable)/sizeof(status_entry); - + while(i>0) { i--; @@ -453,9 +405,10 @@ int addTechIfNeeded(int *techList, int* handleList, int* typeList, int listSize, /* * Utility to get a technology tree and a corresponding handle list from a detected tag. */ -void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, - uint8_t count, jintArray* techList, jintArray* handleList, - jintArray* libnfcTypeList) +void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, uint8_t count, + ScopedLocalRef<jintArray>* techList, + ScopedLocalRef<jintArray>* handleList, + ScopedLocalRef<jintArray>* libnfcTypeList) { int technologies[MAX_NUM_TECHNOLOGIES]; int handles[MAX_NUM_TECHNOLOGIES]; @@ -558,18 +511,18 @@ void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, // Build the Java arrays if (techList != NULL) { - *techList = e->NewIntArray(index); - e->SetIntArrayRegion(*techList, 0, index, technologies); + techList->reset(e->NewIntArray(index)); + e->SetIntArrayRegion(techList->get(), 0, index, technologies); } if (handleList != NULL) { - *handleList = e->NewIntArray(index); - e->SetIntArrayRegion(*handleList, 0, index, handles); + handleList->reset(e->NewIntArray(index)); + e->SetIntArrayRegion(handleList->get(), 0, index, handles); } if (libnfcTypeList != NULL) { - *libnfcTypeList = e->NewIntArray(index); - e->SetIntArrayRegion(*libnfcTypeList, 0, index, libnfctypes); + libnfcTypeList->reset(e->NewIntArray(index)); + e->SetIntArrayRegion(libnfcTypeList->get(), 0, index, libnfctypes); } } diff --git a/nxp/jni/com_android_nfc.h b/nxp/jni/com_android_nfc.h index fcf54cff..dc8f2d37 100755 --- a/nxp/jni/com_android_nfc.h +++ b/nxp/jni/com_android_nfc.h @@ -17,10 +17,12 @@ #ifndef __COM_ANDROID_NFC_JNI_H__ #define __COM_ANDROID_NFC_JNI_H__ +#undef LOG_TAG #define LOG_TAG "NFCJNI" #include <JNIHelp.h> #include <jni.h> +#include <ScopedLocalRef.h> #include <pthread.h> #include <sys/queue.h> @@ -59,10 +61,10 @@ extern "C" { #define PROPERTY_LLCP_WKS 2 #define PROPERTY_LLCP_OPT 3 #define PROPERTY_NFC_DISCOVERY_A 4 -#define PROPERTY_NFC_DISCOVERY_B 5 +#define PROPERTY_NFC_DISCOVERY_B 5 #define PROPERTY_NFC_DISCOVERY_F 6 #define PROPERTY_NFC_DISCOVERY_15693 7 -#define PROPERTY_NFC_DISCOVERY_NCFIP 8 +#define PROPERTY_NFC_DISCOVERY_NCFIP 8 /* Error codes */ #define ERROR_BUFFER_TOO_SMALL -12 @@ -105,6 +107,15 @@ extern "C" { #define SMX_SECURE_ELEMENT_ID 11259375 + +/* These must match the EE_ERROR_ types in NfcService.java */ +#define EE_ERROR_IO -1 +#define EE_ERROR_ALREADY_OPEN -2 +#define EE_ERROR_INIT -3 +#define EE_ERROR_LISTEN_MODE -4 +#define EE_ERROR_EXT_FIELD -5 +#define EE_ERROR_NFC_DISABLED -6 + /* Maximum byte length of an AID. */ #define AID_MAXLEN 16 @@ -142,10 +153,10 @@ struct nfc_jni_native_data int discovery_modes_state[DISCOVERY_MODE_TABLE_SIZE]; phLibNfc_sADD_Cfg_t discovery_cfg; phLibNfc_Registry_Info_t registry_info; - + /* Secure Element selected */ int seId; - + /* LLCP params */ int lto; int miu; @@ -161,7 +172,7 @@ struct nfc_jni_native_data /* p2p modes */ int p2p_initiator_modes; int p2p_target_modes; - + }; typedef struct nfc_jni_native_monitor @@ -233,9 +244,10 @@ nfc_jni_native_monitor_t* nfc_jni_init_monitor(void); nfc_jni_native_monitor_t* nfc_jni_get_monitor(void); int get_technology_type(phNfc_eRemDevType_t type, uint8_t sak); -void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, - uint8_t count, jintArray* techList, jintArray* handleList, - jintArray* typeList); +void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, uint8_t count, + ScopedLocalRef<jintArray>* techList, + ScopedLocalRef<jintArray>* handleList, + ScopedLocalRef<jintArray>* typeList); /* P2P */ phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o); diff --git a/nxp/jni/com_android_nfc_NativeLlcpServiceSocket.cpp b/nxp/jni/com_android_nfc_NativeLlcpServiceSocket.cpp index 2fccfc9c..406079c8 100644 --- a/nxp/jni/com_android_nfc_NativeLlcpServiceSocket.cpp +++ b/nxp/jni/com_android_nfc_NativeLlcpServiceSocket.cpp @@ -16,6 +16,7 @@ #include <semaphore.h> #include <errno.h> +#include <ScopedLocalRef.h> #include "com_android_nfc.h" @@ -73,7 +74,7 @@ static jobject com_NativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint m phLibNfc_Llcp_sSocketOptions_t sOptions; phNfc_sData_t sWorkingBuffer; jfieldID f; - jclass clsNativeLlcpSocket; + ScopedLocalRef<jclass> clsNativeLlcpSocket(e, NULL); jobject clientSocket = NULL; struct nfc_jni_callback_data cb_data; phLibNfc_Handle hIncomingSocket, hServerSocket; @@ -146,7 +147,7 @@ static jobject com_NativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint m } /* Get NativeConnectionOriented class object */ - clsNativeLlcpSocket = e->GetObjectClass(clientSocket); + clsNativeLlcpSocket.reset(e->GetObjectClass(clientSocket)); if(e->ExceptionCheck()) { ALOGD("LLCP Socket get class object error"); @@ -154,15 +155,15 @@ static jobject com_NativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint m } /* Set socket handle */ - f = e->GetFieldID(clsNativeLlcpSocket, "mHandle", "I"); + f = e->GetFieldID(clsNativeLlcpSocket.get(), "mHandle", "I"); e->SetIntField(clientSocket, f,(jint)hIncomingSocket); /* Set socket MIU */ - f = e->GetFieldID(clsNativeLlcpSocket, "mLocalMiu", "I"); + f = e->GetFieldID(clsNativeLlcpSocket.get(), "mLocalMiu", "I"); e->SetIntField(clientSocket, f,(jint)miu); /* Set socket RW */ - f = e->GetFieldID(clsNativeLlcpSocket, "mLocalRw", "I"); + f = e->GetFieldID(clsNativeLlcpSocket.get(), "mLocalRw", "I"); e->SetIntField(clientSocket, f,(jint)rw); TRACE("socket handle 0x%02x: MIU = %d, RW = %d\n",hIncomingSocket, miu, rw); diff --git a/nxp/jni/com_android_nfc_NativeNfcManager.cpp b/nxp/jni/com_android_nfc_NativeNfcManager.cpp index af0e4fbe..9c68bd54 100755 --- a/nxp/jni/com_android_nfc_NativeNfcManager.cpp +++ b/nxp/jni/com_android_nfc_NativeNfcManager.cpp @@ -24,6 +24,7 @@ #include <hardware/hardware.h> #include <hardware/nfc.h> #include <cutils/properties.h> +#include <ScopedLocalRef.h> #include "com_android_nfc.h" @@ -646,7 +647,7 @@ static int is_user_build() { * Performs a software reset */ void emergency_recovery(struct nfc_jni_native_data *nat) { - if (!is_user_build()) { + if (is_user_build()) { ALOGE("emergency_recovery: force restart of NFC service"); } else { // dont recover immediately, so we can debug @@ -1071,24 +1072,16 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, phLibNfc_RemoteDevList_t *psRemoteDevList, uint8_t uNofRemoteDev, NFCSTATUS status) { - JNIEnv *e; NFCSTATUS ret; - jclass tag_cls = NULL; - jobject target_array; - jobject tag; - jmethodID ctor; - jfieldID f; const char * typeName; - jbyteArray tagUid; - jbyteArray generalBytes = NULL; - struct nfc_jni_native_data *nat; struct timespec ts; phNfc_sData_t data; int i; int target_index = 0; // Target that will be reported (if multiple can be >0) - nat = (struct nfc_jni_native_data *)pContext; + struct nfc_jni_native_data* nat = (struct nfc_jni_native_data *)pContext; + JNIEnv *e; nat->vm->GetEnv( (void **)&e, nat->env_version); if(status == NFCSTATUS_DESELECTED) @@ -1099,7 +1092,7 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, e->CallVoidMethod(nat->manager, cached_NfcManager_notifyTargetDeselected); if(e->ExceptionCheck()) { - ALOGE("Exception occured"); + ALOGE("Exception occurred"); kill_client(nat); } } @@ -1110,6 +1103,8 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, target_index = find_preferred_target(psRemoteDevList, uNofRemoteDev); + ScopedLocalRef<jobject> tag(e, NULL); + /* Reset device connected flag */ device_connected_flag = 1; phLibNfc_sRemoteDevInformation_t *remDevInfo = psRemoteDevList[target_index].psRemoteDevInfo; @@ -1117,8 +1112,7 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, if((remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator) || (remDevInfo->RemDevType == phNfc_eNfcIP1_Target)) { - - tag_cls = e->GetObjectClass(nat->cached_P2pDevice); + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_P2pDevice)); if(e->ExceptionCheck()) { ALOGE("Get Object Class Error"); @@ -1127,27 +1121,27 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, } /* New target instance */ - ctor = e->GetMethodID(tag_cls, "<init>", "()V"); - tag = e->NewObject(tag_cls, ctor); + jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); + tag.reset(e->NewObject(tag_cls.get(), ctor)); /* Set P2P Target mode */ - f = e->GetFieldID(tag_cls, "mMode", "I"); + jfieldID f = e->GetFieldID(tag_cls.get(), "mMode", "I"); if(remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator) { ALOGD("Discovered P2P Initiator"); - e->SetIntField(tag, f, (jint)MODE_P2P_INITIATOR); + e->SetIntField(tag.get(), f, (jint)MODE_P2P_INITIATOR); } else { ALOGD("Discovered P2P Target"); - e->SetIntField(tag, f, (jint)MODE_P2P_TARGET); + e->SetIntField(tag.get(), f, (jint)MODE_P2P_TARGET); } if(remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator) { /* Set General Bytes */ - f = e->GetFieldID(tag_cls, "mGeneralBytes", "[B"); + f = e->GetFieldID(tag_cls.get(), "mGeneralBytes", "[B"); TRACE("General Bytes length ="); for(i=0;i<remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length;i++) @@ -1155,23 +1149,22 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, ALOGD("%02x ", remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo[i]); } - generalBytes = e->NewByteArray(remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length); + ScopedLocalRef<jbyteArray> generalBytes(e, e->NewByteArray(remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length)); - e->SetByteArrayRegion(generalBytes, 0, + e->SetByteArrayRegion(generalBytes.get(), 0, remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length, (jbyte *)remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo); - - e->SetObjectField(tag, f, generalBytes); + e->SetObjectField(tag.get(), f, generalBytes.get()); } /* Set tag handle */ - f = e->GetFieldID(tag_cls, "mHandle", "I"); - e->SetIntField(tag, f,(jint)remDevHandle); + f = e->GetFieldID(tag_cls.get(), "mHandle", "I"); + e->SetIntField(tag.get(), f,(jint)remDevHandle); TRACE("Target handle = 0x%08x",remDevHandle); } else { - tag_cls = e->GetObjectClass(nat->cached_NfcTag); + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_NfcTag)); if(e->ExceptionCheck()) { kill_client(nat); @@ -1179,8 +1172,8 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, } /* New tag instance */ - ctor = e->GetMethodID(tag_cls, "<init>", "()V"); - tag = e->NewObject(tag_cls, ctor); + jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); + tag.reset(e->NewObject(tag_cls.get(), ctor)); bool multi_protocol = false; @@ -1191,73 +1184,72 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, } /* Set tag UID */ - f = e->GetFieldID(tag_cls, "mUid", "[B"); + jfieldID f = e->GetFieldID(tag_cls.get(), "mUid", "[B"); data = get_target_uid(remDevInfo); - tagUid = e->NewByteArray(data.length); + ScopedLocalRef<jbyteArray> tagUid(e, e->NewByteArray(data.length)); if(data.length > 0) { - e->SetByteArrayRegion(tagUid, 0, data.length, (jbyte *)data.buffer); + e->SetByteArrayRegion(tagUid.get(), 0, data.length, (jbyte *)data.buffer); } - e->SetObjectField(tag, f, tagUid); + e->SetObjectField(tag.get(), f, tagUid.get()); /* Generate technology list */ - jintArray techList; - jintArray handleList; - jintArray typeList; + ScopedLocalRef<jintArray> techList(e, NULL); + ScopedLocalRef<jintArray> handleList(e, NULL); + ScopedLocalRef<jintArray> typeList(e, NULL); nfc_jni_get_technology_tree(e, psRemoteDevList, multi_protocol ? uNofRemoteDev : 1, &techList, &handleList, &typeList); /* Push the technology list into the java object */ - f = e->GetFieldID(tag_cls, "mTechList", "[I"); - e->SetObjectField(tag, f, techList); + f = e->GetFieldID(tag_cls.get(), "mTechList", "[I"); + e->SetObjectField(tag.get(), f, techList.get()); - f = e->GetFieldID(tag_cls, "mTechHandles", "[I"); - e->SetObjectField(tag, f, handleList); + f = e->GetFieldID(tag_cls.get(), "mTechHandles", "[I"); + e->SetObjectField(tag.get(), f, handleList.get()); - f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I"); - e->SetObjectField(tag, f, typeList); + f = e->GetFieldID(tag_cls.get(), "mTechLibNfcTypes", "[I"); + e->SetObjectField(tag.get(), f, typeList.get()); - f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I"); - e->SetIntField(tag, f,(jint)-1); + f = e->GetFieldID(tag_cls.get(), "mConnectedTechIndex", "I"); + e->SetIntField(tag.get(), f,(jint)-1); - f = e->GetFieldID(tag_cls, "mConnectedHandle", "I"); - e->SetIntField(tag, f,(jint)-1); + f = e->GetFieldID(tag_cls.get(), "mConnectedHandle", "I"); + e->SetIntField(tag.get(), f,(jint)-1); } storedHandle = remDevHandle; if (nat->tag != NULL) { e->DeleteGlobalRef(nat->tag); } - nat->tag = e->NewGlobalRef(tag); + nat->tag = e->NewGlobalRef(tag.get()); /* Notify the service */ TRACE("Notify Nfc Service"); if((remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator) || (remDevInfo->RemDevType == phNfc_eNfcIP1_Target)) { - /* Store the hanlde of the P2P device */ + /* Store the handle of the P2P device */ hLlcpHandle = remDevHandle; /* Notify manager that new a P2P device was found */ - e->CallVoidMethod(nat->manager, cached_NfcManager_notifyLlcpLinkActivation, tag); + e->CallVoidMethod(nat->manager, cached_NfcManager_notifyLlcpLinkActivation, tag.get()); if(e->ExceptionCheck()) { - ALOGE("Exception occured"); + ALOGE("Exception occurred"); kill_client(nat); } } else { /* Notify manager that new a tag was found */ - e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag); + e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag.get()); if(e->ExceptionCheck()) { - ALOGE("Exception occured"); + ALOGE("Exception occurred"); kill_client(nat); } } - e->DeleteLocalRef(tag); } } @@ -1583,6 +1575,7 @@ static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool { NFCSTATUS ret; struct nfc_jni_callback_data cb_data; + int numRetries = 3; /* Create the local semaphore */ if (!nfc_cb_data_init(&cb_data, NULL)) @@ -1603,6 +1596,7 @@ static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool set_CE_A_mode(UNBLOCK_CE_CALLBACK, nat); set_CE_B_mode(UNBLOCK_CE_CALLBACK, nat); +configure: /* Start Polling loop */ TRACE("****** Start NFC Discovery ******"); REENTRANCE_LOCK(); @@ -1619,6 +1613,13 @@ static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"", nat->discovery_cfg.NfcIP_Mode, nat->discovery_cfg.Duration, ret); + if (ret == NFCSTATUS_BUSY && numRetries-- > 0) + { + TRACE("ConfigDiscovery BUSY, retrying"); + usleep(1000000); + goto configure; + } + if(ret != NFCSTATUS_PENDING) { set_CE_A_mode(TURN_CE_OFF, nat); @@ -1657,6 +1658,7 @@ static void nfc_jni_stop_discovery_locked(struct nfc_jni_native_data *nat) phLibNfc_sADD_Cfg_t discovery_cfg; NFCSTATUS ret; struct nfc_jni_callback_data cb_data; + int numRetries = 3; set_CE_A_mode(TURN_CE_OFF, nat); set_CE_B_mode(TURN_CE_OFF, nat); @@ -1672,6 +1674,7 @@ static void nfc_jni_stop_discovery_locked(struct nfc_jni_native_data *nat) discovery_cfg.NfcIP_Target_Mode = 0; discovery_cfg.NfcIP_Tgt_Disable = TRUE; +configure: /* Start Polling loop */ TRACE("****** Stop NFC Discovery ******"); REENTRANCE_LOCK(); @@ -1687,8 +1690,16 @@ static void nfc_jni_stop_discovery_locked(struct nfc_jni_native_data *nat) discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"", discovery_cfg.NfcIP_Mode, discovery_cfg.Duration, ret); + if (ret == NFCSTATUS_BUSY && numRetries-- > 0) + { + TRACE("ConfigDiscovery BUSY, retrying"); + usleep(1000000); + goto configure; + } + if(ret != NFCSTATUS_PENDING) { + ALOGE("[STOP] ConfigDiscovery returned %x", ret); emergency_recovery(nat); } @@ -2397,10 +2408,10 @@ static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls, "notifyLlcpLinkActivation","(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V"); - + cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls, "notifyLlcpLinkDeactivated","(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V"); - + cached_NfcManager_notifyTargetDeselected = e->GetMethodID(cls, "notifyTargetDeselected","()V"); @@ -2424,7 +2435,7 @@ static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject ALOGD("Native Structure initialization failed"); return FALSE; } - + if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1) { ALOGD("Native Structure initialization failed"); @@ -2582,7 +2593,6 @@ static jboolean com_android_nfc_NfcManager_deinitialize(JNIEnv *e, jobject o) /* Secure Element methods */ static jintArray com_android_nfc_NfcManager_doGetSecureElementList(JNIEnv *e, jobject o) { NFCSTATUS ret; - jintArray list= NULL; phLibNfc_SE_List_t se_list[PHLIBNFC_MAXNO_OF_SE]; uint8_t i, se_count = PHLIBNFC_MAXNO_OF_SE; @@ -2595,13 +2605,13 @@ static jintArray com_android_nfc_NfcManager_doGetSecureElementList(JNIEnv *e, jo if (ret != NFCSTATUS_SUCCESS) { ALOGE("phLibNfc_SE_GetSecureElementList() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); - return list; + return NULL; } TRACE("phLibNfc_SE_GetSecureElementList() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); TRACE("Nb SE: %d", se_count); - list =e->NewIntArray(se_count); + jintArray result = e->NewIntArray(se_count); for (i = 0; i < se_count; i++) { if (se_list[i].eSE_Type == phLibNfc_SE_Type_SmartMX) { ALOGD("phLibNfc_SE_GetSecureElementList(): SMX detected"); @@ -2610,12 +2620,10 @@ static jintArray com_android_nfc_NfcManager_doGetSecureElementList(JNIEnv *e, jo ALOGD("phLibNfc_SE_GetSecureElementList(): UICC detected"); ALOGD("SE ID #%d: 0x%08x", i, se_list[i].hSecureElement); } - e->SetIntArrayRegion(list, i, 1, (jint*)&se_list[i].hSecureElement); + e->SetIntArrayRegion(result, i, 1, (jint*)&se_list[i].hSecureElement); } - e->DeleteLocalRef(list); - - return list; + return result; } static void com_android_nfc_NfcManager_doSelectSecureElement(JNIEnv *e, jobject o) { @@ -2636,6 +2644,13 @@ static void com_android_nfc_NfcManager_doSelectSecureElement(JNIEnv *e, jobject goto clean_and_return; } + REENTRANCE_LOCK(); + ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_SUCCESS) { + ALOGD("pphLibNfc_RemoteDev_NtfRegister returned 0x%02x",ret); + goto clean_and_return; + } TRACE("****** Select Secure Element ******"); TRACE("phLibNfc_SE_SetMode()"); @@ -2679,6 +2694,13 @@ static void com_android_nfc_NfcManager_doDeselectSecureElement(JNIEnv *e, jobjec goto clean_and_return; } + REENTRANCE_LOCK(); + ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_SUCCESS) { + ALOGD("pphLibNfc_RemoteDev_NtfRegister returned 0x%02x",ret); + goto clean_and_return; + } TRACE("****** Deselect Secure Element ******"); TRACE("phLibNfc_SE_SetMode()"); @@ -3323,13 +3345,13 @@ static JNINativeMethod gMethods[] = {"doActivateLlcp", "()Z", (void *)com_android_nfc_NfcManager_doActivateLlcp}, - + {"doCreateLlcpConnectionlessSocket", "(ILjava/lang/String;)Lcom/android/nfc/dhimpl/NativeLlcpConnectionlessSocket;", (void *)com_android_nfc_NfcManager_doCreateLlcpConnectionlessSocket}, - + {"doCreateLlcpServiceSocket", "(ILjava/lang/String;III)Lcom/android/nfc/dhimpl/NativeLlcpServiceSocket;", (void *)com_android_nfc_NfcManager_doCreateLlcpServiceSocket}, - + {"doCreateLlcpSocket", "(IIII)Lcom/android/nfc/dhimpl/NativeLlcpSocket;", (void *)com_android_nfc_NfcManager_doCreateLlcpSocket}, diff --git a/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp index bb1bb2a5..9e0a6e23 100755 --- a/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp +++ b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp @@ -152,12 +152,12 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * TRACE("Secure Element Handle: 0x%08x", secureElementHandle); /* Set type name */ - jintArray techList; + ScopedLocalRef<jintArray> techList(e, NULL); nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL); // TODO: Should use the "connected" technology, for now use the first - if ((techList != NULL) && e->GetArrayLength(techList) > 0) { - e->GetIntArrayRegion(techList, 0, 1, &SecureElementTech); + if ((techList.get() != NULL) && e->GetArrayLength(techList.get()) > 0) { + e->GetIntArrayRegion(techList.get(), 0, 1, &SecureElementTech); TRACE("Store Secure Element Info\n"); SecureElementInfo = psRemoteDevList->psRemoteDevInfo; @@ -167,10 +167,6 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * ALOGE("Discovered secure element, but could not resolve tech"); status = NFCSTATUS_FAILED; } - - // This thread may not return to the virtual machine for a long time - // so make sure to delete the local refernce to the tech list. - e->DeleteLocalRef(techList); } clean_and_return: @@ -183,6 +179,7 @@ static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection { NFCSTATUS ret; int semResult; + jint errorCode = EE_ERROR_INIT; phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE]; uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0; @@ -228,7 +225,8 @@ static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection /* Check if NFC device is already connected to a tag or P2P peer */ if (device_connected_flag == 1) { - ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag"); + ALOGE("Unable to open SE connection, device already connected to a P2P peer or a Tag"); + errorCode = EE_ERROR_LISTEN_MODE; goto clean_and_return; } @@ -267,6 +265,7 @@ static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection { // There is an external RF field present, fail the open request ALOGD("Unable to open SE connection, external RF Field detected"); + errorCode = EE_ERROR_EXT_FIELD; goto clean_and_return; } @@ -468,7 +467,7 @@ clean_and_return: nfc_cb_data_deinit(&cb_data_SE_Notification); CONCURRENCY_UNLOCK(); - return 0; + return errorCode; } @@ -730,16 +729,12 @@ static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jintArray techList; TRACE("Get Secure element Type function "); - if(handle == secureElementHandle) - { - techList = e->NewIntArray(1); - e->SetIntArrayRegion(techList, 0, 1, &SecureElementTech); - return techList; - } - else - { + if (handle != secureElementHandle) { return NULL; } + jintArray result = e->NewIntArray(1); + e->SetIntArrayRegion(result, 0, 1, &SecureElementTech); + return result; } diff --git a/nxp/jni/com_android_nfc_NativeNfcTag.cpp b/nxp/jni/com_android_nfc_NativeNfcTag.cpp index 94e56c25..c1c8a4f5 100755 --- a/nxp/jni/com_android_nfc_NativeNfcTag.cpp +++ b/nxp/jni/com_android_nfc_NativeNfcTag.cpp @@ -16,6 +16,8 @@ #include <semaphore.h> #include <errno.h> +#include <ScopedLocalRef.h> +#include <ScopedPrimitiveArray.h> #include "com_android_nfc.h" #include "phNfcHalTypes.h" @@ -133,7 +135,7 @@ static void nfc_jni_transceive_callback(void *pContext, { struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; LOG_CALLBACK("nfc_jni_transceive_callback", status); - + nfc_jni_transceive_buffer = pResBuffer; /* Report the callback status and wake up the caller */ @@ -196,8 +198,8 @@ static jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e, TRACE("phLibNfc_Ndef_Read()"); REENTRANCE_LOCK(); status = phLibNfc_Ndef_Read(handle, &nfc_jni_ndef_rw, - phLibNfc_Ndef_EBegin, - nfc_jni_tag_rw_callback, + phLibNfc_Ndef_EBegin, + nfc_jni_tag_rw_callback, (void *)&cb_data); REENTRANCE_UNLOCK(); if(status != NFCSTATUS_PENDING) @@ -206,7 +208,7 @@ static jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e, goto clean_and_return; } TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); - + /* Wait for callback response */ if(sem_wait(&cb_data.sem)) { @@ -229,7 +231,7 @@ clean_and_return: return buf; } - + static jboolean com_android_nfc_NativeNfcTag_doWrite(JNIEnv *e, jobject o, jbyteArray buf) @@ -292,26 +294,25 @@ clean_and_return: static void set_target_pollBytes(JNIEnv *e, jobject tag, phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo) { - jclass tag_cls = e->GetObjectClass(tag); - jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B"); + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(tag)); + jfieldID f = e->GetFieldID(tag_cls.get(), "mTechPollBytes", "[[B"); - jobjectArray existingPollBytes = (jobjectArray) e->GetObjectField(tag, f); - - if (existingPollBytes != NULL) { + ScopedLocalRef<jobjectArray> existingPollBytes(e, (jobjectArray) e->GetObjectField(tag, f)); + if (existingPollBytes.get() != NULL) { return; } - jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I"); - jintArray techList = (jintArray) e->GetObjectField(tag, techListField); - jint *techId = e->GetIntArrayElements(techList, 0); - int techListLength = e->GetArrayLength(techList); + jfieldID techListField = e->GetFieldID(tag_cls.get(), "mTechList", "[I"); + ScopedLocalRef<jintArray> techList(e, (jintArray) e->GetObjectField(tag, techListField)); + ScopedIntArrayRO techIds(e, techList.get()); + int techListLength = techIds.size(); - jbyteArray pollBytes = e->NewByteArray(0); - jobjectArray techPollBytes = e->NewObjectArray(techListLength, - e->GetObjectClass(pollBytes), 0); + ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0)); + ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get())); + ScopedLocalRef<jobjectArray> techPollBytes(e, e->NewObjectArray(techListLength, byteArrayClass.get(), NULL)); for (int tech = 0; tech < techListLength; tech++) { - switch(techId[tech]) + switch(techIds[tech]) { /* ISO14443-3A: ATQA/SENS_RES */ case TARGET_TYPE_ISO14443_3A: @@ -320,56 +321,52 @@ static void set_target_pollBytes(JNIEnv *e, jobject tag, // at {0x00, 0x0C} in the spec. So eJewel can safely be // translated to {0x00, 0x0C}. const static jbyte JewelAtqA[2] = {0x00, 0x0C}; - pollBytes = e->NewByteArray(2); - e->SetByteArrayRegion(pollBytes, 0, 2, (jbyte*) JewelAtqA); - } - else { - pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA)); - e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA), + pollBytes.reset(e->NewByteArray(2)); + e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*) JewelAtqA); + } else { + pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA))); + e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA), (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA); } break; /* ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES */ case TARGET_TYPE_ISO14443_3B: - pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData) - + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo)); - e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), + pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData) + + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo))); + e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData); - e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), + e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo), (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo); break; /* JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) */ case TARGET_TYPE_FELICA: - pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm) - + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode)); - e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), + pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm) + + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode))); + e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm); - e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), + e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode), (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode); break; /* ISO15693: response flags (1 byte), DSFID (1 byte) */ case TARGET_TYPE_ISO15693: - pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) - + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)); - e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), + pollBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) + + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid))); + e->SetByteArrayRegion(pollBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags); - e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), + e->SetByteArrayRegion(pollBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid), (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid); break; default: - pollBytes = e->NewByteArray(0); + pollBytes.reset(e->NewByteArray(0)); break; } - e->SetObjectArrayElement(techPollBytes, tech, pollBytes); + e->SetObjectArrayElement(techPollBytes.get(), tech, pollBytes.get()); } - e->SetObjectField(tag, f, techPollBytes); - - e->ReleaseIntArrayElements(techList, techId, 0); - + e->SetObjectField(tag, f, techPollBytes.get()); } /* @@ -378,31 +375,30 @@ static void set_target_pollBytes(JNIEnv *e, jobject tag, static void set_target_activationBytes(JNIEnv *e, jobject tag, phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo) { - jclass tag_cls = e->GetObjectClass(tag); - - jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B"); - jobjectArray existingActBytes = (jobjectArray) e->GetObjectField(tag, f); + ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(tag)); - if (existingActBytes != NULL) { + jfieldID f = e->GetFieldID(tag_cls.get(), "mTechActBytes", "[[B"); + ScopedLocalRef<jobjectArray> existingActBytes(e, (jobjectArray) e->GetObjectField(tag, f)); + if (existingActBytes.get() != NULL) { return; } - jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I"); - jintArray techList = (jintArray) e->GetObjectField(tag, techListField); - int techListLength = e->GetArrayLength(techList); - jint *techId = e->GetIntArrayElements(techList, 0); + jfieldID techListField = e->GetFieldID(tag_cls.get(), "mTechList", "[I"); + ScopedLocalRef<jintArray> techList(e, (jintArray) e->GetObjectField(tag, techListField)); + ScopedIntArrayRO techIds(e, techList.get()); + int techListLength = techIds.size(); - jbyteArray actBytes = e->NewByteArray(0); - jobjectArray techActBytes = e->NewObjectArray(techListLength, - e->GetObjectClass(actBytes), 0); + ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0)); + ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get())); + ScopedLocalRef<jobjectArray> techActBytes(e, e->NewObjectArray(techListLength, byteArrayClass.get(), 0)); for (int tech = 0; tech < techListLength; tech++) { - switch(techId[tech]) { + switch(techIds[tech]) { /* ISO14443-3A: SAK/SEL_RES */ case TARGET_TYPE_ISO14443_3A: - actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak)); - e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak), + actBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak))); + e->SetByteArrayRegion(actBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak), (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak); break; /* ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS */ @@ -410,45 +406,40 @@ static void set_target_activationBytes(JNIEnv *e, jobject tag, case TARGET_TYPE_ISO14443_4: // Determine whether -A or -B if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_B_PICC || - psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) { - actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength); - e->SetByteArrayRegion(actBytes, 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength, + psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) { + actBytes.reset(e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength)); + e->SetByteArrayRegion(actBytes.get(), 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength, (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerResp); - } - else if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC || - psRemoteDevInfo->RemDevType == phNfc_eISO14443_4A_PICC) { - actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength); - e->SetByteArrayRegion(actBytes, 0, + } else if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC || + psRemoteDevInfo->RemDevType == phNfc_eISO14443_4A_PICC) { + actBytes.reset(e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength)); + e->SetByteArrayRegion(actBytes.get(), 0, psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength, (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppData); } break; /* ISO15693: response flags (1 byte), DSFID (1 byte) */ case TARGET_TYPE_ISO15693: - actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) - + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)); - e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), + actBytes.reset(e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) + + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid))); + e->SetByteArrayRegion(actBytes.get(), 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags); - e->SetByteArrayRegion(actBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), + e->SetByteArrayRegion(actBytes.get(), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid), (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid); break; default: - actBytes = e->NewByteArray(0); + actBytes.reset(e->NewByteArray(0)); break; } - e->SetObjectArrayElement(techActBytes, tech, actBytes); + e->SetObjectArrayElement(techActBytes.get(), tech, actBytes.get()); } - e->SetObjectField(tag, f, techActBytes); - - e->ReleaseIntArrayElements(techList, techId, 0); + e->SetObjectField(tag, f, techActBytes.get()); } static jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, jobject o, phLibNfc_Handle handle) { - jclass cls; - jfieldID f; jint status; struct nfc_jni_callback_data cb_data; phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; @@ -527,8 +518,6 @@ clean_and_return: static jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, jobject o, phLibNfc_Handle handle) { - jclass cls; - jfieldID f; jint status; struct nfc_jni_callback_data cb_data; phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; @@ -620,8 +609,6 @@ static jint com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o) { phLibNfc_Handle handle = 0; - jclass cls; - jfieldID f; NFCSTATUS status; jboolean result = JNI_FALSE; struct nfc_jni_callback_data cb_data; @@ -688,18 +675,18 @@ static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o) } TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status)); - /* Wait for callback response */ - if(sem_wait(&cb_data.sem)) - { - ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); - goto clean_and_return; - } + /* Wait for callback response */ + if(sem_wait(&cb_data.sem)) + { + ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + goto clean_and_return; + } - /* Disconnect Status */ - if(cb_data.status != NFCSTATUS_SUCCESS) - { - goto clean_and_return; - } + /* Disconnect Status */ + if(cb_data.status != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } } result = JNI_TRUE; diff --git a/nxp/jni/com_android_nfc_NativeP2pDevice.cpp b/nxp/jni/com_android_nfc_NativeP2pDevice.cpp index fa460524..19f3ecc8 100644 --- a/nxp/jni/com_android_nfc_NativeP2pDevice.cpp +++ b/nxp/jni/com_android_nfc_NativeP2pDevice.cpp @@ -17,6 +17,7 @@ #include <semaphore.h> #include <errno.h> +#include <ScopedLocalRef.h> #include "com_android_nfc.h" @@ -122,7 +123,7 @@ static jboolean com_android_nfc_NativeP2pDevice_doConnect(JNIEnv *e, jobject o) jboolean result = JNI_FALSE; struct nfc_jni_callback_data cb_data; - jclass target_cls = NULL; + ScopedLocalRef<jclass> target_cls(e, NULL); jobject tag; jmethodID ctor; jfieldID f; @@ -164,9 +165,9 @@ static jboolean com_android_nfc_NativeP2pDevice_doConnect(JNIEnv *e, jobject o) } /* Set General Bytes */ - target_cls = e->GetObjectClass(o); + target_cls.reset(e->GetObjectClass(o)); - f = e->GetFieldID(target_cls, "mGeneralBytes", "[B"); + f = e->GetFieldID(target_cls.get(), "mGeneralBytes", "[B"); TRACE("General Bytes Length = %d", sGeneralBytes.length); TRACE("General Bytes ="); diff --git a/res/layout/screenshot.xml b/res/layout/screenshot.xml index 24a3a71d..2523e500 100644 --- a/res/layout/screenshot.xml +++ b/res/layout/screenshot.xml @@ -49,5 +49,36 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - /> + /> + <ImageView android:id="@+id/blacklayer" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#ff000000" + android:visibility="gone" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + > + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="0.25" + /> + <TextView android:id="@+id/retrytext" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="0.5" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceLarge" + android:background="@null" + android:textColor="@android:color/holo_blue_light" + /> + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="0.25" + /> + </LinearLayout> </FrameLayout> diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index e7e283c6..3def362c 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC geaktiveer."</string> <string name="touch" msgid="4727218133711188355">"Raak en straal"</string> <string name="beam_progress" msgid="7453634884807323920">"Inkomende straal..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Stralend…"</string> <string name="beam_complete" msgid="477026736424637435">"Straling voltooi"</string> <string name="beam_failed" msgid="5116241718189888630">"Straal het nie voltooi nie"</string> <string name="beam_canceled" msgid="5425192751826544741">"Straal gekanselleer"</string> <string name="cancel" msgid="61873902552555096">"Kanselleer"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Raak om te bekyk"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Die ontvanger se toestel ondersteun nie groot lêeroordrag via \'n straal nie."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Bring toestelle weer bymekaar"</string> <string name="connecting_headset" msgid="3929250919225573008">"Koppel tans"</string> <string name="connected_headset" msgid="4047751837023241955">"Gekoppel"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Kon nie koppel nie"</string> diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index f37d647f..c9547fef 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -6,16 +6,18 @@ <string name="inbound_me_profile_title" msgid="6146013785225412693">"NFC የተቀበላቸው ዕውቂያዎች"</string> <string name="inbound_me_profile_text" msgid="2342757196108092923">"ይሄን ሰው እንደ ዕውቅያ ለማከል ነካ አድርግ፡፡"</string> <string name="outbound_me_profile_title" msgid="2523625031572784769">"NFC ልውውጥ ተጠናቋል"</string> - <string name="outbound_me_profile_text" msgid="5594998841143667989">"ለዚህ ሰው የአንተን ዕውቅያ መረጃ ለመስጠት መታ አድርግ"</string> + <string name="outbound_me_profile_text" msgid="5594998841143667989">"ለእዚህ ሰው የአንተን ዕውቅያ መረጃ ለመስጠት መታ አድርግ"</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC ነቅቷል፡፡"</string> <string name="touch" msgid="4727218133711188355">"ለማብራት ንካ"</string> <string name="beam_progress" msgid="7453634884807323920">"ገቢ ሞገድ..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"ሞገድ በማመንጨት ላይ..."</string> <string name="beam_complete" msgid="477026736424637435">"አመልማሎ ተጠናቅቋል"</string> <string name="beam_failed" msgid="5116241718189888630">"ሞገድ አልተጠናቀቀም"</string> <string name="beam_canceled" msgid="5425192751826544741">"ሞገድ ተሰርዧል"</string> <string name="cancel" msgid="61873902552555096">"ሰርዝ"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"ለማየት ንካ"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"የተቀባዩ መሣሪያ ትልቅ ፋይል በሞገድ በኩል ማስተላለፍ አይደግፍም።"</string> + <string name="beam_try_again" msgid="3364677301009783455">"መሣሪያዎችን ዳግም አንድ ላይ አሰባስብ"</string> <string name="connecting_headset" msgid="3929250919225573008">"በመገናኘት ላይ"</string> <string name="connected_headset" msgid="4047751837023241955">"ተገናኝቷል"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"ማገናኘት አልተቻለም"</string> diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index d7ec39f2..b2bed77c 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -8,14 +8,16 @@ <string name="outbound_me_profile_title" msgid="2523625031572784769">"اكتمل تفاعل NFC"</string> <string name="outbound_me_profile_text" msgid="5594998841143667989">"المس لمنح هذا الشخص معلومات اتصالك."</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"تم تمكين NFC."</string> - <string name="touch" msgid="4727218133711188355">"المس لرسم شعاع"</string> - <string name="beam_progress" msgid="7453634884807323920">"شعاع وارد..."</string> - <string name="beam_complete" msgid="477026736424637435">"اكتمل الشعاع"</string> - <string name="beam_failed" msgid="5116241718189888630">"لم يكتمل الشعاع"</string> - <string name="beam_canceled" msgid="5425192751826544741">"تم إلغاء الشعاع"</string> + <string name="touch" msgid="4727218133711188355">"المس لتبادل البيانات"</string> + <string name="beam_progress" msgid="7453634884807323920">"بيانات واردة..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"إرسال لاسلكي..."</string> + <string name="beam_complete" msgid="477026736424637435">"اكتمل تبادل البيانات"</string> + <string name="beam_failed" msgid="5116241718189888630">"لم يكتمل تبادل البيانات"</string> + <string name="beam_canceled" msgid="5425192751826544741">"تم إلغاء تبادل البيانات"</string> <string name="cancel" msgid="61873902552555096">"إلغاء"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"المس ليتم العرض"</string> - <string name="beam_handover_not_supported" msgid="4083165921751489015">"جهاز المستلم لا يوفر نقل ملفات كبيرة عبر الشعاع."</string> + <string name="beam_handover_not_supported" msgid="4083165921751489015">"جهاز المستلم لا يوفر نقل ملفات كبيرة عبر تبادل البيانات."</string> + <string name="beam_try_again" msgid="3364677301009783455">"تجميع الأجهزة معًا من جديد"</string> <string name="connecting_headset" msgid="3929250919225573008">"جارٍ الاتصال..."</string> <string name="connected_headset" msgid="4047751837023241955">"متصل"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"تعذر الاتصال"</string> diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index b748d04b..94500f69 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC ўключаны."</string> <string name="touch" msgid="4727218133711188355">"Краніце, каб перадаць"</string> <string name="beam_progress" msgid="7453634884807323920">"Уваходная перадача beam..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Ззяючы (Beaming)..."</string> <string name="beam_complete" msgid="477026736424637435">"Працэс перадачы Beam завершаны"</string> <string name="beam_failed" msgid="5116241718189888630">"Перадача Beam не завершана"</string> <string name="beam_canceled" msgid="5425192751826544741">"Перадача Beam адменена"</string> <string name="cancel" msgid="61873902552555096">"Адмена"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Націсніце, каб прагледзець"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Прылада атрымальніка не падтрымлівае перадачу вялікіх файлаў праз Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Зноў аб\'яднаць прылады"</string> <string name="connecting_headset" msgid="3929250919225573008">"Падключэнне"</string> <string name="connected_headset" msgid="4047751837023241955">"Падключана"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Збой падключэння"</string> diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 35149836..30ca2395 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"КБП е активирана."</string> <string name="touch" msgid="4727218133711188355">"Докоснете, за да излъчите"</string> <string name="beam_progress" msgid="7453634884807323920">"Входящо излъчване..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Излъчва се..."</string> <string name="beam_complete" msgid="477026736424637435">"Излъчването завърши"</string> <string name="beam_failed" msgid="5116241718189888630">"Излъчването не завърши"</string> <string name="beam_canceled" msgid="5425192751826544741">"Излъчването бе анулирано"</string> <string name="cancel" msgid="61873902552555096">"Отказ"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Докоснете, за да видите"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Устройството на получателя не поддържа прехвърляне на големи файлове чрез излъчване."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Приближете отново устройствата едно до друго"</string> <string name="connecting_headset" msgid="3929250919225573008">"Свързва се"</string> <string name="connected_headset" msgid="4047751837023241955">"Има връзка"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Не можа да се установи връзка"</string> diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 591776a1..14d70614 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC activat."</string> <string name="touch" msgid="4727218133711188355">"Toca per fer brillar"</string> <string name="beam_progress" msgid="7453634884807323920">"Transferència d\'entrada..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"S\'està compartint..."</string> <string name="beam_complete" msgid="477026736424637435">"Sensor completat"</string> <string name="beam_failed" msgid="5116241718189888630">"El sensor no s\'ha executat"</string> <string name="beam_canceled" msgid="5425192751826544741">"S\'ha desactivat el sensor"</string> <string name="cancel" msgid="61873902552555096">"Cancel·la"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Toca per visualitzar"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"El dispositiu del receptor no és compatible amb la transferència de fitxers grans mitjançant sensors."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Torna a apropar els dispositius"</string> <string name="connecting_headset" msgid="3929250919225573008">"S\'està connectant"</string> <string name="connected_headset" msgid="4047751837023241955">"Connectat"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"No es pot establir la connexió"</string> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 9c7f3f75..8554b852 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -6,16 +6,18 @@ <string name="inbound_me_profile_title" msgid="6146013785225412693">"Kontakt přijatý prostřednictvím komunikace NFC"</string> <string name="inbound_me_profile_text" msgid="2342757196108092923">"Klepnutím přidáte tuto osobu mezi kontakty"</string> <string name="outbound_me_profile_title" msgid="2523625031572784769">"Interakce NFC byla dokončena"</string> - <string name="outbound_me_profile_text" msgid="5594998841143667989">"Klepnutím této osobě předáte své kontaktní informace."</string> + <string name="outbound_me_profile_text" msgid="5594998841143667989">"Klepnutím této osobě předáte své kontaktní údaje."</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Funkce NFC povolena."</string> <string name="touch" msgid="4727218133711188355">"Přenos zahájíte dotykem"</string> <string name="beam_progress" msgid="7453634884807323920">"Příchozí přenos..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Přenášení..."</string> <string name="beam_complete" msgid="477026736424637435">"Přenos dokončen"</string> <string name="beam_failed" msgid="5116241718189888630">"Přenos nebyl dokončen"</string> <string name="beam_canceled" msgid="5425192751826544741">"Přenos byl zrušen"</string> <string name="cancel" msgid="61873902552555096">"Zrušit"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Zobrazte dotykem"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Zařízení příjemce nepodporuje přenos velkých souborů prostřednictvím funkce Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Znovu přibližte zařízení"</string> <string name="connecting_headset" msgid="3929250919225573008">"Připojování"</string> <string name="connected_headset" msgid="4047751837023241955">"Připojeno"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Nelze připojit"</string> diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 23a78a87..de9a94a2 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC er aktiveret."</string> <string name="touch" msgid="4727218133711188355">"Tryk for at overføre"</string> <string name="beam_progress" msgid="7453634884807323920">"Indgående overførsel..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Overfører..."</string> <string name="beam_complete" msgid="477026736424637435">"Overførsel fuldført"</string> <string name="beam_failed" msgid="5116241718189888630">"Overførslen blev ikke fuldført"</string> <string name="beam_canceled" msgid="5425192751826544741">"Overførslen blev annulleret"</string> <string name="cancel" msgid="61873902552555096">"Annuller"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tryk for at se"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Modtagerens enhed understøtter ikke overførsel af store filer via Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Før enhederne sammen igen"</string> <string name="connecting_headset" msgid="3929250919225573008">"Opretter forbindelse"</string> <string name="connected_headset" msgid="4047751837023241955">"Forbundet"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Der kunne ikke oprettes forbindelse"</string> diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index ed85c7c8..2f2899b4 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC aktiviert"</string> <string name="touch" msgid="4727218133711188355">"Zum Beamen berühren"</string> <string name="beam_progress" msgid="7453634884807323920">"Beam wird empfangen..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Beamen..."</string> <string name="beam_complete" msgid="477026736424637435">"Beamen abgeschlossen"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam wurde nicht abgeschlossen."</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam abgebrochen"</string> <string name="cancel" msgid="61873902552555096">"Abbrechen"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Zum Anzeigen berühren"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Das Gerät des Empfängers unterstützt die Übertragung großer Dateien durch Beamen nicht."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Geräte erneut nebeneinander platzieren"</string> <string name="connecting_headset" msgid="3929250919225573008">"Verbindung wird hergestellt"</string> <string name="connected_headset" msgid="4047751837023241955">"Verbunden"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Verbindung nicht möglich"</string> diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index aeab0c26..3ea2188b 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Ενεργοποίηση ΕΚΠ."</string> <string name="touch" msgid="4727218133711188355">"Αγγίξτε για μετάδοση"</string> <string name="beam_progress" msgid="7453634884807323920">"Εισερχόμενη ζεύξη…"</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Αποστολή…"</string> <string name="beam_complete" msgid="477026736424637435">"Ολοκλήρωση ζεύξης"</string> <string name="beam_failed" msgid="5116241718189888630">"Η ζεύξη δεν ολοκληρώθηκε"</string> <string name="beam_canceled" msgid="5425192751826544741">"Ακύρωση ζεύξης"</string> <string name="cancel" msgid="61873902552555096">"Άκυρο"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Αγγίξτε για προβολή"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Η συσκευή του παραλήπτη δεν υποστηρίζει τη μεταφορά μεγάλων αρχείων μέσω ζεύξης."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Φέρτε ξανά τις συσκευές σας σε επαφή"</string> <string name="connecting_headset" msgid="3929250919225573008">"Σύνδεση"</string> <string name="connected_headset" msgid="4047751837023241955">"Συνδέθηκε"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Δεν ήταν δυνατή η σύνδεση"</string> diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index cc8d6950..54b69e29 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC enabled."</string> <string name="touch" msgid="4727218133711188355">"Touch to beam"</string> <string name="beam_progress" msgid="7453634884807323920">"Incoming beam..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Beaming..."</string> <string name="beam_complete" msgid="477026736424637435">"Beam complete"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam did not complete"</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam cancelled"</string> <string name="cancel" msgid="61873902552555096">"Cancel"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Touch to view"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"The receiver\'s device doesn\'t support large file transfer via beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Bring devices together again"</string> <string name="connecting_headset" msgid="3929250919225573008">"Connecting..."</string> <string name="connected_headset" msgid="4047751837023241955">"Connected"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Could not connect"</string> diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 53260096..b93a5014 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Se habilitó la NFC."</string> <string name="touch" msgid="4727218133711188355">"Tocar para transmitir"</string> <string name="beam_progress" msgid="7453634884807323920">"Transmisión entrante..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Transmitiendo..."</string> <string name="beam_complete" msgid="477026736424637435">"Transmisión completa"</string> <string name="beam_failed" msgid="5116241718189888630">"La transmisión no se completó"</string> <string name="beam_canceled" msgid="5425192751826544741">"Transmisión cancelada"</string> <string name="cancel" msgid="61873902552555096">"Cancelar"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Toca para ver"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"El dispositivo del receptor no admite la transferencia de archivos de gran tamaño."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Volver a unir los dispositivos"</string> <string name="connecting_headset" msgid="3929250919225573008">"Conectando..."</string> <string name="connected_headset" msgid="4047751837023241955">"Conectados"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"No se pudo conectar"</string> diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 57d4b6d8..f028a4d0 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC habilitada"</string> <string name="touch" msgid="4727218133711188355">"Toca para compartir"</string> <string name="beam_progress" msgid="7453634884807323920">"Transferencia entrante..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Compartiendo..."</string> <string name="beam_complete" msgid="477026736424637435">"Transferencia completada"</string> <string name="beam_failed" msgid="5116241718189888630">"Transferencia no completada"</string> <string name="beam_canceled" msgid="5425192751826544741">"Transferencia cancelada"</string> <string name="cancel" msgid="61873902552555096">"Cancelar"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tocar para ver"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"El dispositivo del receptor no admite la transferencia de archivos de gran tamaño."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Vuelve a juntar los dispositivos"</string> <string name="connecting_headset" msgid="3929250919225573008">"Conectando..."</string> <string name="connected_headset" msgid="4047751837023241955">"Conectado"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Error al establecer conexión"</string> diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index ae3a4d34..658f0717 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC lubatud."</string> <string name="touch" msgid="4727218133711188355">"Puudutage kiire kasutamiseks"</string> <string name="beam_progress" msgid="7453634884807323920">"Sissetulev kiir ..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Kiirega edastamine ..."</string> <string name="beam_complete" msgid="477026736424637435">"Kiir on valmis"</string> <string name="beam_failed" msgid="5116241718189888630">"Kiir ei lõpetanud toimingut"</string> <string name="beam_canceled" msgid="5425192751826544741">"Kiir on tühistatud"</string> <string name="cancel" msgid="61873902552555096">"Tühista"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Puudutage vaatamiseks"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Vastuvõtja seade ei toeta suurte failide edastamist kiire kaudu."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Ühendage seadmed uuesti"</string> <string name="connecting_headset" msgid="3929250919225573008">"Ühendamine"</string> <string name="connected_headset" msgid="4047751837023241955">"Ühendatud"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Ühendust ei õnnestunud luua"</string> diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 80e1e6a1..dc7a59c3 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"با NFC فعال شده."</string> <string name="touch" msgid="4727218133711188355">"برای پخش، لمس کنید"</string> <string name="beam_progress" msgid="7453634884807323920">"در حال دریافت پرتو..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"پرتو…"</string> <string name="beam_complete" msgid="477026736424637435">"پرتو ارسال شد"</string> <string name="beam_failed" msgid="5116241718189888630">"پرتو کامل نشد"</string> <string name="beam_canceled" msgid="5425192751826544741">"پرتو لغو شد"</string> <string name="cancel" msgid="61873902552555096">"لغو"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"برای مشاهده لمس کنید"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"دستگاه گیرنده انتقال فایلهای بزرگ از طریق پرتو را پشتیبانی نمیکند."</string> + <string name="beam_try_again" msgid="3364677301009783455">"مرتبطکردن دوباره دستگاهها"</string> <string name="connecting_headset" msgid="3929250919225573008">"در حال اتصال"</string> <string name="connected_headset" msgid="4047751837023241955">"اتصال برقرار شد"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"متصل نشد"</string> diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index cc41c46c..1249c765 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC otettu käyttöön."</string> <string name="touch" msgid="4727218133711188355">"Kosketa palkkia"</string> <string name="beam_progress" msgid="7453634884807323920">"Saapuva sisällönjakopyyntö..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Jaetaan sisältöä…"</string> <string name="beam_complete" msgid="477026736424637435">"Sisältö jaettu"</string> <string name="beam_failed" msgid="5116241718189888630">"Jakoa ei suoritettu valmiiksi"</string> <string name="beam_canceled" msgid="5425192751826544741">"Jako peruutettu"</string> <string name="cancel" msgid="61873902552555096">"Peruuta"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Kosketa ja näytä"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Vastaanottajan laite ei tue suurten tiedostojen siirtoa sisällön jakamisen kautta."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Yhdistä laitteet uudelleen"</string> <string name="connecting_headset" msgid="3929250919225573008">"Yhdistetään"</string> <string name="connected_headset" msgid="4047751837023241955">"Yhdistetty"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Ei yhteyttä"</string> diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index c0d92b21..8a122307 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC activée"</string> <string name="touch" msgid="4727218133711188355">"Appuyer pour partager"</string> <string name="beam_progress" msgid="7453634884807323920">"Partage entrant..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Partage en cours…"</string> <string name="beam_complete" msgid="477026736424637435">"Partage terminé."</string> <string name="beam_failed" msgid="5116241718189888630">"Échec du partage."</string> <string name="beam_canceled" msgid="5425192751826544741">"Partage annulé."</string> <string name="cancel" msgid="61873902552555096">"Annuler"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Appuyer pour afficher"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Le récepteur n\'est pas compatible avec le transfert de fichiers volumineux via le partage."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Mettre de nouveau les appareils côte à côte"</string> <string name="connecting_headset" msgid="3929250919225573008">"Connexion en cours…"</string> <string name="connected_headset" msgid="4047751837023241955">"Connecté"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Impossible d’établir la connexion."</string> diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 56f5e5f1..36d1867c 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -10,13 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC सक्षम है."</string> <string name="touch" msgid="4727218133711188355">"बीम करने के लिए स्पर्श करें"</string> <string name="beam_progress" msgid="7453634884807323920">"इनकमिंग बीम..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"बीम हो रहा है..."</string> <string name="beam_complete" msgid="477026736424637435">"बीम करना पूर्ण"</string> <string name="beam_failed" msgid="5116241718189888630">"बीम पूर्ण नहीं हुआ"</string> <string name="beam_canceled" msgid="5425192751826544741">"बीम रद्द"</string> <string name="cancel" msgid="61873902552555096">"रद्द करें"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"देखने के लिए स्पर्श करें"</string> - <!-- no translation found for beam_handover_not_supported (4083165921751489015) --> - <skip /> + <string name="beam_handover_not_supported" msgid="4083165921751489015">"प्राप्तकर्ता का उपकरण, बीम द्वारा बड़ी फ़ाइल के स्थानांतरण का समर्थन नहीं करता."</string> + <string name="beam_try_again" msgid="3364677301009783455">"उपकरणों को पुन: एक साथ लाएं"</string> <string name="connecting_headset" msgid="3929250919225573008">"कनेक्ट हो रहा है"</string> <string name="connected_headset" msgid="4047751837023241955">"कनेक्ट है"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"कनेक्ट नहीं किया जा सका"</string> diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 52baa21f..f5ce8243 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC omogućen."</string> <string name="touch" msgid="4727218133711188355">"Dodirnite za emitiranje"</string> <string name="beam_progress" msgid="7453634884807323920">"Dolazno emitiranje..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Emitiranje..."</string> <string name="beam_complete" msgid="477026736424637435">"Emitiranje je završeno"</string> <string name="beam_failed" msgid="5116241718189888630">"Emitiranje nije dovršeno"</string> <string name="beam_canceled" msgid="5425192751826544741">"Emitiranje otkazano"</string> <string name="cancel" msgid="61873902552555096">"Odustani"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Dodirnite za prikaz"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Uređaj prijamnika ne podržava prijenos velikih datoteka emitiranjem."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Opet povežite uređaje"</string> <string name="connecting_headset" msgid="3929250919225573008">"Povezivanje"</string> <string name="connected_headset" msgid="4047751837023241955">"Povezan"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Spajanje nije bilo moguće"</string> diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index fba3b789..060393c0 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC bekapcsolva"</string> <string name="touch" msgid="4727218133711188355">"Érintse meg a sugárzáshoz"</string> <string name="beam_progress" msgid="7453634884807323920">"Bejövő sugár..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Sugárzás..."</string> <string name="beam_complete" msgid="477026736424637435">"Átvitel befejezve."</string> <string name="beam_failed" msgid="5116241718189888630">"A sugárzás nem fejeződött be"</string> <string name="beam_canceled" msgid="5425192751826544741">"Sugárzás megszakítva"</string> <string name="cancel" msgid="61873902552555096">"Mégse"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"A megtekintéshez érintse meg."</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"A fogadó eszköz nem támogatja a nagyméretű fájlok átvitelét adatsugárzás útján."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Eszközök újbóli összekapcsolása"</string> <string name="connecting_headset" msgid="3929250919225573008">"Csatlakozás"</string> <string name="connected_headset" msgid="4047751837023241955">"Csatlakozva"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"A kapcsolódás sikertelen"</string> diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index b876dc70..2b378ced 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC diaktifkan."</string> <string name="touch" msgid="4727218133711188355">"Sentuh untuk menyorot"</string> <string name="beam_progress" msgid="7453634884807323920">"Pancaran yang masuk..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Memancarkan..."</string> <string name="beam_complete" msgid="477026736424637435">"Beam selesai"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam tidak lengkap"</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam dibatalkan"</string> <string name="cancel" msgid="61873902552555096">"Batal"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Sentuh untuk melihat"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Perangkat penerima tidak mendukung transfer file besar melalui beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Kumpulkan lagi perangkatnya"</string> <string name="connecting_headset" msgid="3929250919225573008">"Menyambungkan"</string> <string name="connected_headset" msgid="4047751837023241955">"Tersambung"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Tidak dapat menyambung"</string> diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index d648a738..a32020e4 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Comunicazione NFC abilitata."</string> <string name="touch" msgid="4727218133711188355">"Tocca per trasmettere"</string> <string name="beam_progress" msgid="7453634884807323920">"Trasmissione in arrivo..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Trasmissione..."</string> <string name="beam_complete" msgid="477026736424637435">"Trasmissione completata"</string> <string name="beam_failed" msgid="5116241718189888630">"Trasmissione non completata"</string> <string name="beam_canceled" msgid="5425192751826544741">"Trasmissione annullata"</string> <string name="cancel" msgid="61873902552555096">"Annulla"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tocca per visualizzare"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Il dispositivo del destinatario non supporta il trasferimento di file di grandi dimensioni tramite Android Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Avvicina di nuovo i dispositivi"</string> <string name="connecting_headset" msgid="3929250919225573008">"Collegamento in corso"</string> <string name="connected_headset" msgid="4047751837023241955">"Collegato"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Impossibile connettersi"</string> diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 063a5e75..8bee61ae 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC מופעל."</string> <string name="touch" msgid="4727218133711188355">"גע כדי להקרין"</string> <string name="beam_progress" msgid="7453634884807323920">"קרן נכנסת..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"מעביר תוכן..."</string> <string name="beam_complete" msgid="477026736424637435">"הקרנה הושלמה"</string> <string name="beam_failed" msgid="5116241718189888630">"הקרן לא הושלמה"</string> <string name="beam_canceled" msgid="5425192751826544741">"הקרן בוטלה"</string> <string name="cancel" msgid="61873902552555096">"ביטול"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"גע כדי להציג"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"המכשיר המקבל אינו תומך בהעברת קובץ גדול באמצעות קרן."</string> + <string name="beam_try_again" msgid="3364677301009783455">"קרב שוב את המכשירים"</string> <string name="connecting_headset" msgid="3929250919225573008">"מתחבר"</string> <string name="connected_headset" msgid="4047751837023241955">"מחובר"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"לא ניתן להתחבר."</string> diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index afd69970..d7929ae7 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFCは有効です。"</string> <string name="touch" msgid="4727218133711188355">"タップしてビーム"</string> <string name="beam_progress" msgid="7453634884807323920">"ビームを受信しています..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"ビームしています..."</string> <string name="beam_complete" msgid="477026736424637435">"ビーム完了"</string> <string name="beam_failed" msgid="5116241718189888630">"ビームが完了しませんでした"</string> <string name="beam_canceled" msgid="5425192751826544741">"ビームをキャンセルしました"</string> <string name="cancel" msgid="61873902552555096">"キャンセル"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"タップして表示"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"受信側の端末は、ビーム経由のサイズの大きなファイルの転送をサポートしていません。"</string> + <string name="beam_try_again" msgid="3364677301009783455">"端末同士をもう一度近づける"</string> <string name="connecting_headset" msgid="3929250919225573008">"接続中"</string> <string name="connected_headset" msgid="4047751837023241955">"接続されました"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"接続できませんでした"</string> diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 1ba5703f..9e45f95a 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC 사용"</string> <string name="touch" msgid="4727218133711188355">"공유하기"</string> <string name="beam_progress" msgid="7453634884807323920">"수신 빔..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"공유 중..."</string> <string name="beam_complete" msgid="477026736424637435">"Beam 완료"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam이 완료되지 않음"</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam 취소됨"</string> <string name="cancel" msgid="61873902552555096">"취소"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"터치하여 보기"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"수신자의 기기는 빔을 통한 대용량 파일 전송을 지원하지 않습니다."</string> + <string name="beam_try_again" msgid="3364677301009783455">"기기 다시 공유"</string> <string name="connecting_headset" msgid="3929250919225573008">"연결 중"</string> <string name="connected_headset" msgid="4047751837023241955">"연결됨"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"연결하지 못함"</string> diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index 06ac1892..59f25413 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"ALR įgalinta."</string> <string name="touch" msgid="4727218133711188355">"Jei norite perduoti, palieskite"</string> <string name="beam_progress" msgid="7453634884807323920">"Gaunamas perdavimas..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Perduodama..."</string> <string name="beam_complete" msgid="477026736424637435">"Perdavimas baigtas"</string> <string name="beam_failed" msgid="5116241718189888630">"Perdavimas nebuvo užbaigtas"</string> <string name="beam_canceled" msgid="5425192751826544741">"Perdavimas atšauktas"</string> <string name="cancel" msgid="61873902552555096">"Atšaukti"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Jei norite peržiūrėti, palieskite"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Gavėjo įrenginyje nepalaikomas didelio failo perdavimas naudojant perdavimo funkciją."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Vėl susiekite įrenginius"</string> <string name="connecting_headset" msgid="3929250919225573008">"Prisijungiama"</string> <string name="connected_headset" msgid="4047751837023241955">"Prisijungta"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Nepavyko prisijungti"</string> diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 0eb9883f..9b123722 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC ir iespējoti."</string> <string name="touch" msgid="4727218133711188355">"Pieskarties, lai projicētu"</string> <string name="beam_progress" msgid="7453634884807323920">"Ienākošie vienumi, izmantojot funkciju Beam..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Notiek kopīgošana, izmantojot funkciju Beam..."</string> <string name="beam_complete" msgid="477026736424637435">"Kopīgošana, izmantojot funkciju Beam, ir pabeigta."</string> <string name="beam_failed" msgid="5116241718189888630">"Kopīgošana, izmantojot funkciju Beam, netika pabeigta"</string> <string name="beam_canceled" msgid="5425192751826544741">"Kopīgošana, izmantojot funkciju Beam, atcelta"</string> <string name="cancel" msgid="61873902552555096">"Atcelt"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Pieskarieties, lai skatītu."</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Saņēmēja ierīce neatbalsta lielu failu pārsūtīšanu, izmantojot funkciju Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Vēlreiz novietojiet ierīces blakus."</string> <string name="connecting_headset" msgid="3929250919225573008">"Notiek savienojuma izveide"</string> <string name="connected_headset" msgid="4047751837023241955">"Savienojums izveidots"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Nevarēja izveidot savienojumu"</string> diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 7e53ff31..a3cf2bb9 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC didayakan."</string> <string name="touch" msgid="4727218133711188355">"Sentuh untuk memancarkan"</string> <string name="beam_progress" msgid="7453634884807323920">"Pancar sedang masuk..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Memancar..."</string> <string name="beam_complete" msgid="477026736424637435">"Pancar selesai"</string> <string name="beam_failed" msgid="5116241718189888630">"Pancar tidak lengkap"</string> <string name="beam_canceled" msgid="5425192751826544741">"Pancar dibatalkan"</string> <string name="cancel" msgid="61873902552555096">"Batal"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Sentuh untuk melihat"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Peranti penerima tidak menyokong pemindahan fail besar melalui pancaran."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Dekatkan peranti semula"</string> <string name="connecting_headset" msgid="3929250919225573008">"Menyambung"</string> <string name="connected_headset" msgid="4047751837023241955">"Disambungkan"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Tidak dapat menyambung"</string> diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 33800069..6dcf07bf 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC er aktivert."</string> <string name="touch" msgid="4727218133711188355">"Berør for å overføre trådløst"</string> <string name="beam_progress" msgid="7453634884807323920">"Innkommende trådløs overføring"</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Sender ..."</string> <string name="beam_complete" msgid="477026736424637435">"Overføring fullført"</string> <string name="beam_failed" msgid="5116241718189888630">"Overføringen ble ikke fullført"</string> <string name="beam_canceled" msgid="5425192751826544741">"Overføringen ble avbrutt"</string> <string name="cancel" msgid="61873902552555096">"Avbryt"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Trykk for å se"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Mottakerens enhet støtter ikke store filoverføringer via Android Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Før enhetene sammen igjen"</string> <string name="connecting_headset" msgid="3929250919225573008">"Kobler til"</string> <string name="connected_headset" msgid="4047751837023241955">"Tilkoblet"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Kunne ikke koble til"</string> diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 3f5b5011..1523f87f 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -23,13 +23,15 @@ <string name="outbound_me_profile_text" msgid="5594998841143667989">"Tik om deze persoon uw contactgegevens te geven."</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC ingeschakeld."</string> <string name="touch" msgid="4727218133711188355">"Tik om uit te zenden"</string> - <string name="beam_progress" msgid="7453634884807323920">"Inkomende beam\u2026"</string> + <string name="beam_progress" msgid="7453634884807323920">"Inkomende beam..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Beamen..."</string> <string name="beam_complete" msgid="477026736424637435">"Beam voltooid"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam mislukt"</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam geannuleerd"</string> <string name="cancel" msgid="61873902552555096">"Annuleren"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tik om te bekijken"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Het apparaat van de ontvanger ondersteunt de overdracht van grote bestanden via Beam niet."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Houd de apparaten nogmaals tegen elkaar"</string> <string name="connecting_headset" msgid="3929250919225573008">"Verbinding maken"</string> <string name="connected_headset" msgid="4047751837023241955">"Verbonden"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Kan geen verbinding maken"</string> diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 89c115fc..5e04d33a 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Komunikacja NFC włączona."</string> <string name="touch" msgid="4727218133711188355">"Dotknij, aby przesłać"</string> <string name="beam_progress" msgid="7453634884807323920">"Odbieram dane zbliżeniowo..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Przesyłam..."</string> <string name="beam_complete" msgid="477026736424637435">"Przesyłanie zbliżeniowe zakończone"</string> <string name="beam_failed" msgid="5116241718189888630">"Przesyłanie zbliżeniowe nie udało się"</string> <string name="beam_canceled" msgid="5425192751826544741">"Przesyłanie zbliżeniowe zostało anulowane"</string> <string name="cancel" msgid="61873902552555096">"Anuluj"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Dotknij, by wyświetlić"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Urządzenie odbierające nie pozwala na zbliżeniowe przesyłanie dużych plików."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Zbliż urządzenia do siebie"</string> <string name="connecting_headset" msgid="3929250919225573008">"Łączenie"</string> <string name="connected_headset" msgid="4047751837023241955">"Połączono"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Nie można nawiązać połączenia"</string> diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 3ff9d203..89d56290 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -8,14 +8,16 @@ <string name="outbound_me_profile_title" msgid="2523625031572784769">"Interação NFC completa"</string> <string name="outbound_me_profile_text" msgid="5594998841143667989">"Toque para dar a esta pessoa as suas informações de contacto."</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC ativado."</string> - <string name="touch" msgid="4727218133711188355">"Toque para transmitir"</string> + <string name="touch" msgid="4727218133711188355">"Tocar para transmitir"</string> <string name="beam_progress" msgid="7453634884807323920">"A receber partilha..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"A transmitir..."</string> <string name="beam_complete" msgid="477026736424637435">"Partilha concluída"</string> <string name="beam_failed" msgid="5116241718189888630">"A partilha não foi concluída"</string> <string name="beam_canceled" msgid="5425192751826544741">"Partilha cancelada"</string> <string name="cancel" msgid="61873902552555096">"Cancelar"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tocar para ver"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"O dispositivo do recetor não suporta a transferência de ficheiros grandes através de partilha."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Juntar os dispositivos novamente"</string> <string name="connecting_headset" msgid="3929250919225573008">"A ligar"</string> <string name="connected_headset" msgid="4047751837023241955">"Ligado"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Não foi possível ligar"</string> diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index fed4fbfa..53aa0be9 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -8,14 +8,16 @@ <string name="outbound_me_profile_title" msgid="2523625031572784769">"Interação de NFC completa"</string> <string name="outbound_me_profile_text" msgid="5594998841143667989">"Toque para fornecer suas informações de contato para essa pessoa"</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC habilitado."</string> - <string name="touch" msgid="4727218133711188355">"Toque para iluminar"</string> - <string name="beam_progress" msgid="7453634884807323920">"Feixe de entrada..."</string> - <string name="beam_complete" msgid="477026736424637435">"Irradiação concluída"</string> - <string name="beam_failed" msgid="5116241718189888630">"O feixe não foi concluído"</string> - <string name="beam_canceled" msgid="5425192751826544741">"Feixe cancelado"</string> + <string name="touch" msgid="4727218133711188355">"Toque para enviar"</string> + <string name="beam_progress" msgid="7453634884807323920">"Beam chegando..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Enviando..."</string> + <string name="beam_complete" msgid="477026736424637435">"Envio concluído"</string> + <string name="beam_failed" msgid="5116241718189888630">"O envio não foi concluído"</string> + <string name="beam_canceled" msgid="5425192751826544741">"Envio cancelado"</string> <string name="cancel" msgid="61873902552555096">"Cancelar"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Toque para visualizar"</string> - <string name="beam_handover_not_supported" msgid="4083165921751489015">"O dispositivo receptor não suporta a transferência de arquivos grandes através do feixe."</string> + <string name="beam_handover_not_supported" msgid="4083165921751489015">"O dispositivo receptor não suporta a transferência de arquivos grandes por meio do Android Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Una dispositivos novamente"</string> <string name="connecting_headset" msgid="3929250919225573008">"Conectando"</string> <string name="connected_headset" msgid="4047751837023241955">"Conectado"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Não foi possível conectar"</string> diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index ce71a2b0..3623493f 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -10,27 +10,22 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC activat."</string> <string name="touch" msgid="4727218133711188355">"Atingeţi pentru transmitere"</string> <string name="beam_progress" msgid="7453634884807323920">"Transmitere primită..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Se transmite..."</string> <string name="beam_complete" msgid="477026736424637435">"Transmitere încheiată"</string> - <!-- no translation found for beam_failed (5116241718189888630) --> - <skip /> - <!-- no translation found for beam_canceled (5425192751826544741) --> - <skip /> - <!-- no translation found for cancel (61873902552555096) --> - <skip /> + <string name="beam_failed" msgid="5116241718189888630">"Transmiterea nu este finalizată"</string> + <string name="beam_canceled" msgid="5425192751826544741">"Transmitere anulată"</string> + <string name="cancel" msgid="61873902552555096">"Anulaţi"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Atingeţi pentru a afişa"</string> - <!-- no translation found for beam_handover_not_supported (4083165921751489015) --> - <skip /> + <string name="beam_handover_not_supported" msgid="4083165921751489015">"Dispozitivul destinatarului nu acceptă transferul fişierelor mari prin fascicul."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Apropiați dispozitivele din nou"</string> <string name="connecting_headset" msgid="3929250919225573008">"Se conectează"</string> <string name="connected_headset" msgid="4047751837023241955">"Conectat"</string> - <!-- no translation found for connect_headset_failed (7500801585498094863) --> - <skip /> + <string name="connect_headset_failed" msgid="7500801585498094863">"Conectarea nu s-a putut realiza."</string> <string name="disconnecting_headset" msgid="868262189044372780">"Se deconectează"</string> <string name="disconnected_headset" msgid="4066109452701733916">"Deconectat"</string> <string name="pairing_headset" msgid="6443461444755646137">"Se împerechează"</string> - <!-- no translation found for pairing_headset_failed (6509629663883514688) --> - <skip /> - <!-- no translation found for failed_to_enable_bt (7229153323594758077) --> - <skip /> + <string name="pairing_headset_failed" msgid="6509629663883514688">"Împerecherea a eşuat"</string> + <string name="failed_to_enable_bt" msgid="7229153323594758077">"Activarea Bluetooth a eşuat"</string> <string name="confirm_pairing" msgid="4112568077038265363">"Sigur doriţi să împerecheaţi dispozitivul Bluetooth <xliff:g id="DEVICE_NAME">%1$s</xliff:g>?"</string> <string name="pair_yes" msgid="3525614878559994448">"Da"</string> <string name="pair_no" msgid="5022308368904055020">"Nu"</string> diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 1d466fcb..bb4ce034 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Служба NFC включена"</string> <string name="touch" msgid="4727218133711188355">"Нажмите, чтобы передать данные"</string> <string name="beam_progress" msgid="7453634884807323920">"Получение данных…"</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Передача данных..."</string> <string name="beam_complete" msgid="477026736424637435">"Передача данных завершена"</string> <string name="beam_failed" msgid="5116241718189888630">"Передача данных не завершена"</string> <string name="beam_canceled" msgid="5425192751826544741">"Передача данных отменена"</string> <string name="cancel" msgid="61873902552555096">"Отмена"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Нажмите, чтобы просмотреть"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Устройство получателя не поддерживает передачу больших объемов данных через Android Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Повторить попытку"</string> <string name="connecting_headset" msgid="3929250919225573008">"Подключение…"</string> <string name="connected_headset" msgid="4047751837023241955">"Подключено"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Не удалось подключиться"</string> diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 21ab94a6..198a7d59 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC povolené."</string> <string name="touch" msgid="4727218133711188355">"Dotykom spustíte prenos"</string> <string name="beam_progress" msgid="7453634884807323920">"Prichádzajúci prenos..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Prenáša sa..."</string> <string name="beam_complete" msgid="477026736424637435">"Prenos bol dokončený"</string> <string name="beam_failed" msgid="5116241718189888630">"Prenos nebol dokončený"</string> <string name="beam_canceled" msgid="5425192751826544741">"Prenos bol zrušený"</string> <string name="cancel" msgid="61873902552555096">"Zrušiť"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Zobrazte dotykom"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Zariadenie príjemcu nepodporuje prenos veľkých súborov prostredníctvom funkcie Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Znova priblížte zariadenia"</string> <string name="connecting_headset" msgid="3929250919225573008">"Prebieha pripájanie"</string> <string name="connected_headset" msgid="4047751837023241955">"Pripojené"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Nepodarilo sa pripojiť"</string> diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 7e2bf317..6288c3b9 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC omogočen."</string> <string name="touch" msgid="4727218133711188355">"Dotaknite se, da pošljete"</string> <string name="beam_progress" msgid="7453634884807323920">"Dohodni prenos ..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Prenašanje ..."</string> <string name="beam_complete" msgid="477026736424637435">"Prenos končan"</string> <string name="beam_failed" msgid="5116241718189888630">"Prenos se ni končal"</string> <string name="beam_canceled" msgid="5425192751826544741">"Prenos je preklican"</string> <string name="cancel" msgid="61873902552555096">"Prekliči"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Dotaknite se za prikaz"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Prejemnikova naprava ne podpira prenosa velikih datotek prek funkcije Android Beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Znova združi naprave"</string> <string name="connecting_headset" msgid="3929250919225573008">"Vzpostavljanje povezave"</string> <string name="connected_headset" msgid="4047751837023241955">"Povezano"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Povezava ni mogoča"</string> diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 0b0f2290..ffe8493f 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC је омогућен."</string> <string name="touch" msgid="4727218133711188355">"Додирните за емитовање"</string> <string name="beam_progress" msgid="7453634884807323920">"Долазно пребацивање..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Пребацивање..."</string> <string name="beam_complete" msgid="477026736424637435">"Пребацивање је довршено"</string> <string name="beam_failed" msgid="5116241718189888630">"Пребацивање се није завршило"</string> <string name="beam_canceled" msgid="5425192751826544741">"Пребацивање је отказано"</string> <string name="cancel" msgid="61873902552555096">"Откажи"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Додирните да бисте прегледали"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Уређај пријемника не подржава пренос великих датотека пребацивањем."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Поново приближите уређаје"</string> <string name="connecting_headset" msgid="3929250919225573008">"Повезивање"</string> <string name="connected_headset" msgid="4047751837023241955">"Повезано"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Повезивање није могуће"</string> diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 14c701c9..c6b950a5 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC aktiverat."</string> <string name="touch" msgid="4727218133711188355">"Tryck här om du vill överföra"</string> <string name="beam_progress" msgid="7453634884807323920">"Inkommande trådlös överföring ..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Överför trådlöst ..."</string> <string name="beam_complete" msgid="477026736424637435">"Den trådlösa överföringen har slutförts"</string> <string name="beam_failed" msgid="5116241718189888630">"Den trådlösa överföringen slutfördes inte"</string> <string name="beam_canceled" msgid="5425192751826544741">"Den trådlösa överföringen avbröts"</string> <string name="cancel" msgid="61873902552555096">"Avbryt"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Tryck och visa"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Mottagarens enheten stöder inte trådlös överföring av stora filer."</string> + <string name="beam_try_again" msgid="3364677301009783455">"För samman enheterna igen"</string> <string name="connecting_headset" msgid="3929250919225573008">"Anslutningen upprättas"</string> <string name="connected_headset" msgid="4047751837023241955">"Anslutningen har upprättats"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Det gick inte att ansluta"</string> diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index a337161f..0cd4dd56 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -5,17 +5,19 @@ <string name="nfcUserLabel" msgid="7708535817084357357">"NFC"</string> <string name="inbound_me_profile_title" msgid="6146013785225412693">"Anwani imepokewa kupitia NFC"</string> <string name="inbound_me_profile_text" msgid="2342757196108092923">"Gusa ili kuongeza mtu huyu kama mwasiliani"</string> - <string name="outbound_me_profile_title" msgid="2523625031572784769">"NFC imekamilisha kuingiliana"</string> + <string name="outbound_me_profile_title" msgid="2523625031572784769">"NFC imemaliza kushirikiana"</string> <string name="outbound_me_profile_text" msgid="5594998841143667989">"Gusa ili kumpa mtu huyu maelezo yako ya mawasiliano."</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC imewezeshwa."</string> <string name="touch" msgid="4727218133711188355">"Gusa kwa boriti"</string> <string name="beam_progress" msgid="7453634884807323920">"Boriti zinazoingia..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Inasambaza..."</string> <string name="beam_complete" msgid="477026736424637435">"Boriti umekamilika"</string> <string name="beam_failed" msgid="5116241718189888630">"Boriti haikukamilisha"</string> <string name="beam_canceled" msgid="5425192751826544741">"Boriti imeghairiwa"</string> <string name="cancel" msgid="61873902552555096">"Ghairi"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Gusa ili utazame"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Kifaa cha upokeaji hakihimili uhamishaji wa faili kubwa kupitia kwenye boriti."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Unganisha vifaa tena"</string> <string name="connecting_headset" msgid="3929250919225573008">"Inaunganisha"</string> <string name="connected_headset" msgid="4047751837023241955">"Imeunganishwa"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Haikuweza kuunganisha"</string> diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index ccacf94b..5fbd740c 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -8,14 +8,16 @@ <string name="outbound_me_profile_title" msgid="2523625031572784769">"ดำเนินการโต้ตอบกับ NFC ให้เสร็จสมบูรณ์"</string> <string name="outbound_me_profile_text" msgid="5594998841143667989">"แตะเพื่อให้ข้อมูลที่อยู่ติดต่อของคุณแก่คนนี้"</string> <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"เปิดใช้งาน NFC แล้ว"</string> - <string name="touch" msgid="4727218133711188355">"แตะเพื่อส่ง"</string> + <string name="touch" msgid="4727218133711188355">"แตะเพื่อบีม"</string> <string name="beam_progress" msgid="7453634884807323920">"บีมขาเข้า..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"กำลังบีม..."</string> <string name="beam_complete" msgid="477026736424637435">"บีมสำเร็จ"</string> <string name="beam_failed" msgid="5116241718189888630">"บีมไม่เสร็จสมบูรณ์"</string> <string name="beam_canceled" msgid="5425192751826544741">"ยกเลิกบีมแล้ว"</string> <string name="cancel" msgid="61873902552555096">"ยกเลิก"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"แตะเพื่อดู"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"อุปกรณ์ของผู้รับไม่สนับสนุนการถ่ายโอนไฟล์ขนาดใหญ่ผ่านการบีม"</string> + <string name="beam_try_again" msgid="3364677301009783455">"นำอุปกรณ์มารวมกันอีกครั้ง"</string> <string name="connecting_headset" msgid="3929250919225573008">"กำลังเชื่อมต่อ"</string> <string name="connected_headset" msgid="4047751837023241955">"เชื่อมต่อแล้ว"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"เชื่อมต่อไม่ได้"</string> diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 86a2ef72..a5c330f0 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Pinagana ang NFC."</string> <string name="touch" msgid="4727218133711188355">"Pindutin upang i-beam"</string> <string name="beam_progress" msgid="7453634884807323920">"Dumarating na beam..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Nagbi-beam..."</string> <string name="beam_complete" msgid="477026736424637435">"Kumpleto na ang pag-beam"</string> <string name="beam_failed" msgid="5116241718189888630">"Hindi nakumpleto ang beam"</string> <string name="beam_canceled" msgid="5425192751826544741">"Kinansela ang beam"</string> <string name="cancel" msgid="61873902552555096">"Kanselahin"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Pindutin upang tingnan"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Hindi sinusuportahan ng device ng receiver ang malaking paglipat ng file sa pamamagitan ng beam."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Pagsamahing muli ang mga device"</string> <string name="connecting_headset" msgid="3929250919225573008">"Kumokonekta"</string> <string name="connected_headset" msgid="4047751837023241955">"Nakakonekta"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Hindi makakonekta"</string> diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index f2306e91..b11bac6a 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC etkin."</string> <string name="touch" msgid="4727218133711188355">"Göndermek için dokunun"</string> <string name="beam_progress" msgid="7453634884807323920">"Gelen ışın..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Işınlanıyor..."</string> <string name="beam_complete" msgid="477026736424637435">"Işınlama tamamlandı"</string> <string name="beam_failed" msgid="5116241718189888630">"Işınlama tamamlanmadı"</string> <string name="beam_canceled" msgid="5425192751826544741">"Işınlama iptal edildi"</string> <string name="cancel" msgid="61873902552555096">"İptal"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Görüntülemek için dokunun"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Alıcının cihazı yüksek boyutlu dosyaların ışınlamayla aktarılmasını desteklemiyor."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Cihazları tekrar bir araya getirin"</string> <string name="connecting_headset" msgid="3929250919225573008">"Bağlanıyor"</string> <string name="connected_headset" msgid="4047751837023241955">"Bağlandı"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Bağlantı kurulamadı"</string> @@ -24,7 +26,7 @@ <string name="pairing_headset" msgid="6443461444755646137">"Eşleştiriliyor"</string> <string name="pairing_headset_failed" msgid="6509629663883514688">"Eşleştirilemedi"</string> <string name="failed_to_enable_bt" msgid="7229153323594758077">"Bluetooth etkinleştirilemedi"</string> - <string name="confirm_pairing" msgid="4112568077038265363">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı Bluetooth cihazını eşleştirmek istediğinizden emin misiniz?"</string> + <string name="confirm_pairing" msgid="4112568077038265363">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı Bluetooth cihazını eşlemek istediğinizden emin misiniz?"</string> <string name="pair_yes" msgid="3525614878559994448">"Evet"</string> <string name="pair_no" msgid="5022308368904055020">"Hayır"</string> </resources> diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 0bb6aac4..189cba80 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC увімкнено."</string> <string name="touch" msgid="4727218133711188355">"Торкніться, щоб передати дані"</string> <string name="beam_progress" msgid="7453634884807323920">"Вхідне передавання даних..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Передавання даних…"</string> <string name="beam_complete" msgid="477026736424637435">"Передавання даних виконано"</string> <string name="beam_failed" msgid="5116241718189888630">"Передавання даних не завершено"</string> <string name="beam_canceled" msgid="5425192751826544741">"Передавання даних скасовано"</string> <string name="cancel" msgid="61873902552555096">"Скасувати"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Торкніться, щоб переглянути"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Пристрій отримувача не підтримує пересилання великих файлів за допомогою функції Передавання даних Android."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Знову притуліть пристрої один до одного"</string> <string name="connecting_headset" msgid="3929250919225573008">"Під’єднання"</string> <string name="connected_headset" msgid="4047751837023241955">"Під’єднано"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Не вдалося з’єднатись"</string> diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 5f887fc8..5cbe7cb3 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"Đã bật NFC."</string> <string name="touch" msgid="4727218133711188355">"Chạm để truyền"</string> <string name="beam_progress" msgid="7453634884807323920">"Tia đến..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Đang chiếu..."</string> <string name="beam_complete" msgid="477026736424637435">"Hoàn tất chiếu"</string> <string name="beam_failed" msgid="5116241718189888630">"Chiếu chưa hoàn tất"</string> <string name="beam_canceled" msgid="5425192751826544741">"Chiếu bị hủy"</string> <string name="cancel" msgid="61873902552555096">"Hủy"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Chạm để xem"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Thiết bị của người nhận không hỗ trợ truyền tệp lớn qua quá trình chiếu."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Nhóm các thiết bị lại với nhau lần nữa"</string> <string name="connecting_headset" msgid="3929250919225573008">"Đang kết nối"</string> <string name="connected_headset" msgid="4047751837023241955">"Đã kết nối"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Không thể kết nối"</string> diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 2cd45ae5..19738329 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC 已启用。"</string> <string name="touch" msgid="4727218133711188355">"触摸即可发送"</string> <string name="beam_progress" msgid="7453634884807323920">"正在接收 Beam 内容..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"正在用 Beam 传送信息..."</string> <string name="beam_complete" msgid="477026736424637435">"Beam 发送完毕"</string> <string name="beam_failed" msgid="5116241718189888630">"Beam 发送未完成"</string> <string name="beam_canceled" msgid="5425192751826544741">"Beam 发送已取消"</string> <string name="cancel" msgid="61873902552555096">"取消"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"触摸即可查看"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"接收者的设备不支持通过 Beam 传输较大的文件。"</string> + <string name="beam_try_again" msgid="3364677301009783455">"再次让两台设备接触"</string> <string name="connecting_headset" msgid="3929250919225573008">"正在连接"</string> <string name="connected_headset" msgid="4047751837023241955">"已连接"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"无法连接"</string> diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 16d16ecf..34d2a867 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"NFC 已啟用。"</string> <string name="touch" msgid="4727218133711188355">"輕觸即可傳輸"</string> <string name="beam_progress" msgid="7453634884807323920">"正在接收傳輸..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"即時傳輸中..."</string> <string name="beam_complete" msgid="477026736424637435">"傳輸完成"</string> <string name="beam_failed" msgid="5116241718189888630">"傳輸未完成"</string> <string name="beam_canceled" msgid="5425192751826544741">"傳輸已取消"</string> <string name="cancel" msgid="61873902552555096">"取消"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"輕觸即可查看"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"接收者的裝置不支援透過 Beam 傳輸大型檔案。"</string> + <string name="beam_try_again" msgid="3364677301009783455">"再次將裝置放在一起"</string> <string name="connecting_headset" msgid="3929250919225573008">"連線中"</string> <string name="connected_headset" msgid="4047751837023241955">"已連線"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"無法連線"</string> diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 2698bea4..9d9759b7 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -10,12 +10,14 @@ <string name="accessibility_nfc_enabled" msgid="7796246979948787735">"I-NFC ivunyelwe."</string> <string name="touch" msgid="4727218133711188355">"Cindezela kwibhimu"</string> <string name="beam_progress" msgid="7453634884807323920">"Ukuvumelanisa okungenayo..."</string> + <string name="beam_outgoing" msgid="4679536649779123495">"Ukuvumelanisa..."</string> <string name="beam_complete" msgid="477026736424637435">"Ukuvumelanisa kuqedile"</string> <string name="beam_failed" msgid="5116241718189888630">"Ukuvumelanisa akuqedile"</string> <string name="beam_canceled" msgid="5425192751826544741">"Ukuvumelanisa kukhanseliwe"</string> <string name="cancel" msgid="61873902552555096">"Khansela"</string> <string name="beam_touch_to_view" msgid="7853129156831642630">"Thinta ukuze ubuke"</string> <string name="beam_handover_not_supported" msgid="4083165921751489015">"Idivayisi yomamukeli ayisekeli ukuhanjiswa kwamafayela amakhulu ngokuvumelanisa."</string> + <string name="beam_try_again" msgid="3364677301009783455">"Phinda uhlanganise ndawonye amadivayisi"</string> <string name="connecting_headset" msgid="3929250919225573008">"Iyaxhuma"</string> <string name="connected_headset" msgid="4047751837023241955">"Ixhunyiwe"</string> <string name="connect_headset_failed" msgid="7500801585498094863">"Ayikwazanga ukuxhuma"</string> diff --git a/res/values/provisioning.xml b/res/values/provisioning.xml new file mode 100644 index 00000000..74e44187 --- /dev/null +++ b/res/values/provisioning.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- NFC resources that may need to be customized + for different hardware or product builds. --> +<resources> + <!-- Whether the device can receive NFC data in setup wizard --> + <bool name="enable_nfc_provisioning">false</bool> + + <!-- The accepted mime-types when NFC is enabled in setup wizard. + Mime-types must be lower case, wildcards are *not* accepted. --> + <string-array name="provisioning_mime_types"> + </string-array> +</resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index 50cbf63c..b9449376 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -20,12 +20,14 @@ <string name="touch">Touch to beam</string> <string name="beam_progress">Incoming beam...</string> + <string name="beam_outgoing">Beaming...</string> <string name="beam_complete">Beam complete</string> <string name="beam_failed">Beam did not complete</string> <string name="beam_canceled">Beam canceled</string> <string name="cancel">Cancel</string> <string name="beam_touch_to_view">Touch to view</string> <string name="beam_handover_not_supported">The receiver\'s device doesn\'t support large file transfer via beam.</string> + <string name="beam_try_again">Bring devices together again</string> <string name="connecting_headset">Connecting</string> <string name="connected_headset">Connected</string> diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java index bfd5d9cf..d93e2029 100755 --- a/src/com/android/nfc/DeviceHost.java +++ b/src/com/android/nfc/DeviceHost.java @@ -45,6 +45,8 @@ public interface DeviceHost { */ public void onLlcpLinkDeactivated(NfcDepEndpoint device); + public void onLlcpFirstPacketReceived(NfcDepEndpoint device); + public void onRemoteFieldActivated(); public void onRemoteFieldDeactivated(); diff --git a/src/com/android/nfc/NfcDispatcher.java b/src/com/android/nfc/NfcDispatcher.java index 1721d1a8..90316ba7 100644 --- a/src/com/android/nfc/NfcDispatcher.java +++ b/src/com/android/nfc/NfcDispatcher.java @@ -33,6 +33,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.content.res.Resources.NotFoundException; import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; @@ -63,19 +64,35 @@ public class NfcDispatcher { final RegisteredComponentCache mTechListFilters; final ContentResolver mContentResolver; final HandoverManager mHandoverManager; + final String[] mProvisioningMimes; // Locked on this PendingIntent mOverrideIntent; IntentFilter[] mOverrideFilters; String[][] mOverrideTechLists; + boolean mProvisioningOnly; - public NfcDispatcher(Context context, HandoverManager handoverManager) { + public NfcDispatcher(Context context, HandoverManager handoverManager, boolean provisionOnly) { mContext = context; mIActivityManager = ActivityManagerNative.getDefault(); mTechListFilters = new RegisteredComponentCache(mContext, NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED); mContentResolver = context.getContentResolver(); mHandoverManager = handoverManager; + synchronized (this) { + mProvisioningOnly = provisionOnly; + } + String[] provisionMimes = null; + if (provisionOnly) { + try { + // Get accepted mime-types + provisionMimes = context.getResources(). + getStringArray(R.array.provisioning_mime_types); + } catch (NotFoundException e) { + provisionMimes = null; + } + } + mProvisioningMimes = provisionMimes; } public synchronized void setForegroundDispatch(PendingIntent intent, @@ -86,6 +103,10 @@ public class NfcDispatcher { mOverrideTechLists = techLists; } + public synchronized void disableProvisioningMode() { + mProvisioningOnly = false; + } + /** * Helper for re-used objects and methods during a single tag dispatch. */ @@ -191,12 +212,14 @@ public class NfcDispatcher { PendingIntent overrideIntent; IntentFilter[] overrideFilters; String[][] overrideTechLists; + boolean provisioningOnly; DispatchInfo dispatch = new DispatchInfo(mContext, tag, message); synchronized (this) { overrideFilters = mOverrideFilters; overrideIntent = mOverrideIntent; overrideTechLists = mOverrideTechLists; + provisioningOnly = mProvisioningOnly; } resumeAppSwitches(); @@ -205,15 +228,20 @@ public class NfcDispatcher { return true; } - if (mHandoverManager.tryHandover(message)) { + if (!provisioningOnly && mHandoverManager.tryHandover(message)) { if (DBG) Log.i(TAG, "matched BT HANDOVER"); return true; } - if (tryNdef(dispatch, message)) { + if (tryNdef(dispatch, message, provisioningOnly)) { return true; } + if (provisioningOnly) { + // We only allow NDEF-based mimeType matching + return false; + } + if (tryTech(dispatch, tag)) { return true; } @@ -304,7 +332,7 @@ public class NfcDispatcher { return false; } - boolean tryNdef(DispatchInfo dispatch, NdefMessage message) { + boolean tryNdef(DispatchInfo dispatch, NdefMessage message, boolean provisioningOnly) { if (message == null) { return false; } @@ -313,6 +341,14 @@ public class NfcDispatcher { // Bail out if the intent does not contain filterable NDEF data if (intent == null) return false; + if (provisioningOnly) { + if (mProvisioningMimes == null || + !(Arrays.asList(mProvisioningMimes).contains(intent.getType()))) { + Log.e(TAG, "Dropping NFC intent in provisioning mode."); + return false; + } + } + // Try to start AAR activity with matching filter List<String> aarPackages = extractAarPackages(message); for (String pkg : aarPackages) { @@ -408,7 +444,7 @@ public class NfcDispatcher { if (DBG) Log.i(TAG, "matched single TECH"); return true; } - dispatch.intent.setClassName((String)null, null); + dispatch.intent.setComponent(null); } else if (matches.size() > 1) { // Multiple matches, show a custom activity chooser dialog Intent intent = new Intent(mContext, TechListChooserActivity.class); diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 952b391c..1876a9e8 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -37,6 +37,7 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.res.Resources.NotFoundException; import android.media.AudioManager; import android.media.SoundPool; import android.net.Uri; @@ -55,6 +56,7 @@ import android.nfc.tech.Ndef; import android.nfc.tech.TagTechnology; import android.os.AsyncTask; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -63,6 +65,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; @@ -115,6 +118,7 @@ public class NfcService implements DeviceHostListener { 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 MSG_LLCP_LINK_FIRST_PACKET = 15; static final int TASK_ENABLE = 1; static final int TASK_DISABLE = 2; @@ -132,6 +136,15 @@ public class NfcService implements DeviceHostListener { static final int ROUTE_OFF = 1; static final int ROUTE_ON_WHEN_SCREEN_ON = 2; + // Return values from NfcEe.open() - these are 1:1 mapped + // to the thrown EE_EXCEPTION_ exceptions in nfc-extras. + static final int EE_ERROR_IO = -1; + static final int EE_ERROR_ALREADY_OPEN = -2; + static final int EE_ERROR_INIT = -3; + static final int EE_ERROR_LISTEN_MODE = -4; + static final int EE_ERROR_EXT_FIELD = -5; + static final int EE_ERROR_NFC_DISABLED = -6; + /** minimum screen state that enables NFC polling (discovery) */ static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; @@ -144,6 +157,12 @@ public class NfcService implements DeviceHostListener { // goes off static final int ROUTING_WATCHDOG_MS = 10000; + // Amount of time to wait before closing the NFCEE connection + // in a disable/shutdown scenario. + static final int WAIT_FOR_NFCEE_OPERATIONS_MS = 5000; + // Polling interval for waiting on NFCEE operations + static final int WAIT_FOR_NFCEE_POLL_MS = 100; + // for use with playSound() public static final int SOUND_START = 0; public static final int SOUND_END = 1; @@ -157,6 +176,12 @@ public class NfcService implements DeviceHostListener { "com.android.nfc_extras.action.AID_SELECTED"; public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; + public static final String ACTION_LLCP_UP = + "com.android.nfc.action.LLCP_UP"; + + public static final String ACTION_LLCP_DOWN = + "com.android.nfc.action.LLCP_DOWN"; + public static final String ACTION_APDU_RECEIVED = "com.android.nfc_extras.action.APDU_RECEIVED"; public static final String EXTRA_APDU_BYTES = @@ -190,6 +215,7 @@ public class NfcService implements DeviceHostListener { // as SE access is not granted for non-owner users. HashSet<String> mSePackages = new HashSet<String>(); int mScreenState; + boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning boolean mIsNdefPushEnabled; boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling @@ -218,11 +244,14 @@ public class NfcService implements DeviceHostListener { NfcAdapterExtrasService mExtrasService; boolean mIsAirplaneSensitive; boolean mIsAirplaneToggleable; + boolean mIsDebugBuild; NfceeAccessControl mNfceeAccessControl; private NfcDispatcher mNfcDispatcher; private PowerManager mPowerManager; private KeyguardManager mKeyguard; + private HandoverManager mHandoverManager; + private ContentResolver mContentResolver; private static NfcService sService; @@ -285,6 +314,14 @@ public class NfcService implements DeviceHostListener { sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); } + /** + * Notifies P2P Device detected, first packet received over LLCP link + */ + @Override + public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { + sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); + } + @Override public void onRemoteFieldActivated() { sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); @@ -331,12 +368,27 @@ public class NfcService implements DeviceHostListener { sService = this; mContext = nfcApplication; + mContentResolver = mContext.getContentResolver(); mDeviceHost = new NativeNfcManager(mContext, this); - HandoverManager handoverManager = new HandoverManager(mContext); - mNfcDispatcher = new NfcDispatcher(mContext, handoverManager); + mHandoverManager = new HandoverManager(mContext); + boolean isNfcProvisioningEnabled = false; + try { + isNfcProvisioningEnabled = mContext.getResources().getBoolean( + R.bool.enable_nfc_provisioning); + } catch (NotFoundException e) { + } - mP2pLinkManager = new P2pLinkManager(mContext, handoverManager, + if (isNfcProvisioningEnabled) { + mInProvisionMode = Settings.Secure.getInt(mContentResolver, + Settings.Global.DEVICE_PROVISIONED, 0) == 0; + } else { + mInProvisionMode = false; + } + + mHandoverManager.setEnabled(!mInProvisionMode); + mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode); + mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager, mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); mSecureElement = new NativeNfcSecureElement(mContext); @@ -350,6 +402,8 @@ public class NfcService implements DeviceHostListener { mState = NfcAdapter.STATE_OFF; mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); + mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mRoutingWakeLock = mPowerManager.newWakeLock( @@ -382,6 +436,7 @@ public class NfcService implements DeviceHostListener { filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_PRESENT); + filter.addAction(Intent.ACTION_USER_SWITCHED); registerForAirplaneMode(filter); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); @@ -411,16 +466,15 @@ public class NfcService implements DeviceHostListener { } void registerForAirplaneMode(IntentFilter filter) { - final ContentResolver resolver = mContext.getContentResolver(); - final String airplaneModeRadios = Settings.System.getString(resolver, - Settings.System.AIRPLANE_MODE_RADIOS); - final String toggleableRadios = Settings.System.getString(resolver, - Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); + final String airplaneModeRadios = Settings.System.getString(mContentResolver, + Settings.Global.AIRPLANE_MODE_RADIOS); + final String toggleableRadios = Settings.System.getString(mContentResolver, + Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); mIsAirplaneSensitive = airplaneModeRadios == null ? true : - airplaneModeRadios.contains(Settings.System.RADIO_NFC); + airplaneModeRadios.contains(Settings.Global.RADIO_NFC); mIsAirplaneToggleable = toggleableRadios == null ? false : - toggleableRadios.contains(Settings.System.RADIO_NFC); + toggleableRadios.contains(Settings.Global.RADIO_NFC); if (mIsAirplaneSensitive) { filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); @@ -624,6 +678,25 @@ public class NfcService implements DeviceHostListener { mP2pLinkManager.enableDisable(false, false); + /* The NFC-EE may still be opened by another process, + * and a transceive() could still be in progress on + * another Binder thread. + * Give it a while to finish existing operations + * before we close it. + */ + Long startTime = SystemClock.elapsedRealtime(); + do { + synchronized (NfcService.this) { + if (mOpenEe == null) + break; + } + try { + Thread.sleep(WAIT_FOR_NFCEE_POLL_MS); + } catch (InterruptedException e) { + // Ignore + } + } while (SystemClock.elapsedRealtime() - startTime < WAIT_FOR_NFCEE_OPERATIONS_MS); + synchronized (NfcService.this) { if (mOpenEe != null) { try { @@ -675,7 +748,7 @@ public class NfcService implements DeviceHostListener { try { Log.i(TAG, "Executing SE wipe"); handle = doOpenSecureElementConnection(); - if (handle == 0) { + if (handle < 0) { Log.w(TAG, "Could not open the secure element"); return; } @@ -699,7 +772,7 @@ public class NfcService implements DeviceHostListener { mDeviceHost.resetTimeouts(); } } finally { - if (handle != 0) { + if (handle >= 0) { doDisconnect(handle); } } @@ -902,7 +975,7 @@ public class NfcService implements DeviceHostListener { @Override public void setNdefPushCallback(INdefPushCallback callback) { mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); - mP2pLinkManager.setNdefCallback(callback); + mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); } @Override @@ -1329,10 +1402,11 @@ public class NfcService implements DeviceHostListener { p.putInt("e", 0); return p; } - private Bundle writeIoException(IOException e) { + + private Bundle writeEeException(int exceptionType, String message) { Bundle p = new Bundle(); - p.putInt("e", -1); - p.putString("m", e.getMessage()); + p.putInt("e", exceptionType); + p.putString("m", message); return p; } @@ -1341,27 +1415,58 @@ public class NfcService implements DeviceHostListener { NfcService.this.enforceNfceeAdminPerm(pkg); Bundle result; - try { - _open(b); + int handle = _open(b); + if (handle < 0) { + result = writeEeException(handle, "NFCEE open exception."); + } else { result = writeNoException(); - } catch (IOException e) { - result = writeIoException(e); } return result; } - private void _open(IBinder b) throws IOException { + /** + * Opens a connection to the secure element. + * + * @return A handle with a value >= 0 in case of success, or a + * negative value in case of failure. + */ + private int _open(IBinder b) { synchronized(NfcService.this) { if (!isNfcEnabled()) { - throw new IOException("NFC adapter is disabled"); + return EE_ERROR_NFC_DISABLED; + } + if (mInProvisionMode) { + // Deny access to the NFCEE as long as the device is being setup + return EE_ERROR_IO; + } + if (mDeviceHost.enablePN544Quirks() && mP2pLinkManager.isLlcpActive()) { + // Don't allow PN544-based devices to open the SE while the LLCP + // link is still up or in a debounce state. This avoids race + // conditions in the NXP stack around P2P/SMX switching. + return EE_ERROR_EXT_FIELD; } if (mOpenEe != null) { - throw new IOException("NFC EE already open"); + return EE_ERROR_ALREADY_OPEN; + } + + boolean restorePolling = false; + if (mDeviceHost.enablePN544Quirks() && mNfcPollingEnabled) { + // Disable polling for tags/P2P when connecting to the SMX + // on PN544-based devices. Whenever nfceeClose is called, + // the polling configuration will be restored. + mDeviceHost.disableDiscovery(); + mNfcPollingEnabled = false; + restorePolling = true; } int handle = doOpenSecureElementConnection(); - if (handle == 0) { - throw new IOException("NFC EE failed to open"); + if (handle < 0) { + + if (restorePolling) { + mDeviceHost.enableDiscovery(); + mNfcPollingEnabled = true; + } + return handle; } mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000); @@ -1377,6 +1482,8 @@ public class NfcService implements DeviceHostListener { for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) { mSePackages.add(packageName); } + + return handle; } } @@ -1389,7 +1496,7 @@ public class NfcService implements DeviceHostListener { _nfcEeClose(getCallingPid(), binder); result = writeNoException(); } catch (IOException e) { - result = writeIoException(e); + result = writeEeException(EE_ERROR_IO, e.getMessage()); } return result; } @@ -1405,7 +1512,7 @@ public class NfcService implements DeviceHostListener { result = writeNoException(); result.putByteArray("out", out); } catch (IOException e) { - result = writeIoException(e); + result = writeEeException(EE_ERROR_IO, e.getMessage()); } return result; } @@ -1505,8 +1612,9 @@ public class NfcService implements DeviceHostListener { } class WatchDogThread extends Thread { - boolean mWatchDogCanceled = false; + final Object mCancelWaiter = new Object(); final int mTimeout; + boolean mCanceled = false; public WatchDogThread(String threadName, int timeout) { super(threadName); @@ -1515,24 +1623,27 @@ public class NfcService implements DeviceHostListener { @Override public void run() { - boolean slept = false; - while (!slept) { - try { - Thread.sleep(mTimeout); - slept = true; - } catch (InterruptedException e) { } - } - synchronized (this) { - if (!mWatchDogCanceled) { - // Trigger watch-dog - Log.e(TAG, "Watchdog fired: name=" + getName() + " threadId=" + - getId() + " timeout=" + mTimeout); - mDeviceHost.doAbort(); + try { + synchronized (mCancelWaiter) { + mCancelWaiter.wait(mTimeout); + if (mCanceled) { + return; + } } + } catch (InterruptedException e) { + // Should not happen; fall-through to abort. + Log.w(TAG, "Watchdog thread interruped."); + interrupt(); } + Log.e(TAG, "Watchdog triggered, aborting."); + mDeviceHost.doAbort(); } + public synchronized void cancel() { - mWatchDogCanceled = true; + synchronized (mCancelWaiter) { + mCanceled = true; + mCancelWaiter.notify(); + } } } @@ -1546,7 +1657,16 @@ public class NfcService implements DeviceHostListener { return; } WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); - + if (mInProvisionMode) { + mInProvisionMode = Settings.Secure.getInt(mContentResolver, + Settings.Global.DEVICE_PROVISIONED, 0) == 0; + if (!mInProvisionMode) { + // Notify dispatcher it's fine to dispatch to any package now + // and allow handover transfers. + mNfcDispatcher.disableProvisioningMode(); + mHandoverManager.setEnabled(true); + } + } try { watchDog.start(); @@ -1599,6 +1719,13 @@ public class NfcService implements DeviceHostListener { mNfcPollingEnabled = true; mDeviceHost.enableDiscovery(); } + } else if (mInProvisionMode && mScreenState >= SCREEN_STATE_ON_LOCKED) { + // Special case for setup provisioning + if (!mNfcPollingEnabled) { + Log.d(TAG, "NFC-C ON"); + mNfcPollingEnabled = true; + mDeviceHost.enableDiscovery(); + } } else { if (force || mNfcPollingEnabled) { Log.d(TAG, "NFC-C OFF"); @@ -1725,6 +1852,16 @@ public class NfcService implements DeviceHostListener { if (DBG) Log.d(TAG, "Tag detected, notifying applications"); TagEndpoint tag = (TagEndpoint) msg.obj; playSound(SOUND_START); + if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { + // When these tags start containing NDEF, they will require + // the stack to deal with them in a different way, since + // they are activated only really shortly. + // For now, don't consider NDEF on these. + if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); + tag.startPresenceChecking(); + dispatchTagEndpoint(tag); + break; + } NdefMessage ndefMsg = tag.findAndReadNdef(); if (ndefMsg != null) { @@ -1790,10 +1927,18 @@ public class NfcService implements DeviceHostListener { break; case MSG_LLCP_LINK_ACTIVATION: + if (mIsDebugBuild) { + Intent actIntent = new Intent(ACTION_LLCP_UP); + mContext.sendBroadcast(actIntent); + } llcpActivated((NfcDepEndpoint) msg.obj); break; case MSG_LLCP_LINK_DEACTIVATED: + if (mIsDebugBuild) { + Intent deactIntent = new Intent(ACTION_LLCP_DOWN); + mContext.sendBroadcast(deactIntent); + } NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; boolean needsDisconnect = false; @@ -1816,7 +1961,9 @@ public class NfcService implements DeviceHostListener { mP2pLinkManager.onLlcpDeactivated(); break; - + case MSG_LLCP_LINK_FIRST_PACKET: + mP2pLinkManager.onLlcpFirstPacketReceived(); + break; case MSG_TARGET_DESELECTED: /* Broadcast Intent Target Deselected */ if (DBG) Log.d(TAG, "Target Deselected"); @@ -1857,7 +2004,6 @@ public class NfcService implements DeviceHostListener { sendSeBroadcast(listenModeDeactivated); break; } - default: Log.e(TAG, "Unknown message received"); break; @@ -2054,14 +2200,16 @@ public class NfcService implements DeviceHostListener { } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { new EnableDisableTask().execute(TASK_ENABLE); } + } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { + mP2pLinkManager.onUserSwitched(); } } }; /** Returns true if airplane mode is currently on */ boolean isAirplaneModeOn() { - return Settings.System.getInt(mContext.getContentResolver(), - Settings.System.AIRPLANE_MODE_ON, 0) == 1; + return Settings.System.getInt(mContentResolver, + Settings.Global.AIRPLANE_MODE_ON, 0) == 1; } /** for debugging only - no i18n */ diff --git a/src/com/android/nfc/P2pEventManager.java b/src/com/android/nfc/P2pEventManager.java index 68f479b8..2e42b1b1 100644 --- a/src/com/android/nfc/P2pEventManager.java +++ b/src/com/android/nfc/P2pEventManager.java @@ -41,6 +41,7 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback { boolean mSending; boolean mNdefSent; boolean mNdefReceived; + boolean mInDebounce; public P2pEventManager(Context context, P2pEventListener.Callback callback) { mNfcService = NfcService.getInstance(); @@ -68,6 +69,7 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback { mNfcService.playSound(NfcService.SOUND_START); mNdefSent = false; mNdefReceived = false; + mInDebounce = false; mVibrator.vibrate(VIBRATION_PATTERN, -1); if (mSendUi != null) { @@ -131,6 +133,7 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback { if (!mNdefSent && !mNdefReceived && mSendUi != null) { mSendUi.finish(SendUi.FINISH_SCALE_UP); } + mInDebounce = false; } @Override @@ -144,4 +147,25 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback { mSending = true; } + + @Override + public void onP2pSendDebounce() { + mInDebounce = true; + mNfcService.playSound(NfcService.SOUND_ERROR); + if (mSendUi != null) { + mSendUi.showSendHint(); + } + } + + @Override + public void onP2pResumeSend() { + if (mInDebounce) { + mVibrator.vibrate(VIBRATION_PATTERN, -1); + mNfcService.playSound(NfcService.SOUND_START); + if (mSendUi != null) { + mSendUi.showStartSend(); + } + } + mInDebounce = false; + } } diff --git a/src/com/android/nfc/P2pLinkManager.java b/src/com/android/nfc/P2pLinkManager.java index 9b23f65d..fb83e184 100755 --- a/src/com/android/nfc/P2pLinkManager.java +++ b/src/com/android/nfc/P2pLinkManager.java @@ -34,17 +34,16 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; +import android.nfc.BeamShareData; import android.nfc.INdefPushCallback; import android.nfc.NdefMessage; import android.nfc.NdefRecord; +import android.nfc.NfcAdapter; import android.os.AsyncTask; -import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.os.RemoteException; import android.os.SystemClock; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.Profile; +import android.os.UserHandle; import android.util.Log; import java.io.FileDescriptor; @@ -79,6 +78,20 @@ interface P2pEventListener { public void onP2pSendComplete(); /** + * + * Called to indicate the link has broken while we were trying to send + * a message. We'll start a debounce timer for the user to get the devices + * back together. UI may show a hint to achieve that + */ + public void onP2pSendDebounce(); + + /** + * Called to indicate a link has come back up after being temporarily + * broken, and sending is resuming + */ + public void onP2pResumeSend(); + + /** * Called to indicate the remote device does not support connection handover */ public void onP2pHandoverNotSupported(); @@ -127,8 +140,11 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba static final int NDEFPUSH_SAP = 0x10; static final int HANDOVER_SAP = 0x14; - static final int LINK_DEBOUNCE_MS = 750; - + static final int LINK_FIRST_PDU_LIMIT_MS = 200; + static final int LINK_NOTHING_TO_SEND_DEBOUNCE_MS = 750; + static final int LINK_SEND_PENDING_DEBOUNCE_MS = 3000; + static final int LINK_SEND_CONFIRMED_DEBOUNCE_MS = 5000; + static final int LINK_SEND_COMPLETE_DEBOUNCE_MS = 250; static final int MSG_DEBOUNCE_TIMEOUT = 1; static final int MSG_RECEIVE_COMPLETE = 2; static final int MSG_RECEIVE_HANDOVER = 3; @@ -136,32 +152,34 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba static final int MSG_START_ECHOSERVER = 5; static final int MSG_STOP_ECHOSERVER = 6; static final int MSG_HANDOVER_NOT_SUPPORTED = 7; + static final int MSG_SHOW_CONFIRMATION_UI = 8; // values for mLinkState static final int LINK_STATE_DOWN = 1; - static final int LINK_STATE_UP = 2; - static final int LINK_STATE_DEBOUNCE =3; + static final int LINK_STATE_WAITING_PDU = 2; + static final int LINK_STATE_UP = 3; + static final int LINK_STATE_DEBOUNCE = 4; // values for mSendState static final int SEND_STATE_NOTHING_TO_SEND = 1; static final int SEND_STATE_NEED_CONFIRMATION = 2; static final int SEND_STATE_SENDING = 3; + static final int SEND_STATE_SEND_COMPLETE = 4; // return values for doSnepProtocol static final int SNEP_SUCCESS = 0; static final int SNEP_FAILURE = 1; - static final int SNEP_HANDOVER_UNSUPPORTED = 2; - static final Uri PROFILE_URI = Profile.CONTENT_VCARD_URI.buildUpon(). - appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true"). - build(); + // return values for doHandover + static final int HANDOVER_SUCCESS = 0; + static final int HANDOVER_FAILURE = 1; + static final int HANDOVER_UNSUPPORTED = 2; final NdefPushServer mNdefPushServer; final SnepServer mDefaultSnepServer; final HandoverServer mHandoverServer; final EchoServer mEchoServer; final ActivityManager mActivityManager; - final PackageManager mPackageManager; final Context mContext; final P2pEventListener mEventListener; final Handler mHandler; @@ -171,16 +189,26 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba final int mDefaultRwSize; // Locked on NdefP2pManager.this + PackageManager mPackageManager; int mLinkState; int mSendState; // valid during LINK_STATE_UP or LINK_STATE_DEBOUNCE boolean mIsSendEnabled; boolean mIsReceiveEnabled; - NdefMessage mMessageToSend; // valid during SEND_STATE_NEED_CONFIRMATION or SEND_STATE_SENDING - Uri[] mUrisToSend; // valid during SEND_STATE_NEED_CONFIRMATION or SEND_STATE_SENDING + NdefMessage mMessageToSend; // not valid in SEND_STATE_NOTHING_TO_SEND + Uri[] mUrisToSend; // not valid in SEND_STATE_NOTHING_TO_SEND + int mSendFlags; // not valid in SEND_STATE_NOTHING_TO_SEND INdefPushCallback mCallbackNdef; + String[] mValidCallbackPackages; SendTask mSendTask; SharedPreferences mPrefs; boolean mFirstBeam; + SnepClient mSnepClient; + HandoverClient mHandoverClient; + NdefPushClient mNdefPushClient; + ConnectTask mConnectTask; + boolean mLlcpServicesConnected; + boolean mLlcpConnectDelayed; + long mLastLlcpActivationTime; public P2pLinkManager(Context context, HandoverManager handoverManager, int defaultMiu, int defaultRwSize) { @@ -207,6 +235,7 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba mHandoverManager = handoverManager; mDefaultMiu = defaultMiu; mDefaultRwSize = defaultRwSize; + mLlcpServicesConnected = false; } /** @@ -236,15 +265,26 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba } /** + * May be called from any thread. + * @return whether the LLCP link is in an active or debounce state + */ + public boolean isLlcpActive() { + synchronized (this) { + return mLinkState != LINK_STATE_DOWN; + } + } + + /** * Set NDEF callback for sending. * May be called from any thread. * NDEF callbacks may be set at any time (even if NFC is * currently off or P2P send is currently off). They will become * active as soon as P2P send is enabled. */ - public void setNdefCallback(INdefPushCallback callbackNdef) { + public void setNdefCallback(INdefPushCallback callbackNdef, int callingUid) { synchronized (this) { mCallbackNdef = callbackNdef; + mValidCallbackPackages = mPackageManager.getPackagesForUid(callingUid); } } @@ -258,38 +298,97 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba if (mEchoServer != null) { mEchoServer.onLlcpActivated(); } - + mLastLlcpActivationTime = SystemClock.elapsedRealtime(); + mLlcpConnectDelayed = false; switch (mLinkState) { case LINK_STATE_DOWN: - mLinkState = LINK_STATE_UP; + mLinkState = LINK_STATE_WAITING_PDU; mSendState = SEND_STATE_NOTHING_TO_SEND; if (DBG) Log.d(TAG, "onP2pInRange()"); mEventListener.onP2pInRange(); - prepareMessageToSend(); if (mMessageToSend != null || (mUrisToSend != null && mHandoverManager.isHandoverSupported())) { - mSendState = SEND_STATE_NEED_CONFIRMATION; - if (DBG) Log.d(TAG, "onP2pSendConfirmationRequested()"); - mEventListener.onP2pSendConfirmationRequested(); + // Ideally we would delay showing the Beam animation until + // we know for certain the other side has SNEP/handover. + // Unfortunately, the NXP LLCP implementation has a bug that + // delays the first SYMM for 750ms if it is the initiator. + // This will cause our SNEP connect to be delayed as well, + // and the animation will be delayed for about a second. + // Alternatively, we could have used WKS as a hint to start + // the animation, but we are only correctly setting the WKS + // since Jelly Bean. + if ((mSendFlags & NfcAdapter.FLAG_NDEF_PUSH_NO_CONFIRM) != 0) { + mSendState = SEND_STATE_SENDING; + onP2pSendConfirmed(false); + } else { + mSendState = SEND_STATE_NEED_CONFIRMATION; + if (DBG) Log.d(TAG, "onP2pSendConfirmationRequested()"); + mEventListener.onP2pSendConfirmationRequested(); + } } break; + case LINK_STATE_WAITING_PDU: + if (DBG) Log.d(TAG, "Unexpected onLlcpActivated() in LINK_STATE_WAITING_PDU"); + return; case LINK_STATE_UP: if (DBG) Log.d(TAG, "Duplicate onLlcpActivated()"); return; case LINK_STATE_DEBOUNCE: - mLinkState = LINK_STATE_UP; + if (mSendState == SEND_STATE_SENDING) { + // Immediately connect and try to send again + mLinkState = LINK_STATE_UP; + connectLlcpServices(); + } else { + mLinkState = LINK_STATE_WAITING_PDU; + } mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT); + break; + } + } + } - if (mSendState == SEND_STATE_SENDING) { - Log.i(TAG, "Retry send..."); - sendNdefMessage(); + /** + * Must be called on UI Thread. + */ + public void onLlcpFirstPacketReceived() { + synchronized (P2pLinkManager.this) { + long totalTime = SystemClock.elapsedRealtime() - mLastLlcpActivationTime; + if (DBG) Log.d(TAG, "Took " + Long.toString(totalTime) + " to get first LLCP PDU"); + switch (mLinkState) { + case LINK_STATE_UP: + if (DBG) Log.d(TAG, "Dropping first LLCP packet received"); + break; + case LINK_STATE_DOWN: + case LINK_STATE_DEBOUNCE: + Log.e(TAG, "Unexpected first LLCP packet received"); + break; + case LINK_STATE_WAITING_PDU: + mLinkState = LINK_STATE_UP; + if (mSendState == SEND_STATE_NOTHING_TO_SEND) + break; + if (totalTime < LINK_FIRST_PDU_LIMIT_MS || mSendState == SEND_STATE_SENDING) { + connectLlcpServices(); + } else { + mLlcpConnectDelayed = true; } break; } } } + public void onUserSwitched() { + // Update the cached package manager in case of user switch + synchronized (P2pLinkManager.this) { + try { + mPackageManager = mContext.createPackageContextAsUser("android", 0, + new UserHandle(ActivityManager.getCurrentUser())).getPackageManager(); + } catch (NameNotFoundException e) { + Log.e(TAG, "Failed to retrieve PackageManager for user"); + } + } + } + void prepareMessageToSend() { synchronized (P2pLinkManager.this) { if (!mIsSendEnabled) { @@ -298,32 +397,63 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba return; } + String runningPackage = null; + List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1); + if (tasks.size() > 0) { + runningPackage = tasks.get(0).topActivity.getPackageName(); + } + + if (runningPackage == null) { + Log.e(TAG, "Could not determine running package."); + mMessageToSend = null; + mUrisToSend = null; + return; + } + // Try application callback first - //TODO: Check that mCallbackNdef refers to the foreground activity if (mCallbackNdef != null) { - try { - mMessageToSend = mCallbackNdef.createMessage(); - mUrisToSend = mCallbackNdef.getUris(); - return; - } catch (RemoteException e) { - // Ignore + // Check to see if the package currently running + // is the one that registered any callbacks + boolean callbackValid = false; + + if (mValidCallbackPackages != null) { + for (String pkg : mValidCallbackPackages) { + if (pkg.equals(runningPackage)) { + callbackValid = true; + break; + } + } } - } - // fall back to default NDEF for this activity, unless the - // application disabled this explicitly in their manifest. - List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1); - if (tasks.size() > 0) { - String pkg = tasks.get(0).baseActivity.getPackageName(); - if (beamDefaultDisabled(pkg)) { - Log.d(TAG, "Disabling default Beam behavior"); - mMessageToSend = null; + if (callbackValid) { + try { + BeamShareData shareData = mCallbackNdef.createBeamShareData(); + mMessageToSend = shareData.ndefMessage; + mUrisToSend = shareData.uris; + mSendFlags = shareData.flags; + return; + } catch (Exception e) { + Log.e(TAG, "Failed NDEF callback: " + e.getMessage()); + } } else { - mMessageToSend = createDefaultNdef(pkg); + // This is not necessarily an error - we no longer unset callbacks from + // the app process itself (to prevent IPC calls on every pause). + // Hence it may simply be a stale callback. + if (DBG) Log.d(TAG, "Last registered callback is not running in the foreground."); } - } else { + } + + // fall back to default NDEF for the foreground activity, unless the + // application disabled this explicitly in their manifest. + if (beamDefaultDisabled(runningPackage)) { + Log.d(TAG, "Disabling default Beam behavior"); mMessageToSend = null; + mUrisToSend = null; + } else { + mMessageToSend = createDefaultNdef(runningPackage); + mUrisToSend = null; } + if (DBG) Log.d(TAG, "mMessageToSend = " + mMessageToSend); if (DBG) Log.d(TAG, "mUrisToSend = " + mUrisToSend); } @@ -349,6 +479,29 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba return new NdefMessage(new NdefRecord[] { appUri, appRecord }); } + void disconnectLlcpServices() { + synchronized (this) { + if (mConnectTask != null) { + mConnectTask.cancel(true); + mConnectTask = null; + } + // Close any already connected LLCP clients + if (mNdefPushClient != null) { + mNdefPushClient.close(); + mNdefPushClient = null; + } + if (mSnepClient != null) { + mSnepClient.close(); + mSnepClient = null; + } + if (mHandoverClient != null) { + mHandoverClient.close(); + mHandoverClient = null; + } + mLlcpServicesConnected = false; + } + } + /** * Must be called on UI Thread. */ @@ -364,11 +517,32 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba case LINK_STATE_DEBOUNCE: Log.i(TAG, "Duplicate onLlcpDectivated()"); break; + case LINK_STATE_WAITING_PDU: case LINK_STATE_UP: // Debounce mLinkState = LINK_STATE_DEBOUNCE; - mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, LINK_DEBOUNCE_MS); + int debounceTimeout = 0; + switch (mSendState) { + case SEND_STATE_NOTHING_TO_SEND: + debounceTimeout = 0; + break; + case SEND_STATE_NEED_CONFIRMATION: + debounceTimeout = LINK_SEND_PENDING_DEBOUNCE_MS; + break; + case SEND_STATE_SENDING: + debounceTimeout = LINK_SEND_CONFIRMED_DEBOUNCE_MS; + break; + case SEND_STATE_SEND_COMPLETE: + debounceTimeout = LINK_SEND_COMPLETE_DEBOUNCE_MS; + break; + } + mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, debounceTimeout); + if (mSendState == SEND_STATE_SENDING) { + Log.e(TAG, "onP2pSendDebounce()"); + mEventListener.onP2pSendDebounce(); + } cancelSendNdefMessage(); + disconnectLlcpServices(); break; } } @@ -406,12 +580,168 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba } } + void connectLlcpServices() { + synchronized (P2pLinkManager.this) { + if (mConnectTask != null) { + Log.e(TAG, "Still had a reference to mConnectTask!"); + } + mConnectTask = new ConnectTask(); + mConnectTask.execute(); + } + } + + // Must be called on UI-thread + void onLlcpServicesConnected() { + if (DBG) Log.d(TAG, "onLlcpServicesConnected"); + synchronized (P2pLinkManager.this) { + if (mLinkState != LINK_STATE_UP) { + return; + } + mLlcpServicesConnected = true; + if (mSendState == SEND_STATE_SENDING) { + // FIXME Keep state to make sure this is only called when in debounce + // and remove logic in P2pEventManager to keep track. + mEventListener.onP2pResumeSend(); + sendNdefMessage(); + } else { + // User still needs to confirm, or we may have received something already. + } + } + } + + final class ConnectTask extends AsyncTask<Void, Void, Boolean> { + @Override + protected void onPostExecute(Boolean result) { + if (isCancelled()) { + if (DBG) Log.d(TAG, "ConnectTask was cancelled"); + return; + } + if (result) { + onLlcpServicesConnected(); + } else { + Log.e(TAG, "Could not connect required NFC transports"); + } + } + + @Override + protected Boolean doInBackground(Void... params) { + boolean needsHandover = false; + boolean needsNdef = false; + boolean success = false; + HandoverClient handoverClient = null; + SnepClient snepClient = null; + NdefPushClient nppClient = null; + + synchronized(P2pLinkManager.this) { + if (mUrisToSend != null) { + needsHandover = true; + } + + if (mMessageToSend != null) { + needsNdef = true; + } + } + // We know either is requested - otherwise this task + // wouldn't have been started. + if (needsHandover) { + handoverClient = new HandoverClient(); + try { + handoverClient.connect(); + success = true; // Regardless of NDEF result + } catch (IOException e) { + handoverClient = null; + } + } + + if (needsNdef || (needsHandover && handoverClient == null)) { + snepClient = new SnepClient(); + try { + snepClient.connect(); + success = true; + } catch (IOException e) { + snepClient = null; + } + + if (!success) { + nppClient = new NdefPushClient(); + try { + nppClient.connect(); + success = true; + } catch (IOException e) { + nppClient = null; + } + } + } + + synchronized (P2pLinkManager.this) { + if (isCancelled()) { + // Cancelled by onLlcpDeactivated on UI thread + if (handoverClient != null) { + handoverClient.close(); + } + if (snepClient != null) { + snepClient.close(); + } + if (nppClient != null) { + nppClient.close(); + } + return false; + } else { + // Once assigned, these are the responsibility of + // the code on the UI thread to release - typically + // through onLlcpDeactivated(). + mHandoverClient = handoverClient; + mSnepClient = snepClient; + mNdefPushClient = nppClient; + return success; + } + } + } + }; + final class SendTask extends AsyncTask<Void, Void, Void> { + NdefPushClient nppClient; + SnepClient snepClient; + HandoverClient handoverClient; + + int doHandover(Uri[] uris) throws IOException { + NdefMessage response = null; + NdefMessage request = mHandoverManager.createHandoverRequestMessage(); + if (request != null) { + if (handoverClient != null) { + response = handoverClient.sendHandoverRequest(request); + } + if (response == null && snepClient != null) { + // Remote device may not support handover service, + // try the (deprecated) SNEP GET implementation + // for devices running Android 4.1 + SnepMessage snepResponse = snepClient.get(request); + response = snepResponse.getNdefMessage(); + } + if (response == null) { + return HANDOVER_UNSUPPORTED; + } + } else { + return HANDOVER_UNSUPPORTED; + } + mHandoverManager.doHandoverUri(uris, response); + return HANDOVER_SUCCESS; + } + + int doSnepProtocol(NdefMessage msg) throws IOException { + if (msg != null) { + snepClient.put(msg); + return SNEP_SUCCESS; + } else { + return SNEP_FAILURE; + } + } + @Override public Void doInBackground(Void... args) { NdefMessage m; Uri[] uris; - boolean result; + boolean result = false; synchronized (P2pLinkManager.this) { if (mLinkState != LINK_STATE_UP || mSendState != SEND_STATE_SENDING) { @@ -419,104 +749,67 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba } m = mMessageToSend; uris = mUrisToSend; + snepClient = mSnepClient; + handoverClient = mHandoverClient; + nppClient = mNdefPushClient; } long time = SystemClock.elapsedRealtime(); - try { - if (DBG) Log.d(TAG, "Sending ndef via SNEP"); - - int snepResult = doSnepProtocol(mHandoverManager, m, uris, - mDefaultMiu, mDefaultRwSize); - - switch (snepResult) { - case SNEP_HANDOVER_UNSUPPORTED: - onHandoverUnsupported(); - return null; - case SNEP_SUCCESS: - result = true; - break; - case SNEP_FAILURE: - result = false; - break; - default: - result = false; - } - } catch (IOException e) { - Log.i(TAG, "Failed to connect over SNEP, trying NPP"); - - if (isCancelled()) { - return null; + if (uris != null) { + if (DBG) Log.d(TAG, "Trying handover request"); + try { + int handoverResult = doHandover(uris); + switch (handoverResult) { + case HANDOVER_SUCCESS: + result = true; + break; + case HANDOVER_FAILURE: + result = false; + break; + case HANDOVER_UNSUPPORTED: + result = false; + onHandoverUnsupported(); + break; + } + } catch (IOException e) { + result = false; } + } - if (m != null) { - result = new NdefPushClient().push(m); - } else { + if (!result && m != null && snepClient != null) { + if (DBG) Log.d(TAG, "Sending ndef via SNEP"); + try { + int snepResult = doSnepProtocol(m); + switch (snepResult) { + case SNEP_SUCCESS: + result = true; + break; + case SNEP_FAILURE: + result = false; + break; + default: + result = false; + } + } catch (IOException e) { result = false; } } - time = SystemClock.elapsedRealtime() - time; - if (DBG) Log.d(TAG, "SendTask result=" + result + ", time ms=" + time); + if (!result && m != null && nppClient != null) { + result = nppClient.push(m); + } + time = SystemClock.elapsedRealtime() - time; + if (DBG) Log.d(TAG, "SendTask result=" + result + ", time ms=" + time); if (result) { onSendComplete(m, time); } - return null; - } - } - static int doSnepProtocol(HandoverManager handoverManager, - NdefMessage msg, Uri[] uris, int miu, int rwSize) throws IOException { - SnepClient snepClient = new SnepClient(miu, rwSize); - try { - snepClient.connect(); - } catch (IOException e) { - // Throw exception to fall back to NPP. - snepClient.close(); - throw new IOException("SNEP not available.", e); + return null; } + }; - try { - if (uris != null) { - HandoverClient handoverClient = new HandoverClient(); - - NdefMessage response = null; - NdefMessage request = handoverManager.createHandoverRequestMessage(); - if (request != null) { - response = handoverClient.sendHandoverRequest(request); - - if (response == null) { - // Remote device may not support handover service, - // try the (deprecated) SNEP GET implementation - // for devices running Android 4.1 - SnepMessage snepResponse = snepClient.get(request); - response = snepResponse.getNdefMessage(); - } - } // else, handover not supported - if (response != null) { - handoverManager.doHandoverUri(uris, response); - } else if (msg != null) { - // For backwards-compatibility to pre-J devices, - // try to push an NDEF message (if any) if the handover GET - // does not work. - snepClient.put(msg); - } else { - // We had a failed handover and no alternate message to - // send; indicate remote device doesn't support handover. - return SNEP_HANDOVER_UNSUPPORTED; - } - } else if (msg != null) { - snepClient.put(msg); - } - return SNEP_SUCCESS; - } catch (IOException e) { - // SNEP available but had errors, don't fall back to NPP. - } finally { - snepClient.close(); - } - return SNEP_FAILURE; - } final HandoverServer.Callback mHandoverCallback = new HandoverServer.Callback() { @Override @@ -647,13 +940,16 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) { break; } - mSendState = SEND_STATE_NOTHING_TO_SEND; + mSendState = SEND_STATE_SEND_COMPLETE; + mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT); if (DBG) Log.d(TAG, "onP2pSendComplete()"); mEventListener.onP2pSendComplete(); if (mCallbackNdef != null) { try { mCallbackNdef.onNdefPushComplete(); - } catch (RemoteException e) { } + } catch (Exception e) { + Log.e(TAG, "Failed NDEF completed callback: " + e.getMessage()); + } } } break; @@ -721,14 +1017,36 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba @Override public void onP2pSendConfirmed() { + onP2pSendConfirmed(true); + } + + private void onP2pSendConfirmed(boolean requireConfirmation) { if (DBG) Log.d(TAG, "onP2pSendConfirmed()"); synchronized (this) { - if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_NEED_CONFIRMATION) { + if (mLinkState == LINK_STATE_DOWN || (requireConfirmation + && mSendState != SEND_STATE_NEED_CONFIRMATION)) { return; } mSendState = SEND_STATE_SENDING; - if (mLinkState == LINK_STATE_UP) { + if (mLinkState == LINK_STATE_WAITING_PDU) { + // We could decide to wait for the first PDU here; but + // that makes us vulnerable to cases where for some reason + // this event is not propagated up by the stack. Instead, + // try to connect now. + mLinkState = LINK_STATE_UP; + connectLlcpServices(); + } else if (mLinkState == LINK_STATE_UP && mLlcpServicesConnected) { sendNdefMessage(); + } else if (mLinkState == LINK_STATE_UP && mLlcpConnectDelayed) { + // Connect was delayed to interop with pre-MR2 stacks; send connect now. + connectLlcpServices(); + } else if (mLinkState == LINK_STATE_DEBOUNCE) { + // Restart debounce timeout + mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT); + mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, + LINK_SEND_CONFIRMED_DEBOUNCE_MS); + // Tell user to tap devices again + mEventListener.onP2pSendDebounce(); } } } @@ -754,6 +1072,8 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba return "LINK_STATE_DEBOUNCE"; case LINK_STATE_UP: return "LINK_STATE_UP"; + case LINK_STATE_WAITING_PDU: + return "LINK_STATE_WAITING_PDU"; default: return "<error>"; } diff --git a/src/com/android/nfc/SendUi.java b/src/com/android/nfc/SendUi.java index 5b5c2346..43da127f 100644 --- a/src/com/android/nfc/SendUi.java +++ b/src/com/android/nfc/SendUi.java @@ -31,12 +31,15 @@ import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.SurfaceTexture; +import android.os.AsyncTask; import android.os.Binder; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; +import android.view.SurfaceControl; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; @@ -72,6 +75,8 @@ import android.widget.Toast; */ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, TimeAnimator.TimeListener, TextureView.SurfaceTextureListener { + static final String TAG = "SendUi"; + static final float INTERMEDIATE_SCALE = 0.6f; static final float[] PRE_SCREENSHOT_SCALE = {1.0f, INTERMEDIATE_SCALE}; @@ -89,6 +94,9 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, static final int SLIDE_OUT_DURATION_MS = 300; + static final float[] BLACK_LAYER_ALPHA_DOWN_RANGE = {0.9f, 0.0f}; + static final float[] BLACK_LAYER_ALPHA_UP_RANGE = {0.0f, 0.9f}; + static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; static final int TEXT_HINT_ALPHA_DURATION_MS = 500; static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; @@ -96,6 +104,15 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, static final int FINISH_SCALE_UP = 0; static final int FINISH_SEND_SUCCESS = 1; + static final int STATE_IDLE = 0; + static final int STATE_W4_SCREENSHOT = 1; + static final int STATE_W4_SCREENSHOT_PRESEND_REQUESTED = 2; + static final int STATE_W4_SCREENSHOT_THEN_STOP = 3; + static final int STATE_W4_PRESEND = 4; + static final int STATE_W4_CONFIRM = 5; + static final int STATE_SENDING = 6; + static final int STATE_COMPLETE = 7; + // all members are only used on UI thread final WindowManager mWindowManager; final Context mContext; @@ -107,8 +124,10 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, final StatusBarManager mStatusBarManager; final View mScreenshotLayout; final ImageView mScreenshotView; + final ImageView mBlackLayer; final TextureView mTextureView; final TextView mTextHint; + final TextView mTextRetry; final Callback mCallback; // The mFrameCounter animation is purely used to count down a certain @@ -128,6 +147,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, final ObjectAnimator mFadeInAnimator; final ObjectAnimator mHintAnimator; final ObjectAnimator mScaleUpAnimator; + final ObjectAnimator mAlphaDownAnimator; + final ObjectAnimator mAlphaUpAnimator; final AnimatorSet mSuccessAnimatorSet; // Besides animating the screenshot, the Beam UI also renders @@ -143,9 +164,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, String mToastString; Bitmap mScreenshotBitmap; - boolean mAttached; - boolean mSending; - + int mState; int mRenderedFrames; // Used for holding the surface @@ -176,7 +195,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mScreenshotLayout.setFocusable(true); mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); - + mTextRetry = (TextView) mScreenshotLayout.findViewById(R.id.retrytext); + mBlackLayer = (ImageView) mScreenshotLayout.findViewById(R.id.blacklayer); mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); mTextureView.setSurfaceTextureListener(this); @@ -244,6 +264,16 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); + alphaDown = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_DOWN_RANGE); + mAlphaDownAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaDown); + mAlphaDownAnimator.setInterpolator(new DecelerateInterpolator()); + mAlphaDownAnimator.setDuration(400); + + alphaUp = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_UP_RANGE); + mAlphaUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaUp); + mAlphaUpAnimator.setInterpolator(new DecelerateInterpolator()); + mAlphaUpAnimator.setDuration(200); + mSuccessAnimatorSet = new AnimatorSet(); mSuccessAnimatorSet.playSequentially(mFastSendAnimator, mFadeInAnimator); @@ -252,25 +282,49 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, } else { mFireflyRenderer = null; } - mAttached = false; + mState = STATE_IDLE; } public void takeScreenshot() { - mScreenshotBitmap = createScreenshot(); + // There's no point in taking the screenshot if + // we're still finishing the previous animation. + if (mState >= STATE_W4_CONFIRM) { + return; + } + mState = STATE_W4_SCREENSHOT; + new ScreenshotTask().execute(); } /** Show pre-send animation */ public void showPreSend() { + switch (mState) { + case STATE_IDLE: + Log.e(TAG, "Unexpected showPreSend() in STATE_IDLE"); + return; + case STATE_W4_SCREENSHOT: + // Still waiting for screenshot, store request in state + // and wait for screenshot completion. + mState = STATE_W4_SCREENSHOT_PRESEND_REQUESTED; + return; + case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: + Log.e(TAG, "Unexpected showPreSend() in STATE_W4_SCREENSHOT_PRESEND_REQUESTED"); + return; + case STATE_W4_PRESEND: + // Expected path, continue below + break; + default: + Log.e(TAG, "Unexpected showPreSend() in state " + Integer.toString(mState)); + return; + } // Update display metrics mDisplay.getRealMetrics(mDisplayMetrics); final int statusBarHeight = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); - if (mScreenshotBitmap == null || mAttached) { - return; - } - mScreenshotView.setOnTouchListener(this); + mBlackLayer.setVisibility(View.GONE); + mBlackLayer.setAlpha(0f); + mScreenshotLayout.setOnTouchListener(this); mScreenshotView.setImageBitmap(mScreenshotBitmap); mScreenshotView.setTranslationX(0f); mScreenshotView.setAlpha(1.0f); @@ -278,6 +332,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mScreenshotLayout.requestFocus(); + mTextHint.setText(mContext.getResources().getString(R.string.touch)); mTextHint.setAlpha(0.0f); mTextHint.setVisibility(View.VISIBLE); mHintAnimator.start(); @@ -310,18 +365,18 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND); mToastString = null; - mSending = false; - mAttached = true; if (!mHardwareAccelerated) { mPreAnimator.start(); } // else, we will start the animation once we get the hardware surface + mState = STATE_W4_CONFIRM; } /** Show starting send animation */ public void showStartSend() { - if (!mAttached) return; + if (mState < STATE_SENDING) return; + mTextRetry.setVisibility(View.GONE); // Update the starting scale - touchscreen-mashers may trigger // this before the pre-animation completes. float currentScale = mScreenshotView.getScaleX(); @@ -331,11 +386,18 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, new float[] {currentScale, 0.0f}); mSlowSendAnimator.setValues(postX, postY); + + float currentAlpha = mBlackLayer.getAlpha(); + if (mBlackLayer.isShown() && currentAlpha > 0.0f) { + PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", + new float[] {currentAlpha, 0.0f}); + mAlphaDownAnimator.setValues(alphaDown); + mAlphaDownAnimator.start(); + } mSlowSendAnimator.start(); } public void finishAndToast(int finishMode, String toast) { - if (!mAttached) return; mToastString = toast; finish(finishMode); @@ -343,7 +405,29 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, /** Return to initial state */ public void finish(int finishMode) { - if (!mAttached) return; + switch (mState) { + case STATE_IDLE: + return; + case STATE_W4_SCREENSHOT: + case STATE_W4_SCREENSHOT_PRESEND_REQUESTED: + // Screenshot is still being captured on a separate thread. + // Update state, and stop everything when the capture is done. + mState = STATE_W4_SCREENSHOT_THEN_STOP; + return; + case STATE_W4_SCREENSHOT_THEN_STOP: + Log.e(TAG, "Unexpected call to finish() in STATE_W4_SCREENSHOT_THEN_STOP"); + return; + case STATE_W4_PRESEND: + // We didn't build up any animation state yet, but + // did store the bitmap. Clear out the bitmap, reset + // state and bail. + mScreenshotBitmap = null; + mState = STATE_IDLE; + return; + default: + // We've started animations and attached a view; tear stuff down below. + break; + } // Stop rendering the fireflies if (mFireflyRenderer != null) { @@ -351,11 +435,13 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, } mTextHint.setVisibility(View.GONE); + mTextRetry.setVisibility(View.GONE); float currentScale = mScreenshotView.getScaleX(); float currentAlpha = mScreenshotView.getAlpha(); if (finishMode == FINISH_SCALE_UP) { + mBlackLayer.setVisibility(View.GONE); PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", new float[] {currentScale, 1.0f}); PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", @@ -372,7 +458,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", new float[] {currentScale, 0.0f}); PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", - new float[] {1.0f, 0.0f}); + new float[] {currentAlpha, 0.0f}); mFastSendAnimator.setValues(postX, postY, alpha); // Reset the fadeIn parameters to start from alpha 1 @@ -383,14 +469,15 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mSlowSendAnimator.cancel(); mSuccessAnimatorSet.start(); } + mState = STATE_COMPLETE; } - public void dismiss() { - if (!mAttached) return; - - // Immediately set to false, to prevent .cancel() calls + void dismiss() { + if (mState < STATE_W4_CONFIRM) return; + // Immediately set to IDLE, to prevent .cancel() calls // below from immediately calling into dismiss() again. - mAttached = false; + // (They can do so on the same thread). + mState = STATE_IDLE; mSurface = null; mFrameCounterAnimator.cancel(); mPreAnimator.cancel(); @@ -398,19 +485,17 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mFastSendAnimator.cancel(); mSuccessAnimatorSet.cancel(); mScaleUpAnimator.cancel(); + mAlphaUpAnimator.cancel(); + mAlphaDownAnimator.cancel(); mWindowManager.removeView(mScreenshotLayout); mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); - releaseScreenshot(); + mScreenshotBitmap = null; if (mToastString != null) { Toast.makeText(mContext, mToastString, Toast.LENGTH_LONG).show(); } mToastString = null; } - public void releaseScreenshot() { - mScreenshotBitmap = null; - } - /** * @return the current display rotation in degrees */ @@ -426,6 +511,37 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, return 0f; } + final class ScreenshotTask extends AsyncTask<Void, Void, Bitmap> { + @Override + protected Bitmap doInBackground(Void... params) { + return createScreenshot(); + } + + @Override + protected void onPostExecute(Bitmap result) { + if (mState == STATE_W4_SCREENSHOT) { + // Screenshot done, wait for request to start preSend anim + mState = STATE_W4_PRESEND; + } else if (mState == STATE_W4_SCREENSHOT_THEN_STOP) { + // We were asked to finish, move to idle state and exit + mState = STATE_IDLE; + } else if (mState == STATE_W4_SCREENSHOT_PRESEND_REQUESTED) { + if (result != null) { + mScreenshotBitmap = result; + mState = STATE_W4_PRESEND; + showPreSend(); + } else { + // Failed to take screenshot; reset state to idle + // and don't do anything + Log.e(TAG, "Failed to create screenshot"); + mState = STATE_IDLE; + } + } else { + Log.e(TAG, "Invalid state on screenshot completion: " + Integer.toString(mState)); + } + } + }; + /** * Returns a screenshot of the current display contents. */ @@ -461,7 +577,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, dims[1] = Math.abs(dims[1]); } - Bitmap bitmap = Surface.screenshot((int) dims[0], (int) dims[1]); + Bitmap bitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]); // Bail if we couldn't take the screenshot if (bitmap == null) { return null; @@ -523,7 +639,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mScreenshotView.setScaleX(1.0f); mScreenshotView.setScaleY(1.0f); } else if (animation == mPreAnimator) { - if (mHardwareAccelerated && mAttached && !mSending) { + if (mHardwareAccelerated && (mState == STATE_W4_CONFIRM)) { mFireflyRenderer.start(mSurface, mSurfaceWidth, mSurfaceHeight); } } @@ -552,10 +668,10 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, @Override public boolean onTouch(View v, MotionEvent event) { - if (!mAttached) { + if (mState != STATE_W4_CONFIRM) { return false; } - mSending = true; + mState = STATE_SENDING; // Ignore future touches mScreenshotView.setOnTouchListener(null); @@ -569,7 +685,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - if (mHardwareAccelerated && !mSending) { + if (mHardwareAccelerated && mState < STATE_COMPLETE) { mRenderedFrames = 0; mFrameCounterAnimator.start(); @@ -594,4 +710,24 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { } + public void showSendHint() { + if (mAlphaDownAnimator.isRunning()) { + mAlphaDownAnimator.cancel(); + } + if (mSlowSendAnimator.isRunning()) { + mSlowSendAnimator.cancel(); + } + mBlackLayer.setScaleX(mScreenshotView.getScaleX()); + mBlackLayer.setScaleY(mScreenshotView.getScaleY()); + mBlackLayer.setVisibility(View.VISIBLE); + mTextHint.setVisibility(View.GONE); + + mTextRetry.setText(mContext.getResources().getString(R.string.beam_try_again)); + mTextRetry.setVisibility(View.VISIBLE); + + PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", + new float[] {mBlackLayer.getAlpha(), 0.9f}); + mAlphaUpAnimator.setValues(alphaUp); + mAlphaUpAnimator.start(); + } } diff --git a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java index c845f89e..f46757c8 100644 --- a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java +++ b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java @@ -25,9 +25,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.media.IAudioService; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; @@ -359,13 +362,20 @@ public class BluetoothHeadsetHandover implements BluetoothProfile.ServiceListene } void startTheMusic() { - Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); - intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_MEDIA_PLAY)); - mContext.sendOrderedBroadcast(intent, null); - intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, - KeyEvent.KEYCODE_MEDIA_PLAY)); - mContext.sendOrderedBroadcast(intent, null); + IAudioService audioService = IAudioService.Stub.asInterface( + ServiceManager.checkService(Context.AUDIO_SERVICE)); + if (audioService != null) { + try { + KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY); + audioService.dispatchMediaKeyEvent(keyEvent); + keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY); + audioService.dispatchMediaKeyEvent(keyEvent); + } catch (RemoteException e) { + Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e); + } + } else { + Log.w(TAG, "Unable to find IAudioService for media key event"); + } } void requestPairConfirmation() { diff --git a/src/com/android/nfc/handover/BluetoothOppHandover.java b/src/com/android/nfc/handover/BluetoothOppHandover.java index fdb5eff7..d6b05a3c 100644 --- a/src/com/android/nfc/handover/BluetoothOppHandover.java +++ b/src/com/android/nfc/handover/BluetoothOppHandover.java @@ -32,7 +32,7 @@ import java.util.Arrays; public class BluetoothOppHandover implements Handler.Callback { static final String TAG = "BluetoothOppHandover"; - static final boolean D = true; + static final boolean DBG = true; static final int STATE_INIT = 0; static final int STATE_TURNING_ON = 1; @@ -129,7 +129,7 @@ public class BluetoothOppHandover implements Handler.Callback { intent.setAction(ACTION_HANDOVER_SEND_MULTIPLE); intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); } - + if (DBG) Log.d(TAG, "Handing off outging transfer to BT"); mContext.sendBroadcast(intent); complete(); diff --git a/src/com/android/nfc/handover/HandoverClient.java b/src/com/android/nfc/handover/HandoverClient.java index 86cd23b3..20e4ef64 100644 --- a/src/com/android/nfc/handover/HandoverClient.java +++ b/src/com/android/nfc/handover/HandoverClient.java @@ -30,28 +30,86 @@ import java.util.Arrays; public final class HandoverClient { private static final String TAG = "HandoverClient"; private static final int MIU = 128; - // Max NDEF length to receive for Hr/Hs messages private static final boolean DBG = false; - public NdefMessage sendHandoverRequest(NdefMessage msg) { - if (msg == null) return null; + private static final int DISCONNECTED = 0; + private static final int CONNECTING = 1; + private static final int CONNECTED = 2; - NfcService service = NfcService.getInstance(); + private static final Object mLock = new Object(); - LlcpSocket sock = null; - int offset = 0; - byte[] buffer = msg.toByteArray(); - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + // Variables below synchronized on mLock + LlcpSocket mSocket; + int mState; + public void connect() throws IOException { + synchronized (mLock) { + if (mState != DISCONNECTED) { + throw new IOException("Socket in use."); + } + mState = CONNECTING; + } + NfcService service = NfcService.getInstance(); + LlcpSocket sock = null; try { sock = service.createLlcpSocket(0, MIU, 1, 1024); - if (sock == null) { - throw new IOException("Could not connect to socket."); + } catch (LlcpException e) { + synchronized (mLock) { + mState = DISCONNECTED; } + throw new IOException("Could not create socket"); + } + try { if (DBG) Log.d(TAG, "about to connect to service " + HandoverServer.HANDOVER_SERVICE_NAME); sock.connectToService(HandoverServer.HANDOVER_SERVICE_NAME); + } catch (IOException e) { + if (sock != null) { + try { + sock.close(); + } catch (IOException e2) { + // Ignore + } + } + synchronized (mLock) { + mState = DISCONNECTED; + } + throw new IOException("Could not connect to handover service"); + } + synchronized (mLock) { + mSocket = sock; + mState = CONNECTED; + } + } + + public void close() { + synchronized (mLock) { + if (mSocket != null) { + try { + mSocket.close(); + } catch (IOException e) { + // Ignore + } + mSocket = null; + } + mState = DISCONNECTED; + } + } + public NdefMessage sendHandoverRequest(NdefMessage msg) throws IOException { + if (msg == null) return null; + LlcpSocket sock = null; + synchronized (mLock) { + if (mState != CONNECTED) { + throw new IOException("Socket not connected"); + } + sock = mSocket; + } + int offset = 0; + byte[] buffer = msg.toByteArray(); + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + + try { int remoteMiu = sock.getRemoteMiu(); if (DBG) Log.d(TAG, "about to send a " + buffer.length + " byte message"); while (offset < buffer.length) { @@ -62,7 +120,7 @@ public final class HandoverClient { offset += length; } - // Now, try to read back the SNEP response + // Now, try to read back the handover response byte[] partial = new byte[sock.getLocalMiu()]; NdefMessage handoverSelectMsg = null; while (true) { @@ -82,8 +140,6 @@ public final class HandoverClient { return handoverSelectMsg; } catch (IOException e) { if (DBG) Log.d(TAG, "couldn't connect to handover service"); - } catch (LlcpException e) { - if (DBG) Log.d(TAG, "couldn't connect to handover service"); } finally { if (sock != null) { try { diff --git a/src/com/android/nfc/handover/HandoverManager.java b/src/com/android/nfc/handover/HandoverManager.java index 6d2271a7..96283013 100644 --- a/src/com/android/nfc/handover/HandoverManager.java +++ b/src/com/android/nfc/handover/HandoverManager.java @@ -81,6 +81,7 @@ public class HandoverManager { Messenger mService = null; boolean mBound; String mLocalBluetoothAddress; + boolean mEnabled; static class BluetoothHandoverData { public boolean valid = false; @@ -160,8 +161,9 @@ public class HandoverManager { IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mReceiver, filter, null, null); - mContext.bindService(new Intent(mContext, HandoverService.class), mConnection, - Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT); + mContext.bindServiceAsUser(new Intent(mContext, HandoverService.class), mConnection, + Context.BIND_AUTO_CREATE, UserHandle.CURRENT); + mEnabled = true; } final BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -171,8 +173,8 @@ public class HandoverManager { if (action.equals(Intent.ACTION_USER_SWITCHED)) { // Re-bind a service for the current user mContext.unbindService(mConnection); - mContext.bindService(new Intent(mContext, HandoverService.class), mConnection, - Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT); + mContext.bindServiceAsUser(new Intent(mContext, HandoverService.class), mConnection, + Context.BIND_AUTO_CREATE, UserHandle.CURRENT); } } }; @@ -214,6 +216,11 @@ public class HandoverManager { return new NdefRecord(NdefRecord.TNF_MIME_MEDIA, TYPE_BT_OOB, new byte[]{'b'}, payload); } + public void setEnabled(boolean enabled) { + synchronized (mLock) { + mEnabled = enabled; + } + } public boolean isHandoverSupported() { return (mBluetoothAdapter != null); } @@ -293,6 +300,8 @@ public class HandoverManager { // while waiting to receive a picture. boolean bluetoothActivating = !mBluetoothAdapter.isEnabled(); synchronized (mLock) { + if (!mEnabled) return null; + if (!mBound) { Log.e(TAG, "Could not connect to handover service"); return null; @@ -314,7 +323,11 @@ public class HandoverManager { whitelistOppDevice(bluetoothData.device); // return BT OOB record so they can perform handover - return (createHandoverSelectMessage(bluetoothActivating)); + NdefMessage selectMessage = (createHandoverSelectMessage(bluetoothActivating)); + if (DBG) Log.d(TAG, "Waiting for incoming transfer, [" + + bluetoothData.device.getAddress() + "]->[" + mLocalBluetoothAddress + "]"); + + return selectMessage; } public boolean tryHandover(NdefMessage m) { @@ -328,6 +341,8 @@ public class HandoverManager { if (!handover.valid) return true; synchronized (mLock) { + if (!mEnabled) return false; + if (mBluetoothAdapter == null) { if (DBG) Log.d(TAG, "BT handover, but BT not available"); return true; @@ -369,6 +384,8 @@ public class HandoverManager { Bundle transferData = new Bundle(); transferData.putParcelable(HandoverService.BUNDLE_TRANSFER, transfer); msg.setData(transferData); + if (DBG) Log.d(TAG, "Initiating outgoing transfer, [" + mLocalBluetoothAddress + + "]->[" + data.device.getAddress() + "]"); try { mService.send(msg); } catch (RemoteException e) { diff --git a/src/com/android/nfc/handover/HandoverService.java b/src/com/android/nfc/handover/HandoverService.java index 261cbca4..181509db 100644 --- a/src/com/android/nfc/handover/HandoverService.java +++ b/src/com/android/nfc/handover/HandoverService.java @@ -32,6 +32,7 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac BluetoothHeadsetHandover.Callback { static final String TAG = "HandoverService"; + static final boolean DBG = true; static final int MSG_REGISTER_CLIENT = 0; static final int MSG_DEREGISTER_CLIENT = 1; @@ -46,9 +47,16 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac static final String ACTION_CANCEL_HANDOVER_TRANSFER = "com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER"; + static final String EXTRA_SOURCE_ADDRESS = "com.android.nfc.handover.extra.SOURCE_ADDRESS"; + static final String EXTRA_INCOMING = + "com.android.nfc.handover.extra.INCOMING"; + + static final String ACTION_HANDOVER_STARTED = + "android.btopp.intent.action.BT_OPP_HANDOVER_STARTED"; + static final String ACTION_BT_OPP_TRANSFER_PROGRESS = "android.btopp.intent.action.BT_OPP_TRANSFER_PROGRESS"; @@ -84,6 +92,9 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac static final String EXTRA_BT_OPP_TRANSFER_URI = "android.btopp.intent.extra.BT_OPP_TRANSFER_URI"; + public static final String EXTRA_BT_OPP_OBJECT_COUNT = + "android.btopp.intent.extra.BT_OPP_OBJECT_COUNT"; + // permission needed to be able to receive handover status requests static final String HANDOVER_STATUS_PERMISSION = "com.android.permission.HANDOVER_STATUS"; @@ -124,6 +135,7 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac filter.addAction(ACTION_BT_OPP_TRANSFER_PROGRESS); filter.addAction(ACTION_CANCEL_HANDOVER_TRANSFER); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + filter.addAction(ACTION_HANDOVER_STARTED); registerReceiver(mReceiver, filter, HANDOVER_STATUS_PERMISSION, mHandler); } @@ -157,6 +169,7 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac notifyClientTransferComplete(pendingTransfer.id); return; } + if (DBG) Log.d(TAG, "Queueing out transfer " + Integer.toString(pendingTransfer.id)); mPendingOutTransfers.add(handover); // Queue the transfer and enable Bluetooth - when it is enabled // the transfer will be started. @@ -284,7 +297,8 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, + BluetoothAdapter.ERROR); if (state == BluetoothAdapter.STATE_ON) { // If there is a pending headset pairing, start it if (mBluetoothHeadsetHandover != null && @@ -292,39 +306,48 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac mBluetoothHeadsetHandover.start(); } - // Start any pending transfers + // Start any pending file transfers startPendingTransfers(); } else if (state == BluetoothAdapter.STATE_OFF) { mBluetoothEnabledByNfc = false; mBluetoothHeadsetConnected = false; } - } - else if (action.equals(ACTION_CANCEL_HANDOVER_TRANSFER)) { + } else if (action.equals(ACTION_CANCEL_HANDOVER_TRANSFER)) { String sourceAddress = intent.getStringExtra(EXTRA_SOURCE_ADDRESS); - HandoverTransfer transfer = findHandoverTransfer(sourceAddress, true); + boolean incoming = (intent.getIntExtra(EXTRA_INCOMING, 1)) == 1; + HandoverTransfer transfer = findHandoverTransfer(sourceAddress, incoming); if (transfer != null) { + if (DBG) Log.d(TAG, "Cancelling transfer " + + Integer.toString(transfer.mTransferId)); transfer.cancel(); } } else if (action.equals(ACTION_BT_OPP_TRANSFER_PROGRESS) || - action.equals(ACTION_BT_OPP_TRANSFER_DONE)) { + action.equals(ACTION_BT_OPP_TRANSFER_DONE) || + action.equals(ACTION_HANDOVER_STARTED)) { int direction = intent.getIntExtra(EXTRA_BT_OPP_TRANSFER_DIRECTION, -1); int id = intent.getIntExtra(EXTRA_BT_OPP_TRANSFER_ID, -1); + if (action.equals(ACTION_HANDOVER_STARTED)) { + // This is always for incoming transfers + direction = DIRECTION_BLUETOOTH_INCOMING; + } String sourceAddress = intent.getStringExtra(EXTRA_BT_OPP_ADDRESS); - if (direction == -1 || id == -1 || sourceAddress == null) return; + if (direction == -1 || sourceAddress == null) return; boolean incoming = (direction == DIRECTION_BLUETOOTH_INCOMING); HandoverTransfer transfer = findHandoverTransfer(sourceAddress, incoming); if (transfer == null) { // There is no transfer running for this source address; most likely - // the transfer was cancelled. We need to tell BT OPP to stop transferring - // in case this was an incoming transfer - Intent cancelIntent = new Intent("android.btopp.intent.action.STOP_HANDOVER_TRANSFER"); - cancelIntent.putExtra(EXTRA_BT_OPP_TRANSFER_ID, id); - sendBroadcast(cancelIntent); + // the transfer was cancelled. We need to tell BT OPP to stop transferring. + if (id != -1) { + if (DBG) Log.d(TAG, "Didn't find transfer, stopping"); + Intent cancelIntent = new Intent( + "android.btopp.intent.action.STOP_HANDOVER_TRANSFER"); + cancelIntent.putExtra(EXTRA_BT_OPP_TRANSFER_ID, id); + sendBroadcast(cancelIntent); + } return; } - if (action.equals(ACTION_BT_OPP_TRANSFER_DONE)) { int handoverStatus = intent.getIntExtra(EXTRA_BT_OPP_TRANSFER_STATUS, HANDOVER_TRANSFER_STATUS_FAILURE); @@ -342,6 +365,11 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac } else if (action.equals(ACTION_BT_OPP_TRANSFER_PROGRESS)) { float progress = intent.getFloatExtra(EXTRA_BT_OPP_TRANSFER_PROGRESS, 0.0f); transfer.updateFileProgress(progress); + } else if (action.equals(ACTION_HANDOVER_STARTED)) { + int count = intent.getIntExtra(EXTRA_BT_OPP_OBJECT_COUNT, 0); + if (count > 0) { + transfer.setObjectCount(count); + } } } } @@ -379,6 +407,9 @@ public class HandoverService extends Service implements HandoverTransfer.Callbac // Play success sound if (success) { mSoundPool.play(mSuccessSound, 1.0f, 1.0f, 0, 0, 1.0f); + } else { + if (DBG) Log.d(TAG, "Transfer failed, final state: " + + Integer.toString(transfer.mState)); } disableBluetoothIfNeeded(); } diff --git a/src/com/android/nfc/handover/HandoverTransfer.java b/src/com/android/nfc/handover/HandoverTransfer.java index 98b59a69..df7addde 100644 --- a/src/com/android/nfc/handover/HandoverTransfer.java +++ b/src/com/android/nfc/handover/HandoverTransfer.java @@ -25,6 +25,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.Locale; /** * A HandoverTransfer object represents a set of files @@ -88,6 +89,9 @@ public class HandoverTransfer implements Handler.Callback, // Variables below are only accessed on the main thread int mState; + int mCurrentCount; + int mSuccessCount; + int mTotalCount; boolean mCalledBack; Long mLastUpdate; // Last time an event occurred for this transfer float mProgress; // Progress in range [0..1] @@ -106,6 +110,8 @@ public class HandoverTransfer implements Handler.Callback, mRemoteDevice = pendingTransfer.remoteDevice; mIncoming = pendingTransfer.incoming; mTransferId = pendingTransfer.id; + // For incoming transfers, count can be set later + mTotalCount = (pendingTransfer.uris != null) ? pendingTransfer.uris.length : 0; mLastUpdate = SystemClock.elapsedRealtime(); mProgress = 0.0f; mState = STATE_NEW; @@ -114,8 +120,10 @@ public class HandoverTransfer implements Handler.Callback, mPaths = new ArrayList<String>(); mMimeTypes = new HashMap<String, String>(); mMediaUris = new HashMap<String, Uri>(); - mCancelIntent = buildCancelIntent(); + mCancelIntent = buildCancelIntent(mIncoming); mUrisScanned = 0; + mCurrentCount = 0; + mSuccessCount = 0; mHandler = new Handler(Looper.getMainLooper(), this); mHandler.sendEmptyMessageDelayed(MSG_TRANSFER_TIMEOUT, ALIVE_CHECK_MS); @@ -147,9 +155,11 @@ public class HandoverTransfer implements Handler.Callback, public void finishTransfer(boolean success, Uri uri, String mimeType) { if (!isRunning()) return; // Ignore when we're no longer running + mCurrentCount++; if (success && uri != null) { + mSuccessCount++; if (DBG) Log.d(TAG, "Transfer success, uri " + uri + " mimeType " + mimeType); - this.mProgress = 1.0f; + mProgress = 0.0f; if (mimeType == null) { mimeType = BluetoothOppHandover.getMimeTypeForUri(mContext, uri); } @@ -164,8 +174,16 @@ public class HandoverTransfer implements Handler.Callback, // Do wait to see if there's another file coming. } mHandler.removeMessages(MSG_NEXT_TRANSFER_TIMER); - mHandler.sendEmptyMessageDelayed(MSG_NEXT_TRANSFER_TIMER, WAIT_FOR_NEXT_TRANSFER_MS); - updateStateAndNotification(STATE_W4_NEXT_TRANSFER); + if (mCurrentCount == mTotalCount) { + if (mIncoming) { + processFiles(); + } else { + updateStateAndNotification(mSuccessCount > 0 ? STATE_SUCCESS : STATE_FAILED); + } + } else { + mHandler.sendEmptyMessageDelayed(MSG_NEXT_TRANSFER_TIMER, WAIT_FOR_NEXT_TRANSFER_MS); + updateStateAndNotification(STATE_W4_NEXT_TRANSFER); + } } public boolean isRunning() { @@ -176,6 +194,10 @@ public class HandoverTransfer implements Handler.Callback, } } + public void setObjectCount(int objectCount) { + mTotalCount = objectCount; + } + void cancel() { if (!isRunning()) return; @@ -189,43 +211,58 @@ public class HandoverTransfer implements Handler.Callback, } void updateNotification() { - if (!mIncoming) return; // No notifications for outgoing transfers - Builder notBuilder = new Notification.Builder(mContext); + String beamString; + if (mIncoming) { + beamString = mContext.getString(R.string.beam_progress); + } else { + beamString = mContext.getString(R.string.beam_outgoing); + } if (mState == STATE_NEW || mState == STATE_IN_PROGRESS || mState == STATE_W4_NEXT_TRANSFER || mState == STATE_W4_MEDIA_SCANNER) { notBuilder.setAutoCancel(false); - notBuilder.setSmallIcon(android.R.drawable.stat_sys_download); - notBuilder.setTicker(mContext.getString(R.string.beam_progress)); - notBuilder.setContentTitle(mContext.getString(R.string.beam_progress)); + notBuilder.setSmallIcon(mIncoming ? android.R.drawable.stat_sys_download : + android.R.drawable.stat_sys_upload); + notBuilder.setTicker(beamString); + notBuilder.setContentTitle(beamString); notBuilder.addAction(R.drawable.ic_menu_cancel_holo_dark, mContext.getString(R.string.cancel), mCancelIntent); - notBuilder.setDeleteIntent(mCancelIntent); - // We do have progress indication on a per-file basis, but in a multi-file - // transfer we don't know the total progress. So for now, just show an - // indeterminate progress bar. - notBuilder.setProgress(100, 0, true); + float progress = 0; + if (mTotalCount > 0) { + float progressUnit = 1.0f / mTotalCount; + progress = (float) mCurrentCount * progressUnit + mProgress * progressUnit; + } + if (mTotalCount > 0 && progress > 0) { + notBuilder.setProgress(100, (int) (100 * progress), false); + } else { + notBuilder.setProgress(100, 0, true); + } } else if (mState == STATE_SUCCESS) { notBuilder.setAutoCancel(true); - notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); + notBuilder.setSmallIcon(mIncoming ? android.R.drawable.stat_sys_download_done : + android.R.drawable.stat_sys_upload_done); notBuilder.setTicker(mContext.getString(R.string.beam_complete)); notBuilder.setContentTitle(mContext.getString(R.string.beam_complete)); - notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view)); - Intent viewIntent = buildViewIntent(); - PendingIntent contentIntent = PendingIntent.getActivity( - mContext, 0, viewIntent, 0, null); + if (mIncoming) { + notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view)); + Intent viewIntent = buildViewIntent(); + PendingIntent contentIntent = PendingIntent.getActivity( + mContext, mTransferId, viewIntent, 0, null); - notBuilder.setContentIntent(contentIntent); + notBuilder.setContentIntent(contentIntent); + } } else if (mState == STATE_FAILED) { notBuilder.setAutoCancel(false); - notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); + notBuilder.setSmallIcon(mIncoming ? android.R.drawable.stat_sys_download_done : + android.R.drawable.stat_sys_upload_done); notBuilder.setTicker(mContext.getString(R.string.beam_failed)); notBuilder.setContentTitle(mContext.getString(R.string.beam_failed)); } else if (mState == STATE_CANCELLED) { notBuilder.setAutoCancel(false); - notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done); + notBuilder.setSmallIcon(mIncoming ? android.R.drawable.stat_sys_download_done : + android.R.drawable.stat_sys_upload_done); notBuilder.setTicker(mContext.getString(R.string.beam_canceled)); notBuilder.setContentTitle(mContext.getString(R.string.beam_canceled)); } else { @@ -323,13 +360,14 @@ public class HandoverTransfer implements Handler.Callback, if (mIncoming) { processFiles(); } else { - updateStateAndNotification(STATE_SUCCESS); + updateStateAndNotification(mSuccessCount > 0 ? STATE_SUCCESS : STATE_FAILED); } return true; } else if (msg.what == MSG_TRANSFER_TIMEOUT) { // No update on this transfer for a while, check // to see if it's still running, and fail it if it is. if (isRunning()) { + if (DBG) Log.d(TAG, "Transfer timed out"); updateStateAndNotification(STATE_FAILED); } } @@ -375,10 +413,12 @@ public class HandoverTransfer implements Handler.Callback, return viewIntent; } - PendingIntent buildCancelIntent() { + PendingIntent buildCancelIntent(boolean incoming) { Intent intent = new Intent(HandoverService.ACTION_CANCEL_HANDOVER_TRANSFER); intent.putExtra(HandoverService.EXTRA_SOURCE_ADDRESS, mRemoteDevice.getAddress()); - PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0); + intent.putExtra(HandoverService.EXTRA_INCOMING, incoming ? 1 : 0); + PendingIntent pi = PendingIntent.getBroadcast(mContext, mTransferId, intent, + PendingIntent.FLAG_ONE_SHOT); return pi; } @@ -407,7 +447,7 @@ public class HandoverTransfer implements Handler.Callback, File generateMultiplePath(String beamRoot) { // Generate a unique directory with the date String format = "yyyy-MM-dd"; - SimpleDateFormat sdf = new SimpleDateFormat(format); + SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US); String newPath = beamRoot + "beam-" + sdf.format(new Date()); File newFile = new File(newPath); int count = 0; diff --git a/src/com/android/nfc/ndefpush/NdefPushClient.java b/src/com/android/nfc/ndefpush/NdefPushClient.java index e48b0af7..842fb988 100755 --- a/src/com/android/nfc/ndefpush/NdefPushClient.java +++ b/src/com/android/nfc/ndefpush/NdefPushClient.java @@ -35,25 +35,72 @@ public class NdefPushClient { private static final int MIU = 128; private static final boolean DBG = true; - public boolean push(NdefMessage msg) { - NfcService service = NfcService.getInstance(); + private static final int DISCONNECTED = 0; + private static final int CONNECTING = 1; + private static final int CONNECTED = 2; - // We only handle a single immediate action for now - NdefPushProtocol proto = new NdefPushProtocol(msg, NdefPushProtocol.ACTION_IMMEDIATE); - byte[] buffer = proto.toByteArray(); - int offset = 0; - int remoteMiu; + final Object mLock = new Object(); + // Variables below locked on mLock + private int mState = DISCONNECTED; + private LlcpSocket mSocket; + + public void connect() throws IOException { + synchronized (mLock) { + if (mState != DISCONNECTED) { + throw new IOException("Socket still in use."); + } + mState = CONNECTING; + } + NfcService service = NfcService.getInstance(); LlcpSocket sock = null; + if (DBG) Log.d(TAG, "about to create socket"); try { - if (DBG) Log.d(TAG, "about to create socket"); - // Connect to the my tag server on the remote side sock = service.createLlcpSocket(0, MIU, 1, 1024); - if (sock == null) { - throw new IOException("Could not connect to socket."); + } catch (LlcpException e) { + synchronized (mLock) { + mState = DISCONNECTED; } + throw new IOException("Could not create socket."); + } + try { if (DBG) Log.d(TAG, "about to connect to service " + NdefPushServer.SERVICE_NAME); sock.connectToService(NdefPushServer.SERVICE_NAME); + } catch (IOException e) { + if (sock != null) { + try { + sock.close(); + } catch (IOException e2) { + + } + } + synchronized (mLock) { + mState = DISCONNECTED; + } + throw new IOException("Could not connect service."); + } + + synchronized (mLock) { + mSocket = sock; + mState = CONNECTED; + } + } + + public boolean push(NdefMessage msg) { + LlcpSocket sock = null; + synchronized (mLock) { + if (mState != CONNECTED) { + Log.e(TAG, "Not connected to NPP."); + return false; + } + sock = mSocket; + } + // We only handle a single immediate action for now + NdefPushProtocol proto = new NdefPushProtocol(msg, NdefPushProtocol.ACTION_IMMEDIATE); + byte[] buffer = proto.toByteArray(); + int offset = 0; + int remoteMiu; + try { remoteMiu = sock.getRemoteMiu(); if (DBG) Log.d(TAG, "about to send a " + buffer.length + " byte message"); while (offset < buffer.length) { @@ -67,10 +114,6 @@ public class NdefPushClient { } catch (IOException e) { Log.e(TAG, "couldn't send tag"); if (DBG) Log.d(TAG, "exception:", e); - } catch (LlcpException e) { - // Most likely the other side doesn't support the my tag protocol - Log.e(TAG, "couldn't send tag"); - if (DBG) Log.d(TAG, "exception:", e); } finally { if (sock != null) { try { @@ -83,4 +126,19 @@ public class NdefPushClient { } return false; } + + public void close() { + synchronized (mLock) { + if (mSocket != null) { + try { + if (DBG) Log.d(TAG, "About to close NPP socket."); + mSocket.close(); + } catch (IOException e) { + // Ignore + } + mSocket = null; + } + mState = DISCONNECTED; + } + } } diff --git a/src/com/android/nfc/snep/SnepClient.java b/src/com/android/nfc/snep/SnepClient.java index fae8143f..03824ccd 100644 --- a/src/com/android/nfc/snep/SnepClient.java +++ b/src/com/android/nfc/snep/SnepClient.java @@ -157,6 +157,9 @@ public final class SnepClient { int fragmentLength = (mFragmentLength == -1) ? miu : Math.min(miu, mFragmentLength); messenger = new SnepMessenger(true, socket, fragmentLength); } catch (LlcpException e) { + synchronized (this) { + mState = DISCONNECTED; + } throw new IOException("Could not connect to socket"); } catch (IOException e) { if (socket != null) { @@ -165,6 +168,9 @@ public final class SnepClient { } catch (IOException e2) { } } + synchronized (this) { + mState = DISCONNECTED; + } throw new IOException("Failed to connect to socket"); } |