1 /*
2 * Copyright (C) 2012 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 "BluetoothServiceJni"
18 #include "com_android_bluetooth.h"
19 #include "hardware/bt_sock.h"
20 #include "utils/Log.h"
21 #include "utils/misc.h"
22 #include "cutils/properties.h"
23 #include "android_runtime/AndroidRuntime.h"
24 #include "android_runtime/Log.h"
25
26 #include <string.h>
27 #include <pthread.h>
28
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32 namespace android {
33
34 #define ADDITIONAL_NREFS 50
35 static jmethodID method_stateChangeCallback;
36 static jmethodID method_adapterPropertyChangedCallback;
37 static jmethodID method_devicePropertyChangedCallback;
38 static jmethodID method_deviceFoundCallback;
39 static jmethodID method_pinRequestCallback;
40 static jmethodID method_sspRequestCallback;
41 static jmethodID method_bondStateChangeCallback;
42 static jmethodID method_aclStateChangeCallback;
43 static jmethodID method_discoveryStateChangeCallback;
44
45 static const bt_interface_t *sBluetoothInterface = NULL;
46 static const btsock_interface_t *sBluetoothSocketInterface = NULL;
47 static JNIEnv *callbackEnv = NULL;
48
49 static jobject sJniCallbacksObj;
50 static jfieldID sJniCallbacksField;
51
52
getBluetoothInterface()53 const bt_interface_t* getBluetoothInterface() {
54 return sBluetoothInterface;
55 }
56
getCallbackEnv()57 JNIEnv* getCallbackEnv() {
58 return callbackEnv;
59 }
60
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)61 void checkAndClearExceptionFromCallback(JNIEnv* env,
62 const char* methodName) {
63 if (env->ExceptionCheck()) {
64 ALOGE("An exception was thrown by callback '%s'.", methodName);
65 LOGE_EX(env);
66 env->ExceptionClear();
67 }
68 }
69
checkCallbackThread()70 static bool checkCallbackThread() {
71 JNIEnv* env = AndroidRuntime::getJNIEnv();
72 if (callbackEnv != env || callbackEnv == NULL) {
73 ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
74 return false;
75 }
76 return true;
77 }
78
adapter_state_change_callback(bt_state_t status)79 static void adapter_state_change_callback(bt_state_t status) {
80 if (!checkCallbackThread()) {
81 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
82 return;
83 }
84 ALOGV("%s: Status is: %d", __FUNCTION__, status);
85
86 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
87
88 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
89 }
90
get_properties(int num_properties,bt_property_t * properties,jintArray * types,jobjectArray * props)91 static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
92 jobjectArray *props) {
93 jbyteArray propVal;
94 for (int i = 0; i < num_properties; i++) {
95 propVal = callbackEnv->NewByteArray(properties[i].len);
96 if (propVal == NULL) goto Fail;
97
98 callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
99 (jbyte*)properties[i].val);
100 callbackEnv->SetObjectArrayElement(*props, i, propVal);
101 // Delete reference to propVal
102 callbackEnv->DeleteLocalRef(propVal);
103 callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
104 }
105 return 0;
106 Fail:
107 if (propVal) callbackEnv->DeleteLocalRef(propVal);
108 ALOGE("Error while allocation of array in %s", __FUNCTION__);
109 return -1;
110 }
111
adapter_properties_callback(bt_status_t status,int num_properties,bt_property_t * properties)112 static void adapter_properties_callback(bt_status_t status, int num_properties,
113 bt_property_t *properties) {
114 jobjectArray props;
115 jintArray types;
116 jbyteArray val;
117 jclass mclass;
118
119 if (!checkCallbackThread()) {
120 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
121 return;
122 }
123
124 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
125
126 if (status != BT_STATUS_SUCCESS) {
127 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
128 return;
129 }
130
131 val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
132 if (val == NULL) {
133 ALOGE("%s: Error allocating byteArray", __FUNCTION__);
134 return;
135 }
136
137 mclass = callbackEnv->GetObjectClass(val);
138
139 /* (BT) Initialize the jobjectArray and jintArray here itself and send the
140 initialized array pointers alone to get_properties */
141
142 props = callbackEnv->NewObjectArray(num_properties, mclass,
143 NULL);
144 if (props == NULL) {
145 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
146 return;
147 }
148
149 types = (jintArray)callbackEnv->NewIntArray(num_properties);
150
151 if (types == NULL) {
152 ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
153 return;
154 }
155 // Delete the reference to val and mclass
156 callbackEnv->DeleteLocalRef(mclass);
157 callbackEnv->DeleteLocalRef(val);
158
159 if (get_properties(num_properties, properties, &types, &props) < 0) {
160 if (props) callbackEnv->DeleteLocalRef(props);
161 if (types) callbackEnv->DeleteLocalRef(types);
162 return;
163 }
164
165 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
166 props);
167 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
168 callbackEnv->DeleteLocalRef(props);
169 callbackEnv->DeleteLocalRef(types);
170 return;
171
172 }
173
remote_device_properties_callback(bt_status_t status,bt_bdaddr_t * bd_addr,int num_properties,bt_property_t * properties)174 static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
175 int num_properties, bt_property_t *properties) {
176 if (!checkCallbackThread()) {
177 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
178 return;
179 }
180
181 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
182
183 if (status != BT_STATUS_SUCCESS) {
184 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
185 return;
186 }
187
188 callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
189
190 jobjectArray props;
191 jbyteArray addr;
192 jintArray types;
193 jbyteArray val;
194 jclass mclass;
195
196 val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
197 if (val == NULL) {
198 ALOGE("%s: Error allocating byteArray", __FUNCTION__);
199 return;
200 }
201
202 mclass = callbackEnv->GetObjectClass(val);
203
204 /* Initialize the jobjectArray and jintArray here itself and send the
205 initialized array pointers alone to get_properties */
206
207 props = callbackEnv->NewObjectArray(num_properties, mclass,
208 NULL);
209 if (props == NULL) {
210 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
211 return;
212 }
213
214 types = (jintArray)callbackEnv->NewIntArray(num_properties);
215
216 if (types == NULL) {
217 ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
218 return;
219 }
220 // Delete the reference to val and mclass
221 callbackEnv->DeleteLocalRef(mclass);
222 callbackEnv->DeleteLocalRef(val);
223
224 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
225 if (addr == NULL) goto Fail;
226 if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
227
228 if (get_properties(num_properties, properties, &types, &props) < 0) {
229 if (props) callbackEnv->DeleteLocalRef(props);
230 if (types) callbackEnv->DeleteLocalRef(types);
231 callbackEnv->PopLocalFrame(NULL);
232 return;
233 }
234
235 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
236 types, props);
237 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
238 callbackEnv->DeleteLocalRef(props);
239 callbackEnv->DeleteLocalRef(types);
240 callbackEnv->DeleteLocalRef(addr);
241 callbackEnv->PopLocalFrame(NULL);
242 return;
243
244 Fail:
245 ALOGE("Error while allocation byte array in %s", __FUNCTION__);
246 }
247
248
device_found_callback(int num_properties,bt_property_t * properties)249 static void device_found_callback(int num_properties, bt_property_t *properties) {
250 jbyteArray addr = NULL;
251 int addr_index;
252
253 for (int i = 0; i < num_properties; i++) {
254 if (properties[i].type == BT_PROPERTY_BDADDR) {
255 addr = callbackEnv->NewByteArray(properties[i].len);
256 if (addr) {
257 callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
258 (jbyte*)properties[i].val);
259 addr_index = i;
260 } else {
261 ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
262 return;
263 }
264 }
265 }
266 if (addr == NULL) {
267 ALOGE("Address is NULL in %s", __FUNCTION__);
268 return;
269 }
270
271 ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
272 (const char *)properties[addr_index].val);
273
274 remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
275 num_properties, properties);
276
277 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
278 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
279 callbackEnv->DeleteLocalRef(addr);
280 }
281
bond_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_bond_state_t state)282 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
283 bt_bond_state_t state) {
284 jbyteArray addr;
285 int i;
286 if (!checkCallbackThread()) {
287 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
288 return;
289 }
290 if (!bd_addr) {
291 ALOGE("Address is null in %s", __FUNCTION__);
292 return;
293 }
294 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
295 if (addr == NULL) {
296 ALOGE("Address allocation failed in %s", __FUNCTION__);
297 return;
298 }
299 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
300
301 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
302 addr, (jint)state);
303 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
304 callbackEnv->DeleteLocalRef(addr);
305 }
306
acl_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_acl_state_t state)307 static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
308 bt_acl_state_t state)
309 {
310 jbyteArray addr;
311 int i;
312 if (!checkCallbackThread()) {
313 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
314 return;
315 }
316 if (!bd_addr) {
317 ALOGE("Address is null in %s", __FUNCTION__);
318 return;
319 }
320 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
321 if (addr == NULL) {
322 ALOGE("Address allocation failed in %s", __FUNCTION__);
323 return;
324 }
325 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
326
327 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
328 addr, (jint)state);
329 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
330 callbackEnv->DeleteLocalRef(addr);
331 }
332
discovery_state_changed_callback(bt_discovery_state_t state)333 static void discovery_state_changed_callback(bt_discovery_state_t state) {
334 jbyteArray addr;
335 if (!checkCallbackThread()) {
336 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
337 return;
338 }
339
340 ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
341
342 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
343 (jint)state);
344
345 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
346 }
347
pin_request_callback(bt_bdaddr_t * bd_addr,bt_bdname_t * bdname,uint32_t cod)348 static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
349 jbyteArray addr, devname;
350 if (!checkCallbackThread()) {
351 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
352 return;
353 }
354 if (!bd_addr) {
355 ALOGE("Address is null in %s", __FUNCTION__);
356 return;
357 }
358
359 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
360 if (addr == NULL) goto Fail;
361 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
362
363 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
364 if (devname == NULL) goto Fail;
365
366 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
367
368 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
369
370 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
371 callbackEnv->DeleteLocalRef(addr);
372 callbackEnv->DeleteLocalRef(devname);
373 return;
374
375 Fail:
376 if (addr) callbackEnv->DeleteLocalRef(addr);
377 if (devname) callbackEnv->DeleteLocalRef(devname);
378 ALOGE("Error while allocating in: %s", __FUNCTION__);
379 }
380
ssp_request_callback(bt_bdaddr_t * bd_addr,bt_bdname_t * bdname,uint32_t cod,bt_ssp_variant_t pairing_variant,uint32_t pass_key)381 static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
382 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
383 jbyteArray addr, devname;
384 if (!checkCallbackThread()) {
385 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
386 return;
387 }
388 if (!bd_addr) {
389 ALOGE("Address is null in %s", __FUNCTION__);
390 return;
391 }
392
393 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
394 if (addr == NULL) goto Fail;
395 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
396
397 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
398 if (devname == NULL) goto Fail;
399 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
400
401 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
402 (jint) pairing_variant, pass_key);
403
404 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
405 callbackEnv->DeleteLocalRef(addr);
406 callbackEnv->DeleteLocalRef(devname);
407 return;
408
409 Fail:
410 if (addr) callbackEnv->DeleteLocalRef(addr);
411 if (devname) callbackEnv->DeleteLocalRef(devname);
412
413 ALOGE("Error while allocating in: %s", __FUNCTION__);
414 }
415
callback_thread_event(bt_cb_thread_evt event)416 static void callback_thread_event(bt_cb_thread_evt event) {
417 JavaVM* vm = AndroidRuntime::getJavaVM();
418 if (event == ASSOCIATE_JVM) {
419 JavaVMAttachArgs args;
420 char name[] = "BT Service Callback Thread";
421 args.version = JNI_VERSION_1_6;
422 args.name = name;
423 args.group = NULL;
424 vm->AttachCurrentThread(&callbackEnv, &args);
425 ALOGV("Callback thread attached: %p", callbackEnv);
426 } else if (event == DISASSOCIATE_JVM) {
427 if (!checkCallbackThread()) {
428 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
429 return;
430 }
431 vm->DetachCurrentThread();
432 }
433 }
434
dut_mode_recv_callback(uint16_t opcode,uint8_t * buf,uint8_t len)435 static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
436
437 }
le_test_mode_recv_callback(bt_status_t status,uint16_t packet_count)438 static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
439
440 ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
441 }
442 bt_callbacks_t sBluetoothCallbacks = {
443 sizeof(sBluetoothCallbacks),
444 adapter_state_change_callback,
445 adapter_properties_callback,
446 remote_device_properties_callback,
447 device_found_callback,
448 discovery_state_changed_callback,
449 pin_request_callback,
450 ssp_request_callback,
451 bond_state_changed_callback,
452 acl_state_changed_callback,
453 callback_thread_event,
454 dut_mode_recv_callback,
455
456 le_test_mode_recv_callback
457 };
458
classInitNative(JNIEnv * env,jclass clazz)459 static void classInitNative(JNIEnv* env, jclass clazz) {
460 int err;
461 hw_module_t* module;
462
463 jclass jniCallbackClass =
464 env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
465 sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
466 "Lcom/android/bluetooth/btservice/JniCallbacks;");
467
468 method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
469
470 method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
471 "adapterPropertyChangedCallback",
472 "([I[[B)V");
473 method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
474 "discoveryStateChangeCallback", "(I)V");
475
476 method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
477 "devicePropertyChangedCallback",
478 "([B[I[[B)V");
479 method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
480 method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
481 "([B[BI)V");
482 method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
483 "([B[BIII)V");
484
485 method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
486 "bondStateChangeCallback", "(I[BI)V");
487
488 method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
489 "aclStateChangeCallback", "(I[BI)V");
490 char value[PROPERTY_VALUE_MAX];
491 property_get("bluetooth.mock_stack", value, "");
492
493 const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
494
495 err = hw_get_module(id, (hw_module_t const**)&module);
496
497 if (err == 0) {
498 hw_device_t* abstraction;
499 err = module->methods->open(module, id, &abstraction);
500 if (err == 0) {
501 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
502 sBluetoothInterface = btStack->get_bluetooth_interface();
503 } else {
504 ALOGE("Error while opening Bluetooth library");
505 }
506 } else {
507 ALOGE("No Bluetooth Library found");
508 }
509 }
510
initNative(JNIEnv * env,jobject obj)511 static bool initNative(JNIEnv* env, jobject obj) {
512 ALOGV("%s:",__FUNCTION__);
513
514 sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
515
516 if (sBluetoothInterface) {
517 int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
518 if (ret != BT_STATUS_SUCCESS) {
519 ALOGE("Error while setting the callbacks \n");
520 sBluetoothInterface = NULL;
521 return JNI_FALSE;
522 }
523 if ( (sBluetoothSocketInterface = (btsock_interface_t *)
524 sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
525 ALOGE("Error getting socket interface");
526 }
527 return JNI_TRUE;
528 }
529 return JNI_FALSE;
530 }
531
cleanupNative(JNIEnv * env,jobject obj)532 static bool cleanupNative(JNIEnv *env, jobject obj) {
533 ALOGV("%s:",__FUNCTION__);
534
535 jboolean result = JNI_FALSE;
536 if (!sBluetoothInterface) return result;
537
538 sBluetoothInterface->cleanup();
539 ALOGI("%s: return from cleanup",__FUNCTION__);
540
541 env->DeleteGlobalRef(sJniCallbacksObj);
542 return JNI_TRUE;
543 }
544
enableNative(JNIEnv * env,jobject obj)545 static jboolean enableNative(JNIEnv* env, jobject obj) {
546 ALOGV("%s:",__FUNCTION__);
547
548 jboolean result = JNI_FALSE;
549 if (!sBluetoothInterface) return result;
550
551 int ret = sBluetoothInterface->enable();
552 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
553 return result;
554 }
555
disableNative(JNIEnv * env,jobject obj)556 static jboolean disableNative(JNIEnv* env, jobject obj) {
557 ALOGV("%s:",__FUNCTION__);
558
559 jboolean result = JNI_FALSE;
560 if (!sBluetoothInterface) return result;
561
562 int ret = sBluetoothInterface->disable();
563 /* Retrun JNI_FALSE only when BTIF explicitly reports
564 BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
565 case which indicates that stack had not been enabled.
566 */
567 result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
568 return result;
569 }
570
startDiscoveryNative(JNIEnv * env,jobject obj)571 static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
572 ALOGV("%s:",__FUNCTION__);
573
574 jboolean result = JNI_FALSE;
575 if (!sBluetoothInterface) return result;
576
577 int ret = sBluetoothInterface->start_discovery();
578 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
579 return result;
580 }
581
cancelDiscoveryNative(JNIEnv * env,jobject obj)582 static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
583 ALOGV("%s:",__FUNCTION__);
584
585 jboolean result = JNI_FALSE;
586 if (!sBluetoothInterface) return result;
587
588 int ret = sBluetoothInterface->cancel_discovery();
589 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
590 return result;
591 }
592
createBondNative(JNIEnv * env,jobject obj,jbyteArray address)593 static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
594 ALOGV("%s:",__FUNCTION__);
595
596 jbyte *addr;
597 jboolean result = JNI_FALSE;
598
599 if (!sBluetoothInterface) return result;
600
601 addr = env->GetByteArrayElements(address, NULL);
602 if (addr == NULL) {
603 jniThrowIOException(env, EINVAL);
604 return result;
605 }
606
607 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
608 env->ReleaseByteArrayElements(address, addr, 0);
609 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
610
611 return result;
612 }
613
removeBondNative(JNIEnv * env,jobject obj,jbyteArray address)614 static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
615 ALOGV("%s:",__FUNCTION__);
616
617 jbyte *addr;
618 jboolean result;
619 if (!sBluetoothInterface) return JNI_FALSE;
620
621 addr = env->GetByteArrayElements(address, NULL);
622 if (addr == NULL) {
623 jniThrowIOException(env, EINVAL);
624 return JNI_FALSE;
625 }
626
627 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
628 env->ReleaseByteArrayElements(address, addr, 0);
629 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
630
631 return result;
632 }
633
cancelBondNative(JNIEnv * env,jobject obj,jbyteArray address)634 static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
635 ALOGV("%s:",__FUNCTION__);
636
637 jbyte *addr;
638 jboolean result;
639 if (!sBluetoothInterface) return JNI_FALSE;
640
641 addr = env->GetByteArrayElements(address, NULL);
642 if (addr == NULL) {
643 jniThrowIOException(env, EINVAL);
644 return JNI_FALSE;
645 }
646
647 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
648 env->ReleaseByteArrayElements(address, addr, 0);
649 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
650
651 return result;
652 }
653
pinReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jboolean accept,jint len,jbyteArray pinArray)654 static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
655 jint len, jbyteArray pinArray) {
656 ALOGV("%s:",__FUNCTION__);
657
658 jbyte *addr, *pinPtr = NULL;
659 jboolean result = JNI_FALSE;
660 if (!sBluetoothInterface) return result;
661
662 addr = env->GetByteArrayElements(address, NULL);
663 if (addr == NULL) {
664 jniThrowIOException(env, EINVAL);
665 return result;
666 }
667
668 if (accept) {
669 pinPtr = env->GetByteArrayElements(pinArray, NULL);
670 if (pinPtr == NULL) {
671 jniThrowIOException(env, EINVAL);
672 env->ReleaseByteArrayElements(address, addr, 0);
673 return result;
674 }
675 }
676
677 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
678 (bt_pin_code_t *) pinPtr);
679 env->ReleaseByteArrayElements(address, addr, 0);
680 env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
681 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
682
683 return result;
684 }
685
sspReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jboolean accept,jint passkey)686 static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
687 jint type, jboolean accept, jint passkey) {
688 ALOGV("%s:",__FUNCTION__);
689
690 jbyte *addr;
691 jboolean result = JNI_FALSE;
692 if (!sBluetoothInterface) return result;
693
694 addr = env->GetByteArrayElements(address, NULL);
695 if (addr == NULL) {
696 jniThrowIOException(env, EINVAL);
697 return result;
698 }
699
700 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
701 (bt_ssp_variant_t) type, accept, passkey);
702 env->ReleaseByteArrayElements(address, addr, 0);
703 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
704
705 return result;
706 }
707
setAdapterPropertyNative(JNIEnv * env,jobject obj,jint type,jbyteArray value)708 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
709 ALOGV("%s:",__FUNCTION__);
710
711 jbyte *val;
712 jboolean result = JNI_FALSE;
713 if (!sBluetoothInterface) return result;
714
715 val = env->GetByteArrayElements(value, NULL);
716 bt_property_t prop;
717 prop.type = (bt_property_type_t) type;
718 prop.len = env->GetArrayLength(value);
719 prop.val = val;
720
721 int ret = sBluetoothInterface->set_adapter_property(&prop);
722 env->ReleaseByteArrayElements(value, val, 0);
723 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
724
725 return result;
726 }
727
getAdapterPropertiesNative(JNIEnv * env,jobject obj)728 static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
729 ALOGV("%s:",__FUNCTION__);
730
731 jboolean result = JNI_FALSE;
732 if (!sBluetoothInterface) return result;
733
734 int ret = sBluetoothInterface->get_adapter_properties();
735 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
736
737 return result;
738 }
739
getAdapterPropertyNative(JNIEnv * env,jobject obj,jint type)740 static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
741 ALOGV("%s:",__FUNCTION__);
742
743 jboolean result = JNI_FALSE;
744 if (!sBluetoothInterface) return result;
745
746 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
747 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
748
749 return result;
750 }
751
getDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type)752 static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
753 ALOGV("%s:",__FUNCTION__);
754
755 jbyte *addr = NULL;
756 jboolean result = JNI_FALSE;
757 if (!sBluetoothInterface) return result;
758
759 addr = env->GetByteArrayElements(address, NULL);
760 if (addr == NULL) {
761 jniThrowIOException(env, EINVAL);
762 return result;
763 }
764
765 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
766 (bt_property_type_t) type);
767 env->ReleaseByteArrayElements(address, addr, 0);
768 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
769
770 return result;
771 }
772
setDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jbyteArray value)773 static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
774 jint type, jbyteArray value) {
775 ALOGV("%s:",__FUNCTION__);
776
777 jbyte *val, *addr;
778 jboolean result = JNI_FALSE;
779 if (!sBluetoothInterface) return result;
780
781 val = env->GetByteArrayElements(value, NULL);
782 if (val == NULL) {
783 jniThrowIOException(env, EINVAL);
784 return result;
785 }
786
787 addr = env->GetByteArrayElements(address, NULL);
788 if (addr == NULL) {
789 env->ReleaseByteArrayElements(value, val, 0);
790 jniThrowIOException(env, EINVAL);
791 return result;
792 }
793
794
795 bt_property_t prop;
796 prop.type = (bt_property_type_t) type;
797 prop.len = env->GetArrayLength(value);
798 prop.val = val;
799
800 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
801 env->ReleaseByteArrayElements(value, val, 0);
802 env->ReleaseByteArrayElements(address, addr, 0);
803
804 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
805
806 return result;
807 }
808
getRemoteServicesNative(JNIEnv * env,jobject obj,jbyteArray address)809 static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
810 ALOGV("%s:",__FUNCTION__);
811
812 jbyte *addr = NULL;
813 jboolean result = JNI_FALSE;
814 if (!sBluetoothInterface) return result;
815
816 addr = env->GetByteArrayElements(address, NULL);
817 if (addr == NULL) {
818 jniThrowIOException(env, EINVAL);
819 return result;
820 }
821
822 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
823 env->ReleaseByteArrayElements(address, addr, 0);
824 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
825 return result;
826 }
827
connectSocketNative(JNIEnv * env,jobject object,jbyteArray address,jint type,jbyteArray uuidObj,jint channel,jint flag)828 static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
829 jbyteArray uuidObj, jint channel, jint flag) {
830 jbyte *addr = NULL, *uuid = NULL;
831 int socket_fd;
832 bt_status_t status;
833
834 if (!sBluetoothSocketInterface) return -1;
835
836 addr = env->GetByteArrayElements(address, NULL);
837 if (!addr) {
838 ALOGE("failed to get Bluetooth device address");
839 goto Fail;
840 }
841
842 uuid = env->GetByteArrayElements(uuidObj, NULL);
843 if (!uuid) {
844 ALOGE("failed to get uuid");
845 goto Fail;
846 }
847
848 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
849 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
850 ALOGE("Socket connection failed: %d", status);
851 goto Fail;
852 }
853
854
855 if (socket_fd < 0) {
856 ALOGE("Fail to creat file descriptor on socket fd");
857 goto Fail;
858 }
859 env->ReleaseByteArrayElements(address, addr, 0);
860 env->ReleaseByteArrayElements(uuidObj, uuid, 0);
861 return socket_fd;
862
863 Fail:
864 if (addr) env->ReleaseByteArrayElements(address, addr, 0);
865 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
866
867 return -1;
868 }
869
createSocketChannelNative(JNIEnv * env,jobject object,jint type,jstring name_str,jbyteArray uuidObj,jint channel,jint flag)870 static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
871 jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
872 const char *service_name;
873 jbyte *uuid = NULL;
874 int socket_fd;
875 bt_status_t status;
876
877 if (!sBluetoothSocketInterface) return -1;
878
879 service_name = env->GetStringUTFChars(name_str, NULL);
880
881 uuid = env->GetByteArrayElements(uuidObj, NULL);
882 if (!uuid) {
883 ALOGE("failed to get uuid");
884 goto Fail;
885 }
886 ALOGE("SOCK FLAG = %x ***********************",flag);
887 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
888 (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
889 ALOGE("Socket listen failed: %d", status);
890 goto Fail;
891 }
892
893 if (socket_fd < 0) {
894 ALOGE("Fail to creat file descriptor on socket fd");
895 goto Fail;
896 }
897 if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
898 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
899 return socket_fd;
900
901 Fail:
902 if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
903 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
904
905 return -1;
906 }
907
configHciSnoopLogNative(JNIEnv * env,jobject obj,jboolean enable)908 static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
909 ALOGV("%s:",__FUNCTION__);
910
911 jboolean result = JNI_FALSE;
912
913 if (!sBluetoothInterface) return result;
914
915 int ret = sBluetoothInterface->config_hci_snoop_log(enable);
916
917 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
918
919 return result;
920 }
921
922 static JNINativeMethod sMethods[] = {
923 /* name, signature, funcPtr */
924 {"classInitNative", "()V", (void *) classInitNative},
925 {"initNative", "()Z", (void *) initNative},
926 {"cleanupNative", "()V", (void*) cleanupNative},
927 {"enableNative", "()Z", (void*) enableNative},
928 {"disableNative", "()Z", (void*) disableNative},
929 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
930 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
931 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
932 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
933 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
934 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
935 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
936 {"createBondNative", "([B)Z", (void*) createBondNative},
937 {"removeBondNative", "([B)Z", (void*) removeBondNative},
938 {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
939 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
940 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
941 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
942 {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
943 {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
944 (void*) createSocketChannelNative},
945 {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative}
946 };
947
register_com_android_bluetooth_btservice_AdapterService(JNIEnv * env)948 int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
949 {
950 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
951 sMethods, NELEM(sMethods));
952 }
953
954 } /* namespace android */
955
956
957 /*
958 * JNI Initialization
959 */
JNI_OnLoad(JavaVM * jvm,void * reserved)960 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
961 {
962 JNIEnv *e;
963 int status;
964
965 ALOGV("Bluetooth Adapter Service : loading JNI\n");
966
967 // Check JNI version
968 if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
969 ALOGE("JNI version mismatch error");
970 return JNI_ERR;
971 }
972
973 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
974 ALOGE("jni adapter service registration failure, status: %d", status);
975 return JNI_ERR;
976 }
977
978 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
979 ALOGE("jni hfp registration failure, status: %d", status);
980 return JNI_ERR;
981 }
982
983 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
984 ALOGE("jni a2dp registration failure: %d", status);
985 return JNI_ERR;
986 }
987
988 if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
989 ALOGE("jni avrcp registration failure: %d", status);
990 return JNI_ERR;
991 }
992
993 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
994 ALOGE("jni hid registration failure: %d", status);
995 return JNI_ERR;
996 }
997
998 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
999 ALOGE("jni hdp registration failure: %d", status);
1000 return JNI_ERR;
1001 }
1002
1003 if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
1004 ALOGE("jni pan registration failure: %d", status);
1005 return JNI_ERR;
1006 }
1007
1008 if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
1009 ALOGE("jni gatt registration failure: %d", status);
1010 return JNI_ERR;
1011 }
1012 return JNI_VERSION_1_6;
1013 }
1014