Merge "AudioService: more fixes for BT A2DP device switch" into rvc-dev am: 200e84a8de

Change-Id: If552c11cc69affc11ed0487b686bdd06d2cc2080
This commit is contained in:
Eric Laurent
2020-05-29 20:33:43 +00:00
committed by Automerger Merge Worker
3 changed files with 43 additions and 40 deletions

View File

@@ -63,7 +63,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
// Delay before checking it music should be unmuted after processing an A2DP message // Delay before checking it music should be unmuted after processing an A2DP message
private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 50; private static final int BTA2DP_MUTE_CHECK_DELAY_MS = 100;
private final @NonNull AudioService mAudioService; private final @NonNull AudioService mAudioService;
private final @NonNull Context mContext; private final @NonNull Context mContext;
@@ -160,8 +160,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
synchronized (mDeviceStateLock) { synchronized (mDeviceStateLock) {
AudioSystem.setParameters( AudioSystem.setParameters(
"BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off")); "BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off"));
onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied"); onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm,
onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied"); false /*fromA2dp*/, "onAudioServerDied");
onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm,
false /*fromA2dp*/, "onAudioServerDied");
} }
// restore devices // restore devices
sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE);
@@ -667,7 +669,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
// Handles request to override default use of A2DP for media. // Handles request to override default use of A2DP for media.
//@GuardedBy("mConnectedDevices") //@GuardedBy("mConnectedDevices")
/*package*/ void setBluetoothA2dpOnInt(boolean on, String source) { /*package*/ void setBluetoothA2dpOnInt(boolean on, boolean fromA2dp, String source) {
// for logging only // for logging only
final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
.append(") from u/pid:").append(Binder.getCallingUid()).append("/") .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
@@ -679,6 +681,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
onSetForceUse( onSetForceUse(
AudioSystem.FOR_MEDIA, AudioSystem.FOR_MEDIA,
mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
fromA2dp,
eventSource); eventSource);
} }
} }
@@ -705,8 +708,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
} }
/*package*/ void postReportNewRoutes() { /*package*/ void postReportNewRoutes(boolean fromA2dp) {
sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); sendMsgNoDelay(fromA2dp ? MSG_REPORT_NEW_ROUTES_A2DP : MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP);
} }
/*package*/ void postA2dpActiveDeviceChange( /*package*/ void postA2dpActiveDeviceChange(
@@ -774,9 +777,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
// These methods are ALL synchronous, in response to message handling in BrokerHandler // These methods are ALL synchronous, in response to message handling in BrokerHandler
// Blocking in any of those will block the message queue // Blocking in any of those will block the message queue
private void onSetForceUse(int useCase, int config, String eventSource) { private void onSetForceUse(int useCase, int config, boolean fromA2dp, String eventSource) {
if (useCase == AudioSystem.FOR_MEDIA) { if (useCase == AudioSystem.FOR_MEDIA) {
postReportNewRoutes(); postReportNewRoutes(fromA2dp);
} }
AudioService.sForceUseLogger.log( AudioService.sForceUseLogger.log(
new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
@@ -870,9 +873,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
break; break;
case MSG_IIL_SET_FORCE_USE: // intended fall-through case MSG_IIL_SET_FORCE_USE: // intended fall-through
case MSG_IIL_SET_FORCE_BT_A2DP_USE: case MSG_IIL_SET_FORCE_BT_A2DP_USE:
onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj); onSetForceUse(msg.arg1, msg.arg2,
(msg.what == MSG_IIL_SET_FORCE_BT_A2DP_USE), (String) msg.obj);
break; break;
case MSG_REPORT_NEW_ROUTES: case MSG_REPORT_NEW_ROUTES:
case MSG_REPORT_NEW_ROUTES_A2DP:
synchronized (mDeviceStateLock) { synchronized (mDeviceStateLock) {
mDeviceInventory.onReportNewRoutes(); mDeviceInventory.onReportNewRoutes();
} }
@@ -1057,7 +1062,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.onSaveRemovePreferredDevice(strategy); mDeviceInventory.onSaveRemovePreferredDevice(strategy);
} break; } break;
case MSG_CHECK_MUTE_MUSIC: case MSG_CHECK_MUTE_MUSIC:
checkMessagesMuteMusic(); checkMessagesMuteMusic(0);
break; break;
default: default:
Log.wtf(TAG, "Invalid message " + msg.what); Log.wtf(TAG, "Invalid message " + msg.what);
@@ -1133,6 +1138,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35; private static final int MSG_L_SPEAKERPHONE_CLIENT_DIED = 35;
private static final int MSG_CHECK_MUTE_MUSIC = 36; private static final int MSG_CHECK_MUTE_MUSIC = 36;
private static final int MSG_REPORT_NEW_ROUTES_A2DP = 37;
private static boolean isMessageHandledUnderWakelock(int msgId) { private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -1224,6 +1230,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity);
} }
if (MESSAGES_MUTE_MUSIC.contains(msg)) {
checkMessagesMuteMusic(msg);
}
synchronized (sLastDeviceConnectionMsgTimeLock) { synchronized (sLastDeviceConnectionMsgTimeLock) {
long time = SystemClock.uptimeMillis() + delay; long time = SystemClock.uptimeMillis() + delay;
@@ -1245,13 +1255,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
default: default:
break; break;
} }
mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj),
time); time);
} }
if (MESSAGES_MUTE_MUSIC.contains(msg)) {
checkMessagesMuteMusic();
}
} }
/** List of messages for which music is muted while processing is pending */ /** List of messages for which music is muted while processing is pending */
@@ -1264,19 +1270,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
} }
private AtomicBoolean mMusicMuted = new AtomicBoolean(false); private AtomicBoolean mMusicMuted = new AtomicBoolean(false);
/** Mutes or unmutes music according to pending A2DP messages */ /** Mutes or unmutes music according to pending A2DP messages */
private void checkMessagesMuteMusic() { private void checkMessagesMuteMusic(int message) {
boolean mute = false; boolean mute = message != 0;
for (int msg : MESSAGES_MUTE_MUSIC) { if (!mute) {
if (mBrokerHandler.hasMessages(msg)) { for (int msg : MESSAGES_MUTE_MUSIC) {
mute = true; if (mBrokerHandler.hasMessages(msg)) {
break; mute = true;
break;
}
} }
} }
if (mute != mMusicMuted.getAndSet(mute)) { if (mute != mMusicMuted.getAndSet(mute)) {
mAudioService.setMusicMute(mute); mAudioService.setMusicMute(mute);
} }

View File

@@ -549,7 +549,7 @@ public class AudioDeviceInventory {
synchronized (mDevicesLock) { synchronized (mDevicesLock) {
if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED) if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
&& DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) { && DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
mDeviceBroker.setBluetoothA2dpOnInt(true, mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/,
"onSetWiredDeviceConnectionState state DISCONNECTED"); "onSetWiredDeviceConnectionState state DISCONNECTED");
} }
@@ -562,7 +562,7 @@ public class AudioDeviceInventory {
} }
if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) { if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) { if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
mDeviceBroker.setBluetoothA2dpOnInt(false, mDeviceBroker.setBluetoothA2dpOnInt(false, false /*fromA2dp*/,
"onSetWiredDeviceConnectionState state not DISCONNECTED"); "onSetWiredDeviceConnectionState state not DISCONNECTED");
} }
mDeviceBroker.checkMusicActive(wdcs.mType, wdcs.mCaller); mDeviceBroker.checkMusicActive(wdcs.mType, wdcs.mCaller);
@@ -879,7 +879,7 @@ public class AudioDeviceInventory {
int a2dpCodec) { int a2dpCodec) {
// enable A2DP before notifying A2DP connection to avoid unnecessary processing in // enable A2DP before notifying A2DP connection to avoid unnecessary processing in
// audio policy manager // audio policy manager
mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource); mDeviceBroker.setBluetoothA2dpOnInt(true, true /*fromA2dp*/, eventSource);
// at this point there could be another A2DP device already connected in APM, but it // at this point there could be another A2DP device already connected in APM, but it
// doesn't matter as this new one will overwrite the previous one // doesn't matter as this new one will overwrite the previous one
final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, final int res = mAudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
@@ -910,7 +910,7 @@ public class AudioDeviceInventory {
mApmConnectedDevices.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, diKey); mApmConnectedDevices.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, diKey);
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
setCurrentAudioRouteNameIfPossible(name); setCurrentAudioRouteNameIfPossible(name, true /*fromA2dp*/);
} }
@GuardedBy("mDevicesLock") @GuardedBy("mDevicesLock")
@@ -955,7 +955,7 @@ public class AudioDeviceInventory {
} }
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
// Remove A2DP routes as well // Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null); setCurrentAudioRouteNameIfPossible(null, true /*fromA2dp*/);
mmi.record(); mmi.record();
} }
@@ -1014,7 +1014,7 @@ public class AudioDeviceInventory {
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID); mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID);
mDeviceBroker.postApplyVolumeOnDevice(streamType, mDeviceBroker.postApplyVolumeOnDevice(streamType,
AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable"); AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable");
setCurrentAudioRouteNameIfPossible(name); setCurrentAudioRouteNameIfPossible(name, false /*fromA2dp*/);
new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceAvailable") new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceAvailable")
.set(MediaMetrics.Property.ADDRESS, address != null ? address : "") .set(MediaMetrics.Property.ADDRESS, address != null ? address : "")
.set(MediaMetrics.Property.DEVICE, .set(MediaMetrics.Property.DEVICE,
@@ -1033,7 +1033,7 @@ public class AudioDeviceInventory {
mConnectedDevices.remove( mConnectedDevices.remove(
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address)); DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
// Remove Hearing Aid routes as well // Remove Hearing Aid routes as well
setCurrentAudioRouteNameIfPossible(null); setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceUnavailable") new MediaMetrics.Item(mMetricsId + "makeHearingAidDeviceUnavailable")
.set(MediaMetrics.Property.ADDRESS, address != null ? address : "") .set(MediaMetrics.Property.ADDRESS, address != null ? address : "")
.set(MediaMetrics.Property.DEVICE, .set(MediaMetrics.Property.DEVICE,
@@ -1042,14 +1042,14 @@ public class AudioDeviceInventory {
} }
@GuardedBy("mDevicesLock") @GuardedBy("mDevicesLock")
private void setCurrentAudioRouteNameIfPossible(String name) { private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
synchronized (mCurAudioRoutes) { synchronized (mCurAudioRoutes) {
if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) { if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
return; return;
} }
if (name != null || !isCurrentDeviceConnected()) { if (name != null || !isCurrentDeviceConnected()) {
mCurAudioRoutes.bluetoothName = name; mCurAudioRoutes.bluetoothName = name;
mDeviceBroker.postReportNewRoutes(); mDeviceBroker.postReportNewRoutes(fromA2dp);
} }
} }
} }
@@ -1236,7 +1236,7 @@ public class AudioDeviceInventory {
} }
if (newConn != mCurAudioRoutes.mainType) { if (newConn != mCurAudioRoutes.mainType) {
mCurAudioRoutes.mainType = newConn; mCurAudioRoutes.mainType = newConn;
mDeviceBroker.postReportNewRoutes(); mDeviceBroker.postReportNewRoutes(false /*fromA2dp*/);
} }
} }
} }

View File

@@ -5904,16 +5904,8 @@ public class AudioService extends IAudioService.Stub
if (state != mIsMutedInternally) { if (state != mIsMutedInternally) {
changed = true; changed = true;
mIsMutedInternally = state; mIsMutedInternally = state;
// mute immediately to avoid delay and preemption when using a message.
// Set the new mute volume. This propagates the values to applyAllVolumes();
// the audio system, otherwise the volume won't be changed
// at the lower level.
sendMsg(mAudioHandler,
MSG_SET_ALL_VOLUMES,
SENDMSG_QUEUE,
0,
0,
this, 0);
} }
} }
if (changed) { if (changed) {