From c0e32f12439e5373dca5879e4eb7e819be7fb417 Mon Sep 17 00:00:00 2001 From: Jaikumar Ganesh Date: Wed, 16 Dec 2009 11:36:39 -0800 Subject: [PATCH] Add a callback for the ConnectSink Call. This takes care of the conditions where the bluez audio drivers are not up and we try to make the call to connect the sink. This would get rid of the hack in Settings app. --- .../android/server/BluetoothA2dpService.java | 26 +++++++++++-- .../android_server_BluetoothA2dpService.cpp | 38 +++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index f2e132b56fe74..03dcf00cd5c96 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -305,7 +305,11 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return false; // State is DISCONNECTED + handleSinkStateChange(device, state, BluetoothA2dp.STATE_CONNECTING); + if (!connectSinkNative(path)) { + // Restore previous state + handleSinkStateChange(device, mAudioDevices.get(device), state); return false; } return true; @@ -321,7 +325,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return false; } - switch (getSinkState(device)) { + int state = getSinkState(device); + switch (state) { case BluetoothA2dp.STATE_DISCONNECTED: return false; case BluetoothA2dp.STATE_DISCONNECTING: @@ -329,11 +334,13 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } // State is CONNECTING or CONNECTED or PLAYING + handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTING); if (!disconnectSinkNative(path)) { + // Restore previous state + handleSinkStateChange(device, mAudioDevices.get(device), state); return false; - } else { - return true; } + return true; } public synchronized boolean suspendSink(BluetoothDevice device) { @@ -512,6 +519,19 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return result; } + private void onConnectSinkResult(String deviceObjectPath, boolean result) { + // If the call was a success, ignore we will update the state + // when we a Sink Property Change + if (!result) { + if (deviceObjectPath != null) { + String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); + BluetoothDevice device = mAdapter.getRemoteDevice(address); + int state = getSinkState(device); + handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED); + } + } + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mAudioDevices.isEmpty()) return; diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp index 7a3bbbb95814e..4eab4b396dd58 100644 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ b/core/jni/android_server_BluetoothA2dpService.cpp @@ -38,6 +38,7 @@ namespace android { #ifdef HAVE_BLUETOOTH static jmethodID method_onSinkPropertyChanged; +static jmethodID method_onConnectSinkResult; typedef struct { JavaVM *vm; @@ -47,6 +48,7 @@ typedef struct { } native_data_t; static native_data_t *nat = NULL; // global native data +static void onConnectSinkResult(DBusMessage *msg, void *user, void *n); static Properties sink_properties[] = { {"State", DBUS_TYPE_STRING}, @@ -133,9 +135,12 @@ static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { LOGV(__FUNCTION__); if (nat) { const char *c_path = env->GetStringUTFChars(path, NULL); + int len = env->GetStringLength(path) + 1; + char *context_path = (char *)calloc(len, sizeof(char)); + strlcpy(context_path, c_path, len); // for callback - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.AudioSink", "Connect", + bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, context_path, + nat, c_path, "org.bluez.AudioSink", "Connect", DBUS_TYPE_INVALID); env->ReleaseStringUTFChars(path, c_path); @@ -237,6 +242,31 @@ DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) { return result; } + +void onConnectSinkResult(DBusMessage *msg, void *user, void *n) { + LOGV(__FUNCTION__); + + native_data_t *nat = (native_data_t *)n; + const char *path = (const char *)user; + DBusError err; + dbus_error_init(&err); + JNIEnv *env; + nat->vm->GetEnv((void**)&env, nat->envVer); + + + bool result = JNI_TRUE; + if (dbus_set_error_from_message(&err, msg)) { + LOG_AND_FREE_DBUS_ERROR(&err); + result = JNI_FALSE; + } + LOGV("... Device Path = %s, result = %d", path, result); + env->CallVoidMethod(nat->me, + method_onConnectSinkResult, + env->NewStringUTF(path), + result); + free(user); +} + #endif @@ -244,7 +274,7 @@ static JNINativeMethod sMethods[] = { {"initNative", "()Z", (void *)initNative}, {"cleanupNative", "()V", (void *)cleanupNative}, - /* Bluez audio 4.40 API */ + /* Bluez audio 4.47 API */ {"connectSinkNative", "(Ljava/lang/String;)Z", (void *)connectSinkNative}, {"disconnectSinkNative", "(Ljava/lang/String;)Z", (void *)disconnectSinkNative}, {"suspendSinkNative", "(Ljava/lang/String;)Z", (void*)suspendSinkNative}, @@ -263,6 +293,8 @@ int register_android_server_BluetoothA2dpService(JNIEnv *env) { #ifdef HAVE_BLUETOOTH method_onSinkPropertyChanged = env->GetMethodID(clazz, "onSinkPropertyChanged", "(Ljava/lang/String;[Ljava/lang/String;)V"); + method_onConnectSinkResult = env->GetMethodID(clazz, "onConnectSinkResult", + "(Ljava/lang/String;Z)V"); #endif return AndroidRuntime::registerNativeMethods(env,