1c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood/* 2c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * Copyright (C) 2012 The Android Open Source Project 3c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * 4c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * you may not use this file except in compliance with the License. 6c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * You may obtain a copy of the License at 7c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * 8c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * 10c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * See the License for the specific language governing permissions and 14c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood * limitations under the License. 15c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood */ 16c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 17c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#define LOG_TAG "BluetoothA2dpSinkServiceJni" 18c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 19c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#define LOG_NDEBUG 0 20c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 21c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#include "com_android_bluetooth.h" 22c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#include "hardware/bt_av.h" 23c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#include "utils/Log.h" 24c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#include "android_runtime/AndroidRuntime.h" 25c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 26c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood#include <string.h> 27c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 28c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodnamespace android { 29c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jmethodID method_onConnectionStateChanged; 30c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jmethodID method_onAudioStateChanged; 31c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jmethodID method_onAudioConfigChanged; 32c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 33c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic const btav_interface_t *sBluetoothA2dpInterface = NULL; 34c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jobject mCallbacksObj = NULL; 35c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic JNIEnv *sCallbackEnv = NULL; 36c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 37c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic bool checkCallbackThread() { 38c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood // Always fetch the latest callbackEnv from AdapterService. 39c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood // Caching this could cause this sCallbackEnv to go out-of-sync 40c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event 41c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood // is received 42c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood //if (sCallbackEnv == NULL) { 43c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv = getCallbackEnv(); 44c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood //} 45c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 46c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood JNIEnv* env = AndroidRuntime::getJNIEnv(); 47c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 48c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return true; 49c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 50c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 51c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void bta2dp_connection_state_callback(btav_connection_state_t state, bt_bdaddr_t* bd_addr) { 52c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jbyteArray addr; 53c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 54c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGI("%s", __FUNCTION__); 55c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 56c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!checkCallbackThread()) { \ 57c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \ 58c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; \ 59c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 60c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 61c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!addr) { 62c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Fail to new jbyteArray bd addr for connection state"); 63c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 64c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 65c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 66c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 67c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr); 68c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state, 69c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr); 70c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 71c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->DeleteLocalRef(addr); 72c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 73c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 74c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* bd_addr) { 75c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jbyteArray addr; 76c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 77c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGI("%s", __FUNCTION__); 78c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 79c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!checkCallbackThread()) { \ 80c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \ 81c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; \ 82c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 83c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 84c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!addr) { 85c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Fail to new jbyteArray bd addr for connection state"); 86c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 87c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 88c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 89c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 90c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr); 91c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state, 92c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr); 93c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 94c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->DeleteLocalRef(addr); 95c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 96c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 97c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void bta2dp_audio_config_callback(bt_bdaddr_t *bd_addr, uint32_t sample_rate, uint8_t channel_count) { 98c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jbyteArray addr; 99c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 100c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGI("%s", __FUNCTION__); 101c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 102c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!checkCallbackThread()) { \ 103c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \ 104c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; \ 105c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 106c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 107c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!addr) { 108c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Fail to new jbyteArray bd addr for connection state"); 109c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 110c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 111c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 112c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 113c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr); 114c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioConfigChanged, addr, (jint)sample_rate, (jint)channel_count); 115c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 116c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sCallbackEnv->DeleteLocalRef(addr); 117c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 118c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 119c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic btav_callbacks_t sBluetoothA2dpCallbacks = { 120c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sizeof(sBluetoothA2dpCallbacks), 121c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bta2dp_connection_state_callback, 122c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bta2dp_audio_state_callback, 123c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bta2dp_audio_config_callback 124c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood}; 125c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 126c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void classInitNative(JNIEnv* env, jclass clazz) { 127c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood int err; 128c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood const bt_interface_t* btInf; 129c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_status_t status; 130c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 131c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood method_onConnectionStateChanged = 132c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); 133c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 134c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood method_onAudioStateChanged = 135c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); 136c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 137c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood method_onAudioConfigChanged = 138c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->GetMethodID(clazz, "onAudioConfigChanged", "([BII)V"); 139c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 140c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGI("%s: succeeds", __FUNCTION__); 141c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 142c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 143c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void initNative(JNIEnv *env, jobject object) { 144c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood const bt_interface_t* btInf; 145c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_status_t status; 146c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 147c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ( (btInf = getBluetoothInterface()) == NULL) { 148c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Bluetooth module is not loaded"); 149c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 150c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 151c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 152c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (sBluetoothA2dpInterface !=NULL) { 153c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGW("Cleaning up A2DP Interface before initializing..."); 154c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sBluetoothA2dpInterface->cleanup(); 155c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sBluetoothA2dpInterface = NULL; 156c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 157c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 158c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (mCallbacksObj != NULL) { 159c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGW("Cleaning up A2DP callback object"); 160c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->DeleteGlobalRef(mCallbacksObj); 161c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood mCallbacksObj = NULL; 162c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 163c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 164c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ( (sBluetoothA2dpInterface = (btav_interface_t *) 165c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_SINK_ID)) == NULL) { 166c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Failed to get Bluetooth A2DP Sink Interface"); 167c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 168c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 169c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 170c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks)) != BT_STATUS_SUCCESS) { 171c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Failed to initialize Bluetooth A2DP Sink, status: %d", status); 172c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sBluetoothA2dpInterface = NULL; 173c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 174c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 175c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 176c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood mCallbacksObj = env->NewGlobalRef(object); 177c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 178c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 179c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic void cleanupNative(JNIEnv *env, jobject object) { 180c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood const bt_interface_t* btInf; 181c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_status_t status; 182c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 183c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ( (btInf = getBluetoothInterface()) == NULL) { 184c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Bluetooth module is not loaded"); 185c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return; 186c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 187c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 188c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (sBluetoothA2dpInterface !=NULL) { 189c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sBluetoothA2dpInterface->cleanup(); 190c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sBluetoothA2dpInterface = NULL; 191c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 192c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 193c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (mCallbacksObj != NULL) { 194c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->DeleteGlobalRef(mCallbacksObj); 195c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood mCallbacksObj = NULL; 196c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 197c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 198c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 199c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) { 200c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jbyte *addr; 201c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_bdaddr_t * btAddr; 202c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_status_t status; 203c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 204c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface); 205c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!sBluetoothA2dpInterface) return JNI_FALSE; 206c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 207c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr = env->GetByteArrayElements(address, NULL); 208c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood btAddr = (bt_bdaddr_t *) addr; 209c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!addr) { 210c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jniThrowIOException(env, EINVAL); 211c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return JNI_FALSE; 212c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 213c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 214c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 215c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Failed HF connection, status: %d", status); 216c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 217c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->ReleaseByteArrayElements(address, addr, 0); 218c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 219c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 220c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 221c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic jboolean disconnectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) { 222c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jbyte *addr; 223c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood bt_status_t status; 224c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 225c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!sBluetoothA2dpInterface) return JNI_FALSE; 226c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 227c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood addr = env->GetByteArrayElements(address, NULL); 228c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if (!addr) { 229c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood jniThrowIOException(env, EINVAL); 230c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return JNI_FALSE; 231c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 232c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 233c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood if ( (status = sBluetoothA2dpInterface->disconnect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 234c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood ALOGE("Failed HF disconnection, status: %d", status); 235c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood } 236c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood env->ReleaseByteArrayElements(address, addr, 0); 237c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 238c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 239c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 240c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodstatic JNINativeMethod sMethods[] = { 241c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood {"classInitNative", "()V", (void *) classInitNative}, 242c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood {"initNative", "()V", (void *) initNative}, 243c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood {"cleanupNative", "()V", (void *) cleanupNative}, 244c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood {"connectA2dpNative", "([B)Z", (void *) connectA2dpNative}, 245c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood {"disconnectA2dpNative", "([B)Z", (void *) disconnectA2dpNative}, 246c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood}; 247c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 248c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwoodint register_com_android_bluetooth_a2dp_sink(JNIEnv* env) 249c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood{ 250c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood return jniRegisterNativeMethods(env, "com/android/bluetooth/a2dp/A2dpSinkStateMachine", 251c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood sMethods, NELEM(sMethods)); 252c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 253c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood 254c030f08f419d596c4aa216c9cca9867e7b5486f0Mike Lockwood} 255