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