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 OOB_TK_SIZE 16
35
36 #define ADDITIONAL_NREFS 50
37 static jmethodID method_stateChangeCallback;
38 static jmethodID method_adapterPropertyChangedCallback;
39 static jmethodID method_devicePropertyChangedCallback;
40 static jmethodID method_deviceFoundCallback;
41 static jmethodID method_pinRequestCallback;
42 static jmethodID method_sspRequestCallback;
43 static jmethodID method_bondStateChangeCallback;
44 static jmethodID method_aclStateChangeCallback;
45 static jmethodID method_discoveryStateChangeCallback;
46 static jmethodID method_setWakeAlarm;
47 static jmethodID method_acquireWakeLock;
48 static jmethodID method_releaseWakeLock;
49 static jmethodID method_energyInfo;
50
51 static struct {
52 jclass clazz;
53 jmethodID constructor;
54 } android_bluetooth_UidTraffic;
55
56 static const bt_interface_t *sBluetoothInterface = NULL;
57 static const btsock_interface_t *sBluetoothSocketInterface = NULL;
58 static JNIEnv *callbackEnv = NULL;
59
60 static jobject sJniAdapterServiceObj;
61 static jobject sJniCallbacksObj;
62 static jfieldID sJniCallbacksField;
63
64
getBluetoothInterface()65 const bt_interface_t* getBluetoothInterface() {
66 return sBluetoothInterface;
67 }
68
getCallbackEnv()69 JNIEnv* getCallbackEnv() {
70 return callbackEnv;
71 }
72
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)73 void checkAndClearExceptionFromCallback(JNIEnv* env,
74 const char* methodName) {
75 if (env->ExceptionCheck()) {
76 ALOGE("An exception was thrown by callback '%s'.", methodName);
77 LOGE_EX(env);
78 env->ExceptionClear();
79 }
80 }
81
checkCallbackThread()82 static bool checkCallbackThread() {
83 JNIEnv* env = AndroidRuntime::getJNIEnv();
84 if (callbackEnv != env || callbackEnv == NULL) {
85 ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
86 return false;
87 }
88 return true;
89 }
90
adapter_state_change_callback(bt_state_t status)91 static void adapter_state_change_callback(bt_state_t status) {
92 if (!checkCallbackThread()) {
93 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
94 return;
95 }
96 ALOGV("%s: Status is: %d", __FUNCTION__, status);
97
98 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
99
100 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
101 }
102
get_properties(int num_properties,bt_property_t * properties,jintArray * types,jobjectArray * props)103 static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
104 jobjectArray *props) {
105 jbyteArray propVal;
106 for (int i = 0; i < num_properties; i++) {
107 propVal = callbackEnv->NewByteArray(properties[i].len);
108 if (propVal == NULL) goto Fail;
109
110 callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
111 (jbyte*)properties[i].val);
112 callbackEnv->SetObjectArrayElement(*props, i, propVal);
113 // Delete reference to propVal
114 callbackEnv->DeleteLocalRef(propVal);
115 callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
116 }
117 return 0;
118 Fail:
119 if (propVal) callbackEnv->DeleteLocalRef(propVal);
120 ALOGE("Error while allocation of array in %s", __FUNCTION__);
121 return -1;
122 }
123
adapter_properties_callback(bt_status_t status,int num_properties,bt_property_t * properties)124 static void adapter_properties_callback(bt_status_t status, int num_properties,
125 bt_property_t *properties) {
126 jobjectArray props;
127 jintArray types;
128 jbyteArray val;
129 jclass mclass;
130
131 if (!checkCallbackThread()) {
132 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
133 return;
134 }
135
136 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
137
138 if (status != BT_STATUS_SUCCESS) {
139 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
140 return;
141 }
142
143 val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
144 if (val == NULL) {
145 ALOGE("%s: Error allocating byteArray", __FUNCTION__);
146 return;
147 }
148
149 mclass = callbackEnv->GetObjectClass(val);
150
151 /* (BT) Initialize the jobjectArray and jintArray here itself and send the
152 initialized array pointers alone to get_properties */
153
154 props = callbackEnv->NewObjectArray(num_properties, mclass,
155 NULL);
156 if (props == NULL) {
157 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
158 return;
159 }
160
161 types = (jintArray)callbackEnv->NewIntArray(num_properties);
162
163 if (types == NULL) {
164 ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
165 return;
166 }
167 // Delete the reference to val and mclass
168 callbackEnv->DeleteLocalRef(mclass);
169 callbackEnv->DeleteLocalRef(val);
170
171 if (get_properties(num_properties, properties, &types, &props) < 0) {
172 if (props) callbackEnv->DeleteLocalRef(props);
173 if (types) callbackEnv->DeleteLocalRef(types);
174 return;
175 }
176
177 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
178 props);
179 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
180 callbackEnv->DeleteLocalRef(props);
181 callbackEnv->DeleteLocalRef(types);
182 return;
183
184 }
185
remote_device_properties_callback(bt_status_t status,bt_bdaddr_t * bd_addr,int num_properties,bt_property_t * properties)186 static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
187 int num_properties, bt_property_t *properties) {
188 if (!checkCallbackThread()) {
189 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
190 return;
191 }
192
193 ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
194
195 if (status != BT_STATUS_SUCCESS) {
196 ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
197 return;
198 }
199
200 callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
201
202 jobjectArray props;
203 jbyteArray addr;
204 jintArray types;
205 jbyteArray val;
206 jclass mclass;
207
208 val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
209 if (val == NULL) {
210 ALOGE("%s: Error allocating byteArray", __FUNCTION__);
211 return;
212 }
213
214 mclass = callbackEnv->GetObjectClass(val);
215
216 /* Initialize the jobjectArray and jintArray here itself and send the
217 initialized array pointers alone to get_properties */
218
219 props = callbackEnv->NewObjectArray(num_properties, mclass,
220 NULL);
221 if (props == NULL) {
222 ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
223 return;
224 }
225
226 types = (jintArray)callbackEnv->NewIntArray(num_properties);
227
228 if (types == NULL) {
229 ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
230 return;
231 }
232 // Delete the reference to val and mclass
233 callbackEnv->DeleteLocalRef(mclass);
234 callbackEnv->DeleteLocalRef(val);
235
236 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
237 if (addr == NULL) goto Fail;
238 if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
239
240 if (get_properties(num_properties, properties, &types, &props) < 0) {
241 if (props) callbackEnv->DeleteLocalRef(props);
242 if (types) callbackEnv->DeleteLocalRef(types);
243 callbackEnv->PopLocalFrame(NULL);
244 return;
245 }
246
247 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
248 types, props);
249 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
250 callbackEnv->DeleteLocalRef(props);
251 callbackEnv->DeleteLocalRef(types);
252 callbackEnv->DeleteLocalRef(addr);
253 callbackEnv->PopLocalFrame(NULL);
254 return;
255
256 Fail:
257 ALOGE("Error while allocation byte array in %s", __FUNCTION__);
258 }
259
260
device_found_callback(int num_properties,bt_property_t * properties)261 static void device_found_callback(int num_properties, bt_property_t *properties) {
262 jbyteArray addr = NULL;
263 int addr_index;
264
265 for (int i = 0; i < num_properties; i++) {
266 if (properties[i].type == BT_PROPERTY_BDADDR) {
267 addr = callbackEnv->NewByteArray(properties[i].len);
268 if (addr) {
269 callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
270 (jbyte*)properties[i].val);
271 addr_index = i;
272 } else {
273 ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
274 return;
275 }
276 }
277 }
278 if (addr == NULL) {
279 ALOGE("Address is NULL in %s", __FUNCTION__);
280 return;
281 }
282
283 ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
284 (const char *)properties[addr_index].val);
285
286 remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
287 num_properties, properties);
288
289 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
290 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
291 callbackEnv->DeleteLocalRef(addr);
292 }
293
bond_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_bond_state_t state)294 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
295 bt_bond_state_t state) {
296 jbyteArray addr;
297 if (!checkCallbackThread()) {
298 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
299 return;
300 }
301 if (!bd_addr) {
302 ALOGE("Address is null in %s", __FUNCTION__);
303 return;
304 }
305 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
306 if (addr == NULL) {
307 ALOGE("Address allocation failed in %s", __FUNCTION__);
308 return;
309 }
310 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
311
312 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
313 addr, (jint)state);
314 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
315 callbackEnv->DeleteLocalRef(addr);
316 }
317
acl_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_acl_state_t state)318 static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
319 bt_acl_state_t state)
320 {
321 jbyteArray addr;
322 if (!checkCallbackThread()) {
323 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
324 return;
325 }
326 if (!bd_addr) {
327 ALOGE("Address is null in %s", __FUNCTION__);
328 return;
329 }
330 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
331 if (addr == NULL) {
332 ALOGE("Address allocation failed in %s", __FUNCTION__);
333 return;
334 }
335 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
336
337 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
338 addr, (jint)state);
339 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
340 callbackEnv->DeleteLocalRef(addr);
341 }
342
discovery_state_changed_callback(bt_discovery_state_t state)343 static void discovery_state_changed_callback(bt_discovery_state_t state) {
344 if (!checkCallbackThread()) {
345 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
346 return;
347 }
348
349 ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
350
351 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
352 (jint)state);
353
354 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
355 }
356
pin_request_callback(bt_bdaddr_t * bd_addr,bt_bdname_t * bdname,uint32_t cod,bool min_16_digits)357 static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
358 bool min_16_digits) {
359 jbyteArray addr = NULL;
360 jbyteArray devname = NULL;
361 if (!checkCallbackThread()) {
362 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
363 return;
364 }
365 if (!bd_addr) {
366 ALOGE("Address is null in %s", __FUNCTION__);
367 return;
368 }
369
370 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
371 if (addr == NULL) goto Fail;
372 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
373
374 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
375 if (devname == NULL) goto Fail;
376
377 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
378
379 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod,
380 min_16_digits);
381
382 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
383 callbackEnv->DeleteLocalRef(addr);
384 callbackEnv->DeleteLocalRef(devname);
385 return;
386
387 Fail:
388 if (addr) callbackEnv->DeleteLocalRef(addr);
389 if (devname) callbackEnv->DeleteLocalRef(devname);
390 ALOGE("Error while allocating in: %s", __FUNCTION__);
391 }
392
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)393 static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
394 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
395 jbyteArray addr = NULL;
396 jbyteArray devname = NULL;
397 if (!checkCallbackThread()) {
398 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
399 return;
400 }
401 if (!bd_addr) {
402 ALOGE("Address is null in %s", __FUNCTION__);
403 return;
404 }
405
406 addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
407 if (addr == NULL) goto Fail;
408 callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
409
410 devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
411 if (devname == NULL) goto Fail;
412 callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
413
414 callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
415 (jint) pairing_variant, pass_key);
416
417 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
418 callbackEnv->DeleteLocalRef(addr);
419 callbackEnv->DeleteLocalRef(devname);
420 return;
421
422 Fail:
423 if (addr) callbackEnv->DeleteLocalRef(addr);
424 if (devname) callbackEnv->DeleteLocalRef(devname);
425
426 ALOGE("Error while allocating in: %s", __FUNCTION__);
427 }
428
callback_thread_event(bt_cb_thread_evt event)429 static void callback_thread_event(bt_cb_thread_evt event) {
430 JavaVM* vm = AndroidRuntime::getJavaVM();
431 if (event == ASSOCIATE_JVM) {
432 JavaVMAttachArgs args;
433 char name[] = "BT Service Callback Thread";
434 args.version = JNI_VERSION_1_6;
435 args.name = name;
436 args.group = NULL;
437 vm->AttachCurrentThread(&callbackEnv, &args);
438 ALOGV("Callback thread attached: %p", callbackEnv);
439 } else if (event == DISASSOCIATE_JVM) {
440 if (!checkCallbackThread()) {
441 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
442 return;
443 }
444 vm->DetachCurrentThread();
445 }
446 }
447
dut_mode_recv_callback(uint16_t opcode,uint8_t * buf,uint8_t len)448 static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
449
450 }
le_test_mode_recv_callback(bt_status_t status,uint16_t packet_count)451 static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
452
453 ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
454 }
455
energy_info_recv_callback(bt_activity_energy_info * p_energy_info,bt_uid_traffic_t * uid_data)456 static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
457 bt_uid_traffic_t* uid_data)
458 {
459 if (!checkCallbackThread()) {
460 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
461 return;
462 }
463
464 jsize len = 0;
465 for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
466 len++;
467 }
468
469 jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
470 jsize i = 0;
471 for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
472 jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
473 android_bluetooth_UidTraffic.constructor,
474 (jint) data->app_uid, (jlong) data->rx_bytes,
475 (jlong) data->tx_bytes);
476 callbackEnv->SetObjectArrayElement(array, i++, uidObj);
477 callbackEnv->DeleteLocalRef(uidObj);
478 }
479
480 callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
481 p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
482 p_energy_info->idle_time, p_energy_info->energy_used, array);
483
484 checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
485 callbackEnv->DeleteLocalRef(array);
486 }
487
488 static bt_callbacks_t sBluetoothCallbacks = {
489 sizeof(sBluetoothCallbacks),
490 adapter_state_change_callback,
491 adapter_properties_callback,
492 remote_device_properties_callback,
493 device_found_callback,
494 discovery_state_changed_callback,
495 pin_request_callback,
496 ssp_request_callback,
497 bond_state_changed_callback,
498 acl_state_changed_callback,
499 callback_thread_event,
500 dut_mode_recv_callback,
501 le_test_mode_recv_callback,
502 energy_info_recv_callback
503 };
504
505 // The callback to call when the wake alarm fires.
506 static alarm_cb sAlarmCallback;
507
508 // The data to pass to the wake alarm callback.
509 static void *sAlarmCallbackData;
510
511 static JavaVMAttachArgs sAttachArgs = {
512 .version = JNI_VERSION_1_6,
513 .name = "bluetooth wake",
514 .group = NULL
515 };
516
set_wake_alarm_callout(uint64_t delay_millis,bool should_wake,alarm_cb cb,void * data)517 static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
518 alarm_cb cb, void *data) {
519 JNIEnv *env;
520 JavaVM *vm = AndroidRuntime::getJavaVM();
521 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
522
523 if (status != JNI_OK && status != JNI_EDETACHED) {
524 ALOGE("%s unable to get environment for JNI call", __func__);
525 return false;
526 }
527
528 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
529 ALOGE("%s unable to attach thread to VM", __func__);
530 return false;
531 }
532
533 sAlarmCallback = cb;
534 sAlarmCallbackData = data;
535
536 jboolean jshould_wake = should_wake ? JNI_TRUE : JNI_FALSE;
537 jboolean ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_setWakeAlarm,
538 (jlong)delay_millis, jshould_wake);
539 if (!ret) {
540 sAlarmCallback = NULL;
541 sAlarmCallbackData = NULL;
542 }
543
544 if (status == JNI_EDETACHED) {
545 vm->DetachCurrentThread();
546 }
547
548 return !!ret;
549 }
550
acquire_wake_lock_callout(const char * lock_name)551 static int acquire_wake_lock_callout(const char *lock_name) {
552 JNIEnv *env;
553 JavaVM *vm = AndroidRuntime::getJavaVM();
554 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
555 if (status != JNI_OK && status != JNI_EDETACHED) {
556 ALOGE("%s unable to get environment for JNI call", __func__);
557 return BT_STATUS_JNI_ENVIRONMENT_ERROR;
558 }
559 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
560 ALOGE("%s unable to attach thread to VM", __func__);
561 return BT_STATUS_JNI_THREAD_ATTACH_ERROR;
562 }
563
564 jint ret = BT_STATUS_SUCCESS;
565 jstring lock_name_jni = env->NewStringUTF(lock_name);
566 if (lock_name_jni) {
567 bool acquired = env->CallBooleanMethod(sJniAdapterServiceObj,
568 method_acquireWakeLock, lock_name_jni);
569 if (!acquired) ret = BT_STATUS_WAKELOCK_ERROR;
570 env->DeleteLocalRef(lock_name_jni);
571 } else {
572 ALOGE("%s unable to allocate string: %s", __func__, lock_name);
573 ret = BT_STATUS_NOMEM;
574 }
575
576 if (status == JNI_EDETACHED) {
577 vm->DetachCurrentThread();
578 }
579
580 return ret;
581 }
582
release_wake_lock_callout(const char * lock_name)583 static int release_wake_lock_callout(const char *lock_name) {
584 JNIEnv *env;
585 JavaVM *vm = AndroidRuntime::getJavaVM();
586 jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
587 if (status != JNI_OK && status != JNI_EDETACHED) {
588 ALOGE("%s unable to get environment for JNI call", __func__);
589 return BT_STATUS_JNI_ENVIRONMENT_ERROR;
590 }
591 if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
592 ALOGE("%s unable to attach thread to VM", __func__);
593 return BT_STATUS_JNI_THREAD_ATTACH_ERROR;
594 }
595
596 jint ret = BT_STATUS_SUCCESS;
597 jstring lock_name_jni = env->NewStringUTF(lock_name);
598 if (lock_name_jni) {
599 bool released = env->CallBooleanMethod(sJniAdapterServiceObj,
600 method_releaseWakeLock, lock_name_jni);
601 if (!released) ret = BT_STATUS_WAKELOCK_ERROR;
602 env->DeleteLocalRef(lock_name_jni);
603 } else {
604 ALOGE("%s unable to allocate string: %s", __func__, lock_name);
605 ret = BT_STATUS_NOMEM;
606 }
607
608 if (status == JNI_EDETACHED) {
609 vm->DetachCurrentThread();
610 }
611
612 return ret;
613 }
614
615 // Called by Java code when alarm is fired. A wake lock is held by the caller
616 // over the duration of this callback.
alarmFiredNative(JNIEnv * env,jobject obj)617 static void alarmFiredNative(JNIEnv *env, jobject obj) {
618 if (sAlarmCallback) {
619 sAlarmCallback(sAlarmCallbackData);
620 } else {
621 ALOGE("%s() - Alarm fired with callback not set!", __FUNCTION__);
622 }
623 }
624
625 static bt_os_callouts_t sBluetoothOsCallouts = {
626 sizeof(sBluetoothOsCallouts),
627 set_wake_alarm_callout,
628 acquire_wake_lock_callout,
629 release_wake_lock_callout,
630 };
631
632
633
classInitNative(JNIEnv * env,jclass clazz)634 static void classInitNative(JNIEnv* env, jclass clazz) {
635 int err;
636 hw_module_t* module;
637
638
639 jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
640 android_bluetooth_UidTraffic.constructor = env->GetMethodID(jniUidTrafficClass,
641 "<init>", "(IJJ)V");
642
643 jclass jniCallbackClass =
644 env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
645 sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
646 "Lcom/android/bluetooth/btservice/JniCallbacks;");
647
648 method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
649
650 method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
651 "adapterPropertyChangedCallback",
652 "([I[[B)V");
653 method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
654 "discoveryStateChangeCallback", "(I)V");
655
656 method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
657 "devicePropertyChangedCallback",
658 "([B[I[[B)V");
659 method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
660 method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
661 "([B[BIZ)V");
662 method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
663 "([B[BIII)V");
664
665 method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
666 "bondStateChangeCallback", "(I[BI)V");
667
668 method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
669 "aclStateChangeCallback", "(I[BI)V");
670
671 method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
672 method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
673 method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
674 method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
675
676 char value[PROPERTY_VALUE_MAX];
677 property_get("bluetooth.mock_stack", value, "");
678
679 const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
680
681 err = hw_get_module(id, (hw_module_t const**)&module);
682
683 if (err == 0) {
684 hw_device_t* abstraction;
685 err = module->methods->open(module, id, &abstraction);
686 if (err == 0) {
687 bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
688 sBluetoothInterface = btStack->get_bluetooth_interface();
689 } else {
690 ALOGE("Error while opening Bluetooth library");
691 }
692 } else {
693 ALOGE("No Bluetooth Library found");
694 }
695 }
696
initNative(JNIEnv * env,jobject obj)697 static bool initNative(JNIEnv* env, jobject obj) {
698 ALOGV("%s:",__FUNCTION__);
699
700 android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
701 env->FindClass("android/bluetooth/UidTraffic"));
702
703 sJniAdapterServiceObj = env->NewGlobalRef(obj);
704 sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
705
706 if (sBluetoothInterface) {
707 int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
708 if (ret != BT_STATUS_SUCCESS) {
709 ALOGE("Error while setting the callbacks: %d\n", ret);
710 sBluetoothInterface = NULL;
711 return JNI_FALSE;
712 }
713 ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
714 if (ret != BT_STATUS_SUCCESS) {
715 ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
716 sBluetoothInterface->cleanup();
717 sBluetoothInterface = NULL;
718 return JNI_FALSE;
719 }
720
721 if ( (sBluetoothSocketInterface = (btsock_interface_t *)
722 sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
723 ALOGE("Error getting socket interface");
724 }
725
726 return JNI_TRUE;
727 }
728 return JNI_FALSE;
729 }
730
cleanupNative(JNIEnv * env,jobject obj)731 static bool cleanupNative(JNIEnv *env, jobject obj) {
732 ALOGV("%s:",__FUNCTION__);
733
734 jboolean result = JNI_FALSE;
735 if (!sBluetoothInterface) return result;
736
737 sBluetoothInterface->cleanup();
738 ALOGI("%s: return from cleanup",__FUNCTION__);
739
740 env->DeleteGlobalRef(sJniCallbacksObj);
741 env->DeleteGlobalRef(sJniAdapterServiceObj);
742 env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
743 android_bluetooth_UidTraffic.clazz = NULL;
744 return JNI_TRUE;
745 }
746
enableNative(JNIEnv * env,jobject obj,jboolean isGuest)747 static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
748 ALOGV("%s:",__FUNCTION__);
749
750 jboolean result = JNI_FALSE;
751 if (!sBluetoothInterface) return result;
752 int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
753 result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;
754 return result;
755 }
756
disableNative(JNIEnv * env,jobject obj)757 static jboolean disableNative(JNIEnv* env, jobject obj) {
758 ALOGV("%s:",__FUNCTION__);
759
760 jboolean result = JNI_FALSE;
761 if (!sBluetoothInterface) return result;
762
763 int ret = sBluetoothInterface->disable();
764 /* Retrun JNI_FALSE only when BTIF explicitly reports
765 BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
766 case which indicates that stack had not been enabled.
767 */
768 result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
769 return result;
770 }
771
startDiscoveryNative(JNIEnv * env,jobject obj)772 static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
773 ALOGV("%s:",__FUNCTION__);
774
775 jboolean result = JNI_FALSE;
776 if (!sBluetoothInterface) return result;
777
778 int ret = sBluetoothInterface->start_discovery();
779 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
780 return result;
781 }
782
cancelDiscoveryNative(JNIEnv * env,jobject obj)783 static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
784 ALOGV("%s:",__FUNCTION__);
785
786 jboolean result = JNI_FALSE;
787 if (!sBluetoothInterface) return result;
788
789 int ret = sBluetoothInterface->cancel_discovery();
790 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
791 return result;
792 }
793
createBondNative(JNIEnv * env,jobject obj,jbyteArray address,jint transport)794 static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
795 ALOGV("%s:",__FUNCTION__);
796
797 jbyte *addr;
798 jboolean result = JNI_FALSE;
799
800 if (!sBluetoothInterface) return result;
801
802 addr = env->GetByteArrayElements(address, NULL);
803 if (addr == NULL) {
804 jniThrowIOException(env, EINVAL);
805 return result;
806 }
807
808 int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);
809 env->ReleaseByteArrayElements(address, addr, 0);
810 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
811
812 return result;
813 }
814
callByteArrayGetter(JNIEnv * env,jobject object,const char * className,const char * methodName)815 static jbyteArray callByteArrayGetter(JNIEnv* env, jobject object,
816 const char* className,
817 const char* methodName) {
818 jclass myClass = env->FindClass(className);
819 jmethodID myMethod = env->GetMethodID(myClass, methodName, "()[B");
820 return (jbyteArray) env->CallObjectMethod(object, myMethod);
821 }
822
createBondOutOfBandNative(JNIEnv * env,jobject obj,jbyteArray address,jint transport,jobject oobData)823 static jboolean createBondOutOfBandNative(JNIEnv* env, jobject obj, jbyteArray address,
824 jint transport, jobject oobData) {
825 jbyte *addr;
826 jboolean result = JNI_FALSE;
827 bt_out_of_band_data_t oob_data;
828
829 memset(&oob_data, 0, sizeof(oob_data));
830
831 if (!sBluetoothInterface) return result;
832
833 addr = env->GetByteArrayElements(address, NULL);
834 if (addr == NULL) {
835 jniThrowIOException(env, EINVAL);
836 return result;
837 }
838
839 jbyte* smTKBytes = NULL;
840 jbyteArray smTK = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getSecurityManagerTk");
841 if (smTK != NULL) {
842 smTKBytes = env->GetByteArrayElements(smTK, NULL);
843 int len = env->GetArrayLength(smTK);
844 if (len != OOB_TK_SIZE) {
845 ALOGI("%s: wrong length of smTK, should be empty or %d bytes.", __FUNCTION__, OOB_TK_SIZE);
846 jniThrowIOException(env, EINVAL);
847 goto done;
848 }
849 memcpy(oob_data.sm_tk, smTKBytes, len);
850 }
851
852 if (sBluetoothInterface->create_bond_out_of_band((bt_bdaddr_t *)addr, transport, &oob_data)
853 == BT_STATUS_SUCCESS)
854 result = JNI_TRUE;
855
856 done:
857 env->ReleaseByteArrayElements(address, addr, 0);
858
859 if (smTK != NULL)
860 env->ReleaseByteArrayElements(smTK, smTKBytes, 0);
861
862 return result;
863 }
864
removeBondNative(JNIEnv * env,jobject obj,jbyteArray address)865 static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
866 ALOGV("%s:",__FUNCTION__);
867
868 jbyte *addr;
869 jboolean result;
870 if (!sBluetoothInterface) return JNI_FALSE;
871
872 addr = env->GetByteArrayElements(address, NULL);
873 if (addr == NULL) {
874 jniThrowIOException(env, EINVAL);
875 return JNI_FALSE;
876 }
877
878 int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
879 env->ReleaseByteArrayElements(address, addr, 0);
880 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
881
882 return result;
883 }
884
cancelBondNative(JNIEnv * env,jobject obj,jbyteArray address)885 static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
886 ALOGV("%s:",__FUNCTION__);
887
888 jbyte *addr;
889 jboolean result;
890 if (!sBluetoothInterface) return JNI_FALSE;
891
892 addr = env->GetByteArrayElements(address, NULL);
893 if (addr == NULL) {
894 jniThrowIOException(env, EINVAL);
895 return JNI_FALSE;
896 }
897
898 int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
899 env->ReleaseByteArrayElements(address, addr, 0);
900 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
901
902 return result;
903 }
904
getConnectionStateNative(JNIEnv * env,jobject obj,jbyteArray address)905 static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) {
906 ALOGV("%s:",__FUNCTION__);
907 if (!sBluetoothInterface) return JNI_FALSE;
908
909 jbyte *addr = env->GetByteArrayElements(address, NULL);
910 if (addr == NULL) {
911 jniThrowIOException(env, EINVAL);
912 return JNI_FALSE;
913 }
914
915 int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr);
916 env->ReleaseByteArrayElements(address, addr, 0);
917
918 return ret;
919 }
920
pinReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jboolean accept,jint len,jbyteArray pinArray)921 static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
922 jint len, jbyteArray pinArray) {
923 ALOGV("%s:",__FUNCTION__);
924
925 jbyte *addr, *pinPtr = NULL;
926 jboolean result = JNI_FALSE;
927 if (!sBluetoothInterface) return result;
928
929 addr = env->GetByteArrayElements(address, NULL);
930 if (addr == NULL) {
931 jniThrowIOException(env, EINVAL);
932 return result;
933 }
934
935 if (accept) {
936 pinPtr = env->GetByteArrayElements(pinArray, NULL);
937 if (pinPtr == NULL) {
938 jniThrowIOException(env, EINVAL);
939 env->ReleaseByteArrayElements(address, addr, 0);
940 return result;
941 }
942 }
943
944 int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
945 (bt_pin_code_t *) pinPtr);
946 env->ReleaseByteArrayElements(address, addr, 0);
947 env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
948 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
949
950 return result;
951 }
952
sspReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jboolean accept,jint passkey)953 static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
954 jint type, jboolean accept, jint passkey) {
955 ALOGV("%s:",__FUNCTION__);
956
957 jbyte *addr;
958 jboolean result = JNI_FALSE;
959 if (!sBluetoothInterface) return result;
960
961 addr = env->GetByteArrayElements(address, NULL);
962 if (addr == NULL) {
963 jniThrowIOException(env, EINVAL);
964 return result;
965 }
966
967 int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
968 (bt_ssp_variant_t) type, accept, passkey);
969 env->ReleaseByteArrayElements(address, addr, 0);
970 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
971
972 return result;
973 }
974
setAdapterPropertyNative(JNIEnv * env,jobject obj,jint type,jbyteArray value)975 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
976 ALOGV("%s:",__FUNCTION__);
977
978 jbyte *val;
979 jboolean result = JNI_FALSE;
980 if (!sBluetoothInterface) return result;
981
982 val = env->GetByteArrayElements(value, NULL);
983 bt_property_t prop;
984 prop.type = (bt_property_type_t) type;
985 prop.len = env->GetArrayLength(value);
986 prop.val = val;
987
988 int ret = sBluetoothInterface->set_adapter_property(&prop);
989 env->ReleaseByteArrayElements(value, val, 0);
990 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
991
992 return result;
993 }
994
getAdapterPropertiesNative(JNIEnv * env,jobject obj)995 static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
996 ALOGV("%s:",__FUNCTION__);
997
998 jboolean result = JNI_FALSE;
999 if (!sBluetoothInterface) return result;
1000
1001 int ret = sBluetoothInterface->get_adapter_properties();
1002 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1003
1004 return result;
1005 }
1006
getAdapterPropertyNative(JNIEnv * env,jobject obj,jint type)1007 static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
1008 ALOGV("%s:",__FUNCTION__);
1009
1010 jboolean result = JNI_FALSE;
1011 if (!sBluetoothInterface) return result;
1012
1013 int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
1014 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1015
1016 return result;
1017 }
1018
getDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type)1019 static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
1020 ALOGV("%s:",__FUNCTION__);
1021
1022 jbyte *addr = NULL;
1023 jboolean result = JNI_FALSE;
1024 if (!sBluetoothInterface) return result;
1025
1026 addr = env->GetByteArrayElements(address, NULL);
1027 if (addr == NULL) {
1028 jniThrowIOException(env, EINVAL);
1029 return result;
1030 }
1031
1032 int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
1033 (bt_property_type_t) type);
1034 env->ReleaseByteArrayElements(address, addr, 0);
1035 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1036
1037 return result;
1038 }
1039
setDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jbyteArray value)1040 static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
1041 jint type, jbyteArray value) {
1042 ALOGV("%s:",__FUNCTION__);
1043
1044 jbyte *val, *addr;
1045 jboolean result = JNI_FALSE;
1046 if (!sBluetoothInterface) return result;
1047
1048 val = env->GetByteArrayElements(value, NULL);
1049 if (val == NULL) {
1050 jniThrowIOException(env, EINVAL);
1051 return result;
1052 }
1053
1054 addr = env->GetByteArrayElements(address, NULL);
1055 if (addr == NULL) {
1056 env->ReleaseByteArrayElements(value, val, 0);
1057 jniThrowIOException(env, EINVAL);
1058 return result;
1059 }
1060
1061
1062 bt_property_t prop;
1063 prop.type = (bt_property_type_t) type;
1064 prop.len = env->GetArrayLength(value);
1065 prop.val = val;
1066
1067 int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
1068 env->ReleaseByteArrayElements(value, val, 0);
1069 env->ReleaseByteArrayElements(address, addr, 0);
1070
1071 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1072
1073 return result;
1074 }
1075
getRemoteServicesNative(JNIEnv * env,jobject obj,jbyteArray address)1076 static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
1077 ALOGV("%s:",__FUNCTION__);
1078
1079 jbyte *addr = NULL;
1080 jboolean result = JNI_FALSE;
1081 if (!sBluetoothInterface) return result;
1082
1083 addr = env->GetByteArrayElements(address, NULL);
1084 if (addr == NULL) {
1085 jniThrowIOException(env, EINVAL);
1086 return result;
1087 }
1088
1089 int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
1090 env->ReleaseByteArrayElements(address, addr, 0);
1091 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1092 return result;
1093 }
1094
connectSocketNative(JNIEnv * env,jobject object,jbyteArray address,jint type,jbyteArray uuidObj,jint channel,jint flag,jint callingUid)1095 static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
1096 jbyteArray uuidObj, jint channel, jint flag, jint callingUid) {
1097 jbyte *addr = NULL, *uuid = NULL;
1098 int socket_fd;
1099 bt_status_t status;
1100
1101 if (!sBluetoothSocketInterface) return -1;
1102
1103 addr = env->GetByteArrayElements(address, NULL);
1104 if (!addr) {
1105 ALOGE("failed to get Bluetooth device address");
1106 goto Fail;
1107 }
1108
1109 if(uuidObj != NULL) {
1110 uuid = env->GetByteArrayElements(uuidObj, NULL);
1111 if (!uuid) {
1112 ALOGE("failed to get uuid");
1113 goto Fail;
1114 }
1115 }
1116
1117 if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
1118 (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1119 != BT_STATUS_SUCCESS) {
1120 ALOGE("Socket connection failed: %d", status);
1121 goto Fail;
1122 }
1123
1124
1125 if (socket_fd < 0) {
1126 ALOGE("Fail to create file descriptor on socket fd");
1127 goto Fail;
1128 }
1129 env->ReleaseByteArrayElements(address, addr, 0);
1130 env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1131 return socket_fd;
1132
1133 Fail:
1134 if (addr) env->ReleaseByteArrayElements(address, addr, 0);
1135 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1136
1137 return -1;
1138 }
1139
createSocketChannelNative(JNIEnv * env,jobject object,jint type,jstring name_str,jbyteArray uuidObj,jint channel,jint flag,jint callingUid)1140 static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
1141 jstring name_str, jbyteArray uuidObj,
1142 jint channel, jint flag, jint callingUid) {
1143 const char *service_name = NULL;
1144 jbyte *uuid = NULL;
1145 int socket_fd;
1146 bt_status_t status;
1147
1148 if (!sBluetoothSocketInterface) return -1;
1149
1150 ALOGV("%s: SOCK FLAG = %x", __FUNCTION__, flag);
1151
1152 if(name_str != NULL) {
1153 service_name = env->GetStringUTFChars(name_str, NULL);
1154 }
1155
1156 if(uuidObj != NULL) {
1157 uuid = env->GetByteArrayElements(uuidObj, NULL);
1158 if (!uuid) {
1159 ALOGE("failed to get uuid");
1160 goto Fail;
1161 }
1162 }
1163 if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
1164 (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1165 != BT_STATUS_SUCCESS) {
1166 ALOGE("Socket listen failed: %d", status);
1167 goto Fail;
1168 }
1169
1170 if (socket_fd < 0) {
1171 ALOGE("Fail to creat file descriptor on socket fd");
1172 goto Fail;
1173 }
1174 if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1175 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1176 return socket_fd;
1177
1178 Fail:
1179 if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1180 if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1181 return -1;
1182 }
1183
configHciSnoopLogNative(JNIEnv * env,jobject obj,jboolean enable)1184 static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
1185 ALOGV("%s:",__FUNCTION__);
1186
1187 jboolean result = JNI_FALSE;
1188
1189 if (!sBluetoothInterface) return result;
1190
1191 int ret = sBluetoothInterface->config_hci_snoop_log(enable);
1192
1193 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1194
1195 return result;
1196 }
1197
readEnergyInfo()1198 static int readEnergyInfo()
1199 {
1200 ALOGV("%s:",__FUNCTION__);
1201 jboolean result = JNI_FALSE;
1202 if (!sBluetoothInterface) return result;
1203 int ret = sBluetoothInterface->read_energy_info();
1204 result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1205 return result;
1206 }
1207
dumpNative(JNIEnv * env,jobject obj,jobject fdObj,jobjectArray argArray)1208 static void dumpNative(JNIEnv *env, jobject obj, jobject fdObj,
1209 jobjectArray argArray)
1210 {
1211 ALOGV("%s()", __FUNCTION__);
1212 if (!sBluetoothInterface) return;
1213
1214 int fd = jniGetFDFromFileDescriptor(env, fdObj);
1215 if (fd < 0) return;
1216
1217 int numArgs = env->GetArrayLength(argArray);
1218
1219 jstring *argObjs = new jstring[numArgs];
1220 const char **args = nullptr;
1221 if (numArgs > 0)
1222 args = new const char*[numArgs];
1223
1224 for (int i = 0; i < numArgs; i++) {
1225 argObjs[i] = (jstring) env->GetObjectArrayElement(argArray, i);
1226 args[i] = env->GetStringUTFChars(argObjs[i], NULL);
1227 }
1228
1229 sBluetoothInterface->dump(fd, args);
1230
1231 for (int i = 0; i < numArgs; i++) {
1232 env->ReleaseStringUTFChars(argObjs[i], args[i]);
1233 }
1234
1235 delete[] args;
1236 delete[] argObjs;
1237 }
1238
factoryResetNative(JNIEnv * env,jobject obj)1239 static jboolean factoryResetNative(JNIEnv *env, jobject obj) {
1240 ALOGV("%s:", __FUNCTION__);
1241 if (!sBluetoothInterface) return JNI_FALSE;
1242 int ret = sBluetoothInterface->config_clear();
1243 return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1244 }
1245
interopDatabaseClearNative(JNIEnv * env,jobject obj)1246 static void interopDatabaseClearNative(JNIEnv *env, jobject obj) {
1247 ALOGV("%s()", __FUNCTION__);
1248 if (!sBluetoothInterface) return;
1249 sBluetoothInterface->interop_database_clear();
1250 }
1251
interopDatabaseAddNative(JNIEnv * env,jobject obj,int feature,jbyteArray address,int length)1252 static void interopDatabaseAddNative(JNIEnv *env, jobject obj, int feature,
1253 jbyteArray address, int length) {
1254 ALOGV("%s()", __FUNCTION__);
1255 if (!sBluetoothInterface) return;
1256
1257 jbyte *addr = env->GetByteArrayElements(address, NULL);
1258 if (addr == NULL) {
1259 jniThrowIOException(env, EINVAL);
1260 return;
1261 }
1262
1263 sBluetoothInterface->interop_database_add(feature, (bt_bdaddr_t *)addr, length);
1264 env->ReleaseByteArrayElements(address, addr, 0);
1265 }
1266
1267 static JNINativeMethod sMethods[] = {
1268 /* name, signature, funcPtr */
1269 {"classInitNative", "()V", (void *) classInitNative},
1270 {"initNative", "()Z", (void *) initNative},
1271 {"cleanupNative", "()V", (void*) cleanupNative},
1272 {"enableNative", "(Z)Z", (void*) enableNative},
1273 {"disableNative", "()Z", (void*) disableNative},
1274 {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
1275 {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
1276 {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
1277 {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
1278 {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
1279 {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
1280 {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
1281 {"createBondNative", "([BI)Z", (void*) createBondNative},
1282 {"createBondOutOfBandNative", "([BILandroid/bluetooth/OobData;)Z", (void*) createBondOutOfBandNative},
1283 {"removeBondNative", "([B)Z", (void*) removeBondNative},
1284 {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
1285 {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
1286 {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
1287 {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
1288 {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
1289 {"connectSocketNative", "([BI[BIII)I", (void*) connectSocketNative},
1290 {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
1291 (void*) createSocketChannelNative},
1292 {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
1293 {"alarmFiredNative", "()V", (void *) alarmFiredNative},
1294 {"readEnergyInfo", "()I", (void*) readEnergyInfo},
1295 {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V", (void*) dumpNative},
1296 {"factoryResetNative", "()Z", (void*)factoryResetNative},
1297 {"interopDatabaseClearNative", "()V", (void*) interopDatabaseClearNative},
1298 {"interopDatabaseAddNative", "(I[BI)V", (void*) interopDatabaseAddNative}
1299 };
1300
register_com_android_bluetooth_btservice_AdapterService(JNIEnv * env)1301 int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
1302 {
1303 return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
1304 sMethods, NELEM(sMethods));
1305 }
1306
1307 } /* namespace android */
1308
1309
1310 /*
1311 * JNI Initialization
1312 */
JNI_OnLoad(JavaVM * jvm,void * reserved)1313 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
1314 {
1315 JNIEnv *e;
1316 int status;
1317
1318 ALOGV("Bluetooth Adapter Service : loading JNI\n");
1319
1320 // Check JNI version
1321 if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
1322 ALOGE("JNI version mismatch error");
1323 return JNI_ERR;
1324 }
1325
1326 if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
1327 ALOGE("jni adapter service registration failure, status: %d", status);
1328 return JNI_ERR;
1329 }
1330
1331 if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
1332 ALOGE("jni hfp registration failure, status: %d", status);
1333 return JNI_ERR;
1334 }
1335
1336 if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {
1337 ALOGE("jni hfp client registration failure, status: %d", status);
1338 return JNI_ERR;
1339 }
1340
1341 if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
1342 ALOGE("jni a2dp source registration failure: %d", status);
1343 return JNI_ERR;
1344 }
1345
1346 if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) {
1347 ALOGE("jni a2dp sink registration failure: %d", status);
1348 return JNI_ERR;
1349 }
1350
1351 if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
1352 ALOGE("jni avrcp target registration failure: %d", status);
1353 return JNI_ERR;
1354 }
1355
1356 if ((status = android::register_com_android_bluetooth_avrcp_controller(e)) < 0) {
1357 ALOGE("jni avrcp controller registration failure: %d", status);
1358 return JNI_ERR;
1359 }
1360
1361 if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
1362 ALOGE("jni hid registration failure: %d", status);
1363 return JNI_ERR;
1364 }
1365
1366 if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
1367 ALOGE("jni hdp registration failure: %d", status);
1368 return JNI_ERR;
1369 }
1370
1371 if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
1372 ALOGE("jni pan registration failure: %d", status);
1373 return JNI_ERR;
1374 }
1375
1376 if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
1377 ALOGE("jni gatt registration failure: %d", status);
1378 return JNI_ERR;
1379 }
1380
1381 if ((status = android::register_com_android_bluetooth_sdp(e)) < 0) {
1382 ALOGE("jni sdp registration failure: %d", status);
1383 return JNI_ERR;
1384 }
1385
1386 return JNI_VERSION_1_6;
1387 }
1388