• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 #define LOG_TAG "BluetoothSdpJni"
18 
19 #define LOG_NDEBUG 0
20 
21 #include "com_android_bluetooth.h"
22 #include "hardware/bt_sdp.h"
23 #include "utils/Log.h"
24 #include "android_runtime/AndroidRuntime.h"
25 
26 #include <string.h>
27 
28 static const uint8_t  UUID_OBEX_OBJECT_PUSH[] = {0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
29                                                  0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
30 static const uint8_t  UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
31                                          0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
32 static const uint8_t  UUID_MAP_MAS[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00,
33                                         0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
34 static const uint8_t  UUID_MAP_MNS[] = {0x00, 0x00, 0x11, 0x33, 0x00, 0x00, 0x10, 0x00,
35                                         0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
36 static const uint8_t  UUID_SPP[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
37                                     0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
38 static const uint8_t  UUID_SAP[] = {0x00, 0x00, 0x11, 0x2D, 0x00, 0x00, 0x10, 0x00,
39                                     0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
40 // TODO:
41 // Both the fact that the UUIDs are declared in multiple places, plus the fact
42 // that there is a mess of UUID comparison and shortening methods will have to
43 // be fixed.
44 // The btcore->uuid module should be used for all instances.
45 
46 #define UUID_MAX_LENGTH 16
47 #define IS_UUID(u1,u2)  !memcmp(u1,u2,UUID_MAX_LENGTH)
48 
49 
50 namespace android {
51 static jmethodID method_sdpRecordFoundCallback;
52 static jmethodID method_sdpMasRecordFoundCallback;
53 static jmethodID method_sdpMnsRecordFoundCallback;
54 static jmethodID method_sdpPseRecordFoundCallback;
55 static jmethodID method_sdpOppOpsRecordFoundCallback;
56 static jmethodID method_sdpSapsRecordFoundCallback;
57 
58 static const btsdp_interface_t *sBluetoothSdpInterface = NULL;
59 
60 static void sdp_search_callback(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid_in,
61         int record_size, bluetooth_sdp_record* record);
62 
63 btsdp_callbacks_t sBluetoothSdpCallbacks = {
64         sizeof(sBluetoothSdpCallbacks),
65         sdp_search_callback
66 };
67 
68 static jobject sCallbacksObj = NULL;
69 static JNIEnv *sCallbackEnv = NULL;
70 
checkCallbackThread()71 static bool checkCallbackThread() {
72     sCallbackEnv = getCallbackEnv();
73 
74     JNIEnv* env = AndroidRuntime::getJNIEnv();
75     if (sCallbackEnv != env || sCallbackEnv == NULL) {
76         ALOGE("Callback env check fail: env: %p, callback: %p", env, sCallbackEnv);
77         return false;
78     }
79     return true;
80 }
81 
initializeNative(JNIEnv * env,jobject object)82 static void initializeNative(JNIEnv *env, jobject object) {
83     const bt_interface_t* btInf;
84     bt_status_t status;
85 
86     if ( (btInf = getBluetoothInterface()) == NULL) {
87         ALOGE("Bluetooth module is not loaded");
88         return;
89     }
90     if (sBluetoothSdpInterface !=NULL) {
91          ALOGW("Cleaning up Bluetooth SDP Interface before initializing...");
92          sBluetoothSdpInterface->deinit();
93          sBluetoothSdpInterface = NULL;
94     }
95     if ( (sBluetoothSdpInterface = (btsdp_interface_t *)
96             btInf->get_profile_interface(BT_PROFILE_SDP_CLIENT_ID)) == NULL) {
97             ALOGE("Error getting SDP client interface");
98     }else{
99         sBluetoothSdpInterface->init(&sBluetoothSdpCallbacks);
100     }
101 
102     sCallbacksObj = env->NewGlobalRef(object);
103 }
104 
classInitNative(JNIEnv * env,jclass clazz)105 static void classInitNative(JNIEnv* env, jclass clazz) {
106 
107     /* generic SDP record (raw data)*/
108     method_sdpRecordFoundCallback = env->GetMethodID(clazz,
109                                                     "sdpRecordFoundCallback",
110                                                     "(I[B[BI[B)V");
111 
112     /* MAS SDP record*/
113     method_sdpMasRecordFoundCallback = env->GetMethodID(clazz,
114                                                     "sdpMasRecordFoundCallback",
115                                                     "(I[B[BIIIIIILjava/lang/String;Z)V");
116     /* MNS SDP record*/
117     method_sdpMnsRecordFoundCallback = env->GetMethodID(clazz,
118                                                     "sdpMnsRecordFoundCallback",
119                                                     "(I[B[BIIIILjava/lang/String;Z)V");
120     /* PBAP PSE record */
121     method_sdpPseRecordFoundCallback = env->GetMethodID(clazz,
122                                                     "sdpPseRecordFoundCallback",
123                                                     "(I[B[BIIIIILjava/lang/String;Z)V");
124     /* OPP Server record */
125     method_sdpOppOpsRecordFoundCallback = env->GetMethodID(clazz,
126                                                     "sdpOppOpsRecordFoundCallback",
127                                                     "(I[B[BIIILjava/lang/String;[BZ)V");
128     /* SAP Server record */
129     method_sdpSapsRecordFoundCallback = env->GetMethodID(clazz,
130                                                     "sdpSapsRecordFoundCallback",
131                                                     "(I[B[BIILjava/lang/String;Z)V");
132 
133 }
134 
sdpSearchNative(JNIEnv * env,jobject obj,jbyteArray address,jbyteArray uuidObj)135 static jboolean sdpSearchNative(JNIEnv *env, jobject obj, jbyteArray address, jbyteArray uuidObj) {
136     ALOGD("%s:",__FUNCTION__);
137 
138     jbyte *addr = NULL, *uuid = NULL;
139     jboolean result = JNI_FALSE;
140     int ret;
141     if (!sBluetoothSdpInterface)
142         goto Fail;
143 
144     addr = env->GetByteArrayElements(address, NULL);
145     if (addr == NULL) {
146         jniThrowIOException(env, EINVAL);
147         goto Fail;
148     }
149     uuid = env->GetByteArrayElements(uuidObj, NULL);
150     if (!uuid) {
151         ALOGE("failed to get uuid");
152         goto Fail;
153     }
154     ALOGD("%s UUID %.*X",__FUNCTION__,16, (uint8_t*)uuid);
155 
156 
157     if ((ret = sBluetoothSdpInterface->sdp_search((bt_bdaddr_t *)addr,
158                     (const uint8_t*)uuid)) != BT_STATUS_SUCCESS) {
159         ALOGE("SDP Search initialization failed: %d", ret);
160         goto Fail;
161     }
162 
163     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
164 
165     Fail:
166     if (addr) env->ReleaseByteArrayElements(address, addr, 0);
167     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
168     return result;
169 }
170 
sdp_search_callback(bt_status_t status,bt_bdaddr_t * bd_addr,uint8_t * uuid_in,int count,bluetooth_sdp_record * records)171 static void sdp_search_callback(bt_status_t status, bt_bdaddr_t *bd_addr, uint8_t* uuid_in,
172         int count, bluetooth_sdp_record* records)
173 {
174 
175     jbyteArray addr = NULL;
176     jbyteArray uuid = NULL;
177     jstring service_name = NULL;
178     int i = 0;
179     bluetooth_sdp_record* record;
180 
181     if (!checkCallbackThread()) {
182         ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
183         goto clean;
184     }
185 
186     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
187     if (addr == NULL) goto clean;
188 
189     uuid = sCallbackEnv->NewByteArray(sizeof(bt_uuid_t));
190     if (uuid == NULL) goto clean;
191 
192     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
193     sCallbackEnv->SetByteArrayRegion(uuid, 0, sizeof(bt_uuid_t), (jbyte*)uuid_in);
194 
195     ALOGD("%s: Status is: %d, Record count: %d", __FUNCTION__, status, count);
196 
197     // Ensure we run the loop at least once, to also signal errors if they occure
198     for(i = 0; i < count || i==0; i++) {
199         bool more_results = (i<(count-1))?true:false;
200         record = &records[i];
201         service_name = NULL;
202         if (record->hdr.service_name_length > 0) {
203             ALOGD("%s, ServiceName:  %s", __FUNCTION__, record->mas.hdr.service_name);
204             service_name = (jstring)sCallbackEnv->NewStringUTF(record->mas.hdr.service_name);
205         }
206 
207         /* call the right callback according to the uuid*/
208         if (IS_UUID(UUID_MAP_MAS,uuid_in)){
209 
210             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpMasRecordFoundCallback,
211                     (jint) status,
212                     addr,
213                     uuid,
214                     (jint)record->mas.mas_instance_id,
215                     (jint)record->mas.hdr.l2cap_psm,
216                     (jint)record->mas.hdr.rfcomm_channel_number,
217                     (jint)record->mas.hdr.profile_version,
218                     (jint)record->mas.supported_features,
219                     (jint)record->mas.supported_message_types,
220                     service_name,
221                     more_results);
222 
223         }else if (IS_UUID(UUID_MAP_MNS,uuid_in)){
224 
225             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpMnsRecordFoundCallback,
226                     (jint) status,
227                     addr,
228                     uuid,
229                     (jint)record->mns.hdr.l2cap_psm,
230                     (jint)record->mns.hdr.rfcomm_channel_number,
231                     (jint)record->mns.hdr.profile_version,
232                     (jint)record->mns.supported_features,
233                     service_name,
234                     more_results);
235 
236         } else if (IS_UUID(UUID_PBAP_PSE, uuid_in)) {
237 
238             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpPseRecordFoundCallback,
239                     (jint) status,
240                     addr,
241                     uuid,
242                     (jint)record->pse.hdr.l2cap_psm,
243                     (jint)record->pse.hdr.rfcomm_channel_number,
244                     (jint)record->pse.hdr.profile_version,
245                     (jint)record->pse.supported_features,
246                     (jint)record->pse.supported_repositories,
247                     service_name,
248                     more_results);
249 
250         } else if (IS_UUID(UUID_OBEX_OBJECT_PUSH, uuid_in)) {
251 
252             jint formats_list_size = record->ops.supported_formats_list_len;
253             jbyteArray formats_list = sCallbackEnv->NewByteArray(formats_list_size);
254             if (formats_list == NULL) goto clean;
255             sCallbackEnv->SetByteArrayRegion(formats_list, 0, formats_list_size,
256                     (jbyte*)record->ops.supported_formats_list);
257 
258             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpOppOpsRecordFoundCallback,
259                     (jint) status,
260                     addr,
261                     uuid,
262                     (jint)record->ops.hdr.l2cap_psm,
263                     (jint)record->ops.hdr.rfcomm_channel_number,
264                     (jint)record->ops.hdr.profile_version,
265                     service_name,
266                     formats_list,
267                     more_results);
268             sCallbackEnv->DeleteLocalRef(formats_list);
269 
270         } else if (IS_UUID(UUID_SAP, uuid_in)) {
271             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpSapsRecordFoundCallback,
272                     (jint) status,
273                     addr,
274                     uuid,
275                     (jint)record->mas.hdr.rfcomm_channel_number,
276                     (jint)record->mas.hdr.profile_version,
277                     service_name,
278                     more_results);
279         } else {
280             // we don't have a wrapper for this uuid, send as raw data
281             jint record_data_size = record->hdr.user1_ptr_len;
282             jbyteArray record_data = NULL;
283 
284             record_data = sCallbackEnv->NewByteArray(record_data_size);
285             if (record_data == NULL) goto clean;
286 
287             sCallbackEnv->SetByteArrayRegion(record_data, 0, record_data_size,
288                     (jbyte*)record->hdr.user1_ptr);
289             sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpRecordFoundCallback,
290                     (jint) status, addr, uuid, record_data_size, record_data);
291 
292             sCallbackEnv->DeleteLocalRef(record_data);
293 
294         }
295         // Cleanup for each iteration
296         if (service_name != NULL) {
297             sCallbackEnv->DeleteLocalRef(service_name);
298             service_name = NULL;
299         }
300     } // End of for-loop
301 
302     clean:
303     if (service_name != NULL)
304         sCallbackEnv->DeleteLocalRef(service_name);
305     if (addr != NULL) sCallbackEnv->DeleteLocalRef(addr);
306     if (uuid != NULL) sCallbackEnv->DeleteLocalRef(uuid);
307     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
308 }
309 
sdpCreateMapMasRecordNative(JNIEnv * env,jobject obj,jstring name_str,jint mas_id,jint scn,jint l2cap_psm,jint version,jint msg_types,jint features)310 static jint sdpCreateMapMasRecordNative(JNIEnv *env, jobject obj, jstring name_str, jint mas_id,
311                                          jint scn, jint l2cap_psm, jint version,
312                                          jint msg_types, jint features) {
313     ALOGD("%s:", __FUNCTION__);
314 
315     const char* service_name = NULL;
316     bluetooth_sdp_record record = {}; // Must be zero initialized
317     int handle=-1;
318     int ret = 0;
319     if (!sBluetoothSdpInterface) return handle;
320 
321     record.mas.hdr.type = SDP_TYPE_MAP_MAS;
322 
323     if (name_str != NULL) {
324         service_name = env->GetStringUTFChars(name_str, NULL);
325         record.mas.hdr.service_name = (char *) service_name;
326         record.mas.hdr.service_name_length = strlen(service_name);
327     } else {
328         record.mas.hdr.service_name = NULL;
329         record.mas.hdr.service_name_length = 0;
330     }
331     record.mas.hdr.rfcomm_channel_number = scn;
332     record.mas.hdr.l2cap_psm = l2cap_psm;
333     record.mas.hdr.profile_version = version;
334 
335     record.mas.mas_instance_id = mas_id;
336     record.mas.supported_features = features;
337     record.mas.supported_message_types = msg_types;
338 
339     if ( (ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle))
340             != BT_STATUS_SUCCESS) {
341         ALOGE("SDP Create record failed: %d", ret);
342         goto Fail;
343     }
344 
345     ALOGD("SDP Create record success - handle: %d", handle);
346 
347     Fail:
348     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
349     return handle;
350 }
351 
sdpCreateMapMnsRecordNative(JNIEnv * env,jobject obj,jstring name_str,jint scn,jint l2cap_psm,jint version,jint features)352 static jint sdpCreateMapMnsRecordNative(JNIEnv *env, jobject obj, jstring name_str,
353                                          jint scn, jint l2cap_psm, jint version,
354                                          jint features) {
355     ALOGD("%s:",__FUNCTION__);
356 
357     const char* service_name = NULL;
358     bluetooth_sdp_record record = {}; // Must be zero initialized
359     int handle=-1;
360     int ret = 0;
361     if (!sBluetoothSdpInterface) return handle;
362 
363     record.mns.hdr.type = SDP_TYPE_MAP_MNS;
364 
365     if (name_str != NULL) {
366         service_name = env->GetStringUTFChars(name_str, NULL);
367         record.mns.hdr.service_name = (char *) service_name;
368         record.mns.hdr.service_name_length = strlen(service_name);
369     } else {
370         record.mns.hdr.service_name = NULL;
371         record.mns.hdr.service_name_length = 0;
372     }
373     record.mns.hdr.rfcomm_channel_number = scn;
374     record.mns.hdr.l2cap_psm = l2cap_psm;
375     record.mns.hdr.profile_version = version;
376 
377     record.mns.supported_features = features;
378 
379     if ( (ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle))
380             != BT_STATUS_SUCCESS) {
381         ALOGE("SDP Create record failed: %d", ret);
382         goto Fail;
383     }
384 
385     ALOGD("SDP Create record success - handle: %d", handle);
386 
387     Fail:
388     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
389     return handle;
390 }
391 
sdpCreatePbapPseRecordNative(JNIEnv * env,jobject obj,jstring name_str,jint scn,jint l2cap_psm,jint version,jint supported_repositories,jint features)392 static jint sdpCreatePbapPseRecordNative(JNIEnv *env, jobject obj, jstring name_str,
393                                          jint scn, jint l2cap_psm, jint version,
394                                          jint supported_repositories, jint features) {
395     ALOGD("%s:",__FUNCTION__);
396 
397     const char* service_name = NULL;
398     bluetooth_sdp_record record = {}; // Must be zero initialized
399     int handle=-1;
400     int ret = 0;
401     if (!sBluetoothSdpInterface) return handle;
402 
403     record.pse.hdr.type = SDP_TYPE_PBAP_PSE;
404 
405     if (name_str != NULL) {
406         service_name = env->GetStringUTFChars(name_str, NULL);
407         record.pse.hdr.service_name = (char *) service_name;
408         record.pse.hdr.service_name_length = strlen(service_name);
409     } else {
410         record.pse.hdr.service_name = NULL;
411         record.pse.hdr.service_name_length = 0;
412     }
413     record.pse.hdr.rfcomm_channel_number = scn;
414     record.pse.hdr.l2cap_psm = l2cap_psm;
415     record.pse.hdr.profile_version = version;
416 
417     record.pse.supported_features = features;
418     record.pse.supported_repositories = supported_repositories;
419 
420     if ( (ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle))
421             != BT_STATUS_SUCCESS) {
422         ALOGE("SDP Create record failed: %d", ret);
423         goto Fail;
424     }
425 
426     ALOGD("SDP Create record success - handle: %d", handle);
427 
428     Fail:
429     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
430     return handle;
431 }
432 
sdpCreateOppOpsRecordNative(JNIEnv * env,jobject obj,jstring name_str,jint scn,jint l2cap_psm,jint version,jbyteArray supported_formats_list)433 static jint sdpCreateOppOpsRecordNative(JNIEnv *env, jobject obj, jstring name_str,
434                                          jint scn, jint l2cap_psm, jint version,
435                                          jbyteArray supported_formats_list) {
436     ALOGD("%s:",__FUNCTION__);
437 
438     const char* service_name = NULL;
439     bluetooth_sdp_record record = {}; // Must be zero initialized
440     jbyte* formats_list;
441     int formats_list_len = 0;
442     int handle=-1;
443     int ret = 0;
444     if (!sBluetoothSdpInterface) return handle;
445 
446     record.ops.hdr.type = SDP_TYPE_OPP_SERVER;
447 
448     if (name_str != NULL) {
449         service_name = env->GetStringUTFChars(name_str, NULL);
450         record.ops.hdr.service_name = (char *) service_name;
451         record.ops.hdr.service_name_length = strlen(service_name);
452     } else {
453         record.ops.hdr.service_name = NULL;
454         record.ops.hdr.service_name_length = 0;
455     }
456     record.ops.hdr.rfcomm_channel_number = scn;
457     record.ops.hdr.l2cap_psm = l2cap_psm;
458     record.ops.hdr.profile_version = version;
459 
460     formats_list = env->GetByteArrayElements(supported_formats_list, NULL);
461     if (formats_list != NULL) {
462         formats_list_len = env->GetArrayLength(supported_formats_list);
463         if (formats_list_len > SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH) {
464             formats_list_len = SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH;
465         }
466         memcpy(record.ops.supported_formats_list, formats_list, formats_list_len);
467     }
468 
469     record.ops.supported_formats_list_len = formats_list_len;
470 
471     if ( (ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle))
472             != BT_STATUS_SUCCESS) {
473         ALOGE("SDP Create record failed: %d", ret);
474         goto Fail;
475     }
476 
477     ALOGD("SDP Create record success - handle: %d", handle);
478 
479     Fail:
480     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
481     if (formats_list) env->ReleaseByteArrayElements(supported_formats_list, formats_list, 0);
482     return handle;
483 }
484 
sdpCreateSapsRecordNative(JNIEnv * env,jobject obj,jstring name_str,jint scn,jint version)485 static jint sdpCreateSapsRecordNative(JNIEnv *env, jobject obj, jstring name_str,
486                                          jint scn, jint version) {
487     ALOGD("%s:",__FUNCTION__);
488 
489     const char* service_name = NULL;
490     bluetooth_sdp_record record = {}; // Must be zero initialized
491     int handle = -1;
492     int ret = 0;
493     if (!sBluetoothSdpInterface) return handle;
494 
495     record.sap.hdr.type = SDP_TYPE_SAP_SERVER;
496 
497     if (name_str != NULL) {
498         service_name = env->GetStringUTFChars(name_str, NULL);
499         record.mas.hdr.service_name = (char *) service_name;
500         record.mas.hdr.service_name_length = strlen(service_name);
501     } else {
502         record.mas.hdr.service_name = NULL;
503         record.mas.hdr.service_name_length = 0;
504     }
505     record.mas.hdr.rfcomm_channel_number = scn;
506     record.mas.hdr.profile_version = version;
507 
508     if ( (ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle))
509             != BT_STATUS_SUCCESS) {
510         ALOGE("SDP Create record failed: %d", ret);
511         goto Fail;
512     }
513 
514     ALOGD("SDP Create record success - handle: %d", handle);
515 
516     Fail:
517     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
518     return handle;
519 }
520 
sdpRemoveSdpRecordNative(JNIEnv * env,jobject obj,jint record_id)521 static jboolean sdpRemoveSdpRecordNative(JNIEnv *env, jobject obj, jint record_id) {
522     ALOGD("%s:",__FUNCTION__);
523 
524     int ret = 0;
525     if (!sBluetoothSdpInterface) return false;
526 
527     if ( (ret = sBluetoothSdpInterface->remove_sdp_record(record_id))
528             != BT_STATUS_SUCCESS) {
529         ALOGE("SDP Remove record failed: %d", ret);
530         return false;
531     }
532 
533     ALOGD("SDP Remove record success - handle: %d", record_id);
534     return true;
535 }
536 
537 
cleanupNative(JNIEnv * env,jobject object)538 static void cleanupNative(JNIEnv *env, jobject object) {
539     const bt_interface_t* btInf;
540     bt_status_t status;
541 
542     if ( (btInf = getBluetoothInterface()) == NULL) {
543         ALOGE("Bluetooth module is not loaded");
544         return;
545     }
546 
547     if (sBluetoothSdpInterface !=NULL) {
548         ALOGW("Cleaning up Bluetooth SDP Interface...");
549         sBluetoothSdpInterface->deinit();
550         sBluetoothSdpInterface = NULL;
551     }
552 
553     if (sCallbacksObj != NULL) {
554         ALOGW("Cleaning up Bluetooth Health object");
555         env->DeleteGlobalRef(sCallbacksObj);
556         sCallbacksObj = NULL;
557     }
558 }
559 
560 static JNINativeMethod sMethods[] = {
561     /* name, signature, funcPtr */
562     {"classInitNative", "()V", (void *) classInitNative},
563     {"initializeNative", "()V", (void *) initializeNative},
564     {"cleanupNative", "()V", (void*) cleanupNative},
565     {"sdpSearchNative", "([B[B)Z", (void*) sdpSearchNative},
566     {"sdpCreateMapMasRecordNative", "(Ljava/lang/String;IIIIII)I",
567         (void*) sdpCreateMapMasRecordNative},
568     {"sdpCreateMapMnsRecordNative", "(Ljava/lang/String;IIII)I",
569         (void*) sdpCreateMapMnsRecordNative},
570     {"sdpCreatePbapPseRecordNative", "(Ljava/lang/String;IIIII)I",
571         (void*) sdpCreatePbapPseRecordNative},
572     {"sdpCreateOppOpsRecordNative", "(Ljava/lang/String;III[B)I",
573         (void*) sdpCreateOppOpsRecordNative},
574     {"sdpCreateSapsRecordNative", "(Ljava/lang/String;II)I",
575         (void*) sdpCreateSapsRecordNative},
576     {"sdpRemoveSdpRecordNative", "(I)Z", (void*) sdpRemoveSdpRecordNative}
577 };
578 
register_com_android_bluetooth_sdp(JNIEnv * env)579 int register_com_android_bluetooth_sdp(JNIEnv* env)
580 {
581     return jniRegisterNativeMethods(env, "com/android/bluetooth/sdp/SdpManager",
582                                     sMethods, NELEM(sMethods));
583 }
584 
585 
586 }
587