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

Commit 1a14ec04 authored by Eric Laurent's avatar Eric Laurent Committed by Android Git Automerger
Browse files

am 12f6a11d: am 8e264a77: Merge "AudioService: fix cross deadlock" into...

am 12f6a11d: am 8e264a77: Merge "AudioService: fix cross deadlock" into lmp-mr1-dev automerge: 8befd6fd

* commit '12f6a11d':
  AudioService: fix cross deadlock
parents ff348f7d 12f6a11d
Loading
Loading
Loading
Loading
+108 −89
Original line number Diff line number Diff line
@@ -740,6 +740,7 @@ public class AudioService extends IAudioService.Stub {
    }

    private void checkAllAliasStreamVolumes() {
        synchronized (VolumeStreamState.class) {
            int numStreamTypes = AudioSystem.getNumStreamTypes();
            for (int streamType = 0; streamType < numStreamTypes; streamType++) {
                if (streamType != mStreamVolumeAlias[streamType]) {
@@ -747,11 +748,12 @@ public class AudioService extends IAudioService.Stub {
                                    setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
                }
                // apply stream volume
            if (!mStreamStates[streamType].isMuted()) {
                if (!mStreamStates[streamType].isMuted_syncVSS()) {
                    mStreamStates[streamType].applyAllVolumes();
                }
            }
        }
    }

    private void checkAllFixedVolumeDevices()
    {
@@ -1520,7 +1522,9 @@ public class AudioService extends IAudioService.Stub {

    /** get stream mute state. */
    public boolean isStreamMute(int streamType) {
        return mStreamStates[streamType].isMuted();
        synchronized (VolumeStreamState.class) {
            return mStreamStates[streamType].isMuted_syncVSS();
        }
    }

    private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
@@ -1658,10 +1662,11 @@ public class AudioService extends IAudioService.Stub {
    public int getStreamVolume(int streamType) {
        ensureValidStreamType(streamType);
        int device = getDeviceForStream(streamType);
        synchronized (VolumeStreamState.class) {
            int index = mStreamStates[streamType].getIndex(device);

            // by convention getStreamVolume() returns 0 when a stream is muted.
        if (mStreamStates[streamType].isMuted()) {
            if (mStreamStates[streamType].isMuted_syncVSS()) {
                index = 0;
            }
            if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
@@ -1670,6 +1675,7 @@ public class AudioService extends IAudioService.Stub {
            }
            return (index + 5) / 10;
        }
    }

    public int getMasterVolume() {
        if (isMasterMute()) return 0;
@@ -1822,7 +1828,7 @@ public class AudioService extends IAudioService.Stub {
                    // on voice capable devices
                    if (isPlatformVoice() &&
                            mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
                        synchronized (mStreamStates[streamType]) {
                        synchronized (VolumeStreamState.class) {
                            Set set = mStreamStates[streamType].mIndex.entrySet();
                            Iterator i = set.iterator();
                            while (i.hasNext()) {
@@ -2321,16 +2327,15 @@ public class AudioService extends IAudioService.Stub {
                continue;
            }

            synchronized (streamState) {
            streamState.readSettings();

            synchronized (VolumeStreamState.class) {
                // unmute stream that was muted but is not affect by mute anymore
                if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) &&
                if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
                        !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
                    int size = streamState.mDeathHandlers.size();
                    for (int i = 0; i < size; i++) {
                        streamState.mDeathHandlers.get(i).mMuteCount = 1;
                        streamState.mDeathHandlers.get(i).mute(false);
                        streamState.mDeathHandlers.get(i).mute_syncVSS(false);
                    }
                }
            }
@@ -3344,6 +3349,12 @@ public class AudioService extends IAudioService.Stub {
    // Inner classes
    ///////////////////////////////////////////////////////////////////////////

    // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
    //  1 mScoclient OR mSafeMediaVolumeState
    //  2   mSetModeDeathHandlers
    //  3     mSettingsLock
    //  4       VolumeStreamState.class
    //  5         mCameraSoundForced
    public class VolumeStreamState {
        private final int mStreamType;

@@ -3425,9 +3436,10 @@ public class AudioService extends IAudioService.Stub {
            }
        }

        public void applyDeviceVolume(int device) {
        // must be called while synchronized VolumeStreamState.class
        public void applyDeviceVolume_syncVSS(int device) {
            int index;
            if (isMuted()) {
            if (isMuted_syncVSS()) {
                index = 0;
            } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
                    || ((device & mFullVolumeDevices) != 0)) {
@@ -3443,7 +3455,7 @@ public class AudioService extends IAudioService.Stub {
                // apply default volume first: by convention this will reset all
                // devices volumes in audio policy manager to the supplied value
                int index;
                if (isMuted()) {
                if (isMuted_syncVSS()) {
                    index = 0;
                } else {
                    index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -3456,7 +3468,7 @@ public class AudioService extends IAudioService.Stub {
                    Map.Entry entry = (Map.Entry)i.next();
                    int device = ((Integer)entry.getKey()).intValue();
                    if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                        if (isMuted()) {
                        if (isMuted_syncVSS()) {
                            index = 0;
                        } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
                                mAvrcpAbsVolSupported)
@@ -3568,12 +3580,12 @@ public class AudioService extends IAudioService.Stub {

        public void mute(IBinder cb, boolean state) {
            synchronized (VolumeStreamState.class) {
                VolumeDeathHandler handler = getDeathHandler(cb, state);
                VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
                if (handler == null) {
                    Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
                    return;
                }
                handler.mute(state);
                handler.mute_syncVSS(state);
            }
        }

@@ -3595,7 +3607,7 @@ public class AudioService extends IAudioService.Stub {
                                || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
                            entry.setValue(mIndexMax);
                        }
                        applyDeviceVolume(device);
                        applyDeviceVolume_syncVSS(device);
                    }
                }
            }
@@ -3619,8 +3631,8 @@ public class AudioService extends IAudioService.Stub {
                mICallback = cb;
            }

            // must be called while synchronized on parent VolumeStreamState
            public void mute(boolean state) {
            // must be called while synchronized VolumeStreamState.class
            public void mute_syncVSS(boolean state) {
                boolean updateVolume = false;
                if (state) {
                    if (mMuteCount == 0) {
@@ -3632,7 +3644,7 @@ public class AudioService extends IAudioService.Stub {
                            }
                            VolumeStreamState.this.mDeathHandlers.add(this);
                            // If the stream is not yet muted by any client, set level to 0
                            if (!VolumeStreamState.this.isMuted()) {
                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
                                updateVolume = true;
                            }
                        } catch (RemoteException e) {
@@ -3656,7 +3668,7 @@ public class AudioService extends IAudioService.Stub {
                            if (mICallback != null) {
                                mICallback.unlinkToDeath(this, 0);
                            }
                            if (!VolumeStreamState.this.isMuted()) {
                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
                                updateVolume = true;
                            }
                        }
@@ -3674,15 +3686,17 @@ public class AudioService extends IAudioService.Stub {

            public void binderDied() {
                Log.w(TAG, "Volume service client died for stream: "+mStreamType);
                synchronized (VolumeStreamState.class) {
                    if (mMuteCount != 0) {
                        // Reset all active mute requests from this client.
                        mMuteCount = 1;
                    mute(false);
                        mute_syncVSS(false);
                    }
                }
            }
        }

        private synchronized int muteCount() {
        private int muteCount() {
            int count = 0;
            int size = mDeathHandlers.size();
            for (int i = 0; i < size; i++) {
@@ -3691,12 +3705,13 @@ public class AudioService extends IAudioService.Stub {
            return count;
        }

        private synchronized boolean isMuted() {
        // must be called while synchronized VolumeStreamState.class
        private boolean isMuted_syncVSS() {
            return muteCount() != 0;
        }

        // only called by mute() which is already synchronized
        private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
        // must be called while synchronized VolumeStreamState.class
        private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
            VolumeDeathHandler handler;
            int size = mDeathHandlers.size();
            for (int i = 0; i < size; i++) {
@@ -3773,8 +3788,9 @@ public class AudioService extends IAudioService.Stub {

        private void setDeviceVolume(VolumeStreamState streamState, int device) {

            synchronized (VolumeStreamState.class) {
                // Apply volume
            streamState.applyDeviceVolume(device);
                streamState.applyDeviceVolume_syncVSS(device);

                // Apply change to all streams using this one as alias
                int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3786,12 +3802,12 @@ public class AudioService extends IAudioService.Stub {
                        int streamDevice = getDeviceForStream(streamType);
                        if ((device != streamDevice) && mAvrcpAbsVolSupported &&
                                ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
                        mStreamStates[streamType].applyDeviceVolume(device);
                            mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
                        }
                        mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
                    }
                    mStreamStates[streamType].applyDeviceVolume(streamDevice);
                }
            }

            // Post a persist volume msg
            sendMsg(mAudioHandler,
                    MSG_PERSIST_VOLUME,
@@ -5032,10 +5048,14 @@ public class AudioService extends IAudioService.Stub {
            boolean cameraSoundForced = mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_camera_sound_forced);
            synchronized (mSettingsLock) {
                boolean cameraSoundForcedChanged = false;
                synchronized (mCameraSoundForced) {
                    if (cameraSoundForced != mCameraSoundForced) {
                        mCameraSoundForced = cameraSoundForced;

                        cameraSoundForcedChanged = true;
                    }
                }
                if (cameraSoundForcedChanged) {
                    if (!isPlatformTelevision()) {
                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
                        if (cameraSoundForced) {
@@ -5068,7 +5088,6 @@ public class AudioService extends IAudioService.Stub {
                            mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
                }
            }
            }
            mVolumeController.setLayoutDirection(config.getLayoutDirection());
        } catch (Exception e) {
            Log.e(TAG, "Error handling configuration change: ", e);