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

Commit fdbee869 authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioService: fix cross deadlock in VolumeStreamState

Synchronize modifications of volume index by VolumeStreamState
class mutex instead of using synchronized methods.
This avoids possible cross deadlock when modifying volume on
two stream types simultaneously and one is slave to the other.

Bug: 13730145.

Change-Id: I13406c71010ce0c2e2f08f660b6101f310396c98
parent d5ee4144
Loading
Loading
Loading
Loading
+147 −133
Original line number Diff line number Diff line
@@ -2857,7 +2857,8 @@ public class AudioService extends IAudioService.Stub {
            return name + "_" + suffix;
        }

        public synchronized void readSettings() {
        public void readSettings() {
            synchronized (VolumeStreamState.class) {
                // force maximum volume on all streams if fixed volume property is set
                if (mUseFixedVolume) {
                    mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
@@ -2908,6 +2909,7 @@ public class AudioService extends IAudioService.Stub {
                    }
                }
            }
        }

        public void applyDeviceVolume(int device) {
            int index;
@@ -2922,7 +2924,8 @@ public class AudioService extends IAudioService.Stub {
            AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
        }

        public synchronized void applyAllVolumes() {
        public void applyAllVolumes() {
            synchronized (VolumeStreamState.class) {
                // apply default volume first: by convention this will reset all
                // devices volumes in audio policy manager to the supplied value
                int index;
@@ -2951,13 +2954,15 @@ public class AudioService extends IAudioService.Stub {
                    }
                }
            }
        }

        public boolean adjustIndex(int deltaIndex, int device) {
            return setIndex(getIndex(device) + deltaIndex,
                            device);
        }

        public synchronized boolean setIndex(int index, int device) {
        public boolean setIndex(int index, int device) {
            synchronized (VolumeStreamState.class) {
                int oldIndex = getIndex(device);
                index = getValidIndex(index);
                synchronized (mCameraSoundForced) {
@@ -2990,8 +2995,10 @@ public class AudioService extends IAudioService.Stub {
                    return false;
                }
            }
        }

        public synchronized int getIndex(int device) {
        public int getIndex(int device) {
            synchronized (VolumeStreamState.class) {
                Integer index = mIndex.get(device);
                if (index == null) {
                    // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
@@ -2999,12 +3006,14 @@ public class AudioService extends IAudioService.Stub {
                }
                return index.intValue();
            }
        }

        public int getMaxIndex() {
            return mIndexMax;
        }

        public synchronized void setAllIndexes(VolumeStreamState srcStream) {
        public void setAllIndexes(VolumeStreamState srcStream) {
            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
@@ -3028,8 +3037,10 @@ public class AudioService extends IAudioService.Stub {
                    setIndex(index, device);
                }
            }
        }

        public synchronized void setAllIndexesToMax() {
        public void setAllIndexesToMax() {
            synchronized (VolumeStreamState.class) {
                Set set = mIndex.entrySet();
                Iterator i = set.iterator();
                while (i.hasNext()) {
@@ -3037,8 +3048,10 @@ public class AudioService extends IAudioService.Stub {
                    entry.setValue(mIndexMax);
                }
            }
        }

        public synchronized void mute(IBinder cb, boolean state) {
        public void mute(IBinder cb, boolean state) {
            synchronized (VolumeStreamState.class) {
                VolumeDeathHandler handler = getDeathHandler(cb, state);
                if (handler == null) {
                    Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
@@ -3046,6 +3059,7 @@ public class AudioService extends IAudioService.Stub {
                }
                handler.mute(state);
            }
        }

        public int getStreamType() {
            return mStreamType;