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
73 jclass cid_NfcAdapter = (*env)->FindClass(env, "android/nfc/NfcAdapter");
\r
74 if (!cid_NfcAdapter)
\r
76 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter class");
\r
77 return CA_STATUS_FAILED;
\r
80 jmethodID mid_getAdapter = (*env)->GetStaticMethodID(env, cid_NfcAdapter,
\r
81 "getDefaultAdapter",
\r
82 "(Landroid/content/Context;)Landroid/nfc/NfcAdapter;");
\r
83 if (!mid_getAdapter)
\r
85 OIC_LOG(ERROR, TAG, "Could not get methodId mid_getAdapter");
\r
86 return CA_STATUS_FAILED;
\r
89 jobject adapter = (*env)->CallStaticObjectMethod(env, cid_NfcAdapter, mid_getAdapter,
\r
93 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter");
\r
94 return CA_STATUS_FAILED;
\r
97 jmethodID mid_setCallback = (*env)->GetMethodID(
\r
98 env, cid_NfcAdapter, "setNdefPushMessageCallback",
\r
99 "(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;"
\r
100 "[Landroid/app/Activity;)V");
\r
101 if (!mid_setCallback)
\r
103 OIC_LOG(ERROR, TAG, "Could not get mid_setCallback");
\r
104 return CA_STATUS_FAILED;
\r
107 jclass cid_Activity = (*env)->FindClass(env, "android/app/Activity");
\r
110 OIC_LOG(ERROR, TAG, "Could not get Activity class");
\r
111 return CA_STATUS_FAILED;
\r
114 jobjectArray tempArr = (jobjectArray) (*env)->NewObjectArray(env, 0, cid_Activity, NULL);
\r
115 (*env)->CallVoidMethod(env, adapter, mid_setCallback, g_nfcInterface, g_activity, tempArr);
\r
117 OIC_LOG(DEBUG, TAG, "SetCreateNdefMessageCallbackfromNative OUT");
\r
118 return CA_STATUS_OK;
\r
121 CAResult_t CANfcCreateJniInterfaceObject()
\r
123 OIC_LOG(DEBUG, TAG, "CANfcCreateJniInterfaceObject IN");
\r
127 OIC_LOG(ERROR, TAG, "g_context is null");
\r
128 return CA_STATUS_FAILED;
\r
133 OIC_LOG(ERROR, TAG, "g_jvm is null");
\r
134 return CA_STATUS_FAILED;
\r
137 bool isAttached = false;
\r
139 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
142 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
143 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
147 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
148 return CA_STATUS_FAILED;
\r
153 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
154 if (!jni_NfcInterface)
\r
156 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface class");
\r
160 jmethodID NfcInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_NfcInterface, "<init>",
\r
161 "(Landroid/content/Context;Landroid/app/Activity;)V");
\r
162 if (!NfcInterfaceConstructorMethod)
\r
164 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface constructor method");
\r
168 jobject jni_nfcInstance = (*env)->NewObject(env, jni_NfcInterface,
\r
169 NfcInterfaceConstructorMethod, g_context,
\r
171 if (!jni_nfcInstance)
\r
173 OIC_LOG(ERROR, TAG, "Create instance for CaNfcInterface failed");
\r
177 g_nfcInterface = (*env)->NewGlobalRef(env, jni_nfcInstance);
\r
178 if (!g_nfcInterface)
\r
180 OIC_LOG(ERROR, TAG, "NewGlobalRef for nfcInterface failed");
\r
184 OIC_LOG(DEBUG, TAG, "Create instance for CaNfcInterface");
\r
186 CAResult_t result = SetCreateNdefMessageCallbackfromNative(env);
\r
187 if (CA_STATUS_OK != result)
\r
189 OIC_LOG(ERROR, TAG, "SetCreateNdefMessageCallbackfromNative failed");
\r
195 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
198 OIC_LOG(DEBUG, TAG, "CANfcCreateJniInterfaceObject OUT");
\r
199 return CA_STATUS_OK;
\r
204 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
207 return CA_STATUS_FAILED;
\r
210 CAResult_t CAInitializeNfcServer()
\r
213 CANfcJNISetContext();
\r
215 CAResult_t result = CANfcCreateJniInterfaceObject();
\r
216 if (CA_STATUS_OK != result)
\r
218 OIC_LOG(ERROR, TAG, "CANfcJniInit failed");
\r
224 CAResult_t CANFCStartServer()
\r
226 bool isAttached = false;
\r
228 OIC_LOG(INFO, TAG, "CANFCStartServer : IN");
\r
231 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
234 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
235 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
239 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
240 return CA_STATUS_FAILED;
\r
245 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
246 if (!jni_NfcInterface)
\r
248 OIC_LOG(ERROR, TAG, "Could not get CaNFCClientInterface class");
\r
252 jmethodID methodId = (*env)->GetMethodID(env, jni_NfcInterface, "caNfcInitialize", "()V");
\r
255 OIC_LOG(ERROR, TAG, "Could not get methodId");
\r
259 if (!g_nfcInterface)
\r
261 OIC_LOG(ERROR, TAG, "g_nfcInterface NULL");
\r
265 (*env)->CallVoidMethod(env, g_nfcInterface, methodId);
\r
266 OIC_LOG(DEBUG, TAG, "caNfcInitialize");
\r
268 jmethodID sendDataMethodId = (*env)->GetMethodID(env, jni_NfcInterface, "processSendRquest",
\r
270 if (!sendDataMethodId)
\r
272 OIC_LOG(ERROR, TAG, "Could not get sendDataMethodId");
\r
276 g_sendMethod = sendDataMethodId;
\r
280 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
283 return CA_STATUS_OK;
\r
288 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
290 return CA_STATUS_FAILED;
\r
294 void CANFCStopServer()
\r
296 // JNI Call to unregstier nfc adapter
\r
300 * Class: org_iotivity_ca_CaNfcInterface
\r
301 * Method: caNativeNfcCreateNdefMessage
\r
302 * Signature: ([B)Landroid/nfc/NdefMessage;
\r
304 JNIEXPORT jobject JNICALL
\r
305 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcCreateNdefMessage(JNIEnv *env, jobject obj,
\r
306 jbyteArray sendData)
\r
308 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : IN");
\r
309 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
\r
310 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", NULL);
\r
312 const char *mime = "application/org.iotivity.ca.sample_service";
\r
313 jstring mimeString = (*env)->NewStringUTF(env, mime);
\r
316 OIC_LOG(ERROR, TAG, "NewStringUTF failed for mimeString");
\r
320 const char *type = "US_ASCII";
\r
321 jstring charSetString = (*env)->NewStringUTF(env, type);
\r
322 if (!charSetString)
\r
324 OIC_LOG(ERROR, TAG, "NewStringUTF failed for charSetString");
\r
328 jclass cid_string = (*env)->FindClass(env, "java/lang/String");
\r
331 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter class for cid_string");
\r
335 jmethodID mid_getBytes = (*env)->GetMethodID(env, cid_string, "getBytes",
\r
336 "(Ljava/lang/String;)[B");
\r
339 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_getBytes");
\r
343 jbyteArray mimeTypeArr = (*env)->CallObjectMethod(env, mimeString, mid_getBytes,
\r
347 OIC_LOG(ERROR, TAG, "getBytes failed for mimeTypeArr");
\r
350 jclass cid_NdefRecord = (*env)->FindClass(env, "android/nfc/NdefRecord");
\r
351 if (!cid_NdefRecord)
\r
353 OIC_LOG(ERROR, TAG, "Could not get NdefRecord class for cid_NdefRecord");
\r
357 jmethodID mid_createRecord = (*env)->GetMethodID(env, cid_NdefRecord, "<init>",
\r
359 if (!mid_createRecord)
\r
361 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createRecord");
\r
365 jfieldID fid_tnfType = (*env)->GetStaticFieldID(env, cid_NdefRecord, "TNF_MIME_MEDIA", "S");
\r
367 jint tnfType = (*env)->GetStaticShortField(env, cid_NdefRecord, fid_tnfType);
\r
368 OIC_LOG_V(ERROR, TAG, "tnfType : %d", tnfType);
\r
370 jbyteArray nullArr = (*env)->NewByteArray(env, 0);
\r
372 jobject ndefRecord = (*env)->NewObject(env, cid_NdefRecord, mid_createRecord, tnfType,
\r
373 mimeTypeArr, nullArr, sendData);
\r
376 OIC_LOG(ERROR, TAG, "createNdefRecord failed for ndefRecord");
\r
380 jclass cid_NdefMsg = (*env)->FindClass(env, "android/nfc/NdefMessage");
\r
383 OIC_LOG(ERROR, TAG, "Could not get NdefMessage class for cid_NdefMsg");
\r
387 jmethodID mid_createMsg = (*env)->GetMethodID(env, cid_NdefMsg, "<init>",
\r
388 "([Landroid/nfc/NdefRecord;)V");
\r
389 if (!mid_createMsg)
\r
391 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createMsg");
\r
394 jobjectArray tempArr = (jobjectArray) (*env)->NewObjectArray(env, 1, cid_NdefRecord,
\r
397 jobject ndefMsg = (*env)->NewObject(env, cid_NdefMsg, mid_createMsg, tempArr);
\r
400 OIC_LOG(ERROR, TAG, "createNdefMessage failed for ndefMsg");
\r
404 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : OUT");
\r
409 * Class: org_iotivity_ca_CaNfcInterface
\r
410 * Method: caNativeNfcInvokeBeam
\r
413 JNIEXPORT jboolean JNICALL
\r
414 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcInvokeBeam(JNIEnv *env, jobject obj)
\r
416 OIC_LOG(DEBUG, TAG, "cANativeNfcInvokeBeam : IN");
\r
417 VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
\r
418 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", false);
\r
420 jclass cid_NfcAdapter = (*env)->FindClass(env, "android/nfc/NfcAdapter");
\r
421 if (!cid_NfcAdapter)
\r
423 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter cid_NfcAdapter ");
\r
427 jmethodID mid_getAdapter = (*env)->GetStaticMethodID(env, cid_NfcAdapter,
\r
428 "getDefaultAdapter",
\r
429 "(Landroid/content/Context;)Landroid/nfc/NfcAdapter;");
\r
430 if (!mid_getAdapter)
\r
432 OIC_LOG(ERROR, TAG, "Could not get methodId mid_getAdapter");
\r
436 jobject adapter = (*env)->CallStaticObjectMethod(env, cid_NfcAdapter, mid_getAdapter,
\r
440 OIC_LOG(ERROR, TAG, "getDefaultAdapter failed adapter");
\r
444 jmethodID mid_invokeBeam = (*env)->GetMethodID(env, cid_NfcAdapter, "invokeBeam",
\r
445 "(Landroid/app/Activity;)Z");
\r
446 if (!mid_invokeBeam)
\r
448 OIC_LOG(ERROR, TAG, "Could not get methodId mid_invokeBeam");
\r
453 jboolean isSuccess = (*env)->CallBooleanMethod(env, adapter, mid_invokeBeam, g_activity);
\r
456 OIC_LOG(ERROR, TAG, "invokeBeam has failed");
\r
458 OIC_LOG(DEBUG, TAG, "cANativeNfcInvokeBeam : OUT");
\r
464 * Class: org_iotivity_ca_CaNfcInterface
\r
465 * Method: caNativeNfcPacketReceived
\r
468 JNIEXPORT void JNICALL
\r
469 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcPacketReceived(JNIEnv *env, jobject obj,
\r
472 OIC_LOG(DEBUG, TAG, "caNfcPacketReceived : IN");
\r
473 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
\r
474 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
\r
475 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
\r
477 char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
\r
479 // get Byte Array and covert to char*
\r
480 jint length = (*env)->GetArrayLength(env, data);
\r
482 if (length >= COAP_MAX_PDU_SIZE)
\r
484 OIC_LOG_V(ERROR, TAG, "caNfcPacketReceived - Invalid CoAP length : %d",
\r
490 jbyte *jni_received_data = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
\r
492 OIC_LOG_V(DEBUG, TAG, "caNfcPacketReceived - raw data received : %s",
\r
493 jni_received_data);
\r
495 memcpy(recvBuffer, (const char*) jni_received_data, length);
\r
496 (*env)->ReleaseByteArrayElements(env, data, jni_received_data, JNI_ABORT);
\r
498 const char* address = "AA:BB:CC:DD:EE:FF";
\r
500 OIC_LOG_V(DEBUG, TAG, "caNfcPacketReceived - data. : %s, %d",
\r
501 recvBuffer, length);
\r
503 CASecureEndpoint_t sep =
\r
505 {.adapter = CA_ADAPTER_NFC,
\r
506 .flags = CA_DEFAULT_FLAGS
\r
509 OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), address);
\r
511 g_packetReceivedCallback(&sep, recvBuffer, length);
\r
512 OIC_LOG(DEBUG, TAG, "caNfcPacketReceived : OUT");
\r
515 CAResult_t CANfcSendDataImpl(const CAEndpoint_t * ep, const char* data, uint32_t dataLen)
\r
517 VERIFY_NON_NULL(ep, TAG, "CANfcSendDataImpl : endpoint is null");
\r
518 VERIFY_NON_NULL(data, TAG, "CANfcSendDataImpl : data is null");
\r
519 OIC_LOG(INFO, TAG, "CANfcSendDataImpl moved env outside");
\r
520 bool isAttached = false;
\r
522 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
525 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
526 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
530 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
531 return CA_STATUS_FAILED;
\r
536 OIC_LOG(INFO, TAG, "creating send buffer");
\r
537 jbyteArray sendData = (*env)->NewByteArray(env, dataLen);
\r
540 OIC_LOG(ERROR, TAG, "Failed to create ByteArray");
\r
543 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
546 return CA_SEND_FAILED;
\r
550 (*env)->SetByteArrayRegion(env, sendData, 0, dataLen, (jbyte*) data);
\r
552 (*env)->CallVoidMethod(env, g_nfcInterface, g_sendMethod, sendData);
\r
553 OIC_LOG(DEBUG, TAG, "send data through NFC");
\r
555 (*env)->DeleteLocalRef(env, sendData);
\r
559 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
562 return CA_STATUS_OK;
\r
565 void CANFCSendData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
\r
567 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
\r
568 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
\r
570 // JNI to Send data
\r
571 CANfcSendDataImpl(endpoint, data, dataLength);
\r