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

Commit 7d214084 authored by Vlad Popa's avatar Vlad Popa
Browse files

CTA2075: Synchronize dispatcher listener map

Fixed possible concurrrent modifications on the listener map in the
dispatcher by guarding the map.

Test: adb shell device_config put media_audio android.media.audio.loudness_configurator_api true
Test: atest LoudnessCodecConfiguratorTest
Bug: 312928467
Change-Id: If97dab0cff99d5adb7cf386a5d1c49379d3f3f46
parent 0815d19a
Loading
Loading
Loading
Loading
+30 −11
Original line number Diff line number Diff line
@@ -27,9 +27,11 @@ import android.os.PersistableBundle;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
@@ -52,6 +54,9 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub {
        private final CallbackUtil.LazyListenerManager<OnLoudnessCodecUpdateListener>
                mLoudnessListenerMgr = new CallbackUtil.LazyListenerManager<>();

        private final Object mLock = new Object();

        @GuardedBy("mLock")
        private final HashMap<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator>
                mConfiguratorListener = new HashMap<>();

@@ -66,7 +71,8 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub {

        @Override
        public void dispatchLoudnessCodecParameterChange(int piid, PersistableBundle params) {
            mLoudnessListenerMgr.callListeners(listener ->
            mLoudnessListenerMgr.callListeners(listener -> {
                synchronized (mLock) {
                    mConfiguratorListener.computeIfPresent(listener, (l, lcConfig) -> {
                        // send the appropriate bundle for the user to update
                        if (lcConfig.getAssignedTrackPiid() == piid) {
@@ -95,9 +101,10 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub {
                                }
                            }
                        }

                        return lcConfig;
                    }));
                    });
                }
            });
        }

        private static Bundle filterLoudnessParams(Bundle bundle) {
@@ -130,22 +137,34 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub {
            mLoudnessListenerMgr.addListener(
                    executor, listener, "addLoudnessCodecListener",
                    () -> dispatcher);
            synchronized (mLock) {
                mConfiguratorListener.put(listener, configurator);
            }
        }

        void removeLoudnessCodecListener(@NonNull LoudnessCodecConfigurator configurator) {
            Objects.requireNonNull(configurator);

            for (Entry<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator> e :
                    mConfiguratorListener.entrySet()) {
            OnLoudnessCodecUpdateListener listenerToRemove = null;
            synchronized (mLock) {
                Iterator<Entry<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator>> iterator =
                        mConfiguratorListener.entrySet().iterator();
                while (iterator.hasNext()) {
                    Entry<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator> e =
                            iterator.next();
                    if (e.getValue() == configurator) {
                        final OnLoudnessCodecUpdateListener listener = e.getKey();
                    mConfiguratorListener.remove(listener);
                    mLoudnessListenerMgr.removeListener(listener, "removeLoudnessCodecListener");
                        iterator.remove();
                        listenerToRemove = listener;
                        break;
                    }
                }
            }
            if (listenerToRemove != null) {
                mLoudnessListenerMgr.removeListener(listenerToRemove,
                        "removeLoudnessCodecListener");
            }
        }
    }

    @NonNull private final IAudioService mAudioService;