am 6b080fb5: am f855a2ff: Merge "Adding support for Absolute Volume" into klp-dev

* commit '6b080fb5733a09ecf4963dc74493493b64752ce2':
  Adding support for Absolute Volume
This commit is contained in:
Matthew Xie
2013-08-18 12:54:21 -07:00
committed by Android Git Automerger
5 changed files with 184 additions and 19 deletions

View File

@@ -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.
*

View File

@@ -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);
}

View File

@@ -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}
*/

View File

@@ -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) &&

View File

@@ -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();