Added internal API to get/set the A2DP Active Device

1. Call BluetoothA2dp.setActiveDevice(BluetoothDevice device) to set
   a connected A2DP device as active.
   The value of "device" could be null to clear the active device
   and stop streaming audio to a Bluetooth device.
2. Listen for BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED intent
   that will contain the latest active device (in EXTRA_DEVICE field).
   If the active device could not be changed, the EXTRA_DEVICE
   field could be null.
3. If setActiveDevice() is NOT in-progress, BluetoothA2dp.getActiveDevice()
   can be used. If setActiveDevice() is in-progress, the result is undefined.
4. BluetoothA2dp.setActiveDevice() could be called by some other parts of
   the system, so interested parties should always listen for
   BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED intents and prepared
   for active device updates.

Bug: 71555243
Test: Manual
Change-Id: I661b6882e8e6b437db50210aec1dd12a10199969
This commit is contained in:
Pavlin Radoslavov
2017-12-19 13:20:06 -08:00
parent 0f05ce94c3
commit 64a9435cc7
2 changed files with 90 additions and 0 deletions

View File

@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -102,6 +103,24 @@ public final class BluetoothA2dp implements BluetoothProfile {
public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
/**
* Intent used to broadcast the selection of a connected device as active.
*
* <p>This intent will have one extra:
* <ul>
* <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
* be null if no device is active. </li>
* </ul>
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
* receive.
*
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
"android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
/**
* Intent used to broadcast the change in the Audio Codec state of the
* A2DP Source profile.
@@ -424,6 +443,75 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
}
/**
* Select a connected device as active.
*
* The active device selection is per profile. An active device's
* purpose is profile-specific. For example, A2DP audio streaming
* is to the active A2DP Sink device. If a remote device is not
* connected, it cannot be selected as active.
*
* <p> This API returns false in scenarios like the profile on the
* device is not connected or Bluetooth is not turned on.
* When this API returns true, it is guaranteed that the
* {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
* with the active device.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* permission.
*
* @param device the remote Bluetooth device. Could be null to clear
* the active device and stop streaming audio to a Bluetooth device.
* @return false on immediate error, true otherwise
* @hide
*/
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
return mService.setActiveDevice(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
/**
* Get the connected device that is active.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
* permission.
*
* @return the connected device that is active or null if no device
* is active
* @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
@Nullable
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getActiveDevice();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return null;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return null;
} finally {
mServiceLock.readLock().unlock();
}
}
/**
* Set priority of the profile
*

View File

@@ -172,6 +172,8 @@
android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast