* commit '6b080fb5733a09ecf4963dc74493493b64752ce2': Adding support for Absolute Volume
This commit is contained in:
@@ -387,6 +387,66 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Avrcp device supports the absolute volume feature.
|
||||
*
|
||||
* @return true if device supports absolute volume
|
||||
* @hide
|
||||
*/
|
||||
public boolean isAvrcpAbsoluteVolumeSupported() {
|
||||
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
|
||||
if (mService != null && isEnabled()) {
|
||||
try {
|
||||
return mService.isAvrcpAbsoluteVolumeSupported();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells remote device to adjust volume. Only if absolute volume is supported.
|
||||
*
|
||||
* @param direction 1 to increase volume, or -1 to decrease volume
|
||||
* @hide
|
||||
*/
|
||||
public void adjustAvrcpAbsoluteVolume(int direction) {
|
||||
if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
|
||||
if (mService != null && isEnabled()) {
|
||||
try {
|
||||
mService.adjustAvrcpAbsoluteVolume(direction);
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells remote device to set an absolute volume. Only if absolute volume is supported
|
||||
*
|
||||
* @param volume Absolute volume to be set on AVRCP side
|
||||
* @hide
|
||||
*/
|
||||
public void setAvrcpAbsoluteVolume(int volume) {
|
||||
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
|
||||
if (mService != null && isEnabled()) {
|
||||
try {
|
||||
mService.setAvrcpAbsoluteVolume(volume);
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if A2DP profile is streaming music.
|
||||
*
|
||||
|
||||
@@ -32,5 +32,8 @@ interface IBluetoothA2dp {
|
||||
int getConnectionState(in BluetoothDevice device);
|
||||
boolean setPriority(in BluetoothDevice device, int priority);
|
||||
int getPriority(in BluetoothDevice device);
|
||||
boolean isAvrcpAbsoluteVolumeSupported();
|
||||
oneway void adjustAvrcpAbsoluteVolume(int direction);
|
||||
oneway void setAvrcpAbsoluteVolume(int volume);
|
||||
boolean isA2dpPlaying(in BluetoothDevice device);
|
||||
}
|
||||
|
||||
@@ -2387,6 +2387,35 @@ public class AudioManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Notifies AudioService that it is connected to an A2DP device that supports absolute volume,
|
||||
* so that AudioService can send volume change events to the A2DP device, rather than handling
|
||||
* them.
|
||||
*/
|
||||
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.avrcpSupportsAbsoluteVolume(address, support);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Notifies AudioService of the volume set on the A2DP device as a callback, so AudioService
|
||||
* is able to update the UI.
|
||||
*/
|
||||
public void avrcpUpdateVolume(int oldVolume, int volume) {
|
||||
IAudioService service = getService();
|
||||
try {
|
||||
service.avrcpUpdateVolume(oldVolume, volume);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Dead object in avrcpUpdateVolume", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
|
||||
@@ -460,6 +460,12 @@ public class AudioService extends IAudioService.Stub {
|
||||
|
||||
private final MediaFocusControl mMediaFocusControl;
|
||||
|
||||
// Reference to BluetoothA2dp to query for AbsoluteVolume.
|
||||
private BluetoothA2dp mA2dp;
|
||||
private final Object mA2dpAvrcpLock = new Object();
|
||||
// If absolute volume is supported in AVRCP device
|
||||
private boolean mAvrcpAbsVolSupported = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Construction
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -901,6 +907,15 @@ public class AudioService extends IAudioService.Stub {
|
||||
int oldIndex = mStreamStates[streamType].getIndex(device);
|
||||
|
||||
if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
|
||||
// Check if volume update should be send to AVRCP
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
if (mA2dp != null && mAvrcpAbsVolSupported) {
|
||||
mA2dp.adjustAvrcpAbsoluteVolume(direction);
|
||||
return;
|
||||
// No need to send volume update, because we will update the volume with a
|
||||
// callback from Avrcp.
|
||||
}
|
||||
}
|
||||
if ((direction == AudioManager.ADJUST_RAISE) &&
|
||||
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
|
||||
Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
|
||||
@@ -998,6 +1013,15 @@ public class AudioService extends IAudioService.Stub {
|
||||
|
||||
index = rescaleIndex(index * 10, streamType, streamTypeAlias);
|
||||
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
if (mA2dp != null && mAvrcpAbsVolSupported) {
|
||||
mA2dp.setAvrcpAbsoluteVolume(index);
|
||||
return;
|
||||
// No need to send volume update, because we will update the volume with a
|
||||
// callback from Avrcp.
|
||||
}
|
||||
}
|
||||
|
||||
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
|
||||
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
|
||||
((device & mFixedVolumeDevices) != 0)) {
|
||||
@@ -2268,21 +2292,23 @@ public class AudioService extends IAudioService.Stub {
|
||||
List<BluetoothDevice> deviceList;
|
||||
switch(profile) {
|
||||
case BluetoothProfile.A2DP:
|
||||
BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
|
||||
deviceList = a2dp.getConnectedDevices();
|
||||
if (deviceList.size() > 0) {
|
||||
btDevice = deviceList.get(0);
|
||||
synchronized (mConnectedDevices) {
|
||||
int state = a2dp.getConnectionState(btDevice);
|
||||
int delay = checkSendBecomingNoisyIntent(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
|
||||
queueMsgUnderWakeLock(mAudioHandler,
|
||||
MSG_SET_A2DP_CONNECTION_STATE,
|
||||
state,
|
||||
0,
|
||||
btDevice,
|
||||
delay);
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
mA2dp = (BluetoothA2dp) proxy;
|
||||
deviceList = mA2dp.getConnectedDevices();
|
||||
if (deviceList.size() > 0) {
|
||||
btDevice = deviceList.get(0);
|
||||
synchronized (mConnectedDevices) {
|
||||
int state = mA2dp.getConnectionState(btDevice);
|
||||
int delay = checkSendBecomingNoisyIntent(
|
||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
|
||||
queueMsgUnderWakeLock(mAudioHandler,
|
||||
MSG_SET_A2DP_CONNECTION_STATE,
|
||||
state,
|
||||
0,
|
||||
btDevice,
|
||||
delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2344,10 +2370,13 @@ public class AudioService extends IAudioService.Stub {
|
||||
public void onServiceDisconnected(int profile) {
|
||||
switch(profile) {
|
||||
case BluetoothProfile.A2DP:
|
||||
synchronized (mConnectedDevices) {
|
||||
if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
|
||||
makeA2dpDeviceUnavailableNow(
|
||||
mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
mA2dp = null;
|
||||
synchronized (mConnectedDevices) {
|
||||
if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
|
||||
makeA2dpDeviceUnavailableNow(
|
||||
mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3697,6 +3726,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
|
||||
private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
|
||||
{
|
||||
if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state);
|
||||
if (btDevice == null) {
|
||||
return;
|
||||
}
|
||||
@@ -3704,6 +3734,20 @@ public class AudioService extends IAudioService.Stub {
|
||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||
address = "";
|
||||
}
|
||||
|
||||
// Disable absolute volume, if device is disconnected
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
if (state == BluetoothProfile.STATE_DISCONNECTED && mAvrcpAbsVolSupported) {
|
||||
mAvrcpAbsVolSupported = false;
|
||||
sendMsg(mAudioHandler,
|
||||
MSG_SET_DEVICE_VOLUME,
|
||||
SENDMSG_QUEUE,
|
||||
getDeviceForStream(AudioSystem.STREAM_MUSIC),
|
||||
0,
|
||||
mStreamStates[AudioSystem.STREAM_MUSIC],
|
||||
0);
|
||||
}
|
||||
}
|
||||
synchronized (mConnectedDevices) {
|
||||
boolean isConnected =
|
||||
(mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
|
||||
@@ -3754,6 +3798,31 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
|
||||
// address is not used for now, but may be used when multiple a2dp devices are supported
|
||||
synchronized (mA2dpAvrcpLock) {
|
||||
mAvrcpAbsVolSupported = support;
|
||||
if (support) {
|
||||
VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
|
||||
int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
|
||||
streamState.setIndex(streamState.getMaxIndex(), device);
|
||||
sendMsg(mAudioHandler,
|
||||
MSG_SET_DEVICE_VOLUME,
|
||||
SENDMSG_QUEUE,
|
||||
device,
|
||||
0,
|
||||
streamState,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void avrcpUpdateVolume(int oldVolume, int volume) {
|
||||
mStreamStates[AudioSystem.STREAM_MUSIC].
|
||||
setIndex(volume, getDeviceForStream(AudioSystem.STREAM_MUSIC));
|
||||
sendVolumeUpdate(AudioSystem.STREAM_MUSIC, oldVolume, volume, AudioManager.FLAG_SHOW_UI);
|
||||
}
|
||||
|
||||
private boolean handleDeviceConnection(boolean connected, int device, String params) {
|
||||
synchronized (mConnectedDevices) {
|
||||
boolean isConnected = (mConnectedDevices.containsKey(device) &&
|
||||
|
||||
@@ -98,6 +98,10 @@ interface IAudioService {
|
||||
|
||||
oneway void reloadAudioSettings();
|
||||
|
||||
oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
|
||||
|
||||
oneway void avrcpUpdateVolume(int oldVolume, int volume);
|
||||
|
||||
void setSpeakerphoneOn(boolean on);
|
||||
|
||||
boolean isSpeakerphoneOn();
|
||||
|
||||
Reference in New Issue
Block a user