summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Cerqueira <cyanogenmod@cerqueira.org>2013-07-25 00:31:49 +0100
committerRicardo Cerqueira <cyanogenmod@cerqueira.org>2013-07-25 00:31:49 +0100
commit2179fd368b019e2f0f419fd0eada5e2b693c18bb (patch)
tree0c217a7c8c5c4221e7883d714b8dd2ff5729a7fc
parent43c1153e4b31194a32b9be7febd5aa4a542cef3c (diff)
parent36cf13f6279056792e154c3222041dc295d2f405 (diff)
downloadandroid_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
-rw-r--r--Android.mk4
-rw-r--r--nci/jni/Android.mk5
-rw-r--r--nci/jni/IntervalTimer.cpp8
-rw-r--r--nci/jni/JavaClassConstants.h1
-rw-r--r--nci/jni/NativeLlcpConnectionlessSocket.cpp81
-rw-r--r--nci/jni/NativeLlcpServiceSocket.cpp3
-rw-r--r--nci/jni/NativeLlcpSocket.cpp90
-rwxr-xr-xnci/jni/NativeNfcManager.cpp370
-rwxr-xr-xnci/jni/NativeNfcTag.cpp112
-rw-r--r--nci/jni/NativeP2pDevice.cpp10
-rwxr-xr-xnci/jni/NativeSecureElement.cpp48
-rwxr-xr-xnci/jni/NfcJniUtil.cpp52
-rwxr-xr-xnci/jni/NfcJniUtil.h17
-rwxr-xr-xnci/jni/NfcTag.cpp225
-rw-r--r--nci/jni/PeerToPeer.cpp130
-rw-r--r--nci/jni/PeerToPeer.h15
-rw-r--r--nci/jni/RouteDataSet.cpp1
-rwxr-xr-xnci/jni/SecureElement.cpp119
-rwxr-xr-xnci/jni/SecureElement.h11
-rwxr-xr-xnci/src/com/android/nfc/dhimpl/NativeNfcManager.java7
-rwxr-xr-xnci/src/com/android/nfc/dhimpl/NativeNfcTag.java7
-rw-r--r--nxp/jni/Android.mk4
-rwxr-xr-xnxp/jni/com_android_nfc.cpp143
-rwxr-xr-xnxp/jni/com_android_nfc.h28
-rw-r--r--nxp/jni/com_android_nfc_NativeLlcpServiceSocket.cpp11
-rwxr-xr-xnxp/jni/com_android_nfc_NativeNfcManager.cpp154
-rwxr-xr-xnxp/jni/com_android_nfc_NativeNfcSecureElement.cpp29
-rwxr-xr-xnxp/jni/com_android_nfc_NativeNfcTag.cpp169
-rw-r--r--nxp/jni/com_android_nfc_NativeP2pDevice.cpp7
-rw-r--r--res/layout/screenshot.xml33
-rw-r--r--res/values-af/strings.xml2
-rw-r--r--res/values-am/strings.xml4
-rw-r--r--res/values-ar/strings.xml14
-rw-r--r--res/values-be/strings.xml2
-rw-r--r--res/values-bg/strings.xml2
-rw-r--r--res/values-ca/strings.xml2
-rw-r--r--res/values-cs/strings.xml4
-rw-r--r--res/values-da/strings.xml2
-rw-r--r--res/values-de/strings.xml2
-rw-r--r--res/values-el/strings.xml2
-rw-r--r--res/values-en-rGB/strings.xml2
-rw-r--r--res/values-es-rUS/strings.xml2
-rw-r--r--res/values-es/strings.xml2
-rw-r--r--res/values-et/strings.xml2
-rw-r--r--res/values-fa/strings.xml2
-rw-r--r--res/values-fi/strings.xml2
-rw-r--r--res/values-fr/strings.xml2
-rw-r--r--res/values-hi/strings.xml5
-rw-r--r--res/values-hr/strings.xml2
-rw-r--r--res/values-hu/strings.xml2
-rw-r--r--res/values-in/strings.xml2
-rw-r--r--res/values-it/strings.xml2
-rw-r--r--res/values-iw/strings.xml2
-rw-r--r--res/values-ja/strings.xml2
-rw-r--r--res/values-ko/strings.xml2
-rw-r--r--res/values-lt/strings.xml2
-rw-r--r--res/values-lv/strings.xml2
-rw-r--r--res/values-ms/strings.xml2
-rw-r--r--res/values-nb/strings.xml2
-rw-r--r--res/values-nl/strings.xml4
-rw-r--r--res/values-pl/strings.xml2
-rw-r--r--res/values-pt-rPT/strings.xml4
-rw-r--r--res/values-pt/strings.xml14
-rw-r--r--res/values-ro/strings.xml23
-rw-r--r--res/values-ru/strings.xml2
-rw-r--r--res/values-sk/strings.xml2
-rw-r--r--res/values-sl/strings.xml2
-rw-r--r--res/values-sr/strings.xml2
-rw-r--r--res/values-sv/strings.xml2
-rw-r--r--res/values-sw/strings.xml4
-rw-r--r--res/values-th/strings.xml4
-rw-r--r--res/values-tl/strings.xml2
-rw-r--r--res/values-tr/strings.xml4
-rw-r--r--res/values-uk/strings.xml2
-rw-r--r--res/values-vi/strings.xml2
-rw-r--r--res/values-zh-rCN/strings.xml2
-rw-r--r--res/values-zh-rTW/strings.xml2
-rw-r--r--res/values-zu/strings.xml2
-rw-r--r--res/values/provisioning.xml27
-rwxr-xr-xres/values/strings.xml2
-rwxr-xr-xsrc/com/android/nfc/DeviceHost.java2
-rw-r--r--src/com/android/nfc/NfcDispatcher.java46
-rwxr-xr-xsrc/com/android/nfc/NfcService.java242
-rw-r--r--src/com/android/nfc/P2pEventManager.java24
-rwxr-xr-xsrc/com/android/nfc/P2pLinkManager.java582
-rw-r--r--src/com/android/nfc/SendUi.java198
-rw-r--r--src/com/android/nfc/handover/BluetoothHeadsetHandover.java24
-rw-r--r--src/com/android/nfc/handover/BluetoothOppHandover.java4
-rw-r--r--src/com/android/nfc/handover/HandoverClient.java82
-rw-r--r--src/com/android/nfc/handover/HandoverManager.java27
-rw-r--r--src/com/android/nfc/handover/HandoverService.java57
-rw-r--r--src/com/android/nfc/handover/HandoverTransfer.java92
-rwxr-xr-xsrc/com/android/nfc/ndefpush/NdefPushClient.java88
-rw-r--r--src/com/android/nfc/snep/SnepClient.java6
94 files changed, 2301 insertions, 1254 deletions
diff --git a/Android.mk b/Android.mk
index 9aa7ee24..00062dfb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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");
}