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_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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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