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