Merge "Fix deadlock caused by wrong locking order" into udc-dev am: cbde6a8f33

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23681582

Change-Id: I42aa37a757ad46d75e94e2794c2ea889eb8d73e4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Vlad Popa
2023-06-16 17:41:37 +00:00
committed by Automerger Merge Worker

View File

@@ -3666,6 +3666,8 @@ public class AudioService extends IAudioService.Stub
* and aliases before mute change changed and after. * and aliases before mute change changed and after.
*/ */
private void muteAliasStreams(int streamAlias, boolean state) { private void muteAliasStreams(int streamAlias, boolean state) {
// Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) { synchronized (VolumeStreamState.class) {
List<Integer> streamsToMute = new ArrayList<>(); List<Integer> streamsToMute = new ArrayList<>();
for (int stream = 0; stream < mStreamStates.length; stream++) { for (int stream = 0; stream < mStreamStates.length; stream++) {
@@ -3674,7 +3676,8 @@ public class AudioService extends IAudioService.Stub
if (!(mCameraSoundForced if (!(mCameraSoundForced
&& (vss.getStreamType() && (vss.getStreamType()
== AudioSystem.STREAM_SYSTEM_ENFORCED))) { == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams"); boolean changed = vss.mute(state, /* apply= */ false,
"muteAliasStreams");
if (changed) { if (changed) {
streamsToMute.add(stream); streamsToMute.add(stream);
} }
@@ -3687,6 +3690,7 @@ public class AudioService extends IAudioService.Stub
}); });
} }
} }
}
private void broadcastMuteSetting(int streamType, boolean isMuted) { private void broadcastMuteSetting(int streamType, boolean isMuted) {
// Stream mute changed, fire the intent. // Stream mute changed, fire the intent.
@@ -3699,6 +3703,9 @@ public class AudioService extends IAudioService.Stub
// Called after a delay when volume down is pressed while muted // Called after a delay when volume down is pressed while muted
private void onUnmuteStream(int stream, int flags) { private void onUnmuteStream(int stream, int flags) {
boolean wasMuted; boolean wasMuted;
// Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
// vss.updateVolumeGroupIndex
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) { synchronized (VolumeStreamState.class) {
final VolumeStreamState streamState = mStreamStates[stream]; final VolumeStreamState streamState = mStreamStates[stream];
// if unmuting causes a change, it was muted // if unmuting causes a change, it was muted
@@ -3714,6 +3721,7 @@ public class AudioService extends IAudioService.Stub
} }
} }
} }
}
@GuardedBy("mHdmiClientLock") @GuardedBy("mHdmiClientLock")
private void maybeSendSystemAudioStatusCommand(boolean isMuteAdjust) { private void maybeSendSystemAudioStatusCommand(boolean isMuteAdjust) {
@@ -7611,9 +7619,13 @@ public class AudioService extends IAudioService.Stub
Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]", Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
newDevice, AudioSystem.getOutputDeviceName(newDevice))); newDevice, AudioSystem.getOutputDeviceName(newDevice)));
} }
// Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
// vss.updateVolumeGroupIndex
synchronized (mSettingsLock) {
mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute"); mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
} }
} }
}
/** /**
* See AudioManager.hasHapticChannels(Context, Uri). * See AudioManager.hasHapticChannels(Context, Uri).
@@ -7646,11 +7658,16 @@ public class AudioService extends IAudioService.Stub
continue; continue;
} }
} }
// need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
// VSS.class. Locking order needs to be preserved
synchronized (mSettingsLock) {
for (int i = 0; i < sVolumeGroupStates.size(); i++) { for (int i = 0; i < sVolumeGroupStates.size(); i++) {
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
vgs.applyAllVolumes(/* userSwitch= */ false); vgs.applyAllVolumes(/* userSwitch= */ false);
} }
} }
}
private void ensureValidAttributes(AudioVolumeGroup avg) { private void ensureValidAttributes(AudioVolumeGroup avg) {
boolean hasAtLeastOneValidAudioAttributes = avg.getAudioAttributes().stream() boolean hasAtLeastOneValidAudioAttributes = avg.getAudioAttributes().stream()
@@ -7685,11 +7702,16 @@ public class AudioService extends IAudioService.Stub
if (DEBUG_VOL) { if (DEBUG_VOL) {
Log.v(TAG, "restoreVolumeGroups"); Log.v(TAG, "restoreVolumeGroups");
} }
// need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
// VSS.class. Locking order needs to be preserved
synchronized (mSettingsLock) {
for (int i = 0; i < sVolumeGroupStates.size(); i++) { for (int i = 0; i < sVolumeGroupStates.size(); i++) {
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
vgs.applyAllVolumes(false/*userSwitch*/); vgs.applyAllVolumes(false/*userSwitch*/);
} }
} }
}
private void dumpVolumeGroups(PrintWriter pw) { private void dumpVolumeGroups(PrintWriter pw) {
pw.println("\nVolume Groups (device: index)"); pw.println("\nVolume Groups (device: index)");
@@ -7824,6 +7846,7 @@ public class AudioService extends IAudioService.Stub
} }
public void adjustVolume(int direction, int flags) { public void adjustVolume(int direction, int flags) {
synchronized (mSettingsLock) {
synchronized (AudioService.VolumeStreamState.class) { synchronized (AudioService.VolumeStreamState.class) {
int device = getDeviceForVolume(); int device = getDeviceForVolume();
int previousIndex = getIndex(device); int previousIndex = getIndex(device);
@@ -7870,6 +7893,7 @@ public class AudioService extends IAudioService.Stub
} }
} }
} }
}
public int getVolumeIndex() { public int getVolumeIndex() {
synchronized (AudioService.VolumeStreamState.class) { synchronized (AudioService.VolumeStreamState.class) {
@@ -7878,6 +7902,7 @@ public class AudioService extends IAudioService.Stub
} }
public void setVolumeIndex(int index, int flags) { public void setVolumeIndex(int index, int flags) {
synchronized (mSettingsLock) {
synchronized (AudioService.VolumeStreamState.class) { synchronized (AudioService.VolumeStreamState.class) {
if (mUseFixedVolume) { if (mUseFixedVolume) {
return; return;
@@ -7885,6 +7910,7 @@ public class AudioService extends IAudioService.Stub
setVolumeIndex(index, getDeviceForVolume(), flags); setVolumeIndex(index, getDeviceForVolume(), flags);
} }
} }
}
@GuardedBy("AudioService.VolumeStreamState.class") @GuardedBy("AudioService.VolumeStreamState.class")
private void setVolumeIndex(int index, int device, int flags) { private void setVolumeIndex(int index, int device, int flags) {
@@ -8689,6 +8715,10 @@ public class AudioService extends IAudioService.Stub
// If associated to volume group, update group cache // If associated to volume group, update group cache
private void updateVolumeGroupIndex(int device, boolean forceMuteState) { private void updateVolumeGroupIndex(int device, boolean forceMuteState) {
// need mSettingsLock when called from setIndex for vgs.mute -> vgs.applyAllVolumes ->
// vss.setIndex which grabs this lock after VSS.class. Locking order needs to be
// preserved
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) { synchronized (VolumeStreamState.class) {
if (mVolumeGroupState != null) { if (mVolumeGroupState != null) {
int groupIndex = (getIndex(device) + 5) / 10; int groupIndex = (getIndex(device) + 5) / 10;
@@ -8696,13 +8726,14 @@ public class AudioService extends IAudioService.Stub
Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
+ ", muted=" + mIsMuted + ", device=" + device + ", index=" + ", muted=" + mIsMuted + ", device=" + device + ", index="
+ getIndex(device) + ", group " + mVolumeGroupState.name() + getIndex(device) + ", group " + mVolumeGroupState.name()
+ " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex + " Muted=" + mVolumeGroupState.isMuted() + ", Index="
+ ", forceMuteState=" + forceMuteState); + groupIndex + ", forceMuteState=" + forceMuteState);
} }
mVolumeGroupState.updateVolumeIndex(groupIndex, device); mVolumeGroupState.updateVolumeIndex(groupIndex, device);
// Only propage mute of stream when applicable // Only propage mute of stream when applicable
if (isMutable()) { if (isMutable()) {
// For call stream, align mute only when muted, not when index is set to 0 // For call stream, align mute only when muted, not when index is set to
// 0
mVolumeGroupState.mute( mVolumeGroupState.mute(
forceMuteState ? mIsMuted : forceMuteState ? mIsMuted :
(groupIndex == 0 && !isCallStream(mStreamType)) (groupIndex == 0 && !isCallStream(mStreamType))
@@ -8711,6 +8742,7 @@ public class AudioService extends IAudioService.Stub
} }
} }
} }
}
/** /**
* Mute/unmute the stream * Mute/unmute the stream