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

Commit 085346ac authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

AudioService: fix deadlock

Source of deadlock:
Thread A:
 readAudioSettings()
  -> checkAllAliasStreamVolumes()
    -> synchronized (VolumeStreamState.class)
         -> mStreamStates[streamType].setAllIndexes()
            -> synchronized (mSettingsLock)
Thread B:
 updateStreamVolumeAlias()
  -> mStreamStates[ACCESSIBILITY].setAllIndexes()
     -> synchronized (mSettingsLock)
        -> synchronized (VolumeStreamState.class)

Fix:
 Ensure all calls to VSS.setAllIndexes() are synchronized
 on mSettingsLock then on VolumeStreamState.class.

Bug: 72122435
Test: see bug for repro
Change-Id: I16ad1d1df88256291c36d8f5b8ebe830fe1b0b84
parent 11817c6b
Loading
Loading
Loading
Loading
+53 −49
Original line number Diff line number Diff line
@@ -1042,6 +1042,7 @@ public class AudioService extends IAudioService.Stub
    }

    private void checkAllAliasStreamVolumes() {
        synchronized (mSettingsLock) {
            synchronized (VolumeStreamState.class) {
                int numStreamTypes = AudioSystem.getNumStreamTypes();
                for (int streamType = 0; streamType < numStreamTypes; streamType++) {
@@ -1054,6 +1055,7 @@ public class AudioService extends IAudioService.Stub
                }
            }
        }
    }

    private void checkAllFixedVolumeDevices()
    {
@@ -1155,13 +1157,16 @@ public class AudioService extends IAudioService.Stub
        if (updateVolumes && mStreamStates != null) {
            updateDefaultVolumes();

            mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
                    caller);

            synchronized (mSettingsLock) {
                synchronized (VolumeStreamState.class) {
                    mStreamStates[AudioSystem.STREAM_DTMF]
                            .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
                    mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
                            System.VOLUME_SETTINGS_INT[a11yStreamAlias];
                    mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
                            mStreamStates[a11yStreamAlias], caller);
                }
            }
            if (sIndependentA11yVolume) {
                // restore the a11y values from the settings
                mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
@@ -4604,12 +4609,12 @@ public class AudioService extends IAudioService.Stub
         * @param srcStream
         * @param caller
         */
        // must be sync'd on mSettingsLock before VolumeStreamState.class
        @GuardedBy("VolumeStreamState.class")
        public void setAllIndexes(VolumeStreamState srcStream, String caller) {
            if (mStreamType == srcStream.mStreamType) {
                return;
            }
            synchronized (mSettingsLock) {
                synchronized (VolumeStreamState.class) {
            int srcStreamType = srcStream.getStreamType();
            // apply default device volume from source stream to all devices first in case
            // some devices are present in this stream state but not in source stream state
@@ -4628,17 +4633,14 @@ public class AudioService extends IAudioService.Stub
                setIndex(index, device, caller);
            }
        }
            }
        }

        @GuardedBy("mSettingsLock")
        // must be sync'd on mSettingsLock before VolumeStreamState.class
        @GuardedBy("VolumeStreamState.class")
        public void setAllIndexesToMax() {
            synchronized (VolumeStreamState.class) {
            for (int i = 0; i < mIndexMap.size(); i++) {
                mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
            }
        }
        }

        public void mute(boolean state) {
            boolean changed = false;
@@ -6224,6 +6226,7 @@ public class AudioService extends IAudioService.Stub
                mCameraSoundForced = cameraSoundForced;
                if (cameraSoundForcedChanged) {
                    if (!mIsSingleVolume) {
                        synchronized (VolumeStreamState.class) {
                            VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
                            if (cameraSoundForced) {
                                s.setAllIndexesToMax();
@@ -6234,6 +6237,7 @@ public class AudioService extends IAudioService.Stub
                                mRingerModeAffectedStreams |=
                                        (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                            }
                        }
                        // take new state into account for streams muted by ringer mode
                        setRingerModeInt(getRingerModeInternal(), false);
                    }