16c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie/*
2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project
3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License");
5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License.
6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at
7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *      http://www.apache.org/licenses/LICENSE-2.0
9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software
11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS,
12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and
14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License.
156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie */
16ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu
176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#define LOG_TAG "BluetoothA2dpServiceJni"
186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
196c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#define LOG_NDEBUG 0
206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
21dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen#include "android_runtime/AndroidRuntime.h"
226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "com_android_bluetooth.h"
236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "hardware/bt_av.h"
246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "utils/Log.h"
256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include <string.h>
276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xienamespace android {
296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jmethodID method_onConnectionStateChanged;
30ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamystatic jmethodID method_onAudioStateChanged;
3133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovstatic jmethodID method_onCodecConfigChanged;
326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
3308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavovstatic struct {
3408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jclass clazz;
3508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jmethodID constructor;
368a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecType;
378a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecPriority;
388a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getSampleRate;
398a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getBitsPerSample;
408a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getChannelMode;
418a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecSpecific1;
428a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecSpecific2;
438a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecSpecific3;
448a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  jmethodID getCodecSpecific4;
4508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov} android_bluetooth_BluetoothCodecConfig;
4608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
4733b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovstatic const btav_source_interface_t* sBluetoothA2dpInterface = NULL;
486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jobject mCallbacksObj = NULL;
496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
50dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenstatic void bta2dp_connection_state_callback(btav_connection_state_t state,
51dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                             bt_bdaddr_t* bd_addr) {
52dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  ALOGI("%s", __func__);
53dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  CallbackEnv sCallbackEnv(__func__);
54dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!sCallbackEnv.valid()) return;
55dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
562116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  ScopedLocalRef<jbyteArray> addr(
572116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)));
582116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  if (!addr.get()) {
592116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach    ALOGE("Fail to new jbyteArray bd addr for connection state");
602116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach    return;
612116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  }
62dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
632116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(bt_bdaddr_t),
642116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach                                   (jbyte*)bd_addr);
65dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
66479b34835a560d032e211c3c27e10384af69c3b9Marie Janssen                               (jint)state, addr.get());
676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
69dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenstatic void bta2dp_audio_state_callback(btav_audio_state_t state,
70dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                        bt_bdaddr_t* bd_addr) {
71dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  ALOGI("%s", __func__);
72dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  CallbackEnv sCallbackEnv(__func__);
73dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!sCallbackEnv.valid()) return;
74dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
752116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  ScopedLocalRef<jbyteArray> addr(
762116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach      sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)));
772116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  if (!addr.get()) {
782116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach    ALOGE("Fail to new jbyteArray bd addr for connection state");
792116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach    return;
802116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  }
81dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
822116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach  sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(bt_bdaddr_t),
832116dbf94fbc00da999ac629c78627983f599a26Andre Eisenbach                                   (jbyte*)bd_addr);
84dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
85479b34835a560d032e211c3c27e10384af69c3b9Marie Janssen                               (jint)state, addr.get());
86ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy}
87ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy
8833b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovstatic void bta2dp_audio_config_callback(
8933b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov    btav_a2dp_codec_config_t codec_config,
9008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
9108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) {
9233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  ALOGI("%s", __func__);
9333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  CallbackEnv sCallbackEnv(__func__);
9433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  if (!sCallbackEnv.valid()) return;
9533b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
9608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jobject codecConfigObj = sCallbackEnv->NewObject(
9708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      android_bluetooth_BluetoothCodecConfig.clazz,
9808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      android_bluetooth_BluetoothCodecConfig.constructor,
9908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      (jint)codec_config.codec_type, (jint)codec_config.codec_priority,
10008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      (jint)codec_config.sample_rate, (jint)codec_config.bits_per_sample,
10108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      (jint)codec_config.channel_mode, (jlong)codec_config.codec_specific_1,
10233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov      (jlong)codec_config.codec_specific_2,
10333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov      (jlong)codec_config.codec_specific_3,
10433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov      (jlong)codec_config.codec_specific_4);
10508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
10608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jsize i = 0;
10708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jobjectArray local_capabilities_array = sCallbackEnv->NewObjectArray(
10808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      (jsize)codecs_local_capabilities.size(),
10908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      android_bluetooth_BluetoothCodecConfig.clazz, NULL);
11008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  for (auto const& cap : codecs_local_capabilities) {
11108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    jobject capObj = sCallbackEnv->NewObject(
11208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        android_bluetooth_BluetoothCodecConfig.clazz,
11308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        android_bluetooth_BluetoothCodecConfig.constructor,
11408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate,
11508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jint)cap.bits_per_sample, (jint)cap.channel_mode,
11608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2,
11708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4);
11808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    sCallbackEnv->SetObjectArrayElement(local_capabilities_array, i++, capObj);
11908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    sCallbackEnv->DeleteLocalRef(capObj);
12008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  }
12108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
12208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  i = 0;
12308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jobjectArray selectable_capabilities_array = sCallbackEnv->NewObjectArray(
12408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      (jsize)codecs_selectable_capabilities.size(),
12508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      android_bluetooth_BluetoothCodecConfig.clazz, NULL);
12608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  for (auto const& cap : codecs_selectable_capabilities) {
12708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    jobject capObj = sCallbackEnv->NewObject(
12808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        android_bluetooth_BluetoothCodecConfig.clazz,
12908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        android_bluetooth_BluetoothCodecConfig.constructor,
13008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate,
13108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jint)cap.bits_per_sample, (jint)cap.channel_mode,
13208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2,
13308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov        (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4);
13408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    sCallbackEnv->SetObjectArrayElement(selectable_capabilities_array, i++,
13508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov                                        capObj);
13608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    sCallbackEnv->DeleteLocalRef(capObj);
13708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  }
13808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
13908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCodecConfigChanged,
14008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov                               codecConfigObj, local_capabilities_array,
14108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov                               selectable_capabilities_array);
14233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov}
14333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
14433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavovstatic btav_source_callbacks_t sBluetoothA2dpCallbacks = {
145dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sizeof(sBluetoothA2dpCallbacks), bta2dp_connection_state_callback,
14633b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov    bta2dp_audio_state_callback, bta2dp_audio_config_callback,
1476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie};
1486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic void classInitNative(JNIEnv* env, jclass clazz) {
15008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  jclass jniBluetoothCodecConfigClass =
15108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      env->FindClass("android/bluetooth/BluetoothCodecConfig");
15208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.constructor =
15308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "<init>", "(IIIIIJJJJ)V");
1548a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecType =
1558a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I");
1568a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecPriority =
1578a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I");
1588a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getSampleRate =
1598a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I");
1608a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getBitsPerSample =
1618a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I");
1628a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getChannelMode =
1638a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I");
1648a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecSpecific1 = env->GetMethodID(
1658a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J");
1668a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecSpecific2 = env->GetMethodID(
1678a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J");
1688a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecSpecific3 = env->GetMethodID(
1698a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J");
1708a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.getCodecSpecific4 = env->GetMethodID(
1718a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J");
17208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
173dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  method_onConnectionStateChanged =
174dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
1756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
176dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  method_onAudioStateChanged =
177dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen      env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
1786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
17908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  method_onCodecConfigChanged = env->GetMethodID(
18008d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      clazz, "onCodecConfigChanged",
18108d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      "(Landroid/bluetooth/BluetoothCodecConfig;[Landroid/bluetooth/"
18208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      "BluetoothCodecConfig;[Landroid/bluetooth/BluetoothCodecConfig;)V");
18333b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
184dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  ALOGI("%s: succeeds", __func__);
1856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
1866c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1878a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavovstatic std::vector<btav_a2dp_codec_config_t> prepareCodecPreferences(
1888a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    JNIEnv* env, jobject object, jobjectArray codecConfigArray) {
1898a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  std::vector<btav_a2dp_codec_config_t> codec_preferences;
1908a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov
1918a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  int numConfigs = env->GetArrayLength(codecConfigArray);
1928a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  for (int i = 0; i < numConfigs; i++) {
1938a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i);
1948a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    if (jcodecConfig == nullptr) continue;
1958a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    if (!env->IsInstanceOf(jcodecConfig,
1968a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov                           android_bluetooth_BluetoothCodecConfig.clazz)) {
1978a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      ALOGE("Invalid BluetoothCodecConfig instance");
1988a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      continue;
1998a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    }
2008a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jint codecType = env->CallIntMethod(
2018a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecType);
2028a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jint codecPriority = env->CallIntMethod(
2038a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecPriority);
2048a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jint sampleRate = env->CallIntMethod(
2058a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getSampleRate);
2068a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jint bitsPerSample = env->CallIntMethod(
2078a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getBitsPerSample);
2088a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jint channelMode = env->CallIntMethod(
2098a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getChannelMode);
2108a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jlong codecSpecific1 = env->CallLongMethod(
2118a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific1);
2128a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jlong codecSpecific2 = env->CallLongMethod(
2138a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific2);
2148a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jlong codecSpecific3 = env->CallLongMethod(
2158a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific3);
2168a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    jlong codecSpecific4 = env->CallLongMethod(
2178a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific4);
2188a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov
2198a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    btav_a2dp_codec_config_t codec_config = {
2208a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_type = static_cast<btav_a2dp_codec_index_t>(codecType),
2218a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_priority =
2228a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov            static_cast<btav_a2dp_codec_priority_t>(codecPriority),
2238a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(sampleRate),
2248a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .bits_per_sample =
2258a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov            static_cast<btav_a2dp_codec_bits_per_sample_t>(bitsPerSample),
2268a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .channel_mode =
2278a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov            static_cast<btav_a2dp_codec_channel_mode_t>(channelMode),
2288a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_specific_1 = codecSpecific1,
2298a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_specific_2 = codecSpecific2,
2308a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_specific_3 = codecSpecific3,
2318a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov        .codec_specific_4 = codecSpecific4};
2328a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov
2338a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    codec_preferences.push_back(codec_config);
2348a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  }
2358a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  return codec_preferences;
2368a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov}
2378a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov
2388a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavovstatic void initNative(JNIEnv* env, jobject object,
2398a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov                       jobjectArray codecConfigArray) {
240dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  const bt_interface_t* btInf = getBluetoothInterface();
241dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (btInf == NULL) {
242dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Bluetooth module is not loaded");
243dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return;
244dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
245dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
246dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (sBluetoothA2dpInterface != NULL) {
247dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGW("Cleaning up A2DP Interface before initializing...");
248dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sBluetoothA2dpInterface->cleanup();
249dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sBluetoothA2dpInterface = NULL;
250dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
251dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
252dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (mCallbacksObj != NULL) {
253dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGW("Cleaning up A2DP callback object");
254dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    env->DeleteGlobalRef(mCallbacksObj);
255dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    mCallbacksObj = NULL;
256dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
257dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
258dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if ((mCallbacksObj = env->NewGlobalRef(object)) == NULL) {
259dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Failed to allocate Global Ref for A2DP Callbacks");
260dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return;
261dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
262dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
26308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef(
26408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov      env->FindClass("android/bluetooth/BluetoothCodecConfig"));
26508d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) {
26608d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    ALOGE("Failed to allocate Global Ref for BluetoothCodecConfig class");
26708d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov    return;
26808d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  }
26908d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
27033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  sBluetoothA2dpInterface =
27133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov      (btav_source_interface_t*)btInf->get_profile_interface(
27233b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov          BT_PROFILE_ADVANCED_AUDIO_ID);
273dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (sBluetoothA2dpInterface == NULL) {
274dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Failed to get Bluetooth A2DP Interface");
275dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return;
276dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
277dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
2788a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  std::vector<btav_a2dp_codec_config_t> codec_priorities =
2798a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      prepareCodecPreferences(env, object, codecConfigArray);
2808a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov
2818a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  bt_status_t status =
2828a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, codec_priorities);
283dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (status != BT_STATUS_SUCCESS) {
284dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status);
285dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sBluetoothA2dpInterface = NULL;
286dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return;
287dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
2886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
2896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
290dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenstatic void cleanupNative(JNIEnv* env, jobject object) {
291dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  const bt_interface_t* btInf = getBluetoothInterface();
292dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (btInf == NULL) {
293dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Bluetooth module is not loaded");
294dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return;
295dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
296dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
297dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (sBluetoothA2dpInterface != NULL) {
298dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sBluetoothA2dpInterface->cleanup();
299dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    sBluetoothA2dpInterface = NULL;
300dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
301dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
30208d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  env->DeleteGlobalRef(android_bluetooth_BluetoothCodecConfig.clazz);
30308d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov  android_bluetooth_BluetoothCodecConfig.clazz = nullptr;
30408d3925d3d72837e6f86c9e0beaed5f7b813ea37Pavlin Radoslavov
305dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (mCallbacksObj != NULL) {
306dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    env->DeleteGlobalRef(mCallbacksObj);
307dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    mCallbacksObj = NULL;
308dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
3096654f5c903de510a70f9e72cd5ad7837b615d93ffredc}
3106654f5c903de510a70f9e72cd5ad7837b615d93ffredc
311dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenstatic jboolean connectA2dpNative(JNIEnv* env, jobject object,
312dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                  jbyteArray address) {
313dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  ALOGI("%s: sBluetoothA2dpInterface: %p", __func__, sBluetoothA2dpInterface);
314dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!sBluetoothA2dpInterface) return JNI_FALSE;
315dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
316dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  jbyte* addr = env->GetByteArrayElements(address, NULL);
317dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!addr) {
318dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    jniThrowIOException(env, EINVAL);
319dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return JNI_FALSE;
320dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
321dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
322dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  bt_status_t status = sBluetoothA2dpInterface->connect((bt_bdaddr_t*)addr);
323dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (status != BT_STATUS_SUCCESS) {
324dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Failed HF connection, status: %d", status);
325dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
326dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  env->ReleaseByteArrayElements(address, addr, 0);
327dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
3286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
3296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
330dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenstatic jboolean disconnectA2dpNative(JNIEnv* env, jobject object,
331dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                     jbyteArray address) {
332dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!sBluetoothA2dpInterface) return JNI_FALSE;
333dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
334dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  jbyte* addr = env->GetByteArrayElements(address, NULL);
335dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (!addr) {
336dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    jniThrowIOException(env, EINVAL);
337dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    return JNI_FALSE;
338dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
339dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen
340dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  bt_status_t status = sBluetoothA2dpInterface->disconnect((bt_bdaddr_t*)addr);
341dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  if (status != BT_STATUS_SUCCESS) {
342dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    ALOGE("Failed HF disconnection, status: %d", status);
343dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  }
344dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  env->ReleaseByteArrayElements(address, addr, 0);
345dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
3466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
3476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
3488a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavovstatic jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object,
3498a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov                                               jobjectArray codecConfigArray) {
35033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  if (!sBluetoothA2dpInterface) return JNI_FALSE;
35133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
3528a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov  std::vector<btav_a2dp_codec_config_t> codec_preferences =
3538a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov      prepareCodecPreferences(env, object, codecConfigArray);
35433b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
35533b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  bt_status_t status = sBluetoothA2dpInterface->config_codec(codec_preferences);
35633b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  if (status != BT_STATUS_SUCCESS) {
35733b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov    ALOGE("Failed codec configuration, status: %d", status);
35833b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  }
35933b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
36033b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov}
36133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov
3626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic JNINativeMethod sMethods[] = {
363dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    {"classInitNative", "()V", (void*)classInitNative},
3648a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    {"initNative", "([Landroid/bluetooth/BluetoothCodecConfig;)V",
3658a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov     (void*)initNative},
366dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    {"cleanupNative", "()V", (void*)cleanupNative},
367dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    {"connectA2dpNative", "([B)Z", (void*)connectA2dpNative},
368dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen    {"disconnectA2dpNative", "([B)Z", (void*)disconnectA2dpNative},
3698a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov    {"setCodecConfigPreferenceNative",
3708a9f762c80d436719375de5d5f83c1c11e9f5723Pavlin Radoslavov     "([Landroid/bluetooth/BluetoothCodecConfig;)Z",
37133b6b7d2b08dcd7ced1809e2ac653c5e8c2514afPavlin Radoslavov     (void*)setCodecConfigPreferenceNative},
3726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie};
3736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
374dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssenint register_com_android_bluetooth_a2dp(JNIEnv* env) {
375dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen  return jniRegisterNativeMethods(env,
376dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                  "com/android/bluetooth/a2dp/A2dpStateMachine",
377dbd48b5fbeb449c31c92cbe8565db5e8f74c41e6Marie Janssen                                  sMethods, NELEM(sMethods));
3786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
3796c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
380