Merge "Implementation of connectivity abstraction feature Release v0.5" into connecti...
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleserver.c
1 #include <jni.h>
2 #include <stdio.h>
3 #include <android/log.h>
4 #include "com_iotivity_jar_CALeInterface.h"
5
6 #define  LOG_TAG   "jni_BLE_Server"
7 #define  LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
8 #define  LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
9
10 static const char *OIC_GATT_SERVICE_UUID = "713d0000-503e-4c75-ba94-3148f18d941e";
11 static const char *OIC_GATT_CHARACTERISTIC_RESPONSE_UUID = "713d0002-503e-4c75-ba94-3148f18d941e";
12 static const char *OIC_GATT_CHARACTERISTIC_REQUEST_UUID = "713d0003-503e-4c75-ba94-3148f18d941e";
13
14 static jobject gContext;
15 static jobject gBluetoothGattServer;
16 static jobject gBluetoothGattServerCallback;
17 static jobject gAdvertiseCallback;
18
19 jobject getUuidFromString(JNIEnv *env, const char* uuid)
20 {
21
22     LOGI("[BLE Server] getUuidFromString");
23
24     jclass jni_cid_UUID = (*env)->FindClass(env, "java/util/UUID");
25     if (!jni_cid_UUID)
26     {
27         LOGI("[BLE Server] jni_cid_UUID is null");
28         return NULL;
29     }
30
31     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_UUID, "fromString",
32             "(Ljava/lang/String;)Ljava/util/UUID;");
33     if (!jni_mid_fromString)
34     {
35         LOGI("[BLE Server] jni_mid_fromString is null");
36         return NULL;
37     }
38
39     jstring str_serviceUUID = (*env)->NewStringUTF(env, uuid);
40     LOGI("[BLE Server] uuid: %s", uuid);
41     jobject jni_obj_serviceUUID = (*env)->CallStaticObjectMethod(env, jni_cid_UUID,
42             jni_mid_fromString, str_serviceUUID);
43     if (!jni_obj_serviceUUID)
44     {
45         LOGI("[BLE][Server] jni_obj_serviceUUID is null");
46         return NULL;
47     }
48
49     return jni_obj_serviceUUID;
50 }
51
52 jobject getParcelUuid(JNIEnv *env, jobject uuid)
53 {
54
55     jclass jni_cid_ParcelUuid = (*env)->FindClass(env, "android/os/ParcelUuid");
56     if (!jni_cid_ParcelUuid)
57     {
58         LOGI("[BLE Server] jni_cid_ParcelUuid is null");
59         return;
60     }
61
62     jmethodID jni_mid_ParcelUuid = (*env)->GetMethodID(env, jni_cid_ParcelUuid, "<init>",
63             "(Ljava/util/UUID;)V");
64     if (!jni_mid_ParcelUuid)
65     {
66         LOGI("[BLE Server] jni_mid_ParcelUuid is null");
67         return;
68     }
69
70     jobject jni_ParcelUuid = (*env)->NewObject(env, jni_cid_ParcelUuid, jni_mid_ParcelUuid, uuid);
71     if (!jni_ParcelUuid)
72     {
73         LOGI("[BLE Server] jni_ParcelUuid is null");
74         return;
75     }
76
77     return jni_ParcelUuid;
78 }
79
80 jobject setData(JNIEnv *env, char* responseData)
81 {
82
83     LOGI("[BLE Server] set response");
84
85     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
86             "android/bluetooth/BluetoothGattServer");
87     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env,
88             "android/bluetooth/BluetoothGattService");
89     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env,
90             "android/bluetooth/BluetoothGattCharacteristic");
91     LOGI("[BLE Server] get classes");
92
93     jmethodID jni_mid_getService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
94             "getService", "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattService;");
95     LOGI("[BLE Server] get methodID");
96
97     jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
98     LOGI("[BLE Server] get serviceUUID");
99
100     if (!gBluetoothGattServer)
101     {
102         LOGI("[BLE Server] gBluetoothGattServer is null");
103         return NULL;
104     }
105
106     jobject jni_obj_bluetoothGattService = (*env)->CallObjectMethod(env, gBluetoothGattServer,
107             jni_mid_getService, jni_obj_serviceUUID);
108     LOGI("[BLE Server] jni_obj_bluetoothGattService");
109
110     jmethodID jni_mid_getCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
111             "getCharacteristic",
112             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothGattCharacteristic;");
113
114     jobject jni_obj_responseUUID = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
115     jobject jni_obj_bluetoothGattCharacteristic = (*env)->CallObjectMethod(env,
116             jni_obj_bluetoothGattService, jni_mid_getCharacteristic, jni_obj_responseUUID);
117     LOGI("[BLE Server] jni_obj_bluetoothGattCharacteristic");
118
119     jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_bluetoothGattCharacteristic,
120             "setValue", "(Ljava/land/String;)Z");
121     jstring str_responseData = (*env)->NewStringUTF(env, responseData);
122     jboolean jni_boolean_setValue = (*env)->CallBooleanMethod(env,
123             jni_obj_bluetoothGattCharacteristic, jni_mid_setValue, str_responseData);
124
125     return jni_obj_bluetoothGattCharacteristic;
126 }
127
128 jboolean sendData(JNIEnv *env, jobject device, jobject responseData)
129 {
130
131     if (!device)
132     {
133         LOGI("[BLE Server] device is null");
134         return JNI_FALSE;
135     }
136
137     if (!responseData)
138     {
139         LOGI("[BLE Server] responseData is null");
140         return JNI_FALSE;
141     }
142
143     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
144             "android/bluetooth/BluetoothGattServer");
145
146     jmethodID jni_mid_notifyCharacteristicChanged =
147             (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "notifyCharacteristicChanged",
148                     "(Landroid/bluetooth/BluetoothDevice;Landroid/bluetooth/BluetoothGattCharacteristic;Z)Z");
149     jboolean jni_boolean_notifyCharacteristicChanged = (*env)->CallBooleanMethod(env,
150             gBluetoothGattServer, jni_mid_notifyCharacteristicChanged, device, responseData,
151             JNI_TRUE);
152
153     if (!jni_boolean_notifyCharacteristicChanged)
154         return JNI_FALSE;
155
156     return JNI_TRUE;
157 }
158
159 jboolean sendResponse(JNIEnv *env, jobject device, jint requestId, jint status, jint offset)
160 {
161
162     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
163             "android/bluetooth/BluetoothGattServer");
164     jmethodID jni_mid_sendResponse = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
165             "sendResponse", "(Landroid/bluetooth/BluetoothDevice;III)Z");
166     (*env)->CallVoidMethod(env, gBluetoothGattServer, jni_mid_sendResponse, device, requestId,
167             status, offset);
168     LOGI("[BLE Server] sendResponse");
169
170 }
171
172 void startAdvertize(JNIEnv *env, jobject advertiseCallback)
173 {
174
175     jclass jni_cid_AdvertiseSettings = (*env)->FindClass(env,
176             "android/bluetooth/le/AdvertiseSettings$Builder");
177
178     jmethodID jni_mid_AdvertiseSettings = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
179             "<init>", "()V");
180
181     jobject jni_AdvertiseSettings = (*env)->NewObject(env, jni_cid_AdvertiseSettings,
182             jni_mid_AdvertiseSettings);
183     if (!jni_AdvertiseSettings)
184     {
185         LOGI("[BLE Server] jni_AdvertiseSettings is null");
186         return;
187     }
188
189     jmethodID jni_mid_setConnectable = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings,
190             "setConnectable", "(Z)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
191
192     jobject jni_obj_setConnectable = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
193             jni_mid_setConnectable, JNI_TRUE);
194     if (!jni_obj_setConnectable)
195     {
196         LOGI("[BLE][Server] jni_obj_setConnectable is null");
197         return;
198     }
199
200     jmethodID jni_mid_setTimeout = (*env)->GetMethodID(env, jni_cid_AdvertiseSettings, "setTimeout",
201             "(I)Landroid/bluetooth/le/AdvertiseSettings$Builder;");
202
203     jobject jni_obj_setTimeout = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
204             jni_mid_setTimeout, 10000);
205     if (!jni_obj_setTimeout)
206     {
207         LOGI("[BLE][Server] jni_obj_setTimeout is null");
208         return;
209     }
210
211     jclass jni_cid_AdvertiseDataBuilder = (*env)->FindClass(env,
212             "android/bluetooth/le/AdvertiseData$Builder");
213
214     jmethodID jni_mid_AdvertiseDataBuilder = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
215             "<init>", "()V");
216
217     jobject jni_AdvertiseDataBuilder = (*env)->NewObject(env, jni_cid_AdvertiseDataBuilder,
218             jni_mid_AdvertiseDataBuilder);
219     if (!jni_AdvertiseDataBuilder)
220     {
221         LOGI("[BLE Server] jni_AdvertiseDataBuilder is null");
222         return;
223     }
224
225     jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
226     jobject jni_ParcelUuid = getParcelUuid(env, jni_obj_serviceUUID);
227     jmethodID jni_mid_addServiceUuid = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
228             "addServiceUuid",
229             "(Landroid/os/ParcelUuid;)Landroid/bluetooth/le/AdvertiseData$Builder;");
230
231     jobject jni_obj_addServiceUuid = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
232             jni_mid_addServiceUuid, jni_ParcelUuid);
233     if (!jni_obj_addServiceUuid)
234     {
235         LOGI("[BLE Server] jni_obj_addServiceUuid is null");
236         return;
237     }
238
239     jclass jni_cid_BTAdapter = (*env)->FindClass(env, "android/bluetooth/BluetoothAdapter");
240     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
241             "getDefaultAdapter", "()Landroid/bluetooth/BluetoothAdapter;");
242
243     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
244             jni_mid_getDefaultAdapter);
245     if (!jni_obj_BTAdapter)
246     {
247         LOGI("[BLE Server] jni_obj_BTAdapter is null");
248         return;
249     }
250
251     jmethodID jni_mid_getBluetoothLeAdvertiser = (*env)->GetMethodID(env, jni_cid_BTAdapter,
252             "getBluetoothLeAdvertiser", "()Landroid/bluetooth/le/BluetoothLeAdvertiser;");
253
254     jobject jni_obj_getBluetoothLeAdvertiser = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
255             jni_mid_getBluetoothLeAdvertiser);
256     if (!jni_obj_getBluetoothLeAdvertiser)
257     {
258         LOGI("[BLE Server] jni_obj_getBluetoothLeAdvertiser is null");
259         return;
260     }
261
262     jmethodID jni_mid_build_LeAdvertiseSettings = (*env)->GetMethodID(env,
263             jni_cid_AdvertiseSettings, "build", "()Landroid/bluetooth/le/AdvertiseSettings;");
264
265     jobject jni_obj_build_LeAdvertiseSettings = (*env)->CallObjectMethod(env, jni_AdvertiseSettings,
266             jni_mid_build_LeAdvertiseSettings);
267     if (!jni_obj_build_LeAdvertiseSettings)
268     {
269         LOGI("[BLE Server] jni_obj_build_LeAdvertiseSettings is null");
270         return;
271     }
272
273     jmethodID jni_mid_build_LeAdvertiseData = (*env)->GetMethodID(env, jni_cid_AdvertiseDataBuilder,
274             "build", "()Landroid/bluetooth/le/AdvertiseData;");
275
276     jobject jni_obj_build_LeAdvertiseData = (*env)->CallObjectMethod(env, jni_AdvertiseDataBuilder,
277             jni_mid_build_LeAdvertiseData);
278     if (!jni_obj_build_LeAdvertiseData)
279     {
280         LOGI("[BLE Server] jni_obj_build_LeAdvertiseData is null");
281         return;
282     }
283
284     jclass jni_cid_leAdvertiser = (*env)->FindClass(env,
285             "android/bluetooth/le/BluetoothLeAdvertiser");
286
287     jmethodID jni_mid_startAdvertising =
288             (*env)->GetMethodID(env, jni_cid_leAdvertiser, "startAdvertising",
289                     "(Landroid/bluetooth/le/AdvertiseSettings;Landroid/bluetooth/le/AdvertiseData;Landroid/bluetooth/le/AdvertiseCallback;)V");
290
291     (*env)->CallVoidMethod(env, jni_obj_getBluetoothLeAdvertiser, jni_mid_startAdvertising,
292             jni_obj_build_LeAdvertiseSettings, jni_obj_build_LeAdvertiseData, advertiseCallback);
293
294     LOGI("[BLE Server] jni start Advertising");
295 }
296
297 jobject openGattServer(JNIEnv *env)
298 {
299
300     jclass jni_cid_context = (*env)->FindClass(env, "android/content/Context");
301     jfieldID jni_fid_bluetoothService = (*env)->GetStaticFieldID(env, jni_cid_context,
302             "BLUETOOTH_SERVICE", "Ljava/lang/String;");
303     jobject jni_obj_bluetoothService = (*env)->GetStaticObjectField(env, jni_cid_context,
304             jni_fid_bluetoothService);
305
306     jmethodID jni_mid_getSystemService = (*env)->GetMethodID(env, jni_cid_context,
307             "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
308     jobject jni_obj_bluetoothManager = (*env)->CallObjectMethod(env, gContext,
309             jni_mid_getSystemService, jni_obj_bluetoothService);
310
311     jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
312     jmethodID jni_mid_openGattServer =
313             (*env)->GetMethodID(env, jni_cid_bluetoothManager, "openGattServer",
314                     "(Landroid/content/Context;Landroid/bluetooth/BluetoothGattServerCallback;)Landroid/bluetooth/BluetoothGattServer;");
315     jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
316             jni_mid_openGattServer, gContext, gBluetoothGattServerCallback);
317
318     return jni_obj_bluetoothGattServer;
319 }
320
321 jobject createGattService(JNIEnv *env)
322 {
323
324     jclass jni_cid_bluetoothGattService = (*env)->FindClass(env,
325             "android/bluetooth/BluetoothGattService");
326     jmethodID jni_mid_bluetoothGattService = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
327             "<init>", "(Ljava/util/UUID;I)V");
328
329     // service uuid object
330     jobject jni_obj_serviceUUID = getUuidFromString(env, OIC_GATT_SERVICE_UUID);
331
332     // service type object
333     jfieldID jni_fid_serviceType = (*env)->GetStaticFieldID(env, jni_cid_bluetoothGattService,
334             "SERVICE_TYPE_PRIMARY", "I");
335     jobject jni_obj_serviceType = (*env)->GetStaticObjectField(env, jni_cid_bluetoothGattService,
336             jni_fid_serviceType);
337
338     jobject jni_bluetoothGattService = (*env)->NewObject(env, jni_cid_bluetoothGattService,
339             jni_mid_bluetoothGattService, jni_obj_serviceUUID, jni_obj_serviceType);
340     if (!jni_bluetoothGattService)
341     {
342         LOGI("[BLE Server] fail to create gatt service instance!");
343         return NULL;
344     }
345
346     jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env,
347             "android/bluetooth/BluetoothGattCharacteristic");
348     jmethodID jni_mid_bluetoothGattCharacteristic = (*env)->GetMethodID(env,
349             jni_cid_bluetoothGattCharacteristic, "<init>", "(Ljava/util/UUID;II)V");
350
351     // characteristic uuid for response
352     jobject jni_obj_readUuid = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
353
354     // characteristic properties
355     jfieldID jni_fid_readProperties = (*env)->GetStaticFieldID(env,
356             jni_cid_bluetoothGattCharacteristic, "PROPERTY_READ", "I");
357     jobject jni_obj_readProperties = (*env)->GetStaticObjectField(env,
358             jni_cid_bluetoothGattCharacteristic, jni_fid_readProperties);
359
360     // characteristic permissions
361     jfieldID jni_fid_readPermissions = (*env)->GetStaticFieldID(env,
362             jni_cid_bluetoothGattCharacteristic, "PERMISSION_READ", "I");
363     jobject jni_obj_readPermissions = (*env)->GetStaticObjectField(env,
364             jni_cid_bluetoothGattCharacteristic, jni_fid_readPermissions);
365
366     jobject jni_readCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
367             jni_mid_bluetoothGattCharacteristic, jni_obj_readUuid, jni_obj_readProperties,
368             jni_obj_readPermissions);
369     if (!jni_readCharacteristic)
370     {
371         LOGI("[BLE Server] fail to create Response Characteristic");
372         return NULL;
373     }
374
375     jobject jni_obj_writeUuid = getUuidFromString(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
376
377     // characteristic properties
378     jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
379             jni_cid_bluetoothGattCharacteristic, "PROPERTY_WRITE", "I");
380     jobject jni_obj_writeProperties = (*env)->GetStaticObjectField(env,
381             jni_cid_bluetoothGattCharacteristic, jni_fid_writeProperties);
382
383     // characteristic permissions
384     jfieldID jni_fid_writePermissions = (*env)->GetStaticFieldID(env,
385             jni_cid_bluetoothGattCharacteristic, "PERMISSION_WRITE", "I");
386     jobject jni_obj_writePermissions = (*env)->GetStaticObjectField(env,
387             jni_cid_bluetoothGattCharacteristic, jni_fid_writePermissions);
388
389     jobject jni_writeCharacteristic = (*env)->NewObject(env, jni_cid_bluetoothGattCharacteristic,
390             jni_mid_bluetoothGattCharacteristic, jni_obj_writeUuid, jni_obj_writeProperties,
391             jni_obj_writePermissions);
392     if (!jni_writeCharacteristic)
393     {
394         LOGI("[BLE Server] fail to create Request Characteristic");
395         return NULL;
396     }
397
398     jmethodID jni_mid_addCharacteristic = (*env)->GetMethodID(env, jni_cid_bluetoothGattService,
399             "addCharacteristic", "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z");
400     jboolean jni_boolean_addReadCharacteristic = (*env)->CallBooleanMethod(env,
401             jni_bluetoothGattService, jni_mid_addCharacteristic, jni_readCharacteristic);
402     if (jni_boolean_addReadCharacteristic == JNI_FALSE)
403     {
404         LOGI("[BLE Server] fail to add jni_boolean_addReadCharacteristic!!");
405         return NULL;
406     }
407
408     jboolean jni_boolean_addWriteCharacteristic = (*env)->CallBooleanMethod(env,
409             jni_bluetoothGattService, jni_mid_addCharacteristic, jni_writeCharacteristic);
410     if (jni_boolean_addWriteCharacteristic == JNI_FALSE)
411     {
412         LOGI("[BLE Server] fail to add jni_boolean_addReadCharacteristic!!");
413         return NULL;
414     }
415
416     LOGI("[BLE Server] jni gatt characteristic added!!");
417     return jni_bluetoothGattService;
418 }
419
420 void startGattServer(JNIEnv *env, jobject gattServerCallback)
421 {
422
423     gBluetoothGattServerCallback = (*env)->NewGlobalRef(env, gattServerCallback);
424
425     // open gatt server
426     jobject bluetoothGattServer = openGattServer(env);
427
428     gBluetoothGattServer = (*env)->NewGlobalRef(env, bluetoothGattServer);
429     LOGI("[BLE Server] Bluetooth Gatt Server started!!");
430
431     // get bluetooth gatt service
432     jobject bluetoothGattService = createGattService(env);
433
434     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
435             "android/bluetooth/BluetoothGattServer");
436     jmethodID jni_mid_addService = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
437             "addService", "(Landroid/bluetooth/BluetoothGattService;)Z");
438     jboolean jni_boolean_addService = (*env)->CallBooleanMethod(env, bluetoothGattServer,
439             jni_mid_addService, bluetoothGattService);
440
441     LOGI("[BLE Server] jni gatt service added!!");
442 }
443
444 void connect(JNIEnv *env, jobject bluetoothDevice)
445 {
446
447     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
448             "android/bluetooth/BluetoothGattServer");
449     jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer, "connect",
450             "(Landroid/bluetooth/BluetoothDevice;Z)Z");
451     jboolean jni_boolean_connect = (*env)->CallBooleanMethod(env, gBluetoothGattServer,
452             jni_mid_connect, bluetoothDevice, JNI_FALSE);
453     LOGI("[BLE Server] connection requested!!");
454 }
455
456 void disconnect(JNIEnv *env, jobject bluetoothDevice)
457 {
458
459     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
460             "android/bluetooth/BluetoothGattServer");
461     jmethodID jni_mid_cancelConnection = (*env)->GetMethodID(env, jni_cid_bluetoothGattServer,
462             "cancelConnection", "(Landroid/bluetooth/BluetoothDevice;)V");
463     (*env)->CallVoidMethod(env, gBluetoothGattServer, jni_mid_cancelConnection, bluetoothDevice);
464     LOGI("[BLE Server] disconnection requested!!");
465 }
466