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