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
216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "com_android_bluetooth.h"
226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "hardware/bt_av.h"
236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "utils/Log.h"
246c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "android_runtime/AndroidRuntime.h"
256c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
266c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include <string.h>
276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xienamespace android {
296c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jmethodID method_onConnectionStateChanged;
30ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamystatic jmethodID method_onAudioStateChanged;
316c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
326c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic const btav_interface_t *sBluetoothA2dpInterface = NULL;
336c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jobject mCallbacksObj = NULL;
346c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic JNIEnv *sCallbackEnv = NULL;
356c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
366c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic bool checkCallbackThread() {
3793f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    // Always fetch the latest callbackEnv from AdapterService.
3893f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    // Caching this could cause this sCallbackEnv to go out-of-sync
3993f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
4093f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    // is received
4193f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    //if (sCallbackEnv == NULL) {
4293f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    sCallbackEnv = getCallbackEnv();
4393f548ff8560bdecdc4bdd2f91f7dacda1e6bbc3Kausik Sinnaswamy    //}
446c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
456c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    JNIEnv* env = AndroidRuntime::getJNIEnv();
466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    return true;
486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
506c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic void bta2dp_connection_state_callback(btav_connection_state_t state, bt_bdaddr_t* bd_addr) {
516c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jbyteArray addr;
526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
53c55a9837c004044051b71bb47182ace156691283Matthew Xie    ALOGI("%s", __FUNCTION__);
546c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
556c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!checkCallbackThread()) {                                       \
56c55a9837c004044051b71bb47182ace156691283Matthew Xie        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
576c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        return;                                                         \
586c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
596c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!addr) {
61c55a9837c004044051b71bb47182ace156691283Matthew Xie        ALOGE("Fail to new jbyteArray bd addr for connection state");
626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        return;
646c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie                                 addr);
696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    sCallbackEnv->DeleteLocalRef(addr);
716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
73ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamystatic void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* bd_addr) {
74ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    jbyteArray addr;
75ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy
76e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie    ALOGI("%s", __FUNCTION__);
77ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy
78ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    if (!checkCallbackThread()) {                                       \
79e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
80ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy        return;                                                         \
81ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    }
82ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
83ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    if (!addr) {
84e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Fail to new jbyteArray bd addr for connection state");
85ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
86ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy        return;
87ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    }
88ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy
89ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
90ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state,
91ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy                                 addr);
92ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
93ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    sCallbackEnv->DeleteLocalRef(addr);
94ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy}
95ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy
966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic btav_callbacks_t sBluetoothA2dpCallbacks = {
976c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    sizeof(sBluetoothA2dpCallbacks),
986c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    bta2dp_connection_state_callback,
9921f921a43af4c93f23f8d3fd52033c9720200e89Ajay Panicker    bta2dp_audio_state_callback,
10021f921a43af4c93f23f8d3fd52033c9720200e89Ajay Panicker    NULL, /* audio_config_cb */
1016c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie};
1026c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1036c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic void classInitNative(JNIEnv* env, jclass clazz) {
1046c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    method_onConnectionStateChanged =
1056c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
1066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
107ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy    method_onAudioStateChanged =
108ac234ef0ddd67471d82f77c41535a5ea1b68b443Kausik Sinnaswamy        env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
1096c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
110c55a9837c004044051b71bb47182ace156691283Matthew Xie    ALOGI("%s: succeeds", __FUNCTION__);
1116c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
1126c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1136654f5c903de510a70f9e72cd5ad7837b615d93ffredcstatic void initNative(JNIEnv *env, jobject object) {
1146654f5c903de510a70f9e72cd5ad7837b615d93ffredc    const bt_interface_t* btInf;
1156654f5c903de510a70f9e72cd5ad7837b615d93ffredc    bt_status_t status;
1166654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1176654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if ( (btInf = getBluetoothInterface()) == NULL) {
118e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Bluetooth module is not loaded");
1196654f5c903de510a70f9e72cd5ad7837b615d93ffredc        return;
1206654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1216654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1226654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if (sBluetoothA2dpInterface !=NULL) {
123e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie         ALOGW("Cleaning up A2DP Interface before initializing...");
1246654f5c903de510a70f9e72cd5ad7837b615d93ffredc         sBluetoothA2dpInterface->cleanup();
1256654f5c903de510a70f9e72cd5ad7837b615d93ffredc         sBluetoothA2dpInterface = NULL;
1266654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1276654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1286654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if (mCallbacksObj != NULL) {
129e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie         ALOGW("Cleaning up A2DP callback object");
1306654f5c903de510a70f9e72cd5ad7837b615d93ffredc         env->DeleteGlobalRef(mCallbacksObj);
1316654f5c903de510a70f9e72cd5ad7837b615d93ffredc         mCallbacksObj = NULL;
1326654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1336654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1346654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if ( (sBluetoothA2dpInterface = (btav_interface_t *)
1356654f5c903de510a70f9e72cd5ad7837b615d93ffredc          btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
136e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Failed to get Bluetooth A2DP Interface");
1376654f5c903de510a70f9e72cd5ad7837b615d93ffredc        return;
1386654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1396654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1406654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks)) != BT_STATUS_SUCCESS) {
141e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status);
1426654f5c903de510a70f9e72cd5ad7837b615d93ffredc        sBluetoothA2dpInterface = NULL;
1436654f5c903de510a70f9e72cd5ad7837b615d93ffredc        return;
1446654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1456654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    mCallbacksObj = env->NewGlobalRef(object);
1476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
1486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1496654f5c903de510a70f9e72cd5ad7837b615d93ffredcstatic void cleanupNative(JNIEnv *env, jobject object) {
1506654f5c903de510a70f9e72cd5ad7837b615d93ffredc    const bt_interface_t* btInf;
1516654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1526654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if ( (btInf = getBluetoothInterface()) == NULL) {
153e469f16e5a7d99471d7db1b216d422e8d12cc4cfMatthew Xie        ALOGE("Bluetooth module is not loaded");
1546654f5c903de510a70f9e72cd5ad7837b615d93ffredc        return;
1556654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1566654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1576654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if (sBluetoothA2dpInterface !=NULL) {
1586654f5c903de510a70f9e72cd5ad7837b615d93ffredc        sBluetoothA2dpInterface->cleanup();
1596654f5c903de510a70f9e72cd5ad7837b615d93ffredc        sBluetoothA2dpInterface = NULL;
1606654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1616654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1626654f5c903de510a70f9e72cd5ad7837b615d93ffredc    if (mCallbacksObj != NULL) {
1636654f5c903de510a70f9e72cd5ad7837b615d93ffredc        env->DeleteGlobalRef(mCallbacksObj);
1646654f5c903de510a70f9e72cd5ad7837b615d93ffredc        mCallbacksObj = NULL;
1656654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
1666654f5c903de510a70f9e72cd5ad7837b615d93ffredc}
1676654f5c903de510a70f9e72cd5ad7837b615d93ffredc
1686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
1696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jbyte *addr;
1706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    bt_bdaddr_t * btAddr;
1716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    bt_status_t status;
1726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
173c55a9837c004044051b71bb47182ace156691283Matthew Xie    ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface);
1746c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!sBluetoothA2dpInterface) return JNI_FALSE;
1756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    addr = env->GetByteArrayElements(address, NULL);
1776c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    btAddr = (bt_bdaddr_t *) addr;
1786c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!addr) {
1796c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        jniThrowIOException(env, EINVAL);
1806c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        return JNI_FALSE;
1816c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
1826c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1836c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
184c55a9837c004044051b71bb47182ace156691283Matthew Xie        ALOGE("Failed HF connection, status: %d", status);
1856c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
1866c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    env->ReleaseByteArrayElements(address, addr, 0);
1876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
1896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1906c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic jboolean disconnectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
1916c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jbyte *addr;
1926c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    bt_status_t status;
1936c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1946c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!sBluetoothA2dpInterface) return JNI_FALSE;
1956c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1966c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    addr = env->GetByteArrayElements(address, NULL);
1976c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if (!addr) {
1986c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        jniThrowIOException(env, EINVAL);
1996c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        return JNI_FALSE;
2006c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
2016c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
2026c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    if ( (status = sBluetoothA2dpInterface->disconnect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
203c55a9837c004044051b71bb47182ace156691283Matthew Xie        ALOGE("Failed HF disconnection, status: %d", status);
2046c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    }
2056c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    env->ReleaseByteArrayElements(address, addr, 0);
2066c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
2076c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
2086c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
2096c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xiestatic JNINativeMethod sMethods[] = {
2106c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    {"classInitNative", "()V", (void *) classInitNative},
2116654f5c903de510a70f9e72cd5ad7837b615d93ffredc    {"initNative", "()V", (void *) initNative},
2126654f5c903de510a70f9e72cd5ad7837b615d93ffredc    {"cleanupNative", "()V", (void *) cleanupNative},
2136c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    {"connectA2dpNative", "([B)Z", (void *) connectA2dpNative},
2146c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    {"disconnectA2dpNative", "([B)Z", (void *) disconnectA2dpNative},
2156c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie};
2166c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
2176c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieint register_com_android_bluetooth_a2dp(JNIEnv* env)
2186c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie{
21921f921a43af4c93f23f8d3fd52033c9720200e89Ajay Panicker    return jniRegisterNativeMethods(env, "com/android/bluetooth/a2dp/A2dpStateMachine",
2206c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie                                    sMethods, NELEM(sMethods));
2216c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
2226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
2236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
224