Home | History | Annotate | Download | only in jni
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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