Merge "Adding support for Absolute Volume" into klp-dev
This commit is contained in:
@@ -387,6 +387,66 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
|||||||
return BluetoothProfile.PRIORITY_OFF;
|
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.
|
* Check if A2DP profile is streaming music.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -32,5 +32,8 @@ interface IBluetoothA2dp {
|
|||||||
int getConnectionState(in BluetoothDevice device);
|
int getConnectionState(in BluetoothDevice device);
|
||||||
boolean setPriority(in BluetoothDevice device, int priority);
|
boolean setPriority(in BluetoothDevice device, int priority);
|
||||||
int getPriority(in BluetoothDevice device);
|
int getPriority(in BluetoothDevice device);
|
||||||
|
boolean isAvrcpAbsoluteVolumeSupported();
|
||||||
|
oneway void adjustAvrcpAbsoluteVolume(int direction);
|
||||||
|
oneway void setAvrcpAbsoluteVolume(int volume);
|
||||||
boolean isA2dpPlaying(in BluetoothDevice device);
|
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}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -460,6 +460,12 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
|
|
||||||
private final MediaFocusControl mMediaFocusControl;
|
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
|
// Construction
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@@ -901,6 +907,15 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
int oldIndex = mStreamStates[streamType].getIndex(device);
|
int oldIndex = mStreamStates[streamType].getIndex(device);
|
||||||
|
|
||||||
if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
|
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) &&
|
if ((direction == AudioManager.ADJUST_RAISE) &&
|
||||||
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
|
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
|
||||||
Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
|
Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
|
||||||
@@ -998,6 +1013,15 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
|
|
||||||
index = rescaleIndex(index * 10, streamType, streamTypeAlias);
|
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;
|
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
|
||||||
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
|
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
|
||||||
((device & mFixedVolumeDevices) != 0)) {
|
((device & mFixedVolumeDevices) != 0)) {
|
||||||
@@ -2268,21 +2292,23 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
List<BluetoothDevice> deviceList;
|
List<BluetoothDevice> deviceList;
|
||||||
switch(profile) {
|
switch(profile) {
|
||||||
case BluetoothProfile.A2DP:
|
case BluetoothProfile.A2DP:
|
||||||
BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
|
synchronized (mA2dpAvrcpLock) {
|
||||||
deviceList = a2dp.getConnectedDevices();
|
mA2dp = (BluetoothA2dp) proxy;
|
||||||
if (deviceList.size() > 0) {
|
deviceList = mA2dp.getConnectedDevices();
|
||||||
btDevice = deviceList.get(0);
|
if (deviceList.size() > 0) {
|
||||||
synchronized (mConnectedDevices) {
|
btDevice = deviceList.get(0);
|
||||||
int state = a2dp.getConnectionState(btDevice);
|
synchronized (mConnectedDevices) {
|
||||||
int delay = checkSendBecomingNoisyIntent(
|
int state = mA2dp.getConnectionState(btDevice);
|
||||||
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
int delay = checkSendBecomingNoisyIntent(
|
||||||
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
|
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
|
||||||
queueMsgUnderWakeLock(mAudioHandler,
|
(state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
|
||||||
MSG_SET_A2DP_CONNECTION_STATE,
|
queueMsgUnderWakeLock(mAudioHandler,
|
||||||
state,
|
MSG_SET_A2DP_CONNECTION_STATE,
|
||||||
0,
|
state,
|
||||||
btDevice,
|
0,
|
||||||
delay);
|
btDevice,
|
||||||
|
delay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2344,10 +2370,13 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
public void onServiceDisconnected(int profile) {
|
public void onServiceDisconnected(int profile) {
|
||||||
switch(profile) {
|
switch(profile) {
|
||||||
case BluetoothProfile.A2DP:
|
case BluetoothProfile.A2DP:
|
||||||
synchronized (mConnectedDevices) {
|
synchronized (mA2dpAvrcpLock) {
|
||||||
if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
|
mA2dp = null;
|
||||||
makeA2dpDeviceUnavailableNow(
|
synchronized (mConnectedDevices) {
|
||||||
mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
|
if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
|
||||||
|
makeA2dpDeviceUnavailableNow(
|
||||||
|
mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3697,6 +3726,7 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
|
|
||||||
private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
|
private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
|
||||||
{
|
{
|
||||||
|
if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state);
|
||||||
if (btDevice == null) {
|
if (btDevice == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3704,6 +3734,20 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
|
||||||
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) {
|
synchronized (mConnectedDevices) {
|
||||||
boolean isConnected =
|
boolean isConnected =
|
||||||
(mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
|
(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) {
|
private boolean handleDeviceConnection(boolean connected, int device, String params) {
|
||||||
synchronized (mConnectedDevices) {
|
synchronized (mConnectedDevices) {
|
||||||
boolean isConnected = (mConnectedDevices.containsKey(device) &&
|
boolean isConnected = (mConnectedDevices.containsKey(device) &&
|
||||||
|
|||||||
@@ -98,6 +98,10 @@ interface IAudioService {
|
|||||||
|
|
||||||
oneway void reloadAudioSettings();
|
oneway void reloadAudioSettings();
|
||||||
|
|
||||||
|
oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
|
||||||
|
|
||||||
|
oneway void avrcpUpdateVolume(int oldVolume, int volume);
|
||||||
|
|
||||||
void setSpeakerphoneOn(boolean on);
|
void setSpeakerphoneOn(boolean on);
|
||||||
|
|
||||||
boolean isSpeakerphoneOn();
|
boolean isSpeakerphoneOn();
|
||||||
|
|||||||
Reference in New Issue
Block a user