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