Loading core/java/android/bluetooth/BluetoothA2dp.java +32 −0 Original line number Diff line number Diff line Loading @@ -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. Loading core/java/android/bluetooth/IBluetoothA2dp.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/server/BluetoothA2dpService.java +44 −0 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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); } core/jni/android_server_BluetoothA2dpService.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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}, }; Loading Loading
core/java/android/bluetooth/BluetoothA2dp.java +32 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
core/java/android/bluetooth/IBluetoothA2dp.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/server/BluetoothA2dpService.java +44 −0 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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); }
core/jni/android_server_BluetoothA2dpService.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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}, }; Loading