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