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