• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #define LOG_TAG "BtGatt.JNI"
19 
20 #define LOG_NDEBUG 0
21 
22 #define CHECK_CALLBACK_ENV                                                      \
23    if (!checkCallbackThread()) {                                                \
24        error("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
25        return;                                                                  \
26    }
27 
28 #include "com_android_bluetooth.h"
29 #include "hardware/bt_gatt.h"
30 #include "utils/Log.h"
31 #include "android_runtime/AndroidRuntime.h"
32 
33 #include <string.h>
34 
35 #include <cutils/log.h>
36 #define info(fmt, ...)  ALOGI ("%s(L%d): " fmt,__FUNCTION__, __LINE__,  ## __VA_ARGS__)
37 #define debug(fmt, ...) ALOGD ("%s(L%d): " fmt,__FUNCTION__, __LINE__,  ## __VA_ARGS__)
38 #define warn(fmt, ...) ALOGW ("WARNING: %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__)
39 #define error(fmt, ...) ALOGE ("ERROR: %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__)
40 #define asrt(s) if(!(s)) ALOGE ("%s(L%d): ASSERT %s failed! ##",__FUNCTION__, __LINE__, #s)
41 
42 #define BD_ADDR_LEN 6
43 
44 #define UUID_PARAMS(uuid_ptr) \
45     uuid_lsb(uuid_ptr),  uuid_msb(uuid_ptr)
46 
47 #define CHAR_ID_PARAMS(char_ptr) \
48     char_ptr->inst_id, \
49     UUID_PARAMS((&char_ptr->uuid))
50 
51 #define SRVC_ID_PARAMS(srvc_ptr) \
52     (srvc_ptr->is_primary ? \
53     BTGATT_SERVICE_TYPE_PRIMARY : BTGATT_SERVICE_TYPE_SECONDARY), \
54     CHAR_ID_PARAMS((&srvc_ptr->id))
55 
56 
set_uuid(uint8_t * uuid,jlong uuid_msb,jlong uuid_lsb)57 static void set_uuid(uint8_t* uuid, jlong uuid_msb, jlong uuid_lsb)
58 {
59     for (int i = 0; i != 8; ++i)
60     {
61         uuid[i]     = (uuid_lsb >> (8 * i)) & 0xFF;
62         uuid[i + 8] = (uuid_msb >> (8 * i)) & 0xFF;
63     }
64 }
65 
uuid_lsb(bt_uuid_t * uuid)66 static uint64_t uuid_lsb(bt_uuid_t* uuid)
67 {
68     uint64_t  lsb = 0;
69     int i;
70 
71     for (i = 7; i >= 0; i--)
72     {
73         lsb <<= 8;
74         lsb |= uuid->uu[i];
75     }
76 
77     return lsb;
78 }
79 
uuid_msb(bt_uuid_t * uuid)80 static uint64_t uuid_msb(bt_uuid_t* uuid)
81 {
82     uint64_t msb = 0;
83     int i;
84 
85     for (i = 15; i >= 8; i--)
86     {
87         msb <<= 8;
88         msb |= uuid->uu[i];
89     }
90 
91     return msb;
92 }
93 
bd_addr_str_to_addr(const char * str,uint8_t * bd_addr)94 static void bd_addr_str_to_addr(const char* str, uint8_t *bd_addr)
95 {
96     int    i;
97     char   c;
98 
99     c = *str++;
100     for (i = 0; i < BD_ADDR_LEN; i++)
101     {
102         if (c >= '0' && c <= '9')
103             bd_addr[i] = c - '0';
104         else if (c >= 'a' && c <= 'z')
105             bd_addr[i] = c - 'a' + 10;
106         else   // (c >= 'A' && c <= 'Z')
107             bd_addr[i] = c - 'A' + 10;
108 
109         c = *str++;
110         if (c != ':')
111         {
112             bd_addr[i] <<= 4;
113             if (c >= '0' && c <= '9')
114                 bd_addr[i] |= c - '0';
115             else if (c >= 'a' && c <= 'z')
116                 bd_addr[i] |= c - 'a' + 10;
117             else   // (c >= 'A' && c <= 'Z')
118                 bd_addr[i] |= c - 'A' + 10;
119 
120             c = *str++;
121         }
122 
123         c = *str++;
124     }
125 }
126 
jstr2bdaddr(JNIEnv * env,bt_bdaddr_t * bda,jstring address)127 static void jstr2bdaddr(JNIEnv* env, bt_bdaddr_t *bda, jstring address)
128 {
129     const char* c_bda = env->GetStringUTFChars(address, NULL);
130     if (c_bda != NULL && bda != NULL && strlen(c_bda) == 17)
131     {
132         bd_addr_str_to_addr(c_bda, bda->address);
133         env->ReleaseStringUTFChars(address, c_bda);
134     }
135 }
136 
137 namespace android {
138 
139 /**
140  * Client callback methods
141  */
142 
143 static jmethodID method_onClientRegistered;
144 static jmethodID method_onScanResult;
145 static jmethodID method_onConnected;
146 static jmethodID method_onDisconnected;
147 static jmethodID method_onReadCharacteristic;
148 static jmethodID method_onWriteCharacteristic;
149 static jmethodID method_onExecuteCompleted;
150 static jmethodID method_onSearchCompleted;
151 static jmethodID method_onSearchResult;
152 static jmethodID method_onReadDescrExtProp;
153 static jmethodID method_onReadDescriptor;
154 static jmethodID method_onWriteDescriptor;
155 static jmethodID method_onNotify;
156 static jmethodID method_onGetCharacteristic;
157 static jmethodID method_onGetDescriptor;
158 static jmethodID method_onGetIncludedService;
159 static jmethodID method_onRegisterForNotifications;
160 static jmethodID method_onReadRemoteRssi;
161 
162 /**
163  * Server callback methods
164  */
165 static jmethodID method_onServerRegistered;
166 static jmethodID method_onClientConnected;
167 static jmethodID method_onServiceAdded;
168 static jmethodID method_onIncludedServiceAdded;
169 static jmethodID method_onCharacteristicAdded;
170 static jmethodID method_onDescriptorAdded;
171 static jmethodID method_onServiceStarted;
172 static jmethodID method_onServiceStopped;
173 static jmethodID method_onServiceDeleted;
174 static jmethodID method_onResponseSendCompleted;
175 static jmethodID method_onAttributeRead;
176 static jmethodID method_onAttributeWrite;
177 static jmethodID method_onExecuteWrite;
178 
179 /**
180  * Static variables
181  */
182 
183 static const btgatt_interface_t *sGattIf = NULL;
184 static jobject mCallbacksObj = NULL;
185 static JNIEnv *sCallbackEnv = NULL;
186 
checkCallbackThread()187 static bool checkCallbackThread() {
188     sCallbackEnv = getCallbackEnv();
189 
190     JNIEnv* env = AndroidRuntime::getJNIEnv();
191     if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
192     return true;
193 }
194 
195 /**
196  * BTA client callbacks
197  */
198 
btgattc_register_app_cb(int status,int clientIf,bt_uuid_t * app_uuid)199 void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid)
200 {
201     CHECK_CALLBACK_ENV
202     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status,
203         clientIf, UUID_PARAMS(app_uuid));
204     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
205 }
206 
btgattc_scan_result_cb(bt_bdaddr_t * bda,int rssi,uint8_t * adv_data)207 void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data)
208 {
209     CHECK_CALLBACK_ENV
210 
211     char c_address[32];
212     snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
213         bda->address[0], bda->address[1], bda->address[2],
214         bda->address[3], bda->address[4], bda->address[5]);
215 
216     jstring address = sCallbackEnv->NewStringUTF(c_address);
217     jbyteArray jb = sCallbackEnv->NewByteArray(62);
218     sCallbackEnv->SetByteArrayRegion(jb, 0, 62, (jbyte *) adv_data);
219 
220     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanResult
221         , address, rssi, jb);
222 
223     sCallbackEnv->DeleteLocalRef(address);
224     sCallbackEnv->DeleteLocalRef(jb);
225     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
226 }
227 
btgattc_open_cb(int conn_id,int status,int clientIf,bt_bdaddr_t * bda)228 void btgattc_open_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
229 {
230     CHECK_CALLBACK_ENV
231 
232     char c_address[32];
233     snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
234         bda->address[0], bda->address[1], bda->address[2],
235         bda->address[3], bda->address[4], bda->address[5]);
236 
237     jstring address = sCallbackEnv->NewStringUTF(c_address);
238     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnected,
239         clientIf, conn_id, status, address);
240     sCallbackEnv->DeleteLocalRef(address);
241     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
242 }
243 
btgattc_close_cb(int conn_id,int status,int clientIf,bt_bdaddr_t * bda)244 void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
245 {
246     CHECK_CALLBACK_ENV
247     char c_address[32];
248     snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
249         bda->address[0], bda->address[1], bda->address[2],
250         bda->address[3], bda->address[4], bda->address[5]);
251 
252     jstring address = sCallbackEnv->NewStringUTF(c_address);
253     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDisconnected,
254         clientIf, conn_id, status, address);
255     sCallbackEnv->DeleteLocalRef(address);
256     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
257 }
258 
btgattc_search_complete_cb(int conn_id,int status)259 void btgattc_search_complete_cb(int conn_id, int status)
260 {
261     CHECK_CALLBACK_ENV
262     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchCompleted,
263                                  conn_id, status);
264     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
265 }
266 
btgattc_search_result_cb(int conn_id,btgatt_srvc_id_t * srvc_id)267 void btgattc_search_result_cb(int conn_id, btgatt_srvc_id_t *srvc_id)
268 {
269     CHECK_CALLBACK_ENV
270     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchResult, conn_id,
271         SRVC_ID_PARAMS(srvc_id));
272     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
273 }
274 
btgattc_get_characteristic_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_char_id_t * char_id,int char_prop)275 void btgattc_get_characteristic_cb(int conn_id, int status,
276                 btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
277                 int char_prop)
278 {
279     CHECK_CALLBACK_ENV
280     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetCharacteristic
281         , conn_id, status, SRVC_ID_PARAMS(srvc_id), CHAR_ID_PARAMS(char_id)
282         , char_prop);
283     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
284 }
285 
btgattc_get_descriptor_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_char_id_t * char_id,bt_uuid_t * descr_id)286 void btgattc_get_descriptor_cb(int conn_id, int status,
287                 btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id,
288                 bt_uuid_t *descr_id)
289 {
290     CHECK_CALLBACK_ENV
291     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetDescriptor
292         , conn_id, status, SRVC_ID_PARAMS(srvc_id), CHAR_ID_PARAMS(char_id)
293         , UUID_PARAMS(descr_id));
294     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
295 }
296 
btgattc_get_included_service_cb(int conn_id,int status,btgatt_srvc_id_t * srvc_id,btgatt_srvc_id_t * incl_srvc_id)297 void btgattc_get_included_service_cb(int conn_id, int status,
298                 btgatt_srvc_id_t *srvc_id, btgatt_srvc_id_t *incl_srvc_id)
299 {
300     CHECK_CALLBACK_ENV
301     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetIncludedService
302         , conn_id, status, SRVC_ID_PARAMS(srvc_id), SRVC_ID_PARAMS(incl_srvc_id));
303     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
304 }
305 
btgattc_register_for_notification_cb(int conn_id,int registered,int status,btgatt_srvc_id_t * srvc_id,btgatt_char_id_t * char_id)306 void btgattc_register_for_notification_cb(int conn_id, int registered, int status,
307                                           btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id)
308 {
309     CHECK_CALLBACK_ENV
310     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRegisterForNotifications
311         , conn_id, status, registered, SRVC_ID_PARAMS(srvc_id), CHAR_ID_PARAMS(char_id));
312     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
313 }
314 
btgattc_notify_cb(int conn_id,btgatt_notify_params_t * p_data)315 void btgattc_notify_cb(int conn_id, btgatt_notify_params_t *p_data)
316 {
317     CHECK_CALLBACK_ENV
318 
319     char c_address[32];
320     snprintf(c_address, sizeof(c_address), "%02X:%02X:%02X:%02X:%02X:%02X",
321         p_data->bda.address[0], p_data->bda.address[1], p_data->bda.address[2],
322         p_data->bda.address[3], p_data->bda.address[4], p_data->bda.address[5]);
323 
324     jstring address = sCallbackEnv->NewStringUTF(c_address);
325     jbyteArray jb = sCallbackEnv->NewByteArray(p_data->len);
326     sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->len, (jbyte *) p_data->value);
327 
328     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNotify
329         , conn_id, address, SRVC_ID_PARAMS((&p_data->srvc_id))
330         , CHAR_ID_PARAMS((&p_data->char_id)), p_data->is_notify, jb);
331 
332     sCallbackEnv->DeleteLocalRef(address);
333     sCallbackEnv->DeleteLocalRef(jb);
334     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
335 }
336 
btgattc_read_characteristic_cb(int conn_id,int status,btgatt_read_params_t * p_data)337 void btgattc_read_characteristic_cb(int conn_id, int status, btgatt_read_params_t *p_data)
338 {
339     CHECK_CALLBACK_ENV
340 
341     jbyteArray jb;
342     if ( status == 0 )      //successful
343     {
344         jb = sCallbackEnv->NewByteArray(p_data->value.len);
345         sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->value.len,
346             (jbyte *) p_data->value.value);
347     } else {
348         uint8_t value = 0;
349         jb = sCallbackEnv->NewByteArray(1);
350         sCallbackEnv->SetByteArrayRegion(jb, 0, 1, (jbyte *) &value);
351     }
352 
353     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadCharacteristic
354         , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
355         , CHAR_ID_PARAMS((&p_data->char_id)), p_data->value_type, jb);
356     sCallbackEnv->DeleteLocalRef(jb);
357     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
358 }
359 
btgattc_write_characteristic_cb(int conn_id,int status,btgatt_write_params_t * p_data)360 void btgattc_write_characteristic_cb(int conn_id, int status, btgatt_write_params_t *p_data)
361 {
362     CHECK_CALLBACK_ENV
363     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic
364         , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
365         , CHAR_ID_PARAMS((&p_data->char_id)));
366     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
367 }
368 
btgattc_execute_write_cb(int conn_id,int status)369 void btgattc_execute_write_cb(int conn_id, int status)
370 {
371     CHECK_CALLBACK_ENV
372     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteCompleted
373         , conn_id, status);
374     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
375 }
376 
btgattc_read_descriptor_cb(int conn_id,int status,btgatt_read_params_t * p_data)377 void btgattc_read_descriptor_cb(int conn_id, int status, btgatt_read_params_t *p_data)
378 {
379     CHECK_CALLBACK_ENV
380 
381     jbyteArray jb;
382     if ( p_data->value.len != 0 )
383     {
384         jb = sCallbackEnv->NewByteArray(p_data->value.len);
385         sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->value.len,
386                                 (jbyte *) p_data->value.value);
387     } else {
388         jb = sCallbackEnv->NewByteArray(1);
389     }
390 
391     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadDescriptor
392         , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
393         , CHAR_ID_PARAMS((&p_data->char_id)), UUID_PARAMS((&p_data->descr_id))
394         , p_data->value_type, jb);
395 
396     sCallbackEnv->DeleteLocalRef(jb);
397     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
398 }
399 
btgattc_write_descriptor_cb(int conn_id,int status,btgatt_write_params_t * p_data)400 void btgattc_write_descriptor_cb(int conn_id, int status, btgatt_write_params_t *p_data)
401 {
402     CHECK_CALLBACK_ENV
403     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor
404         , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
405         , CHAR_ID_PARAMS((&p_data->char_id)), UUID_PARAMS((&p_data->descr_id)));
406     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
407 }
408 
btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t * bda,int rssi,int status)409 void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status)
410 {
411     CHECK_CALLBACK_ENV
412 
413     char c_address[32];
414     snprintf(c_address, sizeof(c_address),"%02X:%02X:%02X:%02X:%02X:%02X",
415         bda->address[0], bda->address[1], bda->address[2],
416         bda->address[3], bda->address[4], bda->address[5]);
417     jstring address = sCallbackEnv->NewStringUTF(c_address);
418     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadRemoteRssi,
419        client_if, address, rssi, status);
420     sCallbackEnv->DeleteLocalRef(address);
421     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
422 }
423 
424 static const btgatt_client_callbacks_t sGattClientCallbacks = {
425     btgattc_register_app_cb,
426     btgattc_scan_result_cb,
427     btgattc_open_cb,
428     btgattc_close_cb,
429     btgattc_search_complete_cb,
430     btgattc_search_result_cb,
431     btgattc_get_characteristic_cb,
432     btgattc_get_descriptor_cb,
433     btgattc_get_included_service_cb,
434     btgattc_register_for_notification_cb,
435     btgattc_notify_cb,
436     btgattc_read_characteristic_cb,
437     btgattc_write_characteristic_cb,
438     btgattc_read_descriptor_cb,
439     btgattc_write_descriptor_cb,
440     btgattc_execute_write_cb,
441     btgattc_remote_rssi_cb
442 };
443 
444 
445 /**
446  * BTA server callbacks
447  */
448 
btgatts_register_app_cb(int status,int server_if,bt_uuid_t * uuid)449 void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid)
450 {
451     CHECK_CALLBACK_ENV
452     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerRegistered
453         , status, server_if, UUID_PARAMS(uuid));
454     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
455 }
456 
btgatts_connection_cb(int conn_id,int server_if,int connected,bt_bdaddr_t * bda)457 void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda)
458 {
459     CHECK_CALLBACK_ENV
460 
461     char c_address[32];
462     sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
463             bda->address[0], bda->address[1], bda->address[2],
464             bda->address[3], bda->address[4], bda->address[5]);
465 
466     jstring address = sCallbackEnv->NewStringUTF(c_address);
467     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientConnected,
468                                  address, connected, conn_id, server_if);
469     sCallbackEnv->DeleteLocalRef(address);
470     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
471 }
472 
btgatts_service_added_cb(int status,int server_if,btgatt_srvc_id_t * srvc_id,int srvc_handle)473 void btgatts_service_added_cb(int status, int server_if,
474                               btgatt_srvc_id_t *srvc_id, int srvc_handle)
475 {
476     CHECK_CALLBACK_ENV
477     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceAdded, status,
478                                  server_if, SRVC_ID_PARAMS(srvc_id),
479                                  srvc_handle);
480     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
481 }
482 
btgatts_included_service_added_cb(int status,int server_if,int srvc_handle,int incl_srvc_handle)483 void btgatts_included_service_added_cb(int status, int server_if,
484                                    int srvc_handle,
485                                    int incl_srvc_handle)
486 {
487     CHECK_CALLBACK_ENV
488     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onIncludedServiceAdded,
489                                  status, server_if, srvc_handle, incl_srvc_handle);
490     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
491 }
492 
btgatts_characteristic_added_cb(int status,int server_if,bt_uuid_t * char_id,int srvc_handle,int char_handle)493 void btgatts_characteristic_added_cb(int status, int server_if, bt_uuid_t *char_id,
494                                      int srvc_handle, int char_handle)
495 {
496     CHECK_CALLBACK_ENV
497     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCharacteristicAdded,
498                                  status, server_if, UUID_PARAMS(char_id),
499                                  srvc_handle, char_handle);
500     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
501 }
502 
btgatts_descriptor_added_cb(int status,int server_if,bt_uuid_t * descr_id,int srvc_handle,int descr_handle)503 void btgatts_descriptor_added_cb(int status, int server_if,
504                                  bt_uuid_t *descr_id, int srvc_handle,
505                                  int descr_handle)
506 {
507     CHECK_CALLBACK_ENV
508     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDescriptorAdded,
509                                  status, server_if, UUID_PARAMS(descr_id),
510                                  srvc_handle, descr_handle);
511     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
512 }
513 
btgatts_service_started_cb(int status,int server_if,int srvc_handle)514 void btgatts_service_started_cb(int status, int server_if, int srvc_handle)
515 {
516     CHECK_CALLBACK_ENV
517     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceStarted, status,
518                                  server_if, srvc_handle);
519     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
520 }
521 
btgatts_service_stopped_cb(int status,int server_if,int srvc_handle)522 void btgatts_service_stopped_cb(int status, int server_if, int srvc_handle)
523 {
524     CHECK_CALLBACK_ENV
525     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceStopped, status,
526                                  server_if, srvc_handle);
527     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
528 }
529 
btgatts_service_deleted_cb(int status,int server_if,int srvc_handle)530 void btgatts_service_deleted_cb(int status, int server_if, int srvc_handle)
531 {
532     CHECK_CALLBACK_ENV
533     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceDeleted, status,
534                                  server_if, srvc_handle);
535     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
536 }
537 
btgatts_request_read_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int attr_handle,int offset,bool is_long)538 void btgatts_request_read_cb(int conn_id, int trans_id, bt_bdaddr_t *bda,
539                              int attr_handle, int offset, bool is_long)
540 {
541     CHECK_CALLBACK_ENV
542 
543     char c_address[32];
544     sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
545             bda->address[0], bda->address[1], bda->address[2],
546             bda->address[3], bda->address[4], bda->address[5]);
547 
548     jstring address = sCallbackEnv->NewStringUTF(c_address);
549     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAttributeRead,
550                                  address, conn_id, trans_id, attr_handle,
551                                  offset, is_long);
552     sCallbackEnv->DeleteLocalRef(address);
553     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
554 }
555 
btgatts_request_write_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int attr_handle,int offset,int length,bool need_rsp,bool is_prep,uint8_t * value)556 void btgatts_request_write_cb(int conn_id, int trans_id,
557                               bt_bdaddr_t *bda, int attr_handle,
558                               int offset, int length,
559                               bool need_rsp, bool is_prep, uint8_t* value)
560 {
561     CHECK_CALLBACK_ENV
562 
563     char c_address[32];
564     sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
565             bda->address[0], bda->address[1], bda->address[2],
566             bda->address[3], bda->address[4], bda->address[5]);
567 
568     jstring address = sCallbackEnv->NewStringUTF(c_address);
569 
570     jbyteArray val = sCallbackEnv->NewByteArray(length);
571     if (val) sCallbackEnv->SetByteArrayRegion(val, 0, length, (jbyte*)value);
572     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAttributeWrite,
573                                  address, conn_id, trans_id, attr_handle,
574                                  offset, length, need_rsp, is_prep, val);
575     sCallbackEnv->DeleteLocalRef(address);
576     sCallbackEnv->DeleteLocalRef(val);
577     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
578 }
579 
btgatts_request_exec_write_cb(int conn_id,int trans_id,bt_bdaddr_t * bda,int exec_write)580 void btgatts_request_exec_write_cb(int conn_id, int trans_id,
581                                    bt_bdaddr_t *bda, int exec_write)
582 {
583     CHECK_CALLBACK_ENV
584 
585     char c_address[32];
586     sprintf(c_address, "%02X:%02X:%02X:%02X:%02X:%02X",
587             bda->address[0], bda->address[1], bda->address[2],
588             bda->address[3], bda->address[4], bda->address[5]);
589 
590     jstring address = sCallbackEnv->NewStringUTF(c_address);
591     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteWrite,
592                                  address, conn_id, trans_id, exec_write);
593     sCallbackEnv->DeleteLocalRef(address);
594     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
595 }
596 
btgatts_response_confirmation_cb(int status,int handle)597 void btgatts_response_confirmation_cb(int status, int handle)
598 {
599     CHECK_CALLBACK_ENV
600     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onResponseSendCompleted,
601                                  status, handle);
602     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
603 }
604 
605 static const btgatt_server_callbacks_t sGattServerCallbacks = {
606     btgatts_register_app_cb,
607     btgatts_connection_cb,
608     btgatts_service_added_cb,
609     btgatts_included_service_added_cb,
610     btgatts_characteristic_added_cb,
611     btgatts_descriptor_added_cb,
612     btgatts_service_started_cb,
613     btgatts_service_stopped_cb,
614     btgatts_service_deleted_cb,
615     btgatts_request_read_cb,
616     btgatts_request_write_cb,
617     btgatts_request_exec_write_cb,
618     btgatts_response_confirmation_cb
619 };
620 
621 /**
622  * GATT callbacks
623  */
624 
625 static const btgatt_callbacks_t sGattCallbacks = {
626     sizeof(btgatt_callbacks_t),
627     &sGattClientCallbacks,
628     &sGattServerCallbacks
629 };
630 
631 /**
632  * Native function definitions
633  */
634 
classInitNative(JNIEnv * env,jclass clazz)635 static void classInitNative(JNIEnv* env, jclass clazz) {
636 
637     // Client callbacks
638 
639     method_onClientRegistered = env->GetMethodID(clazz, "onClientRegistered", "(IIJJ)V");
640     method_onScanResult = env->GetMethodID(clazz, "onScanResult", "(Ljava/lang/String;I[B)V");
641     method_onConnected   = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V");
642     method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V");
643     method_onReadCharacteristic = env->GetMethodID(clazz, "onReadCharacteristic", "(IIIIJJIJJI[B)V");
644     method_onWriteCharacteristic = env->GetMethodID(clazz, "onWriteCharacteristic", "(IIIIJJIJJ)V");
645     method_onExecuteCompleted = env->GetMethodID(clazz, "onExecuteCompleted",  "(II)V");
646     method_onSearchCompleted = env->GetMethodID(clazz, "onSearchCompleted",  "(II)V");
647     method_onSearchResult = env->GetMethodID(clazz, "onSearchResult", "(IIIJJ)V");
648     method_onReadDescriptor = env->GetMethodID(clazz, "onReadDescriptor", "(IIIIJJIJJJJI[B)V");
649     method_onWriteDescriptor = env->GetMethodID(clazz, "onWriteDescriptor", "(IIIIJJIJJJJ)V");
650     method_onNotify = env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IIJJIJJZ[B)V");
651     method_onGetCharacteristic = env->GetMethodID(clazz, "onGetCharacteristic", "(IIIIJJIJJI)V");
652     method_onGetDescriptor = env->GetMethodID(clazz, "onGetDescriptor", "(IIIIJJIJJJJ)V");
653     method_onGetIncludedService = env->GetMethodID(clazz, "onGetIncludedService", "(IIIIJJIIJJ)V");
654     method_onRegisterForNotifications = env->GetMethodID(clazz, "onRegisterForNotifications", "(IIIIIJJIJJ)V");
655     method_onReadRemoteRssi = env->GetMethodID(clazz, "onReadRemoteRssi", "(ILjava/lang/String;II)V");
656 
657      // Server callbacks
658 
659     method_onServerRegistered = env->GetMethodID(clazz, "onServerRegistered", "(IIJJ)V");
660     method_onClientConnected = env->GetMethodID(clazz, "onClientConnected", "(Ljava/lang/String;ZII)V");
661     method_onServiceAdded = env->GetMethodID(clazz, "onServiceAdded", "(IIIIJJI)V");
662     method_onIncludedServiceAdded = env->GetMethodID(clazz, "onIncludedServiceAdded", "(IIII)V");
663     method_onCharacteristicAdded  = env->GetMethodID(clazz, "onCharacteristicAdded", "(IIJJII)V");
664     method_onDescriptorAdded = env->GetMethodID(clazz, "onDescriptorAdded", "(IIJJII)V");
665     method_onServiceStarted = env->GetMethodID(clazz, "onServiceStarted", "(III)V");
666     method_onServiceStopped = env->GetMethodID(clazz, "onServiceStopped", "(III)V");
667     method_onServiceDeleted = env->GetMethodID(clazz, "onServiceDeleted", "(III)V");
668     method_onResponseSendCompleted = env->GetMethodID(clazz, "onResponseSendCompleted", "(II)V");
669     method_onAttributeRead= env->GetMethodID(clazz, "onAttributeRead", "(Ljava/lang/String;IIIIZ)V");
670     method_onAttributeWrite= env->GetMethodID(clazz, "onAttributeWrite", "(Ljava/lang/String;IIIIIZZ[B)V");
671     method_onExecuteWrite= env->GetMethodID(clazz, "onExecuteWrite", "(Ljava/lang/String;III)V");
672 
673     info("classInitNative: Success!");
674 }
675 
676 static const bt_interface_t* btIf;
677 
initializeNative(JNIEnv * env,jobject object)678 static void initializeNative(JNIEnv *env, jobject object) {
679     if(btIf)
680         return;
681 
682     if ( (btIf = getBluetoothInterface()) == NULL) {
683         error("Bluetooth module is not loaded");
684         return;
685     }
686 
687     if (sGattIf != NULL) {
688          ALOGW("Cleaning up Bluetooth GATT Interface before initializing...");
689          sGattIf->cleanup();
690          sGattIf = NULL;
691     }
692 
693     if (mCallbacksObj != NULL) {
694          ALOGW("Cleaning up Bluetooth GATT callback object");
695          env->DeleteGlobalRef(mCallbacksObj);
696          mCallbacksObj = NULL;
697     }
698 
699     if ( (sGattIf = (btgatt_interface_t *)
700           btIf->get_profile_interface(BT_PROFILE_GATT_ID)) == NULL) {
701         error("Failed to get Bluetooth GATT Interface");
702         return;
703     }
704 
705     bt_status_t status;
706     if ( (status = sGattIf->init(&sGattCallbacks)) != BT_STATUS_SUCCESS) {
707         error("Failed to initialize Bluetooth GATT, status: %d", status);
708         sGattIf = NULL;
709         return;
710     }
711 
712     mCallbacksObj = env->NewGlobalRef(object);
713 }
714 
cleanupNative(JNIEnv * env,jobject object)715 static void cleanupNative(JNIEnv *env, jobject object) {
716     bt_status_t status;
717     if (!btIf) return;
718 
719     if (sGattIf != NULL) {
720         sGattIf->cleanup();
721         sGattIf = NULL;
722     }
723 
724     if (mCallbacksObj != NULL) {
725         env->DeleteGlobalRef(mCallbacksObj);
726         mCallbacksObj = NULL;
727     }
728     btIf = NULL;
729 }
730 
731 /**
732  * Native Client functions
733  */
734 
gattClientGetDeviceTypeNative(JNIEnv * env,jobject object,jstring address)735 static int gattClientGetDeviceTypeNative(JNIEnv* env, jobject object, jstring address)
736 {
737     if (!sGattIf) return 0;
738     bt_bdaddr_t bda;
739     jstr2bdaddr(env, &bda, address);
740     return sGattIf->client->get_device_type(&bda);
741 }
742 
gattClientRegisterAppNative(JNIEnv * env,jobject object,jlong app_uuid_lsb,jlong app_uuid_msb)743 static void gattClientRegisterAppNative(JNIEnv* env, jobject object,
744                                         jlong app_uuid_lsb, jlong app_uuid_msb )
745 {
746     bt_uuid_t uuid;
747 
748     if (!sGattIf) return;
749     set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
750     sGattIf->client->register_client(&uuid);
751 }
752 
gattClientUnregisterAppNative(JNIEnv * env,jobject object,jint clientIf)753 static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clientIf)
754 {
755     if (!sGattIf) return;
756     sGattIf->client->unregister_client(clientIf);
757 }
758 
gattClientScanNative(JNIEnv * env,jobject object,jint clientIf,jboolean start)759 static void gattClientScanNative(JNIEnv* env, jobject object, jint clientIf, jboolean start)
760 {
761     if (!sGattIf) return;
762     sGattIf->client->scan(clientIf, start);
763 }
764 
gattClientConnectNative(JNIEnv * env,jobject object,jint clientif,jstring address,jboolean isDirect)765 static void gattClientConnectNative(JNIEnv* env, jobject object, jint clientif,
766                                  jstring address, jboolean isDirect)
767 {
768     if (!sGattIf) return;
769 
770     bt_bdaddr_t bda;
771     jstr2bdaddr(env, &bda, address);
772     sGattIf->client->connect(clientif, &bda, isDirect);
773 }
774 
gattClientDisconnectNative(JNIEnv * env,jobject object,jint clientIf,jstring address,jint conn_id)775 static void gattClientDisconnectNative(JNIEnv* env, jobject object, jint clientIf,
776                                   jstring address, jint conn_id)
777 {
778     if (!sGattIf) return;
779     bt_bdaddr_t bda;
780     jstr2bdaddr(env, &bda, address);
781     sGattIf->client->disconnect(clientIf, &bda, conn_id);
782 }
783 
gattClientRefreshNative(JNIEnv * env,jobject object,jint clientIf,jstring address)784 static void gattClientRefreshNative(JNIEnv* env, jobject object, jint clientIf,
785                                     jstring address)
786 {
787     if (!sGattIf) return;
788 
789     bt_bdaddr_t bda;
790     jstr2bdaddr(env, &bda, address);
791     sGattIf->client->refresh(clientIf, &bda);
792 }
793 
gattClientSearchServiceNative(JNIEnv * env,jobject object,jint conn_id,jboolean search_all,jlong service_uuid_lsb,jlong service_uuid_msb)794 static void gattClientSearchServiceNative(JNIEnv* env, jobject object, jint conn_id,
795             jboolean search_all, jlong service_uuid_lsb, jlong service_uuid_msb)
796 {
797     if (!sGattIf) return;
798 
799     bt_uuid_t uuid;
800     set_uuid(uuid.uu, service_uuid_msb, service_uuid_lsb);
801     sGattIf->client->search_service(conn_id, search_all ? 0 : &uuid);
802 }
803 
gattClientGetCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb)804 static void gattClientGetCharacteristicNative(JNIEnv* env, jobject object,
805     jint conn_id,
806     jint  service_type, jint  service_id_inst_id,
807     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
808     jint  char_id_inst_id,
809     jlong char_id_uuid_lsb, jlong char_id_uuid_msb)
810 {
811     if (!sGattIf) return;
812 
813     btgatt_srvc_id_t srvc_id;
814     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
815     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
816 
817     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
818 
819     btgatt_char_id_t char_id;
820     char_id.inst_id = (uint8_t) char_id_inst_id;
821     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
822 
823     if (char_id_uuid_lsb == 0)
824     {
825         sGattIf->client->get_characteristic(conn_id, &srvc_id, 0);
826     } else {
827         sGattIf->client->get_characteristic(conn_id, &srvc_id, &char_id);
828     }
829 }
830 
gattClientGetDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb)831 static void gattClientGetDescriptorNative(JNIEnv* env, jobject object,
832     jint conn_id,
833     jint  service_type, jint  service_id_inst_id,
834     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
835     jint  char_id_inst_id,
836     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
837     jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb)
838 {
839     if (!sGattIf) return;
840 
841     btgatt_srvc_id_t srvc_id;
842     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
843     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
844     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
845 
846     btgatt_char_id_t char_id;
847     char_id.inst_id = (uint8_t) char_id_inst_id;
848     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
849 
850     bt_uuid_t descr_id;
851     set_uuid(descr_id.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
852 
853     if (descr_id_uuid_lsb == 0)
854     {
855         sGattIf->client->get_descriptor(conn_id, &srvc_id, &char_id, 0);
856     } else {
857         sGattIf->client->get_descriptor(conn_id, &srvc_id, &char_id, &descr_id);
858     }
859 }
860 
gattClientGetIncludedServiceNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint incl_service_id_inst_id,jint incl_service_type,jlong incl_service_id_uuid_lsb,jlong incl_service_id_uuid_msb)861 static void gattClientGetIncludedServiceNative(JNIEnv* env, jobject object,
862     jint conn_id, jint service_type, jint service_id_inst_id,
863     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
864     jint incl_service_id_inst_id, jint incl_service_type,
865     jlong incl_service_id_uuid_lsb, jlong incl_service_id_uuid_msb)
866 {
867     if (!sGattIf) return;
868 
869     btgatt_srvc_id_t srvc_id;
870     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
871     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
872     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
873 
874     btgatt_srvc_id_t  incl_srvc_id;
875     incl_srvc_id.id.inst_id = (uint8_t) incl_service_id_inst_id;
876     incl_srvc_id.is_primary = (incl_service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
877     set_uuid(incl_srvc_id.id.uuid.uu, incl_service_id_uuid_msb, incl_service_id_uuid_lsb);
878 
879     if (incl_service_id_uuid_lsb == 0)
880     {
881         sGattIf->client->get_included_service(conn_id, &srvc_id, 0);
882     } else {
883         sGattIf->client->get_included_service(conn_id, &srvc_id, &incl_srvc_id);
884     }
885 }
886 
gattClientReadCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint authReq)887 static void gattClientReadCharacteristicNative(JNIEnv* env, jobject object,
888     jint conn_id, jint  service_type, jint  service_id_inst_id,
889     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
890     jint  char_id_inst_id,
891     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
892     jint authReq)
893 {
894     if (!sGattIf) return;
895 
896     btgatt_srvc_id_t srvc_id;
897     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
898     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
899     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
900 
901     btgatt_char_id_t char_id;
902     char_id.inst_id = (uint8_t) char_id_inst_id;
903     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
904 
905     sGattIf->client->read_characteristic(conn_id, &srvc_id, &char_id, authReq);
906 }
907 
gattClientReadDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb,jint authReq)908 static void gattClientReadDescriptorNative(JNIEnv* env, jobject object,
909     jint conn_id, jint  service_type, jint  service_id_inst_id,
910     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
911     jint  char_id_inst_id,
912     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
913     jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
914     jint authReq)
915 {
916     if (!sGattIf) return;
917 
918     btgatt_srvc_id_t srvc_id;
919     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
920     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
921     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
922 
923     btgatt_char_id_t char_id;
924     char_id.inst_id = (uint8_t) char_id_inst_id;
925     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
926 
927     bt_uuid_t descr_id;
928     set_uuid(descr_id.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
929 
930     sGattIf->client->read_descriptor(conn_id, &srvc_id, &char_id, &descr_id, authReq);
931 }
932 
gattClientWriteCharacteristicNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jint write_type,jint auth_req,jbyteArray value)933 static void gattClientWriteCharacteristicNative(JNIEnv* env, jobject object,
934     jint conn_id, jint  service_type, jint  service_id_inst_id,
935     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
936     jint  char_id_inst_id,
937     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
938     jint write_type, jint auth_req, jbyteArray value)
939 {
940     if (!sGattIf) return;
941 
942     btgatt_srvc_id_t srvc_id;
943     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
944     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
945     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
946 
947     btgatt_char_id_t char_id;
948     char_id.inst_id = (uint8_t) char_id_inst_id;
949     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
950 
951     uint16_t len = (uint16_t) env->GetArrayLength(value);
952     jbyte *p_value = env->GetByteArrayElements(value, NULL);
953     if (p_value == NULL) return;
954 
955     sGattIf->client->write_characteristic(conn_id, &srvc_id, &char_id,
956                                     write_type, len, auth_req, (char*)p_value);
957     env->ReleaseByteArrayElements(value, p_value, 0);
958 }
959 
gattClientExecuteWriteNative(JNIEnv * env,jobject object,jint conn_id,jboolean execute)960 static void gattClientExecuteWriteNative(JNIEnv* env, jobject object,
961     jint conn_id, jboolean execute)
962 {
963     if (!sGattIf) return;
964     sGattIf->client->execute_write(conn_id, execute ? 1 : 0);
965 }
966 
gattClientWriteDescriptorNative(JNIEnv * env,jobject object,jint conn_id,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jlong descr_id_uuid_lsb,jlong descr_id_uuid_msb,jint write_type,jint auth_req,jbyteArray value)967 static void gattClientWriteDescriptorNative(JNIEnv* env, jobject object,
968     jint conn_id, jint  service_type, jint service_id_inst_id,
969     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
970     jint char_id_inst_id,
971     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
972     jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
973     jint write_type, jint auth_req, jbyteArray value)
974 {
975     if (!sGattIf) return;
976 
977     btgatt_srvc_id_t srvc_id;
978     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
979     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
980     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
981 
982     btgatt_char_id_t char_id;
983     char_id.inst_id = (uint8_t) char_id_inst_id;
984     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
985 
986     bt_uuid_t descr_id;
987     set_uuid(descr_id.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
988 
989     uint16_t len = (uint16_t) env->GetArrayLength(value);
990     jbyte *p_value = env->GetByteArrayElements(value, NULL);
991     if (p_value == NULL) return;
992 
993     sGattIf->client->write_descriptor(conn_id, &srvc_id, &char_id, &descr_id,
994                                     write_type, len, auth_req, (char*)p_value);
995     env->ReleaseByteArrayElements(value, p_value, 0);
996 }
997 
gattClientRegisterForNotificationsNative(JNIEnv * env,jobject object,jint clientIf,jstring address,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint char_id_inst_id,jlong char_id_uuid_lsb,jlong char_id_uuid_msb,jboolean enable)998 static void gattClientRegisterForNotificationsNative(JNIEnv* env, jobject object,
999     jint clientIf, jstring address,
1000     jint  service_type, jint service_id_inst_id,
1001     jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
1002     jint char_id_inst_id,
1003     jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
1004     jboolean enable)
1005 {
1006     if (!sGattIf) return;
1007 
1008     btgatt_srvc_id_t srvc_id;
1009     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
1010     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
1011     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
1012 
1013     btgatt_char_id_t char_id;
1014     char_id.inst_id = (uint8_t) char_id_inst_id;
1015     set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
1016 
1017     bt_bdaddr_t bd_addr;
1018     const char *c_address = env->GetStringUTFChars(address, NULL);
1019     bd_addr_str_to_addr(c_address, bd_addr.address);
1020 
1021     if (enable)
1022         sGattIf->client->register_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
1023     else
1024         sGattIf->client->deregister_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
1025 }
1026 
gattClientReadRemoteRssiNative(JNIEnv * env,jobject object,jint clientif,jstring address)1027 static void gattClientReadRemoteRssiNative(JNIEnv* env, jobject object, jint clientif,
1028                                  jstring address)
1029 {
1030     if (!sGattIf) return;
1031 
1032     bt_bdaddr_t bda;
1033     jstr2bdaddr(env, &bda, address);
1034 
1035     sGattIf->client->read_remote_rssi(clientif, &bda);
1036 }
1037 
1038 
1039 /**
1040  * Native server functions
1041  */
gattServerRegisterAppNative(JNIEnv * env,jobject object,jlong app_uuid_lsb,jlong app_uuid_msb)1042 static void gattServerRegisterAppNative(JNIEnv* env, jobject object,
1043                                         jlong app_uuid_lsb, jlong app_uuid_msb )
1044 {
1045     bt_uuid_t uuid;
1046     if (!sGattIf) return;
1047     set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
1048     sGattIf->server->register_server(&uuid);
1049 }
1050 
gattServerUnregisterAppNative(JNIEnv * env,jobject object,jint serverIf)1051 static void gattServerUnregisterAppNative(JNIEnv* env, jobject object, jint serverIf)
1052 {
1053     if (!sGattIf) return;
1054     sGattIf->server->unregister_server(serverIf);
1055 }
1056 
gattServerConnectNative(JNIEnv * env,jobject object,jint server_if,jstring address,jboolean is_direct)1057 static void gattServerConnectNative(JNIEnv *env, jobject object,
1058                                  jint server_if, jstring address, jboolean is_direct)
1059 {
1060     if (!sGattIf) return;
1061 
1062     bt_bdaddr_t bd_addr;
1063     const char *c_address = env->GetStringUTFChars(address, NULL);
1064     bd_addr_str_to_addr(c_address, bd_addr.address);
1065 
1066     sGattIf->server->connect(server_if, &bd_addr, is_direct);
1067 }
1068 
gattServerDisconnectNative(JNIEnv * env,jobject object,jint serverIf,jstring address,jint conn_id)1069 static void gattServerDisconnectNative(JNIEnv* env, jobject object, jint serverIf,
1070                                   jstring address, jint conn_id)
1071 {
1072     if (!sGattIf) return;
1073     bt_bdaddr_t bda;
1074     jstr2bdaddr(env, &bda, address);
1075     sGattIf->server->disconnect(serverIf, &bda, conn_id);
1076 }
1077 
gattServerAddServiceNative(JNIEnv * env,jobject object,jint server_if,jint service_type,jint service_id_inst_id,jlong service_id_uuid_lsb,jlong service_id_uuid_msb,jint num_handles)1078 static void gattServerAddServiceNative (JNIEnv *env, jobject object,
1079         jint server_if, jint service_type, jint service_id_inst_id,
1080         jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
1081         jint num_handles)
1082 {
1083     if (!sGattIf) return;
1084 
1085     btgatt_srvc_id_t srvc_id;
1086     srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
1087     srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
1088     set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
1089 
1090     sGattIf->server->add_service(server_if, &srvc_id, num_handles);
1091 }
1092 
gattServerAddIncludedServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jint included_svc_handle)1093 static void gattServerAddIncludedServiceNative (JNIEnv *env, jobject object,
1094         jint server_if, jint svc_handle, jint included_svc_handle)
1095 {
1096     if (!sGattIf) return;
1097     sGattIf->server->add_included_service(server_if, svc_handle,
1098                                           included_svc_handle);
1099 }
1100 
gattServerAddCharacteristicNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jlong char_uuid_lsb,jlong char_uuid_msb,jint properties,jint permissions)1101 static void gattServerAddCharacteristicNative (JNIEnv *env, jobject object,
1102         jint server_if, jint svc_handle,
1103         jlong char_uuid_lsb, jlong char_uuid_msb,
1104         jint properties, jint permissions)
1105 {
1106     if (!sGattIf) return;
1107 
1108     bt_uuid_t uuid;
1109     set_uuid(uuid.uu, char_uuid_msb, char_uuid_lsb);
1110 
1111     sGattIf->server->add_characteristic(server_if, svc_handle,
1112                                         &uuid, properties, permissions);
1113 }
1114 
gattServerAddDescriptorNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jlong desc_uuid_lsb,jlong desc_uuid_msb,jint permissions)1115 static void gattServerAddDescriptorNative (JNIEnv *env, jobject object,
1116         jint server_if, jint svc_handle,
1117         jlong desc_uuid_lsb, jlong desc_uuid_msb,
1118         jint permissions)
1119 {
1120     if (!sGattIf) return;
1121 
1122     bt_uuid_t uuid;
1123     set_uuid(uuid.uu, desc_uuid_msb, desc_uuid_lsb);
1124 
1125     sGattIf->server->add_descriptor(server_if, svc_handle, &uuid, permissions);
1126 }
1127 
gattServerStartServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle,jint transport)1128 static void gattServerStartServiceNative (JNIEnv *env, jobject object,
1129         jint server_if, jint svc_handle, jint transport )
1130 {
1131     if (!sGattIf) return;
1132     sGattIf->server->start_service(server_if, svc_handle, transport);
1133 }
1134 
gattServerStopServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle)1135 static void gattServerStopServiceNative (JNIEnv *env, jobject object,
1136                                          jint server_if, jint svc_handle)
1137 {
1138     if (!sGattIf) return;
1139     sGattIf->server->stop_service(server_if, svc_handle);
1140 }
1141 
gattServerDeleteServiceNative(JNIEnv * env,jobject object,jint server_if,jint svc_handle)1142 static void gattServerDeleteServiceNative (JNIEnv *env, jobject object,
1143                                            jint server_if, jint svc_handle)
1144 {
1145     if (!sGattIf) return;
1146     sGattIf->server->delete_service(server_if, svc_handle);
1147 }
1148 
gattServerSendIndicationNative(JNIEnv * env,jobject object,jint server_if,jint attr_handle,jint conn_id,jbyteArray val)1149 static void gattServerSendIndicationNative (JNIEnv *env, jobject object,
1150         jint server_if, jint attr_handle, jint conn_id, jbyteArray val)
1151 {
1152     if (!sGattIf) return;
1153 
1154     jbyte* array = env->GetByteArrayElements(val, 0);
1155     int val_len = env->GetArrayLength(val);
1156 
1157     sGattIf->server->send_indication(server_if, attr_handle, conn_id, val_len,
1158                                      /*confirm*/ 1, (char*)array);
1159     env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1160 }
1161 
gattServerSendNotificationNative(JNIEnv * env,jobject object,jint server_if,jint attr_handle,jint conn_id,jbyteArray val)1162 static void gattServerSendNotificationNative (JNIEnv *env, jobject object,
1163         jint server_if, jint attr_handle, jint conn_id, jbyteArray val)
1164 {
1165     if (!sGattIf) return;
1166 
1167     jbyte* array = env->GetByteArrayElements(val, 0);
1168     int val_len = env->GetArrayLength(val);
1169 
1170     sGattIf->server->send_indication(server_if, attr_handle, conn_id, val_len,
1171                                      /*confirm*/ 0, (char*)array);
1172     env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1173 }
1174 
gattServerSendResponseNative(JNIEnv * env,jobject object,jint server_if,jint conn_id,jint trans_id,jint status,jint handle,jint offset,jbyteArray val,jint auth_req)1175 static void gattServerSendResponseNative (JNIEnv *env, jobject object,
1176         jint server_if, jint conn_id, jint trans_id, jint status,
1177         jint handle, jint offset, jbyteArray val, jint auth_req)
1178 {
1179     if (!sGattIf) return;
1180 
1181     btgatt_response_t response;
1182 
1183     response.attr_value.handle = handle;
1184     response.attr_value.auth_req = auth_req;
1185     response.attr_value.offset = offset;
1186     response.attr_value.len = 0;
1187 
1188     if (val != NULL)
1189     {
1190         response.attr_value.len = (uint16_t) env->GetArrayLength(val);
1191         jbyte* array = env->GetByteArrayElements(val, 0);
1192 
1193         for (int i = 0; i != response.attr_value.len; ++i)
1194             response.attr_value.value[i] = (uint8_t) array[i];
1195         env->ReleaseByteArrayElements(val, array, JNI_ABORT);
1196     }
1197 
1198     sGattIf->server->send_response(conn_id, trans_id, status, &response);
1199 }
1200 
gattTestNative(JNIEnv * env,jobject object,jint command,jlong uuid1_lsb,jlong uuid1_msb,jstring bda1,jint p1,jint p2,jint p3,jint p4,jint p5)1201 static void gattTestNative(JNIEnv *env, jobject object, jint command,
1202                            jlong uuid1_lsb, jlong uuid1_msb, jstring bda1,
1203                            jint p1, jint p2, jint p3, jint p4, jint p5 )
1204 {
1205     if (!sGattIf) return;
1206 
1207     bt_bdaddr_t bt_bda1;
1208     jstr2bdaddr(env, &bt_bda1, bda1);
1209 
1210     bt_uuid_t uuid1;
1211     set_uuid(uuid1.uu, uuid1_msb, uuid1_lsb);
1212 
1213     btgatt_test_params_t params;
1214     params.bda1 = &bt_bda1;
1215     params.uuid1 = &uuid1;
1216     params.u1 = p1;
1217     params.u2 = p2;
1218     params.u3 = p3;
1219     params.u4 = p4;
1220     params.u5 = p5;
1221     sGattIf->client->test_command(command, &params);
1222 }
1223 
1224 /**
1225  * JNI function definitinos
1226  */
1227 
1228 static JNINativeMethod sMethods[] = {
1229     {"classInitNative", "()V", (void *) classInitNative},
1230     {"initializeNative", "()V", (void *) initializeNative},
1231     {"cleanupNative", "()V", (void *) cleanupNative},
1232 
1233     {"gattClientGetDeviceTypeNative", "(Ljava/lang/String;)I", (void *) gattClientGetDeviceTypeNative},
1234     {"gattClientRegisterAppNative", "(JJ)V", (void *) gattClientRegisterAppNative},
1235     {"gattClientUnregisterAppNative", "(I)V", (void *) gattClientUnregisterAppNative},
1236     {"gattClientScanNative", "(IZ)V", (void *) gattClientScanNative},
1237     {"gattClientConnectNative", "(ILjava/lang/String;Z)V", (void *) gattClientConnectNative},
1238     {"gattClientDisconnectNative", "(ILjava/lang/String;I)V", (void *) gattClientDisconnectNative},
1239     {"gattClientRefreshNative", "(ILjava/lang/String;)V", (void *) gattClientRefreshNative},
1240     {"gattClientSearchServiceNative", "(IZJJ)V", (void *) gattClientSearchServiceNative},
1241     {"gattClientGetCharacteristicNative", "(IIIJJIJJ)V", (void *) gattClientGetCharacteristicNative},
1242     {"gattClientGetDescriptorNative", "(IIIJJIJJJJ)V", (void *) gattClientGetDescriptorNative},
1243     {"gattClientGetIncludedServiceNative", "(IIIJJIIJJ)V", (void *) gattClientGetIncludedServiceNative},
1244     {"gattClientReadCharacteristicNative", "(IIIJJIJJI)V", (void *) gattClientReadCharacteristicNative},
1245     {"gattClientReadDescriptorNative", "(IIIJJIJJJJI)V", (void *) gattClientReadDescriptorNative},
1246     {"gattClientWriteCharacteristicNative", "(IIIJJIJJII[B)V", (void *) gattClientWriteCharacteristicNative},
1247     {"gattClientWriteDescriptorNative", "(IIIJJIJJJJII[B)V", (void *) gattClientWriteDescriptorNative},
1248     {"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative},
1249     {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative},
1250     {"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative},
1251 
1252     {"gattServerRegisterAppNative", "(JJ)V", (void *) gattServerRegisterAppNative},
1253     {"gattServerUnregisterAppNative", "(I)V", (void *) gattServerUnregisterAppNative},
1254     {"gattServerConnectNative", "(ILjava/lang/String;Z)V", (void *) gattServerConnectNative},
1255     {"gattServerDisconnectNative", "(ILjava/lang/String;I)V", (void *) gattServerDisconnectNative},
1256     {"gattServerAddServiceNative", "(IIIJJI)V", (void *) gattServerAddServiceNative},
1257     {"gattServerAddIncludedServiceNative", "(III)V", (void *) gattServerAddIncludedServiceNative},
1258     {"gattServerAddCharacteristicNative", "(IIJJII)V", (void *) gattServerAddCharacteristicNative},
1259     {"gattServerAddDescriptorNative", "(IIJJI)V", (void *) gattServerAddDescriptorNative},
1260     {"gattServerStartServiceNative", "(III)V", (void *) gattServerStartServiceNative},
1261     {"gattServerStopServiceNative", "(II)V", (void *) gattServerStopServiceNative},
1262     {"gattServerDeleteServiceNative", "(II)V", (void *) gattServerDeleteServiceNative},
1263     {"gattServerSendIndicationNative", "(III[B)V", (void *) gattServerSendIndicationNative},
1264     {"gattServerSendNotificationNative", "(III[B)V", (void *) gattServerSendNotificationNative},
1265     {"gattServerSendResponseNative", "(IIIIII[BI)V", (void *) gattServerSendResponseNative},
1266 
1267     {"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void *) gattTestNative},
1268 };
1269 
register_com_android_bluetooth_gatt(JNIEnv * env)1270 int register_com_android_bluetooth_gatt(JNIEnv* env)
1271 {
1272     return jniRegisterNativeMethods(env, "com/android/bluetooth/gatt/GattService",
1273                                     sMethods, NELEM(sMethods));
1274 }
1275 
1276 }
1277