• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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