Merge "AudioService: make all BT device updates async"

This commit is contained in:
TreeHugger Robot
2019-03-04 21:25:40 +00:00
committed by Android (Google) Code Review
6 changed files with 154 additions and 83 deletions

View File

@@ -4068,6 +4068,10 @@ public class AudioManager {
/**
* Indicate Hearing Aid connection state change and eventually suppress
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
* This operation is asynchronous but its execution will still be sequentially scheduled
* relative to calls to {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
* * BluetoothDevice, int, int, boolean, int)} and
* and {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
* @param device Bluetooth device connected/disconnected
* @param state new connection state (BluetoothProfile.STATE_xxx)
* @param musicDevice Default get system volume for the connecting device.
@@ -4075,27 +4079,27 @@ public class AudioManager {
* {@link android.bluetooth.BluetoothProfile.HEARING_AID})
* @param suppressNoisyIntent if true the
* {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
* @return a delay in ms that the caller should wait before broadcasting
* BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED intent.
* {@hide}
*/
public int setBluetoothHearingAidDeviceConnectionState(
public void setBluetoothHearingAidDeviceConnectionState(
BluetoothDevice device, int state, boolean suppressNoisyIntent,
int musicDevice) {
final IAudioService service = getService();
int delay = 0;
try {
delay = service.setBluetoothHearingAidDeviceConnectionState(device,
service.setBluetoothHearingAidDeviceConnectionState(device,
state, suppressNoisyIntent, musicDevice);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return delay;
}
/**
* Indicate A2DP source or sink connection state change and eventually suppress
* the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
* This operation is asynchronous but its execution will still be sequentially scheduled
* relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
* int, boolean, int)} and
* {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
* @param device Bluetooth device connected/disconnected
* @param state new connection state, {@link BluetoothProfile#STATE_CONNECTED}
* or {@link BluetoothProfile#STATE_DISCONNECTED}
@@ -4105,26 +4109,27 @@ public class AudioManager {
* {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
* @param suppressNoisyIntent if true the
* {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
* @return a delay in ms that the caller should wait before broadcasting
* BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
* {@hide}
*/
public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
BluetoothDevice device, int state,
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
final IAudioService service = getService();
int delay = 0;
try {
delay = service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
state, profile, suppressNoisyIntent, a2dpVolume);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return delay;
}
/**
* Indicate A2DP device configuration has changed.
* This operation is asynchronous but its execution will still be sequentially scheduled
* relative to calls to
* {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice, int, int,
* boolean, int)} and
* {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice, int, boolean, int)}
* @param device Bluetooth device whose configuration has changed.
* {@hide}
*/

View File

@@ -228,10 +228,10 @@ interface IAudioService {
oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
int setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
int state, boolean suppressNoisyIntent, int musicDevice);
int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,

View File

@@ -201,51 +201,72 @@ import java.util.ArrayList;
}
}
/*package*/ int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
private static final class BtDeviceConnectionInfo {
final @NonNull BluetoothDevice mDevice;
final @AudioService.BtProfileConnectionState int mState;
final int mProfile;
final boolean mSupprNoisy;
final int mVolume;
BtDeviceConnectionInfo(@NonNull BluetoothDevice device,
@AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int vol) {
mDevice = device;
mState = state;
mProfile = profile;
mSupprNoisy = suppressNoisyIntent;
mVolume = vol;
}
}
/*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state
// only querying address as this is the only readily available field
// on the device
+ " addr=" + device.getAddress()
+ " prof=" + profile + " supprNoisy=" + suppressNoisyIntent
+ " vol=" + a2dpVolume)).printLog(TAG));
synchronized (mDeviceStateLock) {
if (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
new BtHelper.BluetoothA2dpDeviceInfo(device))) {
AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
"A2DP connection state ignored"));
return 0;
}
return mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
device, state, profile, suppressNoisyIntent,
AudioSystem.DEVICE_NONE, a2dpVolume);
}
final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
suppressNoisyIntent, a2dpVolume);
// TODO add a check to try to remove unprocessed messages for the same device (the old
// check didn't work), and make sure it doesn't conflict with config change message
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
}
/*package*/ int handleBluetoothA2dpActiveDeviceChange(
@NonNull BluetoothDevice device,
@AudioService.BtProfileConnectionState int state, int profile,
boolean suppressNoisyIntent, int a2dpVolume) {
// FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
// of handleBluetoothA2dpDeviceConfigChange and
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
synchronized (mDeviceStateLock) {
return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
suppressNoisyIntent, a2dpVolume);
}
}
/*package*/ int setBluetoothHearingAidDeviceConnectionState(
private static final class HearingAidDeviceConnectionInfo {
final @NonNull BluetoothDevice mDevice;
final @AudioService.BtProfileConnectionState int mState;
final boolean mSupprNoisy;
final int mMusicDevice;
final @NonNull String mEventSource;
HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device,
@AudioService.BtProfileConnectionState int state,
boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
mDevice = device;
mState = state;
mSupprNoisy = suppressNoisyIntent;
mMusicDevice = musicDevice;
mEventSource = eventSource;
}
}
/*package*/ void postBluetoothHearingAidDeviceConnectionState(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setHearingAidDeviceConnectionState state=" + state
+ " addr=" + device.getAddress()
+ " supprNoisy=" + suppressNoisyIntent
+ " src=" + eventSource)).printLog(TAG));
synchronized (mDeviceStateLock) {
return mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
device, state, suppressNoisyIntent, musicDevice);
}
final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo(
device, state, suppressNoisyIntent, musicDevice, eventSource);
sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
}
// never called by system components
@@ -766,6 +787,35 @@ import java.util.ArrayList;
mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
}
break;
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: {
final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
+ " state=" + info.mState
// only querying address as this is the only readily available
// field on the device
+ " addr=" + info.mDevice.getAddress()
+ " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
+ " vol=" + info.mVolume)).printLog(TAG));
synchronized (mDeviceStateLock) {
mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
AudioSystem.DEVICE_NONE, info.mVolume);
}
} break;
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: {
final HearingAidDeviceConnectionInfo info =
(HearingAidDeviceConnectionInfo) msg.obj;
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
"setHearingAidDeviceConnectionState state=" + info.mState
+ " addr=" + info.mDevice.getAddress()
+ " supprNoisy=" + info.mSupprNoisy
+ " src=" + info.mEventSource)).printLog(TAG));
synchronized (mDeviceStateLock) {
mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
}
} break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -809,6 +859,10 @@ import java.util.ArrayList;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
// process external command to (dis)connect an A2DP device
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
// process external command to (dis)connect a hearing aid device
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -821,6 +875,8 @@ import java.util.ArrayList;
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
return true;
default:
return false;

View File

@@ -578,7 +578,7 @@ public final class AudioDeviceInventory {
return mCurAudioRoutes;
}
/*package*/ int setBluetoothA2dpDeviceConnectionState(
/*package*/ void setBluetoothA2dpDeviceConnectionState(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
int delay;
@@ -614,46 +614,50 @@ public final class AudioDeviceInventory {
delay);
}
}
return delay;
}
/*package*/ int handleBluetoothA2dpActiveDeviceChange(
@NonNull BluetoothDevice device,
@AudioService.BtProfileConnectionState int state, int profile,
boolean suppressNoisyIntent, int a2dpVolume) {
if (state == BluetoothProfile.STATE_DISCONNECTED) {
return setBluetoothA2dpDeviceConnectionState(device, state, profile,
suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
}
// state == BluetoothProfile.STATE_CONNECTED
synchronized (mConnectedDevices) {
for (int i = 0; i < mConnectedDevices.size(); i++) {
final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
continue;
}
// If A2DP device exists, this is either an active device change or
// device config change
final String existingDevicekey = mConnectedDevices.keyAt(i);
final String deviceName = device.getName();
final String address = device.getAddress();
final String newDeviceKey = DeviceInfo.makeDeviceListKey(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
// Device not equal to existing device, active device change
if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
mConnectedDevices.remove(existingDevicekey);
mConnectedDevices.put(newDeviceKey, new DeviceInfo(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
address, a2dpCodec));
mDeviceBroker.postA2dpActiveDeviceChange(
new BtHelper.BluetoothA2dpDeviceInfo(
device, a2dpVolume, a2dpCodec));
return 0;
} else {
// Device config change for existing device
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
return 0;
// method was added by QC but never used, and now conflicts with async behavior of
// handleBluetoothA2dpDeviceConfigChange and
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
if (false) {
if (state == BluetoothProfile.STATE_DISCONNECTED) {
setBluetoothA2dpDeviceConnectionState(device, state, profile,
suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
}
// state == BluetoothProfile.STATE_CONNECTED
synchronized (mConnectedDevices) {
for (int i = 0; i < mConnectedDevices.size(); i++) {
final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
continue;
}
// If A2DP device exists, this is either an active device change or
// device config change
final String existingDevicekey = mConnectedDevices.keyAt(i);
final String deviceName = device.getName();
final String address = device.getAddress();
final String newDeviceKey = DeviceInfo.makeDeviceListKey(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
// Device not equal to existing device, active device change
if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
mConnectedDevices.remove(existingDevicekey);
mConnectedDevices.put(newDeviceKey, new DeviceInfo(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
address, a2dpCodec));
mDeviceBroker.postA2dpActiveDeviceChange(
new BtHelper.BluetoothA2dpDeviceInfo(
device, a2dpVolume, a2dpCodec));
return 0;
} else {
// Device config change for existing device
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
return 0;
}
}
}
}

View File

@@ -4041,7 +4041,10 @@ public class AudioService extends IAudioService.Stub
@Retention(RetentionPolicy.SOURCE)
public @interface BtProfileConnectionState {}
public int setBluetoothHearingAidDeviceConnectionState(
/**
* See AudioManager.setBluetoothHearingAidDeviceConnectionState()
*/
public void setBluetoothHearingAidDeviceConnectionState(
@NonNull BluetoothDevice device, @BtProfileConnectionState int state,
boolean suppressNoisyIntent, int musicDevice)
{
@@ -4053,14 +4056,14 @@ public class AudioService extends IAudioService.Stub
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
+ " (dis)connection, got " + state);
}
return mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
device, state, suppressNoisyIntent, musicDevice, "AudioService");
}
/**
* See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
*/
public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int a2dpVolume) {
if (device == null) {
@@ -4071,7 +4074,7 @@ public class AudioService extends IAudioService.Stub
throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
+ " (dis)connection, got " + state);
}
return mDeviceBroker.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
profile, suppressNoisyIntent, a2dpVolume);
}
@@ -4094,6 +4097,9 @@ public class AudioService extends IAudioService.Stub
public int handleBluetoothA2dpActiveDeviceChange(
BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
int a2dpVolume) {
// FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
// of handleBluetoothA2dpDeviceConfigChange and
// setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
if (device == null) {
throw new IllegalArgumentException("Illegal null device");
}

View File

@@ -426,7 +426,7 @@ public class BtHelper {
final BluetoothDevice btDevice = deviceList.get(0);
final @BluetoothProfile.BtProfileState int state =
mHearingAid.getConnectionState(btDevice);
mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
btDevice, state,
/*suppressNoisyIntent*/ false,
/*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,