Merge branch 'tizen' into tizen_5.5
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleclient_jni.c
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <jni.h>
24 #include <unistd.h>
25
26 #include "calestate.h"
27 #include "caleclient.h"
28 #include "caleserver.h"
29 #include "caleutils.h"
30 #include "caleinterface.h"
31 #include "caadapterutils.h"
32
33 #include "uarraylist.h"
34 #include "logger.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37 #include "cathreadpool.h" /* for thread pool */
38 #include "octhread.h"
39 #include "uarraylist.h"
40 #include "org_iotivity_ca_CaLeClientInterface.h"
41 #include "caleclient_utils.h"
42 #include "caleclient.h"
43
44 JNIEXPORT void JNICALL
45 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
46                                                                     jobject callback)
47 {
48     OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
49     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
50     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
51     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
52
53     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
54     CACheckJNIException(env);
55 }
56
57 JNIEXPORT void JNICALL
58 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
59                                                                           jobject obj,
60                                                                           jobject callback)
61 {
62     OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
63     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
64     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
65     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
66
67     g_leScanCallback = (*env)->NewGlobalRef(env, callback);
68     CACheckJNIException(env);
69 }
70
71 JNIEXPORT void JNICALL
72 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
73                                                                   jobject callback)
74 {
75     OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
76     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
77     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
78     VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
79
80     g_leGattCallback = (*env)->NewGlobalRef(env, callback);
81     CACheckJNIException(env);
82 }
83
84 JNIEXPORT void JNICALL
85 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
86                                                           jobject device)
87 {
88     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
89     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
90     VERIFY_NON_NULL_VOID(device, TAG, "device is null");
91
92     CAResult_t res = CALEClientAddScanDeviceToList(env, device);
93     if (CA_STATUS_OK != res)
94     {
95         OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
96     }
97 }
98
99 JNIEXPORT void JNICALL
100 Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
101                                                                 jint errorCode)
102 {
103     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
104     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
105
106     switch (errorCode)
107     {
108         case 1:
109             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
110             break;
111
112         case 2:
113             OIC_LOG(ERROR, TAG,
114                     "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
115             break;
116
117         case 3:
118             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
119             break;
120
121         case 4:
122             OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
123             break;
124
125         default:
126             OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
127             break;
128     }
129 }
130
131 /*
132  * Class:     org_iotivity_ca_jar_caleinterface
133  * Method:    CALeGattConnectionStateChangeCallback
134  * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
135  */
136 JNIEXPORT void JNICALL
137 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
138                                                                                jobject obj,
139                                                                                jobject gatt,
140                                                                                jint status,
141                                                                                jint newstate)
142 {
143     OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
144               newstate);
145     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
146     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
147     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
148
149     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
150
151     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
152     if (!jni_address)
153     {
154         OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
155         goto error_exit;
156     }
157
158     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
159     if (!address)
160     {
161         OIC_LOG(ERROR, TAG, "address is null");
162         CACheckJNIException(env);
163         goto error_exit;
164     }
165     OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
166
167     if (state_connected == newstate)
168     {
169         OIC_LOG(DEBUG, TAG, "LE is connected");
170         if (GATT_SUCCESS == status)
171         {
172             CAResult_t res = CALEUpdateDeviceState(address,
173                                                    CA_LE_CONNECTION_STATE,
174                                                    STATE_CONNECTED,
175                                                    g_deviceStateList,
176                                                    g_deviceStateListMutex);
177             (*env)->ReleaseStringUTFChars(env, jni_address, address);
178             if (CA_STATUS_OK != res)
179             {
180                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
181                 goto error_exit;
182             }
183
184             res = CALEClientAddGattobjToList(env, gatt);
185             if (CA_STATUS_OK != res)
186             {
187                 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
188                 goto error_exit;
189             }
190
191             res = CALEClientDiscoverServices(env, gatt);
192             if (CA_STATUS_OK != res)
193             {
194                 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
195                 goto error_exit;
196             }
197         }
198         else
199         {
200             OIC_LOG(INFO, TAG, "unknown status");
201             (*env)->ReleaseStringUTFChars(env, jni_address, address);
202         }
203     }
204     else // STATE_DISCONNECTED == newstate
205     {
206         OIC_LOG(DEBUG, TAG, "LE is disconnected");
207
208         if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING,
209                              g_deviceStateList, g_deviceStateListMutex))
210         {
211             OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING");
212             CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
213                                                    STATE_SEND_FAIL,
214                                                    g_deviceStateList,
215                                                    g_deviceStateListMutex);
216             if (CA_STATUS_OK != res)
217             {
218                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
219             }
220         }
221
222         CAResult_t res = CALEUpdateDeviceState(address,
223                                                CA_LE_CONNECTION_STATE,
224                                                STATE_DISCONNECTED,
225                                                g_deviceStateList,
226                                                g_deviceStateListMutex);
227         if (CA_STATUS_OK != res)
228         {
229             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
230         }
231         (*env)->ReleaseStringUTFChars(env, jni_address, address);
232
233         res = CALEClientGattClose(env, gatt);
234         if (CA_STATUS_OK != res)
235         {
236             OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
237         }
238
239         if (CALECheckConnectionStateValue(status))
240         {
241             // this state is unexpected reason to disconnect
242             // if the reason is suitable, connection logic of the device will be destroyed.
243             OIC_LOG(INFO, TAG, "connection logic destroy");
244         }
245         else
246         {
247             // other reason except for gatt_success is expected to running
248             // background connection in BT platform.
249             OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
250         }
251         CALEClientUpdateSendCnt(env);
252     }
253     return;
254
255     // error label.
256 error_exit:
257     CALEClientSendFinish(env, gatt);
258     return;
259 }
260
261 /*
262  * Class:     org_iotivity_ca_jar_caleinterface
263  * Method:    CALeGattServicesDiscoveredCallback
264  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
265  */
266 JNIEXPORT void JNICALL
267 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
268                                                                             jobject obj,
269                                                                             jobject gatt,
270                                                                             jint status)
271 {
272     OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
273     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
274     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
275     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
276
277     if (GATT_SUCCESS != status) // discovery error
278     {
279         CALEClientSendFinish(env, gatt);
280         return;
281     }
282
283     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
284     if (!jni_address)
285     {
286         CALEClientSendFinish(env, gatt);
287         return;
288     }
289
290     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
291     if (!address)
292     {
293         CACheckJNIException(env);
294         CALEClientSendFinish(env, gatt);
295         return;
296     }
297
298     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
299     if (!jni_uuid)
300     {
301         OIC_LOG(ERROR, TAG, "jni_uuid is null");
302         goto error_exit;
303     }
304
305     jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
306     if (!jni_obj_GattCharacteristic)
307     {
308         OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
309         goto error_exit;
310     }
311
312     CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
313                                                              jni_obj_GattCharacteristic);
314     if (CA_STATUS_OK != res)
315     {
316         OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
317         goto error_exit;
318     }
319
320     res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
321     if (CA_STATUS_OK != res)
322     {
323         OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
324
325         res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE,
326                                  g_deviceStateList, g_deviceStateListMutex);
327         if (CA_STATUS_OK != res)
328         {
329             OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
330             goto error_exit;
331         }
332
333         res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
334                                     STATE_SERVICE_CONNECTED,
335                                     g_deviceStateList,
336                                     g_deviceStateListMutex);
337         if (CA_STATUS_OK != res)
338         {
339             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
340             goto error_exit;
341         }
342
343         res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
344         if (CA_STATUS_OK != res)
345         {
346             OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
347             goto error_exit;
348         }
349     }
350     else
351     {
352         res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE,
353                                  g_deviceStateList, g_deviceStateListMutex);
354         if (CA_STATUS_OK != res)
355         {
356             OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
357             goto error_exit;
358         }
359     }
360
361 #ifdef SCAN_INTERVAL
362     // reset interval scan logic
363     CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
364 #endif
365
366     OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
367     (*env)->ReleaseStringUTFChars(env, jni_address, address);
368     return;
369
370     // error label.
371 error_exit:
372     OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
373     (*env)->ReleaseStringUTFChars(env, jni_address, address);
374     CALEClientSendFinish(env, gatt);
375     return;
376 }
377
378 /*
379  * Class:     org_iotivity_ca_jar_caleinterface
380  * Method:    CALeGattCharacteristicWritjclasseCallback
381  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
382  */
383 JNIEXPORT void JNICALL
384 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
385         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
386 {
387     OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
388     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
389     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
390     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
391
392     // send success & signal
393     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
394     if (!jni_address)
395     {
396         goto error_exit;
397     }
398
399     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
400     if (!address)
401     {
402         CACheckJNIException(env);
403         goto error_exit;
404     }
405
406     if (GATT_SUCCESS != status) // error case
407     {
408         OIC_LOG(ERROR, TAG, "send failure");
409
410         // retry to write
411         CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
412         if (CA_STATUS_OK != res)
413         {
414             OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
415             oc_mutex_lock(g_threadWriteCharacteristicMutex);
416             g_isSignalSetFlag = true;
417             oc_cond_signal(g_threadWriteCharacteristicCond);
418             oc_mutex_unlock(g_threadWriteCharacteristicMutex);
419
420             CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
421                                                    STATE_SEND_FAIL,
422                                                    g_deviceStateList,
423                                                    g_deviceStateListMutex);
424             if (CA_STATUS_OK != res)
425             {
426                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
427             }
428
429             if (g_clientErrorCallback)
430             {
431                 jint length = (*env)->GetArrayLength(env, data);
432                 CACheckJNIException(env);
433                 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
434                 CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length,
435                                    false, "writeChar failure");
436             }
437
438             (*env)->ReleaseStringUTFChars(env, jni_address, address);
439             goto error_exit;
440         }
441     }
442     else
443     {
444         OIC_LOG(DEBUG, TAG, "send success");
445         CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
446                                                STATE_SEND_SUCCESS,
447                                                g_deviceStateList,
448                                                g_deviceStateListMutex);
449         if (CA_STATUS_OK != res)
450         {
451             OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
452         }
453
454         oc_mutex_lock(g_threadWriteCharacteristicMutex);
455         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
456         g_isSignalSetFlag = true;
457         oc_cond_signal(g_threadWriteCharacteristicCond);
458         oc_mutex_unlock(g_threadWriteCharacteristicMutex);
459
460         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0,
461                            (*env)->GetArrayLength(env, data),
462                            true, "writeChar success");
463     }
464
465     (*env)->ReleaseStringUTFChars(env, jni_address, address);
466     return;
467
468     // error label.
469 error_exit:
470
471     CALEClientSendFinish(env, gatt);
472     return;
473 }
474
475 /*
476  * Class:     org_iotivity_ca_jar_caleinterface
477  * Method:    CALeGattCharacteristicChangedCallback
478  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
479  */
480 JNIEXPORT void JNICALL
481 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
482         JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
483 {
484     OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
485     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
486     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
487     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
488     VERIFY_NON_NULL_VOID(data, TAG, "data is null");
489
490     // get Byte Array and convert to uint8_t*
491     jint length = (*env)->GetArrayLength(env, data);
492
493     jboolean isCopy;
494     jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
495     CACheckJNIException(env);
496
497     uint8_t* receivedData = OICMalloc(length);
498     if (!receivedData)
499     {
500         OIC_LOG(ERROR, TAG, "receivedData is null");
501         return;
502     }
503
504     memcpy(receivedData, jni_byte_responseData, length);
505     (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
506
507     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
508     if (!jni_address)
509     {
510         OIC_LOG(ERROR, TAG, "jni_address is null");
511         OICFree(receivedData);
512         return;
513     }
514
515     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
516     if (!address)
517     {
518         OIC_LOG(ERROR, TAG, "address is null");
519         CACheckJNIException(env);
520         OICFree(receivedData);
521         return;
522     }
523
524     OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
525               receivedData, length);
526
527     uint32_t sentLength = 0;
528     oc_mutex_lock(g_bleServerBDAddressMutex);
529     g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
530     oc_mutex_unlock(g_bleServerBDAddressMutex);
531
532     (*env)->ReleaseStringUTFChars(env, jni_address, address);
533 }
534
535 /*
536  * Class:     org_iotivity_ca_jar_caleinterface
537  * Method:    CALeGattDescriptorWriteCallback
538  * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
539  */
540 JNIEXPORT void JNICALL
541 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
542                                                                          jobject gatt,
543                                                                          jint status)
544 {
545     OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
546     VERIFY_NON_NULL_VOID(env, TAG, "env is null");
547     VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
548     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
549
550     if (GATT_SUCCESS != status) // error
551     {
552         goto error_exit;
553     }
554
555     jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
556     if (!jni_address)
557     {
558         goto error_exit;
559     }
560
561     const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
562     if (!address)
563     {
564         CACheckJNIException(env);
565         goto error_exit;
566     }
567
568     CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
569                                            STATE_SERVICE_CONNECTED,
570                                            g_deviceStateList,
571                                            g_deviceStateListMutex);
572     (*env)->ReleaseStringUTFChars(env, jni_address, address);
573     if (CA_STATUS_OK != res)
574     {
575         OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
576         goto error_exit;
577     }
578
579     res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
580     if (CA_STATUS_OK != res)
581     {
582         OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
583         goto error_exit;
584     }
585     return;
586
587 // error label.
588 error_exit:
589
590     CALEClientSendFinish(env, gatt);
591     return;
592 }
593
594 JNIEXPORT void JNICALL
595 Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env,
596                                                                     jobject obj,
597                                                                     jobject gatt,
598                                                                     jint mtu,
599                                                                     jint status)
600 {
601     OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, "
602               "mtu[%d-including Header size 3 byte]", status, mtu);
603
604     (void)obj;
605
606     if (0 == status || 133 == status)
607     {
608         if (g_sendBuffer)
609         {
610             CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
611             if (CA_STATUS_OK != res)
612             {
613                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
614             }
615         }
616         else
617         {
618             OIC_LOG(INFO, TAG, "mtu nego is done");
619             jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
620             if (!jni_address)
621             {
622                 CALEClientSendFinish(env, gatt);
623                 return;
624             }
625
626             const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
627             if (!address)
628             {
629                 CACheckJNIException(env);
630                 (*env)->DeleteLocalRef(env, jni_address);
631                 CALEClientSendFinish(env, gatt);
632                 return;
633             }
634
635             // update mtu size
636             CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE,
637                                             g_deviceStateList, g_deviceStateListMutex);
638             if (CA_STATUS_OK != res)
639             {
640                 OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed");
641             }
642
643             res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
644                                         STATE_SEND_MTU_NEGO_SUCCESS,
645                                         g_deviceStateList,
646                                         g_deviceStateListMutex);
647             if (CA_STATUS_OK != res)
648             {
649                 OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
650             }
651             CALEClientUpdateSendCnt(env);
652             (*env)->ReleaseStringUTFChars(env, jni_address, address);
653             (*env)->DeleteLocalRef(env, jni_address);
654         }
655     }
656 }