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