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