diff options
author | Android (Google) Code Review <android-gerrit@google.com> | 2009-09-30 14:24:46 -0400 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-09-30 14:24:46 -0400 |
commit | e5661c40a62dc3556ece353b3b74fdde249c228e (patch) | |
tree | 6034a32184ed8e8fcac569eae63dea577ee86cca | |
parent | 170d9df0f3e3d7ad5652ccfe0d0bd53d74685d1d (diff) | |
parent | f9bbe1e71a502fe7bd1f4a23ba5bbe4dde0d9d57 (diff) | |
download | frameworks_base-e5661c40a62dc3556ece353b3b74fdde249c228e.zip frameworks_base-e5661c40a62dc3556ece353b3b74fdde249c228e.tar.gz frameworks_base-e5661c40a62dc3556ece353b3b74fdde249c228e.tar.bz2 |
Merge change I8366852f into eclair
* changes:
Bluetooth A2DP suspend/resume functionality
-rw-r--r-- | core/java/android/bluetooth/BluetoothA2dp.java | 32 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothA2dp.aidl | 2 | ||||
-rw-r--r-- | core/java/android/server/BluetoothA2dpService.java | 44 | ||||
-rw-r--r-- | core/jni/android_server_BluetoothA2dpService.cpp | 34 |
4 files changed, 112 insertions, 0 deletions
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 2e9612a..a736ad1 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -133,6 +133,38 @@ public final class BluetoothA2dp { } } + /** Initiate suspend from an A2DP sink. + * Listen for SINK_STATE_CHANGED_ACTION to find out when + * suspend is completed. + * @param device Remote BT device. + * @return false on immediate error, true otherwise + * @hide + */ + public int suspendSink(BluetoothDevice device) { + try { + return mService.suspendSink(device); + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + + /** Initiate resume from an suspended A2DP sink. + * Listen for SINK_STATE_CHANGED_ACTION to find out when + * resume is completed. + * @param device Remote BT device. + * @return false on immediate error, true otherwise + * @hide + */ + public int resumeSink(BluetoothDevice device) { + try { + return mService.resumeSink(device); + } catch (RemoteException e) { + Log.e(TAG, "", e); + return false; + } + } + /** Check if a specified A2DP sink is connected. * @param device Remote BT device. * @return True if connected (or playing), false otherwise and on error. diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl index 2df7f23..002cf4e 100644 --- a/core/java/android/bluetooth/IBluetoothA2dp.aidl +++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl @@ -26,6 +26,8 @@ import android.bluetooth.BluetoothDevice; interface IBluetoothA2dp { boolean connectSink(in BluetoothDevice device); boolean disconnectSink(in BluetoothDevice device); + boolean suspendSink(in BluetoothDevice device); + boolean resumeSink(in BluetoothDevice device); BluetoothDevice[] getConnectedSinks(); // change to Set<> once AIDL supports int getSinkState(in BluetoothDevice device); boolean setSinkPriority(in BluetoothDevice device, int priority); diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 0fc2e7e..4a5f431 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -325,6 +325,48 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } } + public synchronized boolean suspendSink(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + if (DBG) log("suspendSink(" + device + ")"); + if (device == null || mAudioDevices == null) { + return false; + } + String path = mBluetoothService.getObjectPathFromAddress(device.getAddress()); + if (path == null) { + return false; + } + switch (mAudioDevices.get(device)) { + case BluetoothA2dp.STATE_CONNECTED: + return true; + case BluetoothA2dp.STATE_PLAYING: + return suspendSinkNative(path); + default: + return false; + } + } + + public synchronized boolean resumeSink(BluetoothDevice device) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + if (DBG) log("resumeSink(" + device + ")"); + if (device == null || mAudioDevices == null) { + return false; + } + String path = mBluetoothService.getObjectPathFromAddress(device.getAddress()); + if (path == null) { + return false; + } + switch (mAudioDevices.get(device)) { + case BluetoothA2dp.STATE_PLAYING: + return true; + case BluetoothA2dp.STATE_CONNECTED: + return resumeSinkNative(path); + default: + return false; + } + } + public synchronized BluetoothDevice[] getConnectedSinks() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); Set<BluetoothDevice> sinks = lookupSinksMatchingStates( @@ -445,5 +487,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private native void cleanupNative(); private synchronized native boolean connectSinkNative(String path); private synchronized native boolean disconnectSinkNative(String path); + private synchronized native boolean suspendSinkNative(String path); + private synchronized native boolean resumeSinkNative(String path); private synchronized native Object []getSinkPropertiesNative(String path); } diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp index ba13519..7a3bbbb 100644 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ b/core/jni/android_server_BluetoothA2dpService.cpp @@ -163,6 +163,38 @@ static jboolean disconnectSinkNative(JNIEnv *env, jobject object, return JNI_FALSE; } +static jboolean suspendSinkNative(JNIEnv *env, jobject object, + jstring path) { +#ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); + if (nat) { + const char *c_path = env->GetStringUTFChars(path, NULL); + bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, + c_path, "org.bluez.audio.Sink", "Suspend", + DBUS_TYPE_INVALID); + env->ReleaseStringUTFChars(path, c_path); + return ret ? JNI_TRUE : JNI_FALSE; + } +#endif + return JNI_FALSE; +} + +static jboolean resumeSinkNative(JNIEnv *env, jobject object, + jstring path) { +#ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); + if (nat) { + const char *c_path = env->GetStringUTFChars(path, NULL); + bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, + c_path, "org.bluez.audio.Sink", "Resume", + DBUS_TYPE_INVALID); + env->ReleaseStringUTFChars(path, c_path); + return ret ? JNI_TRUE : JNI_FALSE; + } +#endif + return JNI_FALSE; +} + #ifdef HAVE_BLUETOOTH DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) { DBusError err; @@ -215,6 +247,8 @@ static JNINativeMethod sMethods[] = { /* Bluez audio 4.40 API */ {"connectSinkNative", "(Ljava/lang/String;)Z", (void *)connectSinkNative}, {"disconnectSinkNative", "(Ljava/lang/String;)Z", (void *)disconnectSinkNative}, + {"suspendSinkNative", "(Ljava/lang/String;)Z", (void*)suspendSinkNative}, + {"resumeSinkNative", "(Ljava/lang/String;)Z", (void*)resumeSinkNative}, {"getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", (void *)getSinkPropertiesNative}, }; |