Loading android/app/jni/com_android_bluetooth_a2dp.cpp +42 −30 Original line number Diff line number Diff line Loading @@ -51,8 +51,8 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; static void bta2dp_connection_state_callback(btav_connection_state_t state, RawAddress* bd_addr) { static void bta2dp_connection_state_callback(RawAddress* bd_addr, btav_connection_state_t state) { ALOGI("%s", __func__); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -62,18 +62,18 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { ALOGE("Fail to new jbyteArray bd addr for connection state"); ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_state_callback(btav_audio_state_t state, RawAddress* bd_addr) { static void bta2dp_audio_state_callback(RawAddress* bd_addr, btav_audio_state_t state) { ALOGI("%s", __func__); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -83,18 +83,18 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { ALOGE("Fail to new jbyteArray bd addr for connection state"); ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_config_callback( btav_a2dp_codec_config_t codec_config, RawAddress* bd_addr, btav_a2dp_codec_config_t codec_config, std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities, std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) { ALOGI("%s", __func__); Loading Loading @@ -146,9 +146,18 @@ static void bta2dp_audio_config_callback( sCallbackEnv->DeleteLocalRef(capObj); } sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCodecConfigChanged, codecConfigObj, local_capabilities_array, selectable_capabilities_array); ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(RawAddress::kLength)); if (!addr.get()) { ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, RawAddress::kLength, (jbyte*)bd_addr->address); sCallbackEnv->CallVoidMethod( mCallbacksObj, method_onCodecConfigChanged, addr.get(), codecConfigObj, local_capabilities_array, selectable_capabilities_array); } static btav_source_callbacks_t sBluetoothA2dpCallbacks = { Loading Loading @@ -181,15 +190,16 @@ static void classInitNative(JNIEnv* env, jclass clazz) { jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V"); method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onAudioStateChanged", "([BI)V"); method_onCodecConfigChanged = env->GetMethodID( clazz, "onCodecConfigChanged", "(Landroid/bluetooth/BluetoothCodecConfig;[Landroid/bluetooth/" "BluetoothCodecConfig;[Landroid/bluetooth/BluetoothCodecConfig;)V"); method_onCodecConfigChanged = env->GetMethodID(clazz, "onCodecConfigChanged", "([BLandroid/bluetooth/BluetoothCodecConfig;" "[Landroid/bluetooth/BluetoothCodecConfig;" "[Landroid/bluetooth/BluetoothCodecConfig;)V"); ALOGI("%s: succeeds", __func__); } Loading @@ -204,7 +214,7 @@ static std::vector<btav_a2dp_codec_config_t> prepareCodecPreferences( if (jcodecConfig == nullptr) continue; if (!env->IsInstanceOf(jcodecConfig, android_bluetooth_BluetoothCodecConfig.clazz)) { ALOGE("Invalid BluetoothCodecConfig instance"); ALOGE("%s: Invalid BluetoothCodecConfig instance", __func__); continue; } jint codecType = env->CallIntMethod( Loading Loading @@ -252,31 +262,32 @@ static void initNative(JNIEnv* env, jobject object, const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { ALOGE("Bluetooth module is not loaded"); ALOGE("%s: Bluetooth module is not loaded", __func__); return; } if (sBluetoothA2dpInterface != nullptr) { ALOGW("Cleaning up A2DP Interface before initializing..."); ALOGW("%s: Cleaning up A2DP Interface before initializing...", __func__); sBluetoothA2dpInterface->cleanup(); sBluetoothA2dpInterface = nullptr; } if (mCallbacksObj != nullptr) { ALOGW("Cleaning up A2DP callback object"); ALOGW("%s: Cleaning up A2DP callback object", __func__); env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { ALOGE("Failed to allocate Global Ref for A2DP Callbacks"); ALOGE("%s: Failed to allocate Global Ref for A2DP Callbacks", __func__); return; } android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef( env->FindClass("android/bluetooth/BluetoothCodecConfig")); if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) { ALOGE("Failed to allocate Global Ref for BluetoothCodecConfig class"); ALOGE("%s: Failed to allocate Global Ref for BluetoothCodecConfig class", __func__); return; } Loading @@ -284,7 +295,7 @@ static void initNative(JNIEnv* env, jobject object, (btav_source_interface_t*)btInf->get_profile_interface( BT_PROFILE_ADVANCED_AUDIO_ID); if (sBluetoothA2dpInterface == nullptr) { ALOGE("Failed to get Bluetooth A2DP Interface"); ALOGE("%s: Failed to get Bluetooth A2DP Interface", __func__); return; } Loading @@ -294,7 +305,8 @@ static void initNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, codec_priorities); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status); ALOGE("%s: Failed to initialize Bluetooth A2DP, status: %d", __func__, status); sBluetoothA2dpInterface = nullptr; return; } Loading @@ -306,7 +318,7 @@ static void cleanupNative(JNIEnv* env, jobject object) { const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { ALOGE("Bluetooth module is not loaded"); ALOGE("%s: Bluetooth module is not loaded", __func__); return; } Loading Loading @@ -338,7 +350,7 @@ static jboolean connectA2dpNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->connect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed HF connection, status: %d", status); ALOGE("%s: Failed HF connection, status: %d", __func__, status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; Loading @@ -358,7 +370,7 @@ static jboolean disconnectA2dpNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->disconnect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed HF disconnection, status: %d", status); ALOGE("%s: Failed HF disconnection, status: %d", __func__, status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; Loading @@ -375,7 +387,7 @@ static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->config_codec(codec_preferences); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed codec configuration, status: %d", status); ALOGE("%s: Failed codec configuration, status: %d", __func__, status); } return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } Loading android/app/jni/com_android_bluetooth_a2dp_sink.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -33,8 +33,8 @@ static jmethodID method_onAudioConfigChanged; static const btav_sink_interface_t* sBluetoothA2dpInterface = NULL; static jobject mCallbacksObj = NULL; static void bta2dp_connection_state_callback(btav_connection_state_t state, RawAddress* bd_addr) { static void bta2dp_connection_state_callback(RawAddress* bd_addr, btav_connection_state_t state) { ALOGI("%s", __func__); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; Loading @@ -49,11 +49,11 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_state_callback(btav_audio_state_t state, RawAddress* bd_addr) { static void bta2dp_audio_state_callback(RawAddress* bd_addr, btav_audio_state_t state) { ALOGI("%s", __func__); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; Loading @@ -68,7 +68,7 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_config_callback(RawAddress* bd_addr, Loading Loading @@ -99,10 +99,10 @@ static btav_sink_callbacks_t sBluetoothA2dpCallbacks = { static void classInitNative(JNIEnv* env, jclass clazz) { method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V"); method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onAudioStateChanged", "([BI)V"); method_onAudioConfigChanged = env->GetMethodID(clazz, "onAudioConfigChanged", "([BII)V"); Loading android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +14 −15 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ package com.android.bluetooth.a2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothCodecConfig; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; import android.support.annotation.VisibleForTesting; import android.util.Log; Loading Loading @@ -135,11 +136,11 @@ public class A2dpNativeInterface { // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void onConnectionStateChanged(int state, byte[] address) { private void onConnectionStateChanged(byte[] address, int state) { A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = state; event.device = getDevice(address); event.valueInt = state; if (DBG) { Log.d(TAG, "onConnectionStateChanged: " + event); Loading @@ -147,10 +148,10 @@ public class A2dpNativeInterface { sendMessageToService(event); } private void onAudioStateChanged(int state, byte[] address) { private void onAudioStateChanged(byte[] address, int state) { A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = state; event.device = getDevice(address); event.valueInt = state; if (DBG) { Log.d(TAG, "onAudioStateChanged: " + event); Loading @@ -158,21 +159,19 @@ public class A2dpNativeInterface { sendMessageToService(event); } private void onCodecConfigChanged(BluetoothCodecConfig newCodecConfig, private void onCodecConfigChanged(byte[] address, BluetoothCodecConfig newCodecConfig, BluetoothCodecConfig[] codecsLocalCapabilities, BluetoothCodecConfig[] codecsSelectableCapabilities) { if (DBG) { Log.d(TAG, "onCodecConfigChanged: " + newCodecConfig); } // TODO: We need to use A2dpStackEvent instead of specialized service calls. A2dpService service = A2dpService.getA2dpService(); if (service != null) { service.onCodecConfigChangedFromNative(newCodecConfig, A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED); event.device = getDevice(address); event.codecStatus = new BluetoothCodecStatus(newCodecConfig, codecsLocalCapabilities, codecsSelectableCapabilities); } else { Log.w(TAG, "onCodecConfigChanged ignored: service not available"); if (DBG) { Log.d(TAG, "onCodecConfigChanged: " + event); } sendMessageToService(event); } // Native methods that call into the JNI interface Loading android/app/src/com/android/bluetooth/a2dp/A2dpService.java +1 −13 Original line number Diff line number Diff line Loading @@ -399,21 +399,9 @@ public class A2dpService extends ProfileService { // Handle messages from native (JNI) to Java void messageFromNative(A2dpStackEvent stackEvent) { if (DBG) { Log.d(TAG, "messageFromNative(): " + stackEvent); } mStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent); } // TODO: This method should go away and should be replaced with // the messageFromNative(A2dpStackEvent) mechanism void onCodecConfigChangedFromNative(BluetoothCodecConfig newCodecConfig, BluetoothCodecConfig[] codecsLocalCapabilities, BluetoothCodecConfig[] codecsSelectableCapabilities) { mStateMachine.onCodecConfigChanged(newCodecConfig, codecsLocalCapabilities, codecsSelectableCapabilities); } // Binder object: Must be static class or memory leak may occur private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub implements IProfileServiceBinder { Loading android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java +11 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.bluetooth.a2dp; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; /** Loading @@ -27,10 +28,12 @@ public class A2dpStackEvent { private static final int EVENT_TYPE_NONE = 0; public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; public static final int EVENT_TYPE_AUDIO_STATE_CHANGED = 2; public static final int EVENT_TYPE_CODEC_CONFIG_CHANGED = 3; public int type = EVENT_TYPE_NONE; public int valueInt = 0; public BluetoothDevice device = null; public int valueInt = 0; public BluetoothCodecStatus codecStatus = null; A2dpStackEvent(int type) { this.type = type; Loading @@ -41,8 +44,12 @@ public class A2dpStackEvent { // event dump StringBuilder result = new StringBuilder(); result.append("A2dpStackEvent {type:" + eventTypeToString(type)); result.append(", device:" + device); result.append(", value1:" + valueInt); result.append(", device:" + device + "}"); if (codecStatus != null) { result.append(", codecStatus:" + codecStatus); } result.append("}"); return result.toString(); } Loading @@ -55,6 +62,8 @@ public class A2dpStackEvent { return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; case EVENT_TYPE_AUDIO_STATE_CHANGED: return "EVENT_TYPE_AUDIO_STATE_CHANGED"; case EVENT_TYPE_CODEC_CONFIG_CHANGED: return "EVENT_TYPE_CODEC_CONFIG_CHANGED"; default: return "EVENT_TYPE_UNKNOWN:" + type; } Loading Loading
android/app/jni/com_android_bluetooth_a2dp.cpp +42 −30 Original line number Diff line number Diff line Loading @@ -51,8 +51,8 @@ static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; static void bta2dp_connection_state_callback(btav_connection_state_t state, RawAddress* bd_addr) { static void bta2dp_connection_state_callback(RawAddress* bd_addr, btav_connection_state_t state) { ALOGI("%s", __func__); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -62,18 +62,18 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { ALOGE("Fail to new jbyteArray bd addr for connection state"); ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_state_callback(btav_audio_state_t state, RawAddress* bd_addr) { static void bta2dp_audio_state_callback(RawAddress* bd_addr, btav_audio_state_t state) { ALOGI("%s", __func__); std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); Loading @@ -83,18 +83,18 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { ALOGE("Fail to new jbyteArray bd addr for connection state"); ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_config_callback( btav_a2dp_codec_config_t codec_config, RawAddress* bd_addr, btav_a2dp_codec_config_t codec_config, std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities, std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) { ALOGI("%s", __func__); Loading Loading @@ -146,9 +146,18 @@ static void bta2dp_audio_config_callback( sCallbackEnv->DeleteLocalRef(capObj); } sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCodecConfigChanged, codecConfigObj, local_capabilities_array, selectable_capabilities_array); ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(RawAddress::kLength)); if (!addr.get()) { ALOGE("%s: Fail to new jbyteArray bd addr", __func__); return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, RawAddress::kLength, (jbyte*)bd_addr->address); sCallbackEnv->CallVoidMethod( mCallbacksObj, method_onCodecConfigChanged, addr.get(), codecConfigObj, local_capabilities_array, selectable_capabilities_array); } static btav_source_callbacks_t sBluetoothA2dpCallbacks = { Loading Loading @@ -181,15 +190,16 @@ static void classInitNative(JNIEnv* env, jclass clazz) { jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V"); method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onAudioStateChanged", "([BI)V"); method_onCodecConfigChanged = env->GetMethodID( clazz, "onCodecConfigChanged", "(Landroid/bluetooth/BluetoothCodecConfig;[Landroid/bluetooth/" "BluetoothCodecConfig;[Landroid/bluetooth/BluetoothCodecConfig;)V"); method_onCodecConfigChanged = env->GetMethodID(clazz, "onCodecConfigChanged", "([BLandroid/bluetooth/BluetoothCodecConfig;" "[Landroid/bluetooth/BluetoothCodecConfig;" "[Landroid/bluetooth/BluetoothCodecConfig;)V"); ALOGI("%s: succeeds", __func__); } Loading @@ -204,7 +214,7 @@ static std::vector<btav_a2dp_codec_config_t> prepareCodecPreferences( if (jcodecConfig == nullptr) continue; if (!env->IsInstanceOf(jcodecConfig, android_bluetooth_BluetoothCodecConfig.clazz)) { ALOGE("Invalid BluetoothCodecConfig instance"); ALOGE("%s: Invalid BluetoothCodecConfig instance", __func__); continue; } jint codecType = env->CallIntMethod( Loading Loading @@ -252,31 +262,32 @@ static void initNative(JNIEnv* env, jobject object, const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { ALOGE("Bluetooth module is not loaded"); ALOGE("%s: Bluetooth module is not loaded", __func__); return; } if (sBluetoothA2dpInterface != nullptr) { ALOGW("Cleaning up A2DP Interface before initializing..."); ALOGW("%s: Cleaning up A2DP Interface before initializing...", __func__); sBluetoothA2dpInterface->cleanup(); sBluetoothA2dpInterface = nullptr; } if (mCallbacksObj != nullptr) { ALOGW("Cleaning up A2DP callback object"); ALOGW("%s: Cleaning up A2DP callback object", __func__); env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { ALOGE("Failed to allocate Global Ref for A2DP Callbacks"); ALOGE("%s: Failed to allocate Global Ref for A2DP Callbacks", __func__); return; } android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef( env->FindClass("android/bluetooth/BluetoothCodecConfig")); if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) { ALOGE("Failed to allocate Global Ref for BluetoothCodecConfig class"); ALOGE("%s: Failed to allocate Global Ref for BluetoothCodecConfig class", __func__); return; } Loading @@ -284,7 +295,7 @@ static void initNative(JNIEnv* env, jobject object, (btav_source_interface_t*)btInf->get_profile_interface( BT_PROFILE_ADVANCED_AUDIO_ID); if (sBluetoothA2dpInterface == nullptr) { ALOGE("Failed to get Bluetooth A2DP Interface"); ALOGE("%s: Failed to get Bluetooth A2DP Interface", __func__); return; } Loading @@ -294,7 +305,8 @@ static void initNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, codec_priorities); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status); ALOGE("%s: Failed to initialize Bluetooth A2DP, status: %d", __func__, status); sBluetoothA2dpInterface = nullptr; return; } Loading @@ -306,7 +318,7 @@ static void cleanupNative(JNIEnv* env, jobject object) { const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { ALOGE("Bluetooth module is not loaded"); ALOGE("%s: Bluetooth module is not loaded", __func__); return; } Loading Loading @@ -338,7 +350,7 @@ static jboolean connectA2dpNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->connect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed HF connection, status: %d", status); ALOGE("%s: Failed HF connection, status: %d", __func__, status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; Loading @@ -358,7 +370,7 @@ static jboolean disconnectA2dpNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->disconnect((RawAddress*)addr); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed HF disconnection, status: %d", status); ALOGE("%s: Failed HF disconnection, status: %d", __func__, status); } env->ReleaseByteArrayElements(address, addr, 0); return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; Loading @@ -375,7 +387,7 @@ static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, bt_status_t status = sBluetoothA2dpInterface->config_codec(codec_preferences); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed codec configuration, status: %d", status); ALOGE("%s: Failed codec configuration, status: %d", __func__, status); } return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } Loading
android/app/jni/com_android_bluetooth_a2dp_sink.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -33,8 +33,8 @@ static jmethodID method_onAudioConfigChanged; static const btav_sink_interface_t* sBluetoothA2dpInterface = NULL; static jobject mCallbacksObj = NULL; static void bta2dp_connection_state_callback(btav_connection_state_t state, RawAddress* bd_addr) { static void bta2dp_connection_state_callback(RawAddress* bd_addr, btav_connection_state_t state) { ALOGI("%s", __func__); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; Loading @@ -49,11 +49,11 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_state_callback(btav_audio_state_t state, RawAddress* bd_addr) { static void bta2dp_audio_state_callback(RawAddress* bd_addr, btav_audio_state_t state) { ALOGI("%s", __func__); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; Loading @@ -68,7 +68,7 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint)state, addr.get()); addr.get(), (jint)state); } static void bta2dp_audio_config_callback(RawAddress* bd_addr, Loading Loading @@ -99,10 +99,10 @@ static btav_sink_callbacks_t sBluetoothA2dpCallbacks = { static void classInitNative(JNIEnv* env, jclass clazz) { method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V"); method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); env->GetMethodID(clazz, "onAudioStateChanged", "([BI)V"); method_onAudioConfigChanged = env->GetMethodID(clazz, "onAudioConfigChanged", "([BII)V"); Loading
android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +14 −15 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ package com.android.bluetooth.a2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothCodecConfig; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; import android.support.annotation.VisibleForTesting; import android.util.Log; Loading Loading @@ -135,11 +136,11 @@ public class A2dpNativeInterface { // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void onConnectionStateChanged(int state, byte[] address) { private void onConnectionStateChanged(byte[] address, int state) { A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); event.valueInt = state; event.device = getDevice(address); event.valueInt = state; if (DBG) { Log.d(TAG, "onConnectionStateChanged: " + event); Loading @@ -147,10 +148,10 @@ public class A2dpNativeInterface { sendMessageToService(event); } private void onAudioStateChanged(int state, byte[] address) { private void onAudioStateChanged(byte[] address, int state) { A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); event.valueInt = state; event.device = getDevice(address); event.valueInt = state; if (DBG) { Log.d(TAG, "onAudioStateChanged: " + event); Loading @@ -158,21 +159,19 @@ public class A2dpNativeInterface { sendMessageToService(event); } private void onCodecConfigChanged(BluetoothCodecConfig newCodecConfig, private void onCodecConfigChanged(byte[] address, BluetoothCodecConfig newCodecConfig, BluetoothCodecConfig[] codecsLocalCapabilities, BluetoothCodecConfig[] codecsSelectableCapabilities) { if (DBG) { Log.d(TAG, "onCodecConfigChanged: " + newCodecConfig); } // TODO: We need to use A2dpStackEvent instead of specialized service calls. A2dpService service = A2dpService.getA2dpService(); if (service != null) { service.onCodecConfigChangedFromNative(newCodecConfig, A2dpStackEvent event = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED); event.device = getDevice(address); event.codecStatus = new BluetoothCodecStatus(newCodecConfig, codecsLocalCapabilities, codecsSelectableCapabilities); } else { Log.w(TAG, "onCodecConfigChanged ignored: service not available"); if (DBG) { Log.d(TAG, "onCodecConfigChanged: " + event); } sendMessageToService(event); } // Native methods that call into the JNI interface Loading
android/app/src/com/android/bluetooth/a2dp/A2dpService.java +1 −13 Original line number Diff line number Diff line Loading @@ -399,21 +399,9 @@ public class A2dpService extends ProfileService { // Handle messages from native (JNI) to Java void messageFromNative(A2dpStackEvent stackEvent) { if (DBG) { Log.d(TAG, "messageFromNative(): " + stackEvent); } mStateMachine.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent); } // TODO: This method should go away and should be replaced with // the messageFromNative(A2dpStackEvent) mechanism void onCodecConfigChangedFromNative(BluetoothCodecConfig newCodecConfig, BluetoothCodecConfig[] codecsLocalCapabilities, BluetoothCodecConfig[] codecsSelectableCapabilities) { mStateMachine.onCodecConfigChanged(newCodecConfig, codecsLocalCapabilities, codecsSelectableCapabilities); } // Binder object: Must be static class or memory leak may occur private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub implements IProfileServiceBinder { Loading
android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java +11 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.bluetooth.a2dp; import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; /** Loading @@ -27,10 +28,12 @@ public class A2dpStackEvent { private static final int EVENT_TYPE_NONE = 0; public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; public static final int EVENT_TYPE_AUDIO_STATE_CHANGED = 2; public static final int EVENT_TYPE_CODEC_CONFIG_CHANGED = 3; public int type = EVENT_TYPE_NONE; public int valueInt = 0; public BluetoothDevice device = null; public int valueInt = 0; public BluetoothCodecStatus codecStatus = null; A2dpStackEvent(int type) { this.type = type; Loading @@ -41,8 +44,12 @@ public class A2dpStackEvent { // event dump StringBuilder result = new StringBuilder(); result.append("A2dpStackEvent {type:" + eventTypeToString(type)); result.append(", device:" + device); result.append(", value1:" + valueInt); result.append(", device:" + device + "}"); if (codecStatus != null) { result.append(", codecStatus:" + codecStatus); } result.append("}"); return result.toString(); } Loading @@ -55,6 +62,8 @@ public class A2dpStackEvent { return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; case EVENT_TYPE_AUDIO_STATE_CHANGED: return "EVENT_TYPE_AUDIO_STATE_CHANGED"; case EVENT_TYPE_CODEC_CONFIG_CHANGED: return "EVENT_TYPE_CODEC_CONFIG_CHANGED"; default: return "EVENT_TYPE_UNKNOWN:" + type; } Loading