Merge "Fix deadlock caused by wrong locking order" into udc-dev
This commit is contained in:
@@ -3666,25 +3666,29 @@ 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) {
|
||||||
synchronized (VolumeStreamState.class) {
|
// Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex
|
||||||
List<Integer> streamsToMute = new ArrayList<>();
|
synchronized (mSettingsLock) {
|
||||||
for (int stream = 0; stream < mStreamStates.length; stream++) {
|
synchronized (VolumeStreamState.class) {
|
||||||
VolumeStreamState vss = mStreamStates[stream];
|
List<Integer> streamsToMute = new ArrayList<>();
|
||||||
if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
|
for (int stream = 0; stream < mStreamStates.length; stream++) {
|
||||||
if (!(mCameraSoundForced
|
VolumeStreamState vss = mStreamStates[stream];
|
||||||
&& (vss.getStreamType()
|
if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
|
||||||
== AudioSystem.STREAM_SYSTEM_ENFORCED))) {
|
if (!(mCameraSoundForced
|
||||||
boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams");
|
&& (vss.getStreamType()
|
||||||
if (changed) {
|
== AudioSystem.STREAM_SYSTEM_ENFORCED))) {
|
||||||
streamsToMute.add(stream);
|
boolean changed = vss.mute(state, /* apply= */ false,
|
||||||
|
"muteAliasStreams");
|
||||||
|
if (changed) {
|
||||||
|
streamsToMute.add(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
streamsToMute.forEach(streamToMute -> {
|
||||||
|
mStreamStates[streamToMute].doMute();
|
||||||
|
broadcastMuteSetting(streamToMute, state);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
streamsToMute.forEach(streamToMute -> {
|
|
||||||
mStreamStates[streamToMute].doMute();
|
|
||||||
broadcastMuteSetting(streamToMute, state);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3699,18 +3703,22 @@ 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;
|
||||||
synchronized (VolumeStreamState.class) {
|
// Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
|
||||||
final VolumeStreamState streamState = mStreamStates[stream];
|
// vss.updateVolumeGroupIndex
|
||||||
// if unmuting causes a change, it was muted
|
synchronized (mSettingsLock) {
|
||||||
wasMuted = streamState.mute(false, "onUnmuteStream");
|
synchronized (VolumeStreamState.class) {
|
||||||
|
final VolumeStreamState streamState = mStreamStates[stream];
|
||||||
|
// if unmuting causes a change, it was muted
|
||||||
|
wasMuted = streamState.mute(false, "onUnmuteStream");
|
||||||
|
|
||||||
final int device = getDeviceForStream(stream);
|
final int device = getDeviceForStream(stream);
|
||||||
final int index = streamState.getIndex(device);
|
final int index = streamState.getIndex(device);
|
||||||
sendVolumeUpdate(stream, index, index, flags, device);
|
sendVolumeUpdate(stream, index, index, flags, device);
|
||||||
}
|
}
|
||||||
if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
|
if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
|
||||||
synchronized (mHdmiClientLock) {
|
synchronized (mHdmiClientLock) {
|
||||||
maybeSendSystemAudioStatusCommand(true);
|
maybeSendSystemAudioStatusCommand(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7611,7 +7619,11 @@ 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)));
|
||||||
}
|
}
|
||||||
mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
|
// Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
|
||||||
|
// vss.updateVolumeGroupIndex
|
||||||
|
synchronized (mSettingsLock) {
|
||||||
|
mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7646,9 +7658,14 @@ public class AudioService extends IAudioService.Stub
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
|
|
||||||
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
|
// need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
|
||||||
vgs.applyAllVolumes(/* userSwitch= */ false);
|
// VSS.class. Locking order needs to be preserved
|
||||||
|
synchronized (mSettingsLock) {
|
||||||
|
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
|
||||||
|
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
|
||||||
|
vgs.applyAllVolumes(/* userSwitch= */ false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7685,9 +7702,14 @@ public class AudioService extends IAudioService.Stub
|
|||||||
if (DEBUG_VOL) {
|
if (DEBUG_VOL) {
|
||||||
Log.v(TAG, "restoreVolumeGroups");
|
Log.v(TAG, "restoreVolumeGroups");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
|
|
||||||
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
|
// need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
|
||||||
vgs.applyAllVolumes(false/*userSwitch*/);
|
// VSS.class. Locking order needs to be preserved
|
||||||
|
synchronized (mSettingsLock) {
|
||||||
|
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
|
||||||
|
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
|
||||||
|
vgs.applyAllVolumes(false/*userSwitch*/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7824,49 +7846,51 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void adjustVolume(int direction, int flags) {
|
public void adjustVolume(int direction, int flags) {
|
||||||
synchronized (AudioService.VolumeStreamState.class) {
|
synchronized (mSettingsLock) {
|
||||||
int device = getDeviceForVolume();
|
synchronized (AudioService.VolumeStreamState.class) {
|
||||||
int previousIndex = getIndex(device);
|
int device = getDeviceForVolume();
|
||||||
if (isMuteAdjust(direction) && !isMutable()) {
|
int previousIndex = getIndex(device);
|
||||||
// Non mutable volume group
|
if (isMuteAdjust(direction) && !isMutable()) {
|
||||||
if (DEBUG_VOL) {
|
// Non mutable volume group
|
||||||
Log.d(TAG, "invalid mute on unmutable volume group " + name());
|
if (DEBUG_VOL) {
|
||||||
}
|
Log.d(TAG, "invalid mute on unmutable volume group " + name());
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (direction) {
|
|
||||||
case AudioManager.ADJUST_TOGGLE_MUTE: {
|
|
||||||
// Note: If muted by volume 0, unmute will restore volume 0.
|
|
||||||
mute(!mIsMuted);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AudioManager.ADJUST_UNMUTE:
|
|
||||||
// Note: If muted by volume 0, unmute will restore volume 0.
|
|
||||||
mute(false);
|
|
||||||
break;
|
|
||||||
case AudioManager.ADJUST_MUTE:
|
|
||||||
// May be already muted by setvolume 0, prevent from setting same value
|
|
||||||
if (previousIndex != 0) {
|
|
||||||
// bypass persist
|
|
||||||
mute(true);
|
|
||||||
}
|
}
|
||||||
mIsMuted = true;
|
return;
|
||||||
break;
|
}
|
||||||
case AudioManager.ADJUST_RAISE:
|
switch (direction) {
|
||||||
// As for stream, RAISE during mute will increment the index
|
case AudioManager.ADJUST_TOGGLE_MUTE: {
|
||||||
setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags);
|
// Note: If muted by volume 0, unmute will restore volume 0.
|
||||||
break;
|
mute(!mIsMuted);
|
||||||
case AudioManager.ADJUST_LOWER:
|
break;
|
||||||
// For stream, ADJUST_LOWER on a muted VSS is a no-op
|
}
|
||||||
// If we decide to unmute on ADJUST_LOWER, cannot fallback on
|
case AudioManager.ADJUST_UNMUTE:
|
||||||
// adjustStreamVolume for group associated to legacy stream type
|
// Note: If muted by volume 0, unmute will restore volume 0.
|
||||||
if (isMuted() && previousIndex != 0) {
|
|
||||||
mute(false);
|
mute(false);
|
||||||
} else {
|
break;
|
||||||
int newIndex = Math.max(previousIndex - 1, mIndexMin);
|
case AudioManager.ADJUST_MUTE:
|
||||||
setVolumeIndex(newIndex, device, flags);
|
// May be already muted by setvolume 0, prevent from setting same value
|
||||||
}
|
if (previousIndex != 0) {
|
||||||
break;
|
// bypass persist
|
||||||
|
mute(true);
|
||||||
|
}
|
||||||
|
mIsMuted = true;
|
||||||
|
break;
|
||||||
|
case AudioManager.ADJUST_RAISE:
|
||||||
|
// As for stream, RAISE during mute will increment the index
|
||||||
|
setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags);
|
||||||
|
break;
|
||||||
|
case AudioManager.ADJUST_LOWER:
|
||||||
|
// For stream, ADJUST_LOWER on a muted VSS is a no-op
|
||||||
|
// If we decide to unmute on ADJUST_LOWER, cannot fallback on
|
||||||
|
// adjustStreamVolume for group associated to legacy stream type
|
||||||
|
if (isMuted() && previousIndex != 0) {
|
||||||
|
mute(false);
|
||||||
|
} else {
|
||||||
|
int newIndex = Math.max(previousIndex - 1, mIndexMin);
|
||||||
|
setVolumeIndex(newIndex, device, flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7878,11 +7902,13 @@ public class AudioService extends IAudioService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumeIndex(int index, int flags) {
|
public void setVolumeIndex(int index, int flags) {
|
||||||
synchronized (AudioService.VolumeStreamState.class) {
|
synchronized (mSettingsLock) {
|
||||||
if (mUseFixedVolume) {
|
synchronized (AudioService.VolumeStreamState.class) {
|
||||||
return;
|
if (mUseFixedVolume) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setVolumeIndex(index, getDeviceForVolume(), flags);
|
||||||
}
|
}
|
||||||
setVolumeIndex(index, getDeviceForVolume(), flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8689,24 +8715,30 @@ 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) {
|
||||||
synchronized (VolumeStreamState.class) {
|
// need mSettingsLock when called from setIndex for vgs.mute -> vgs.applyAllVolumes ->
|
||||||
if (mVolumeGroupState != null) {
|
// vss.setIndex which grabs this lock after VSS.class. Locking order needs to be
|
||||||
int groupIndex = (getIndex(device) + 5) / 10;
|
// preserved
|
||||||
if (DEBUG_VOL) {
|
synchronized (mSettingsLock) {
|
||||||
Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
|
synchronized (VolumeStreamState.class) {
|
||||||
+ ", muted=" + mIsMuted + ", device=" + device + ", index="
|
if (mVolumeGroupState != null) {
|
||||||
+ getIndex(device) + ", group " + mVolumeGroupState.name()
|
int groupIndex = (getIndex(device) + 5) / 10;
|
||||||
+ " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex
|
if (DEBUG_VOL) {
|
||||||
+ ", forceMuteState=" + forceMuteState);
|
Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
|
||||||
}
|
+ ", muted=" + mIsMuted + ", device=" + device + ", index="
|
||||||
mVolumeGroupState.updateVolumeIndex(groupIndex, device);
|
+ getIndex(device) + ", group " + mVolumeGroupState.name()
|
||||||
// Only propage mute of stream when applicable
|
+ " Muted=" + mVolumeGroupState.isMuted() + ", Index="
|
||||||
if (isMutable()) {
|
+ groupIndex + ", forceMuteState=" + forceMuteState);
|
||||||
// For call stream, align mute only when muted, not when index is set to 0
|
}
|
||||||
mVolumeGroupState.mute(
|
mVolumeGroupState.updateVolumeIndex(groupIndex, device);
|
||||||
forceMuteState ? mIsMuted :
|
// Only propage mute of stream when applicable
|
||||||
(groupIndex == 0 && !isCallStream(mStreamType))
|
if (isMutable()) {
|
||||||
|| mIsMuted);
|
// For call stream, align mute only when muted, not when index is set to
|
||||||
|
// 0
|
||||||
|
mVolumeGroupState.mute(
|
||||||
|
forceMuteState ? mIsMuted :
|
||||||
|
(groupIndex == 0 && !isCallStream(mStreamType))
|
||||||
|
|| mIsMuted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user