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 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
152 if (!jni_NfcInterface)
\r
154 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface class");
\r
158 jmethodID NfcInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_NfcInterface, "<init>",
\r
159 "(Landroid/content/Context;Landroid/app/Activity;)V");
\r
160 if (!NfcInterfaceConstructorMethod)
\r
162 OIC_LOG(ERROR, TAG, "Could not get CaNfcInterface constructor method");
\r
166 jobject jni_nfcInstance = (*env)->NewObject(env, jni_NfcInterface,
\r
167 NfcInterfaceConstructorMethod, g_context,
\r
169 if (!jni_nfcInstance)
\r
171 OIC_LOG(ERROR, TAG, "Create instance for CaNfcInterface failed");
\r
175 g_nfcInterface = (*env)->NewGlobalRef(env, jni_nfcInstance);
\r
176 if (!g_nfcInterface)
\r
178 OIC_LOG(ERROR, TAG, "NewGlobalRef for nfcInterface failed");
\r
182 OIC_LOG(DEBUG, TAG, "Create instance for CaNfcInterface");
\r
184 CAResult_t result = SetCreateNdefMessageCallbackfromNative(env);
\r
185 if (CA_STATUS_OK != result)
\r
187 OIC_LOG(ERROR, TAG, "SetCreateNdefMessageCallbackfromNative failed");
\r
193 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
196 OIC_LOG(DEBUG, TAG, "CANfcCreateJniInterfaceObject OUT");
\r
197 return CA_STATUS_OK;
\r
202 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
205 return CA_STATUS_FAILED;
\r
208 CAResult_t CAInitializeNfcServer()
\r
211 CANfcJNISetContext();
\r
213 CAResult_t result = CANfcCreateJniInterfaceObject();
\r
214 if (CA_STATUS_OK != result)
\r
216 OIC_LOG(ERROR, TAG, "CANfcJniInit failed");
\r
222 CAResult_t CANFCStartServer()
\r
224 bool isAttached = false;
\r
226 OIC_LOG(INFO, TAG, "CANFCStartServer : IN");
\r
229 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
232 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
233 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
237 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
238 return CA_STATUS_FAILED;
\r
243 jclass jni_NfcInterface = (*env)->FindClass(env, "org/iotivity/ca/CaNfcInterface");
\r
244 if (!jni_NfcInterface)
\r
246 OIC_LOG(ERROR, TAG, "Could not get CaNFCClientInterface class");
\r
250 jmethodID methodId = (*env)->GetMethodID(env, jni_NfcInterface, "caNfcInitialize", "()V");
\r
253 OIC_LOG(ERROR, TAG, "Could not get methodId");
\r
257 if (!g_nfcInterface)
\r
259 OIC_LOG(ERROR, TAG, "g_nfcInterface NULL");
\r
263 (*env)->CallVoidMethod(env, g_nfcInterface, methodId);
\r
264 OIC_LOG(DEBUG, TAG, "caNfcInitialize");
\r
266 jmethodID sendDataMethodId = (*env)->GetMethodID(env, jni_NfcInterface, "processSendRquest",
\r
268 if (!sendDataMethodId)
\r
270 OIC_LOG(ERROR, TAG, "Could not get sendDataMethodId");
\r
274 g_sendMethod = sendDataMethodId;
\r
278 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
281 return CA_STATUS_OK;
\r
286 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
288 return CA_STATUS_FAILED;
\r
292 void CANFCStopServer()
\r
294 // JNI Call to unregstier nfc adapter
\r
298 * Class: org_iotivity_ca_CaNfcInterface
\r
299 * Method: caNativeNfcCreateNdefMessage
\r
300 * Signature: ([B)Landroid/nfc/NdefMessage;
\r
302 JNIEXPORT jobject JNICALL
\r
303 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcCreateNdefMessage(JNIEnv *env, jobject obj,
\r
304 jbyteArray sendData)
\r
306 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : IN");
\r
307 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
\r
308 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", NULL);
\r
310 const char *mime = "application/org.iotivity.ca.sample_service";
\r
311 jstring mimeString = (*env)->NewStringUTF(env, mime);
\r
314 OIC_LOG(ERROR, TAG, "NewStringUTF failed for mimeString");
\r
318 const char *type = "US_ASCII";
\r
319 jstring charSetString = (*env)->NewStringUTF(env, type);
\r
320 if (!charSetString)
\r
322 OIC_LOG(ERROR, TAG, "NewStringUTF failed for charSetString");
\r
326 jclass cid_string = (*env)->FindClass(env, "java/lang/String");
\r
329 OIC_LOG(ERROR, TAG, "Could not get NfcAdapter class for cid_string");
\r
333 jmethodID mid_getBytes = (*env)->GetMethodID(env, cid_string, "getBytes",
\r
334 "(Ljava/lang/String;)[B");
\r
337 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_getBytes");
\r
341 jbyteArray mimeTypeArr = (*env)->CallObjectMethod(env, mimeString, mid_getBytes,
\r
345 OIC_LOG(ERROR, TAG, "getBytes failed for mimeTypeArr");
\r
348 jclass cid_NdefRecord = (*env)->FindClass(env, "android/nfc/NdefRecord");
\r
349 if (!cid_NdefRecord)
\r
351 OIC_LOG(ERROR, TAG, "Could not get NdefRecord class for cid_NdefRecord");
\r
355 jmethodID mid_createRecord = (*env)->GetMethodID(env, cid_NdefRecord, "<init>",
\r
357 if (!mid_createRecord)
\r
359 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createRecord");
\r
363 jfieldID fid_tnfType = (*env)->GetStaticFieldID(env, cid_NdefRecord, "TNF_MIME_MEDIA", "S");
\r
365 jint tnfType = (*env)->GetStaticShortField(env, cid_NdefRecord, fid_tnfType);
\r
366 OIC_LOG_V(ERROR, TAG, "tnfType : %d", tnfType);
\r
368 jbyteArray nullArr = (*env)->NewByteArray(env, 0);
\r
370 jobject ndefRecord = (*env)->NewObject(env, cid_NdefRecord, mid_createRecord, tnfType,
\r
371 mimeTypeArr, nullArr, sendData);
\r
374 OIC_LOG(ERROR, TAG, "createNdefRecord failed for ndefRecord");
\r
378 jclass cid_NdefMsg = (*env)->FindClass(env, "android/nfc/NdefMessage");
\r
381 OIC_LOG(ERROR, TAG, "Could not get NdefMessage class for cid_NdefMsg");
\r
385 jmethodID mid_createMsg = (*env)->GetMethodID(env, cid_NdefMsg, "<init>",
\r
386 "([Landroid/nfc/NdefRecord;)V");
\r
387 if (!mid_createMsg)
\r
389 OIC_LOG(ERROR, TAG, "Could not get methodId for mid_createMsg");
\r
392 jobjectArray tempArr = (jobjectArray) (*env)->NewObjectArray(env, 1, cid_NdefRecord,
\r
395 jobject ndefMsg = (*env)->NewObject(env, cid_NdefMsg, mid_createMsg, tempArr);
\r
398 OIC_LOG(ERROR, TAG, "createNdefMessage failed for ndefMsg");
\r
402 OIC_LOG(DEBUG, TAG, "caNativeNfcCreateNdefMessage : OUT");
\r
407 * Class: org_iotivity_ca_CaNfcInterface
\r
408 * Method: caNativeNfcInvokeBeam
\r
411 JNIEXPORT jboolean JNICALL
\r
412 Java_org_iotivity_ca_CaNfcInterface_caNativeNfcInvokeBeam(JNIEnv *env, jobject obj)
\r
414 OIC_LOG(DEBUG, TAG, "cANativeNfcInvokeBeam : IN");
\r
415 VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
\r
416 VERIFY_NON_NULL_RET(obj, TAG, "obj is null", false);
\r
417 VERIFY_NON_NULL_RET(g_context, TAG, "g_context is null", false);
\r
418 VERIFY_NON_NULL_RET(g_activity, TAG, "g_activity 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 VERIFY_NON_NULL(g_jvm, TAG, "CANfcSendDataImpl : g_jvm is null");
\r
521 OIC_LOG(INFO, TAG, "CANfcSendDataImpl moved env outside");
\r
522 bool isAttached = false;
\r
524 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
\r
527 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
\r
528 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
\r
532 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
\r
533 return CA_STATUS_FAILED;
\r
538 OIC_LOG(INFO, TAG, "creating send buffer");
\r
539 jbyteArray sendData = (*env)->NewByteArray(env, dataLen);
\r
542 OIC_LOG(ERROR, TAG, "Failed to create ByteArray");
\r
545 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
548 return CA_SEND_FAILED;
\r
552 (*env)->SetByteArrayRegion(env, sendData, 0, dataLen, (jbyte*) data);
\r
554 (*env)->CallVoidMethod(env, g_nfcInterface, g_sendMethod, sendData);
\r
555 OIC_LOG(DEBUG, TAG, "send data through NFC");
\r
557 (*env)->DeleteLocalRef(env, sendData);
\r
561 (*g_jvm)->DetachCurrentThread(g_jvm);
\r
564 return CA_STATUS_OK;
\r
567 void CANFCSendData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
\r
569 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
\r
570 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
\r
572 // JNI to Send data
\r
573 CANfcSendDataImpl(endpoint, data, dataLength);
\r