Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95c59ea5 authored by Vlad Popa's avatar Vlad Popa
Browse files

Fix deadlock caused by wrong locking order

The correct order to lock is mSettingsLock -> VolumeStreamState.class.
In some cases this order was broken which lead to some deadlocks. Add
quick fix. Might still need to investigate whether we need both locks,
for details see b/287066735

Test: atest AudioManagerTest
Bug: 283969676
Bug: 283436164
Change-Id: I27afb8da18511291f8786833bf55250097a8e705
Merged-In: Id9c9fe4bd78d23dff92bf3a32c6f16d8e7b96720
parent 0665ff26
Loading
Loading
Loading
Loading
+127 −95
Original line number Diff line number Diff line
@@ -3666,6 +3666,8 @@ public class AudioService extends IAudioService.Stub
     * and aliases before mute change changed and after.
     */
    private void muteAliasStreams(int streamAlias, boolean state) {
        // Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex
        synchronized (mSettingsLock) {
            synchronized (VolumeStreamState.class) {
                List<Integer> streamsToMute = new ArrayList<>();
                for (int stream = 0; stream < mStreamStates.length; stream++) {
@@ -3674,7 +3676,8 @@ public class AudioService extends IAudioService.Stub
                        if (!(mCameraSoundForced
                                && (vss.getStreamType()
                                == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
                        boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams");
                            boolean changed = vss.mute(state, /* apply= */ false,
                                    "muteAliasStreams");
                            if (changed) {
                                streamsToMute.add(stream);
                            }
@@ -3687,6 +3690,7 @@ public class AudioService extends IAudioService.Stub
                });
            }
        }
    }
    private void broadcastMuteSetting(int streamType, boolean isMuted) {
        // 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
    private void onUnmuteStream(int stream, int flags) {
        boolean wasMuted;
        // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
        // vss.updateVolumeGroupIndex
        synchronized (mSettingsLock) {
            synchronized (VolumeStreamState.class) {
                final VolumeStreamState streamState = mStreamStates[stream];
                // if unmuting causes a change, it was muted
@@ -3714,6 +3721,7 @@ public class AudioService extends IAudioService.Stub
                }
            }
        }
    }
    @GuardedBy("mHdmiClientLock")
    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]",
                        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");
            }
        }
    }
    /**
     * See AudioManager.hasHapticChannels(Context, Uri).
@@ -7646,11 +7658,16 @@ public class AudioService extends IAudioService.Stub
                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++) {
                final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
                vgs.applyAllVolumes(/* userSwitch= */ false);
            }
        }
    }
    private void ensureValidAttributes(AudioVolumeGroup avg) {
        boolean hasAtLeastOneValidAudioAttributes = avg.getAudioAttributes().stream()
@@ -7685,11 +7702,16 @@ public class AudioService extends IAudioService.Stub
        if (DEBUG_VOL) {
            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++) {
                final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
                vgs.applyAllVolumes(false/*userSwitch*/);
            }
        }
    }
    private void dumpVolumeGroups(PrintWriter pw) {
        pw.println("\nVolume Groups (device: index)");
@@ -7824,6 +7846,7 @@ public class AudioService extends IAudioService.Stub
        }
        public void adjustVolume(int direction, int flags) {
            synchronized (mSettingsLock) {
                synchronized (AudioService.VolumeStreamState.class) {
                    int device = getDeviceForVolume();
                    int previousIndex = getIndex(device);
@@ -7870,6 +7893,7 @@ public class AudioService extends IAudioService.Stub
                    }
                }
            }
        }
        public int getVolumeIndex() {
            synchronized (AudioService.VolumeStreamState.class) {
@@ -7878,6 +7902,7 @@ public class AudioService extends IAudioService.Stub
        }
        public void setVolumeIndex(int index, int flags) {
            synchronized (mSettingsLock) {
                synchronized (AudioService.VolumeStreamState.class) {
                    if (mUseFixedVolume) {
                        return;
@@ -7885,6 +7910,7 @@ public class AudioService extends IAudioService.Stub
                    setVolumeIndex(index, getDeviceForVolume(), flags);
                }
            }
        }
        @GuardedBy("AudioService.VolumeStreamState.class")
        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
        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) {
                    if (mVolumeGroupState != null) {
                        int groupIndex = (getIndex(device) + 5) / 10;
@@ -8696,13 +8726,14 @@ public class AudioService extends IAudioService.Stub
                            Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
                                    + ", muted=" + mIsMuted + ", device=" + device + ", index="
                                    + getIndex(device) + ", group " + mVolumeGroupState.name()
                                + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex
                                + ", forceMuteState=" + forceMuteState);
                                    + " Muted=" + mVolumeGroupState.isMuted() + ", Index="
                                    + groupIndex + ", forceMuteState=" + forceMuteState);
                        }
                        mVolumeGroupState.updateVolumeIndex(groupIndex, device);
                        // Only propage mute of stream when applicable
                        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(
                                    forceMuteState ? mIsMuted :
                                            (groupIndex == 0 && !isCallStream(mStreamType))
@@ -8711,6 +8742,7 @@ public class AudioService extends IAudioService.Stub
                    }
                }
            }
        }
        /**
         * Mute/unmute the stream