1 /* ****************************************************************j
\r
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 ******************************************************************/
\r
20 #include "canfcinterface.h"
\r
22 #include "caadapterutils.h"
\r
23 #include "camutex.h"
\r
24 #include "oic_malloc.h"
\r
25 #include "oic_string.h"
\r
29 * Logging tag for module name
\r
31 #define TAG "NFC_SERVER"
\r
33 static CANFCPacketReceivedCallback g_packetReceivedCallback;
\r
35 static JavaVM *g_jvm = NULL;
\r
36 static jobject g_context = NULL;
\r
37 static jobject g_activity = NULL;
\r
38 static jobject g_nfcInterface = NULL;
\r
39 static jmethodID g_sendMethod = NULL;
\r
41 static void CANfcJniInit();
\r
42 static void CANfcJNISetContext();
\r
43 static CAResult_t CANfcCreateJniInterfaceObject();
\r
44 static CAResult_t CANfcSendDataImpl(const CAEndpoint_t * ep, const char* data, uint32_t dataLen);
\r
46 static const char CLASS_NFCINTERFACE[] = "org/iotivity/ca/CaNfcInterface";
\r
48 static void CANfcJniInit()
\r
50 OIC_LOG(DEBUG, TAG, "CANfcJniInit");
\r
51 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
\r
54 static void CANfcJNISetContext()
\r
56 OIC_LOG(DEBUG, TAG, "CANfcJNISetContext");
\r
57 g_context = (jobject) CANativeJNIGetContext();
\r
58 g_activity = (jobject) CANativeGetActivity();
\r
61 void CANFCSetPacketReceiveCallback(CANFCPacketReceivedCallback callback)
\r
63 OIC_LOG(DEBUG, TAG, "IN");
\r
65 g_packetReceivedCallback = callback;
\r
67 OIC_LOG(DEBUG, TAG, "OUT");
\r
70 CAResult_t SetCreateNdefMessageCallbackfromNative(JNIEnv* env)
\r
72 OIC_LOG(DEBUG, TAG, "SetCreateNdefMessageCallbackfromNative IN");
\r
74 VERIFY_NON_NULL(env, TAG, "env");
\r
75 VERIFY_NON_NULL(g_context, TAG, "g_context");
\r
76 VERIFY_NON_NULL(g_activity, TAG, "g_activity");
\r
77 VERIFY_NON_NULL(g_nfcInterface, TAG, "g_nfcInterface");
\r
79 jclass cid_NfcAdapter = (*env)->FindClass(env, "android/nfc/NfcAdapter");
\r
80 if (!cid_NfcAdapter)
\r
82 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter class");
\r
83 return CA_STATUS_FAILED;
\r
86 jmethodID mid_getAdapter = (*env)->GetStaticMethodID(env, cid_NfcAdapter,
\r
87 "getDefaultAdapter",
\r
88 "(Landroid/content/Context;)Landroid/nfc/NfcAdapter;");
\r
89 if (!mid_getAdapter)
\r
91 OIC_LOG(ERROR, TAG, "Could not get methodId mid_getAdapter");
\r
92 return CA_STATUS_FAILED;
\r
95 jobject adapter = (*env)->CallStaticObjectMethod(env, cid_NfcAdapter, mid_getAdapter,
\r
99 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter");
\r
100 return CA_STATUS_FAILED;
\r
103 jmethodID mid_setCallback = (*env)->GetMethodID(
\r
104 env, cid_NfcAdapter, "setNdefPushMessageCallback",
\r
105 "(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;"
\r
106 "[Landroid/app/Activity;)V");
\r
107 if (!mid_setCallback)
\r
109 OIC_LOG(ERROR, TAG, "Could not get mid_setCallback");
\r
110 return CA_STATUS_FAILED;
\r
113 jclass cid_Activity = (*env)->FindClass(env, "android/app/Activity");
\r
116 OIC_LOG(ERROR, TAG, "Could not get Activity class");
\r
117 return CA_STATUS_FAILED;
\r
120 jobjectArray tempArr = (jobjectArray) (*env)->NewObjectArray(env, 0, cid_Activity, NULL);
\r
121 (*env)->CallVoidMethod(env, adapter, mid_setCallback, g_nfcInterface, g_activity, tempArr);
\r
123 OIC_LOG(DEBUG, TAG, "SetCreateNdefMessageCallbackfromNative OUT");
\r
124 return CA_STATUS_OK;
\r
127 CAResult_t CANfcCreateJniInterfaceObject()
\r
129 OIC_LOG(DEBUG, TAG, "CANfcCreateJniInterfaceObject IN");
\r
131 VERIFY_NON_NULL(g_activity, TAG, "g_activity");
\r
132 VERIFY_NON_NULL(g_context, TAG, "g_context");
\r
133 VERIFY_NON_NULL(g_jvm, TAG, "g_jvm");
\r
135 bool isAttached = false;
\r
137 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
140 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
141 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
145 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
146 return CA_STATUS_FAILED;
\r
151 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, "android/content/Context",
\r
152 "getApplicationContext",
\r
153 "()Landroid/content/Context;");
\r
155 if (!mid_getApplicationContext)
\r
157 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
\r
158 return CA_STATUS_FAILED;
\r
161 jobject jApplicationContext = (*env)->CallObjectMethod(env, g_context,
\r
162 mid_getApplicationContext);
\r
163 if (!jApplicationContext)
\r
165 OIC_LOG(ERROR, TAG, "Could not get application context");
\r
166 return CA_STATUS_FAILED;
\r
169 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
170 if (!jni_NfcInterface)
\r
172 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface class");
\r
176 jmethodID NfcInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_NfcInterface, "<init>",
\r
177 "(Landroid/content/Context;Landroid/app/Activity;)V");
\r
178 if (!NfcInterfaceConstructorMethod)
\r
180 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface constructor method");
\r
184 jobject jni_nfcInstance = (*env)->NewObject(env, jni_NfcInterface,
\r
185 NfcInterfaceConstructorMethod, jApplicationContext,
\r
187 if (!jni_nfcInstance)
\r
189 OIC_LOG(ERROR, TAG, "Create instance for CaNfcInterface failed");
\r
193 g_nfcInterface = (*env)->NewGlobalRef(env, jni_nfcInstance);
\r
194 if (!g_nfcInterface)
\r
196 OIC_LOG(ERROR, TAG, "NewGlobalRef for nfcInterface failed");
\r
200 OIC_LOG(DEBUG, TAG, "Create instance for CaNfcInterface");
\r
202 CAResult_t result = SetCreateNdefMessageCallbackfromNative(env);
\r
203 if (CA_STATUS_OK != result)
\r
205 OIC_LOG(ERROR, TAG, "SetCreateNdefMessageCallbackfromNative failed");
\r
211 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
214 OIC_LOG(DEBUG, TAG, "CANfcCreateJniInterfaceObject OUT");
\r
215 return CA_STATUS_OK;
\r
220 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
223 return CA_STATUS_FAILED;
\r
226 CAResult_t CAInitializeNfcServer()
\r
229 CANfcJNISetContext();
\r
231 CAResult_t result = CANfcCreateJniInterfaceObject();
\r
232 if (CA_STATUS_OK != result)
\r
234 OIC_LOG(ERROR, TAG, "CANfcJniInit failed");
\r
240 CAResult_t CANFCStartServer()
\r
242 bool isAttached = false;
\r
244 OIC_LOG(INFO, TAG, "CANFCStartServer : IN");
\r
247 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
250 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
251 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
255 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
256 return CA_STATUS_FAILED;
\r
261 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
262 if (!jni_NfcInterface)
\r
264 OIC_LOG(ERROR, TAG, "Could not get CaNFCClientInterface class");
\r
268 jmethodID methodId = (*env)->GetMethodID(env, jni_NfcInterface, "caNfcInitialize", "()V");
\r
271 OIC_LOG(ERROR, TAG, "Could not get methodId");
\r
275 if (!g_nfcInterface)
\r
277 OIC_LOG(ERROR, TAG, "g_nfcInterface NULL");
\r
281 (*env)->CallVoidMethod(env, g_nfcInterface, methodId);
\r
282 OIC_LOG(DEBUG, TAG, "caNfcInitialize");
\r
284 jmethodID sendDataMethodId = (*env)->GetMethodID(env, jni_NfcInterface, "processSendRquest",
\r
286 if (!sendDataMethodId)
\r
288 OIC_LOG(ERROR, TAG, "Could not get sendDataMethodId");
\r
292 g_sendMethod = sendDataMethodId;
\r
296 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
299 return CA_STATUS_OK;
\r
304 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
306 return CA_STATUS_FAILED;
\r
310 void CANFCStopServer()
\r
312 // JNI Call to unregstier nfc adapter
\r
316 * Class: org_iotivity_ca_CaNfcInterface
\r
317 * Method: caNativeNfcCreateNdefMessage
\r
318 * Signature: ([B)Landroid/nfc/NdefMessage;
\r
320 JNIEXPORT jobject JNICALL
\r
321 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcCreateNdefMessage(JNIEnv *env, jobject obj,
\r
322 jbyteArray sendData)
\r
324 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : IN");
\r
325 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
\r
326 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", NULL);
\r
328 const char *mime = "application/org.iotivity.ca.sample_service";
\r
329 jstring mimeString = (*env)->NewStringUTF(env, mime);
\r
332 OIC_LOG(ERROR, TAG, "NewStringUTF failed for mimeString");
\r
336 const char *type = "US_ASCII";
\r
337 jstring charSetString = (*env)->NewStringUTF(env, type);
\r
338 if (!charSetString)
\r
340 OIC_LOG(ERROR, TAG, "NewStringUTF failed for charSetString");
\r
344 jclass cid_string = (*env)->FindClass(env, "java/lang/String");
\r
347 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter class for cid_string");
\r
351 jmethodID mid_getBytes = (*env)->GetMethodID(env, cid_string, "getBytes",
\r
352 "(Ljava/lang/String;)[B");
\r
355 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_getBytes");
\r
359 jbyteArray mimeTypeArr = (*env)->CallObjectMethod(env, mimeString, mid_getBytes,
\r
363 OIC_LOG(ERROR, TAG, "getBytes failed for mimeTypeArr");
\r
366 jclass cid_NdefRecord = (*env)->FindClass(env, "android/nfc/NdefRecord");
\r
367 if (!cid_NdefRecord)
\r
369 OIC_LOG(ERROR, TAG, "Could not get NdefRecord class for cid_NdefRecord");
\r
373 jmethodID mid_createRecord = (*env)->GetMethodID(env, cid_NdefRecord, "<init>",
\r
375 if (!mid_createRecord)
\r
377 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createRecord");
\r
381 jfieldID fid_tnfType = (*env)->GetStaticFieldID(env, cid_NdefRecord, "TNF_MIME_MEDIA", "S");
\r
383 jint tnfType = (*env)->GetStaticShortField(env, cid_NdefRecord, fid_tnfType);
\r
384 OIC_LOG_V(ERROR, TAG, "tnfType : %d", tnfType);
\r
386 jbyteArray nullArr = (*env)->NewByteArray(env, 0);
\r
388 jobject ndefRecord = (*env)->NewObject(env, cid_NdefRecord, mid_createRecord, tnfType,
\r
389 mimeTypeArr, nullArr, sendData);
\r
392 OIC_LOG(ERROR, TAG, "createNdefRecord failed for ndefRecord");
\r
396 jclass cid_NdefMsg = (*env)->FindClass(env, "android/nfc/NdefMessage");
\r
399 OIC_LOG(ERROR, TAG, "Could not get NdefMessage class for cid_NdefMsg");
\r
403 jmethodID mid_createMsg = (*env)->GetMethodID(env, cid_NdefMsg, "<init>",
\r
404 "([Landroid/nfc/NdefRecord;)V");
\r
405 if (!mid_createMsg)
\r
407 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createMsg");
\r
410 jobjectArray tempArr = (jobjectArray) (*env)->NewObjectArray(env, 1, cid_NdefRecord,
\r
413 jobject ndefMsg = (*env)->NewObject(env, cid_NdefMsg, mid_createMsg, tempArr);
\r
416 OIC_LOG(ERROR, TAG, "createNdefMessage failed for ndefMsg");
\r
420 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : OUT");
\r
425 * Class: org_iotivity_ca_CaNfcInterface
\r
426 * Method: caNativeNfcInvokeBeam
\r
429 JNIEXPORT jboolean JNICALL
\r
430 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcInvokeBeam(JNIEnv *env, jobject obj)
\r
432 OIC_LOG(DEBUG, TAG, "cANativeNfcInvokeBeam : IN");
\r
433 VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
\r
434 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", false);
\r
435 VERIFY_NON_NULL_RET(g_context, TAG, "g_context is null", false);
\r
436 VERIFY_NON_NULL_RET(g_activity, TAG, "g_activity is null", false);
\r
438 jclass cid_NfcAdapter = (*env)->FindClass(env, "android/nfc/NfcAdapter");
\r
439 if (!cid_NfcAdapter)
\r
441 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter cid_NfcAdapter ");
\r
445 jmethodID mid_getAdapter = (*env)->GetStaticMethodID(env, cid_NfcAdapter,
\r
446 "getDefaultAdapter",
\r
447 "(Landroid/content/Context;)Landroid/nfc/NfcAdapter;");
\r
448 if (!mid_getAdapter)
\r
450 OIC_LOG(ERROR, TAG, "Could not get methodId mid_getAdapter");
\r
454 jobject adapter = (*env)->CallStaticObjectMethod(env, cid_NfcAdapter, mid_getAdapter,
\r
458 OIC_LOG(ERROR, TAG, "getDefaultAdapter failed adapter");
\r
462 jmethodID mid_invokeBeam = (*env)->GetMethodID(env, cid_NfcAdapter, "invokeBeam",
\r
463 "(Landroid/app/Activity;)Z");
\r
464 if (!mid_invokeBeam)
\r
466 OIC_LOG(ERROR, TAG, "Could not get methodId mid_invokeBeam");
\r
471 jboolean isSuccess = (*env)->CallBooleanMethod(env, adapter, mid_invokeBeam, g_activity);
\r
474 OIC_LOG(ERROR, TAG, "invokeBeam has failed");
\r
476 OIC_LOG(DEBUG, TAG, "cANativeNfcInvokeBeam : OUT");
\r
482 * Class: org_iotivity_ca_CaNfcInterface
\r
483 * Method: caNativeNfcPacketReceived
\r
486 JNIEXPORT void JNICALL
\r
487 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcPacketReceived(JNIEnv *env, jobject obj,
\r
490 OIC_LOG(DEBUG, TAG, "caNfcPacketReceived : IN");
\r
491 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
\r
492 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
\r
493 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
\r
495 char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
\r
497 // get Byte Array and covert to char*
\r
498 jint length = (*env)->GetArrayLength(env, data);
\r
500 if (length >= COAP_MAX_PDU_SIZE)
\r
502 OIC_LOG_V(ERROR, TAG, "caNfcPacketReceived - Invalid CoAP length : %d",
\r
508 jbyte *jni_received_data = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
\r
510 OIC_LOG_V(DEBUG, TAG, "caNfcPacketReceived - raw data received : %s",
\r
511 jni_received_data);
\r
513 memcpy(recvBuffer, (const char*) jni_received_data, length);
\r
514 (*env)->ReleaseByteArrayElements(env, data, jni_received_data, JNI_ABORT);
\r
516 const char* address = "AA:BB:CC:DD:EE:FF";
\r
518 OIC_LOG_V(DEBUG, TAG, "caNfcPacketReceived - data. : %s, %d",
\r
519 recvBuffer, length);
\r
521 CASecureEndpoint_t sep =
\r
523 {.adapter = CA_ADAPTER_NFC,
\r
524 .flags = CA_DEFAULT_FLAGS
\r
527 OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), address);
\r
529 g_packetReceivedCallback(&sep, recvBuffer, length);
\r
530 OIC_LOG(DEBUG, TAG, "caNfcPacketReceived : OUT");
\r
533 CAResult_t CANfcSendDataImpl(const CAEndpoint_t * ep, const char* data, uint32_t dataLen)
\r
535 VERIFY_NON_NULL(ep, TAG, "CANfcSendDataImpl : endpoint is null");
\r
536 VERIFY_NON_NULL(data, TAG, "CANfcSendDataImpl : data is null");
\r
537 VERIFY_NON_NULL(g_jvm, TAG, "CANfcSendDataImpl : g_jvm is null");
\r
539 OIC_LOG(INFO, TAG, "CANfcSendDataImpl moved env outside");
\r
540 bool isAttached = false;
\r
542 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
545 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
546 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
550 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
551 return CA_STATUS_FAILED;
\r
556 OIC_LOG(INFO, TAG, "creating send buffer");
\r
557 jbyteArray sendData = (*env)->NewByteArray(env, dataLen);
\r
560 OIC_LOG(ERROR, TAG, "Failed to create ByteArray");
\r
563 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
566 return CA_SEND_FAILED;
\r
570 (*env)->SetByteArrayRegion(env, sendData, 0, dataLen, (jbyte*) data);
\r
572 (*env)->CallVoidMethod(env, g_nfcInterface, g_sendMethod, sendData);
\r
573 OIC_LOG(DEBUG, TAG, "send data through NFC");
\r
575 (*env)->DeleteLocalRef(env, sendData);
\r
579 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
582 return CA_STATUS_OK;
\r
585 void CANFCSendData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
\r
587 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
\r
588 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
\r
590 // JNI to Send data
\r
591 CANfcSendDataImpl(endpoint, data, dataLength);
\r