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 #include <bluetooth/log.h>
20 #include <jni.h>
21 #include <nativehelper/JNIHelp.h>
22 #include <nativehelper/scoped_local_ref.h>
23
24 #include <cerrno>
25 #include <cstdint>
26 #include <cstring>
27
28 #include "com_android_bluetooth.h"
29 #include "hardware/bluetooth.h"
30 #include "hardware/bt_sdp.h"
31 #include "types/bluetooth/uuid.h"
32 #include "types/raw_address.h"
33
34 using bluetooth::Uuid;
35
36 static const Uuid UUID_OBEX_OBJECT_PUSH = Uuid::From16Bit(0x1105);
37 static const Uuid UUID_PBAP_PSE = Uuid::From16Bit(0x112F);
38 static const Uuid UUID_MAP_MAS = Uuid::From16Bit(0x1132);
39 static const Uuid UUID_MAP_MNS = Uuid::From16Bit(0x1133);
40 static const Uuid UUID_SAP = Uuid::From16Bit(0x112D);
41 static const Uuid UUID_DIP = Uuid::From16Bit(0x1200);
42
43 namespace android {
44 static jmethodID method_sdpRecordFoundCallback;
45 static jmethodID method_sdpMasRecordFoundCallback;
46 static jmethodID method_sdpMnsRecordFoundCallback;
47 static jmethodID method_sdpPseRecordFoundCallback;
48 static jmethodID method_sdpOppOpsRecordFoundCallback;
49 static jmethodID method_sdpSapsRecordFoundCallback;
50 static jmethodID method_sdpDipRecordFoundCallback;
51
52 static const btsdp_interface_t* sBluetoothSdpInterface = NULL;
53
54 static void sdp_search_callback(bt_status_t status, const RawAddress& bd_addr, const Uuid& uuid_in,
55 int record_size, bluetooth_sdp_record* record);
56
57 btsdp_callbacks_t sBluetoothSdpCallbacks = {sizeof(sBluetoothSdpCallbacks), sdp_search_callback};
58
59 static jobject sCallbacksObj = NULL;
60
initializeNative(JNIEnv * env,jobject object)61 static void initializeNative(JNIEnv* env, jobject object) {
62 const bt_interface_t* btInf = getBluetoothInterface();
63
64 if (btInf == NULL) {
65 log::error("Bluetooth module is not loaded");
66 return;
67 }
68 if (sBluetoothSdpInterface != NULL) {
69 log::warn("Cleaning up Bluetooth SDP Interface before initializing...");
70 sBluetoothSdpInterface->deinit();
71 sBluetoothSdpInterface = NULL;
72 }
73
74 sBluetoothSdpInterface =
75 (btsdp_interface_t*)btInf->get_profile_interface(BT_PROFILE_SDP_CLIENT_ID);
76 if (sBluetoothSdpInterface == NULL) {
77 log::error("Error getting SDP client interface");
78 } else {
79 sBluetoothSdpInterface->init(&sBluetoothSdpCallbacks);
80 }
81
82 sCallbacksObj = env->NewGlobalRef(object);
83 }
84
sdpSearchNative(JNIEnv * env,jobject,jbyteArray address,jbyteArray uuidObj)85 static jboolean sdpSearchNative(JNIEnv* env, jobject /* obj */, jbyteArray address,
86 jbyteArray uuidObj) {
87 log::debug("");
88
89 if (!sBluetoothSdpInterface) {
90 return JNI_FALSE;
91 }
92
93 jbyte* addr = env->GetByteArrayElements(address, NULL);
94 if (addr == NULL) {
95 jniThrowIOException(env, EINVAL);
96 return JNI_FALSE;
97 }
98
99 jbyte* raw_uuid = env->GetByteArrayElements(uuidObj, NULL);
100 if (!raw_uuid) {
101 log::error("failed to get uuid");
102 env->ReleaseByteArrayElements(address, addr, 0);
103 return JNI_FALSE;
104 }
105 Uuid uuid = Uuid::From128BitBE((uint8_t*)raw_uuid);
106 log::debug("UUID {}", uuid);
107
108 int ret = sBluetoothSdpInterface->sdp_search((RawAddress*)addr, uuid);
109 if (ret != BT_STATUS_SUCCESS) {
110 log::error("SDP Search initialization failed: {}", ret);
111 }
112
113 if (addr) {
114 env->ReleaseByteArrayElements(address, addr, 0);
115 }
116 if (raw_uuid) {
117 env->ReleaseByteArrayElements(uuidObj, raw_uuid, 0);
118 }
119 return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
120 }
121
sdp_search_callback(bt_status_t status,const RawAddress & bd_addr,const Uuid & uuid_in,int count,bluetooth_sdp_record * records)122 static void sdp_search_callback(bt_status_t status, const RawAddress& bd_addr, const Uuid& uuid_in,
123 int count, bluetooth_sdp_record* records) {
124 CallbackEnv sCallbackEnv(__func__);
125 if (!sCallbackEnv.valid()) {
126 return;
127 }
128
129 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
130 sCallbackEnv->NewByteArray(sizeof(RawAddress)));
131 if (!addr.get()) {
132 return;
133 }
134
135 ScopedLocalRef<jbyteArray> uuid(sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(Uuid)));
136 if (!uuid.get()) {
137 return;
138 }
139
140 sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (const jbyte*)&bd_addr);
141 sCallbackEnv->SetByteArrayRegion(uuid.get(), 0, sizeof(Uuid),
142 (const jbyte*)uuid_in.To128BitBE().data());
143
144 log::debug("Status is: {}, Record count: {}", bt_status_text(status), count);
145
146 // Ensure we run the loop at least once, to also signal errors if they occur
147 for (int i = 0; i < count || i == 0; i++) {
148 bool more_results = (i < (count - 1)) ? true : false;
149 bluetooth_sdp_record* record = &records[i];
150 ScopedLocalRef<jstring> service_name(sCallbackEnv.get(), NULL);
151 if (record->hdr.service_name_length > 0) {
152 log::debug("ServiceName: {}", record->mas.hdr.service_name);
153 service_name.reset((jstring)sCallbackEnv->NewStringUTF(record->mas.hdr.service_name));
154 }
155
156 /* call the right callback according to the uuid*/
157 if (uuid_in == UUID_MAP_MAS) {
158 sCallbackEnv->CallVoidMethod(
159 sCallbacksObj, method_sdpMasRecordFoundCallback, (jint)status, addr.get(), uuid.get(),
160 (jint)record->mas.mas_instance_id, (jint)record->mas.hdr.l2cap_psm,
161 (jint)record->mas.hdr.rfcomm_channel_number, (jint)record->mas.hdr.profile_version,
162 (jint)record->mas.supported_features, (jint)record->mas.supported_message_types,
163 service_name.get(), more_results);
164
165 } else if (uuid_in == UUID_MAP_MNS) {
166 sCallbackEnv->CallVoidMethod(
167 sCallbacksObj, method_sdpMnsRecordFoundCallback, (jint)status, addr.get(), uuid.get(),
168 (jint)record->mns.hdr.l2cap_psm, (jint)record->mns.hdr.rfcomm_channel_number,
169 (jint)record->mns.hdr.profile_version, (jint)record->mns.supported_features,
170 service_name.get(), more_results);
171
172 } else if (uuid_in == UUID_PBAP_PSE) {
173 sCallbackEnv->CallVoidMethod(
174 sCallbacksObj, method_sdpPseRecordFoundCallback, (jint)status, addr.get(), uuid.get(),
175 (jint)record->pse.hdr.l2cap_psm, (jint)record->pse.hdr.rfcomm_channel_number,
176 (jint)record->pse.hdr.profile_version, (jint)record->pse.supported_features,
177 (jint)record->pse.supported_repositories, service_name.get(), more_results);
178
179 } else if (uuid_in == UUID_OBEX_OBJECT_PUSH) {
180 jint formats_list_size = record->ops.supported_formats_list_len;
181 ScopedLocalRef<jbyteArray> formats_list(sCallbackEnv.get(),
182 sCallbackEnv->NewByteArray(formats_list_size));
183 if (!formats_list.get()) {
184 return;
185 }
186 sCallbackEnv->SetByteArrayRegion(formats_list.get(), 0, formats_list_size,
187 (jbyte*)record->ops.supported_formats_list);
188
189 sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpOppOpsRecordFoundCallback, (jint)status,
190 addr.get(), uuid.get(), (jint)record->ops.hdr.l2cap_psm,
191 (jint)record->ops.hdr.rfcomm_channel_number,
192 (jint)record->ops.hdr.profile_version, service_name.get(),
193 formats_list.get(), more_results);
194
195 } else if (uuid_in == UUID_SAP) {
196 sCallbackEnv->CallVoidMethod(
197 sCallbacksObj, method_sdpSapsRecordFoundCallback, (jint)status, addr.get(),
198 uuid.get(), (jint)record->mas.hdr.rfcomm_channel_number,
199 (jint)record->mas.hdr.profile_version, service_name.get(), more_results);
200 } else if (uuid_in == UUID_DIP) {
201 log::debug("Get UUID_DIP");
202 sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpDipRecordFoundCallback, (jint)status,
203 addr.get(), uuid.get(), (jint)record->dip.spec_id,
204 (jint)record->dip.vendor, (jint)record->dip.vendor_id_source,
205 (jint)record->dip.product, (jint)record->dip.version,
206 record->dip.primary_record, more_results);
207 } else {
208 // we don't have a wrapper for this uuid, send as raw data
209 jint record_data_size = record->hdr.user1_ptr_len;
210 ScopedLocalRef<jbyteArray> record_data(sCallbackEnv.get(),
211 sCallbackEnv->NewByteArray(record_data_size));
212 if (!record_data.get()) {
213 return;
214 }
215
216 sCallbackEnv->SetByteArrayRegion(record_data.get(), 0, record_data_size,
217 (jbyte*)record->hdr.user1_ptr);
218 sCallbackEnv->CallVoidMethod(sCallbacksObj, method_sdpRecordFoundCallback, (jint)status,
219 addr.get(), uuid.get(), record_data_size, record_data.get());
220 }
221 } // End of for-loop
222 }
223
sdpCreateMapMasRecordNative(JNIEnv * env,jobject,jstring name_str,jint mas_id,jint scn,jint l2cap_psm,jint version,jint msg_types,jint features)224 static jint sdpCreateMapMasRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str,
225 jint mas_id, jint scn, jint l2cap_psm, jint version,
226 jint msg_types, jint features) {
227 log::debug("");
228 if (!sBluetoothSdpInterface) {
229 return -1;
230 }
231
232 bluetooth_sdp_record record = {}; // Must be zero initialized
233 record.mas.hdr.type = SDP_TYPE_MAP_MAS;
234
235 const char* service_name = NULL;
236 if (name_str != NULL) {
237 service_name = env->GetStringUTFChars(name_str, NULL);
238 record.mas.hdr.service_name = (char*)service_name;
239 record.mas.hdr.service_name_length = strlen(service_name);
240 } else {
241 record.mas.hdr.service_name = NULL;
242 record.mas.hdr.service_name_length = 0;
243 }
244 record.mas.hdr.rfcomm_channel_number = scn;
245 record.mas.hdr.l2cap_psm = l2cap_psm;
246 record.mas.hdr.profile_version = version;
247
248 record.mas.mas_instance_id = mas_id;
249 record.mas.supported_features = features;
250 record.mas.supported_message_types = msg_types;
251
252 int handle = -1;
253 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
254 if (ret != BT_STATUS_SUCCESS) {
255 log::error("SDP Create record failed: {}", ret);
256 } else {
257 log::debug("SDP Create record success - handle: {}", handle);
258 }
259
260 if (service_name) {
261 env->ReleaseStringUTFChars(name_str, service_name);
262 }
263 return handle;
264 }
265
sdpCreateMapMnsRecordNative(JNIEnv * env,jobject,jstring name_str,jint scn,jint l2cap_psm,jint version,jint features)266 static jint sdpCreateMapMnsRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str, jint scn,
267 jint l2cap_psm, jint version, jint features) {
268 log::debug("");
269 if (!sBluetoothSdpInterface) {
270 return -1;
271 }
272
273 bluetooth_sdp_record record = {}; // Must be zero initialized
274 record.mns.hdr.type = SDP_TYPE_MAP_MNS;
275
276 const char* service_name = NULL;
277 if (name_str != NULL) {
278 service_name = env->GetStringUTFChars(name_str, NULL);
279 record.mns.hdr.service_name = (char*)service_name;
280 record.mns.hdr.service_name_length = strlen(service_name);
281 } else {
282 record.mns.hdr.service_name = NULL;
283 record.mns.hdr.service_name_length = 0;
284 }
285 record.mns.hdr.rfcomm_channel_number = scn;
286 record.mns.hdr.l2cap_psm = l2cap_psm;
287 record.mns.hdr.profile_version = version;
288
289 record.mns.supported_features = features;
290
291 int handle = -1;
292 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
293 if (ret != BT_STATUS_SUCCESS) {
294 log::error("SDP Create record failed: {}", ret);
295 } else {
296 log::debug("SDP Create record success - handle: {}", handle);
297 }
298
299 if (service_name) {
300 env->ReleaseStringUTFChars(name_str, service_name);
301 }
302 return handle;
303 }
304
sdpCreatePbapPceRecordNative(JNIEnv * env,jobject,jstring name_str,jint version)305 static jint sdpCreatePbapPceRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str,
306 jint version) {
307 log::debug("");
308 if (!sBluetoothSdpInterface) {
309 return -1;
310 }
311
312 bluetooth_sdp_record record = {}; // Must be zero initialized
313 record.pce.hdr.type = SDP_TYPE_PBAP_PCE;
314
315 const char* service_name = NULL;
316 if (name_str != NULL) {
317 service_name = env->GetStringUTFChars(name_str, NULL);
318 record.pce.hdr.service_name = (char*)service_name;
319 record.pce.hdr.service_name_length = strlen(service_name);
320 } else {
321 record.pce.hdr.service_name = NULL;
322 record.pce.hdr.service_name_length = 0;
323 }
324 record.pce.hdr.profile_version = version;
325
326 int handle = -1;
327 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
328 if (ret != BT_STATUS_SUCCESS) {
329 log::error("SDP Create record failed: {}", ret);
330 } else {
331 log::debug("SDP Create record success - handle: {}", handle);
332 }
333
334 if (service_name) {
335 env->ReleaseStringUTFChars(name_str, service_name);
336 }
337 return handle;
338 }
339
sdpCreatePbapPseRecordNative(JNIEnv * env,jobject,jstring name_str,jint scn,jint l2cap_psm,jint version,jint supported_repositories,jint features)340 static jint sdpCreatePbapPseRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str, jint scn,
341 jint l2cap_psm, jint version, jint supported_repositories,
342 jint features) {
343 log::debug("");
344 if (!sBluetoothSdpInterface) {
345 return -1;
346 }
347
348 bluetooth_sdp_record record = {}; // Must be zero initialized
349 record.pse.hdr.type = SDP_TYPE_PBAP_PSE;
350
351 const char* service_name = NULL;
352 if (name_str != NULL) {
353 service_name = env->GetStringUTFChars(name_str, NULL);
354 record.pse.hdr.service_name = (char*)service_name;
355 record.pse.hdr.service_name_length = strlen(service_name);
356 } else {
357 record.pse.hdr.service_name = NULL;
358 record.pse.hdr.service_name_length = 0;
359 }
360 record.pse.hdr.rfcomm_channel_number = scn;
361 record.pse.hdr.l2cap_psm = l2cap_psm;
362 record.pse.hdr.profile_version = version;
363
364 record.pse.supported_features = features;
365 record.pse.supported_repositories = supported_repositories;
366
367 int handle = -1;
368 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
369 if (ret != BT_STATUS_SUCCESS) {
370 log::error("SDP Create record failed: {}", ret);
371 } else {
372 log::debug("SDP Create record success - handle: {}", handle);
373 }
374
375 if (service_name) {
376 env->ReleaseStringUTFChars(name_str, service_name);
377 }
378 return handle;
379 }
380
sdpCreateOppOpsRecordNative(JNIEnv * env,jobject,jstring name_str,jint scn,jint l2cap_psm,jint version,jbyteArray supported_formats_list)381 static jint sdpCreateOppOpsRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str, jint scn,
382 jint l2cap_psm, jint version,
383 jbyteArray supported_formats_list) {
384 log::debug("");
385 if (!sBluetoothSdpInterface) {
386 return -1;
387 }
388
389 bluetooth_sdp_record record = {}; // Must be zero initialized
390 record.ops.hdr.type = SDP_TYPE_OPP_SERVER;
391
392 const char* service_name = NULL;
393 if (name_str != NULL) {
394 service_name = env->GetStringUTFChars(name_str, NULL);
395 record.ops.hdr.service_name = (char*)service_name;
396 record.ops.hdr.service_name_length = strlen(service_name);
397 } else {
398 record.ops.hdr.service_name = NULL;
399 record.ops.hdr.service_name_length = 0;
400 }
401 record.ops.hdr.rfcomm_channel_number = scn;
402 record.ops.hdr.l2cap_psm = l2cap_psm;
403 record.ops.hdr.profile_version = version;
404
405 int formats_list_len = 0;
406 jbyte* formats_list = env->GetByteArrayElements(supported_formats_list, NULL);
407 if (formats_list != NULL) {
408 formats_list_len = env->GetArrayLength(supported_formats_list);
409 if (formats_list_len > SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH) {
410 formats_list_len = SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH;
411 }
412 memcpy(record.ops.supported_formats_list, formats_list, formats_list_len);
413 }
414
415 record.ops.supported_formats_list_len = formats_list_len;
416
417 int handle = -1;
418 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
419 if (ret != BT_STATUS_SUCCESS) {
420 log::error("SDP Create record failed: {}", ret);
421 } else {
422 log::debug("SDP Create record success - handle: {}", handle);
423 }
424
425 if (service_name) {
426 env->ReleaseStringUTFChars(name_str, service_name);
427 }
428 if (formats_list) {
429 env->ReleaseByteArrayElements(supported_formats_list, formats_list, 0);
430 }
431 return handle;
432 }
433
sdpCreateSapsRecordNative(JNIEnv * env,jobject,jstring name_str,jint scn,jint version)434 static jint sdpCreateSapsRecordNative(JNIEnv* env, jobject /* obj */, jstring name_str, jint scn,
435 jint version) {
436 log::debug("");
437 if (!sBluetoothSdpInterface) {
438 return -1;
439 }
440
441 bluetooth_sdp_record record = {}; // Must be zero initialized
442 record.sap.hdr.type = SDP_TYPE_SAP_SERVER;
443
444 const char* service_name = NULL;
445 if (name_str != NULL) {
446 service_name = env->GetStringUTFChars(name_str, NULL);
447 record.mas.hdr.service_name = (char*)service_name;
448 record.mas.hdr.service_name_length = strlen(service_name);
449 } else {
450 record.mas.hdr.service_name = NULL;
451 record.mas.hdr.service_name_length = 0;
452 }
453 record.mas.hdr.rfcomm_channel_number = scn;
454 record.mas.hdr.profile_version = version;
455
456 int handle = -1;
457 int ret = sBluetoothSdpInterface->create_sdp_record(&record, &handle);
458 if (ret != BT_STATUS_SUCCESS) {
459 log::error("SDP Create record failed: {}", ret);
460 } else {
461 log::debug("SDP Create record success - handle: {}", handle);
462 }
463
464 if (service_name) {
465 env->ReleaseStringUTFChars(name_str, service_name);
466 }
467 return handle;
468 }
469
sdpRemoveSdpRecordNative(JNIEnv *,jobject,jint record_id)470 static jboolean sdpRemoveSdpRecordNative(JNIEnv* /* env */, jobject /* obj */, jint record_id) {
471 log::debug("");
472 if (!sBluetoothSdpInterface) {
473 return false;
474 }
475
476 int ret = sBluetoothSdpInterface->remove_sdp_record(record_id);
477 if (ret != BT_STATUS_SUCCESS) {
478 log::error("SDP Remove record failed: {}", ret);
479 return false;
480 }
481
482 log::debug("SDP Remove record success - handle: {}", record_id);
483 return true;
484 }
485
cleanupNative(JNIEnv * env,jobject)486 static void cleanupNative(JNIEnv* env, jobject /* object */) {
487 const bt_interface_t* btInf = getBluetoothInterface();
488
489 if (btInf == NULL) {
490 log::error("Bluetooth module is not loaded");
491 return;
492 }
493
494 if (sBluetoothSdpInterface != NULL) {
495 log::warn("Cleaning up Bluetooth SDP Interface...");
496 sBluetoothSdpInterface->deinit();
497 sBluetoothSdpInterface = NULL;
498 }
499
500 if (sCallbacksObj != NULL) {
501 log::warn("Cleaning up Bluetooth SDP object");
502 env->DeleteGlobalRef(sCallbacksObj);
503 sCallbacksObj = NULL;
504 }
505 }
506
register_com_android_bluetooth_sdp(JNIEnv * env)507 int register_com_android_bluetooth_sdp(JNIEnv* env) {
508 const JNINativeMethod methods[] = {
509 {"initializeNative", "()V", (void*)initializeNative},
510 {"cleanupNative", "()V", (void*)cleanupNative},
511 {"sdpSearchNative", "([B[B)Z", (void*)sdpSearchNative},
512 {"sdpCreateMapMasRecordNative", "(Ljava/lang/String;IIIIII)I",
513 (void*)sdpCreateMapMasRecordNative},
514 {"sdpCreateMapMnsRecordNative", "(Ljava/lang/String;IIII)I",
515 (void*)sdpCreateMapMnsRecordNative},
516 {"sdpCreatePbapPceRecordNative", "(Ljava/lang/String;I)I",
517 (void*)sdpCreatePbapPceRecordNative},
518 {"sdpCreatePbapPseRecordNative", "(Ljava/lang/String;IIIII)I",
519 (void*)sdpCreatePbapPseRecordNative},
520 {"sdpCreateOppOpsRecordNative", "(Ljava/lang/String;III[B)I",
521 (void*)sdpCreateOppOpsRecordNative},
522 {"sdpCreateSapsRecordNative", "(Ljava/lang/String;II)I",
523 (void*)sdpCreateSapsRecordNative},
524 {"sdpRemoveSdpRecordNative", "(I)Z", (void*)sdpRemoveSdpRecordNative},
525 };
526 const int result = REGISTER_NATIVE_METHODS(
527 env, "com/android/bluetooth/sdp/SdpManagerNativeInterface", methods);
528 if (result != 0) {
529 return result;
530 }
531
532 const JNIJavaMethod javaMethods[] = {
533 {"sdpRecordFoundCallback", "(I[B[BI[B)V", &method_sdpRecordFoundCallback},
534 {"sdpMasRecordFoundCallback", "(I[B[BIIIIIILjava/lang/String;Z)V",
535 &method_sdpMasRecordFoundCallback},
536 {"sdpMnsRecordFoundCallback", "(I[B[BIIIILjava/lang/String;Z)V",
537 &method_sdpMnsRecordFoundCallback},
538 {"sdpPseRecordFoundCallback", "(I[B[BIIIIILjava/lang/String;Z)V",
539 &method_sdpPseRecordFoundCallback},
540 {"sdpOppOpsRecordFoundCallback", "(I[B[BIIILjava/lang/String;[BZ)V",
541 &method_sdpOppOpsRecordFoundCallback},
542 {"sdpSapsRecordFoundCallback", "(I[B[BIILjava/lang/String;Z)V",
543 &method_sdpSapsRecordFoundCallback},
544 {"sdpDipRecordFoundCallback", "(I[B[BIIIIIZZ)V", &method_sdpDipRecordFoundCallback},
545 };
546 GET_JAVA_METHODS(env, "com/android/bluetooth/sdp/SdpManagerNativeInterface", javaMethods);
547
548 return 0;
549 }
550 } // namespace android
551