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