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