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

Commit a42cd7ec authored by Alex Shabalin's avatar Alex Shabalin Committed by Alexandr Shabalin
Browse files

Put all access to the MediaDevices within the synchronized block.

Guard mMediaDevices and mCurrentConnectedDevice with `syncrhonized (mLock)`.

Bug: 428663871
Flag: EXEMPT bugfix
Test: on a physical device
Change-Id: I9449f860c31cbb27f23bc7c584272aa4111907cf
parent e3b8df3a
Loading
Loading
Loading
Loading
+42 −23
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -211,11 +212,13 @@ public abstract class InfoMediaManager {
    private static final String TAG = "InfoMediaManager";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    protected final Object mLock = new Object();
    protected final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
    @GuardedBy("mLock")
    protected final List<MediaDevice> mMediaDevices = new ArrayList<>();
    @NonNull protected final Context mContext;
    @NonNull protected final String mPackageName;
    @NonNull protected final UserHandle mUserHandle;
    private final Collection<MediaDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
    @GuardedBy("mLock")
    private MediaDevice mCurrentConnectedDevice;
    private MediaController mMediaController;
    private PlaybackInfo mLastKnownPlaybackInfo;
@@ -378,7 +381,8 @@ public abstract class InfoMediaManager {
    }

    protected final void notifyCurrentConnectedDeviceChanged() {
        final String id = mCurrentConnectedDevice != null ? mCurrentConnectedDevice.getId() : null;
        MediaDevice device = getCurrentConnectedDevice();
        final String id = device != null ? device.getId() : null;
        dispatchConnectedDeviceChanged(id);
    }

@@ -388,14 +392,20 @@ public abstract class InfoMediaManager {
        Api34Impl.onRouteListingPreferenceUpdated(routeListingPreference, mPreferenceItemMap);
    }

    @VisibleForTesting
    @Nullable
    protected final MediaDevice findMediaDevice(@NonNull String id) {
        for (MediaDevice mediaDevice : mMediaDevices) {
            if (mediaDevice.getId().equals(id)) {
                return mediaDevice;
        return getMediaDevices().stream()
                .filter(device -> device.getId().equals(id))
                .findFirst()
                .orElse(null);
    }

    @NonNull
    private List<MediaDevice> getMediaDevices() {
        synchronized (mLock) {
            return new ArrayList<>(mMediaDevices);
        }
        Log.e(TAG, "findMediaDevice() can't find device with id: " + id);
        return null;
    }

    /**
@@ -412,7 +422,9 @@ public abstract class InfoMediaManager {
        if (!mCallbacks.contains(callback)) {
            mCallbacks.add(callback);
            if (wasEmpty) {
                synchronized (mLock) {
                    mMediaDevices.clear();
                }
                registerRouter();
                if (mMediaController != null) {
                    mMediaController.registerCallback(mMediaControllerCallback);
@@ -472,8 +484,10 @@ public abstract class InfoMediaManager {
     * @return MediaDevice
     */
    MediaDevice getCurrentConnectedDevice() {
        synchronized (mLock) {
            return mCurrentConnectedDevice;
        }
    }

    /* package */ void connectToDevice(MediaDevice device, RoutingChangeInfo routingChangeInfo) {
        Log.i(TAG, "connectToDevice(), device = " + device.getName() + "/" + device.getId());
@@ -689,7 +703,7 @@ public abstract class InfoMediaManager {
            dispatchOnSuggestedDeviceUpdated();
        }
        if (updateMediaDevicesSuggestionState()) {
            dispatchDeviceListAdded(mMediaDevices);
            dispatchDeviceListAdded(getMediaDevices());
        }
    }

@@ -736,6 +750,7 @@ public abstract class InfoMediaManager {

    private boolean isSuggestedDeviceSelected(
            @NonNull SuggestedDeviceState newSuggestedDeviceState) {
        synchronized (mLock) {
            return mMediaDevices.stream().anyMatch(device ->
                    device.isSelected()
                            && Objects.equals(
@@ -744,6 +759,7 @@ public abstract class InfoMediaManager {
                                    .getSuggestedDeviceInfo()
                                    .getRouteId()));
        }
    }

    final void onConnectionAttemptedForSuggestion(@NonNull SuggestedDeviceState suggestion) {
        if (!Objects.equals(suggestion, mSuggestedDeviceState)) {
@@ -847,7 +863,7 @@ public abstract class InfoMediaManager {

    protected final void refreshDevices() {
        rebuildDeviceList();
        dispatchDeviceListAdded(mMediaDevices);
        dispatchDeviceListAdded(getMediaDevices());
    }

    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
@@ -858,7 +874,7 @@ public abstract class InfoMediaManager {
            RoutingSessionInfo activeSession = getActiveRoutingSession();

            for (MediaRoute2Info route : getAvailableRoutes(activeSession)) {
                addMediaDevice(route, activeSession);
                addMediaDeviceLocked(route, activeSession);
            }

            // In practice, mMediaDevices should always have at least one route.
@@ -905,11 +921,13 @@ public abstract class InfoMediaManager {

    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
    @SuppressWarnings("NewApi")
    @GuardedBy("mLock")
    @VisibleForTesting
    void addMediaDevice(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo activeSession) {
    void addMediaDeviceLocked(@NonNull MediaRoute2Info route,
            @NonNull RoutingSessionInfo activeSession) {
        DynamicRouteAttributes dynamicRouteAttributes =
                getDynamicRouteAttributes(activeSession, route);
        MediaDevice mediaDevice = createMediaDeviceFromRoute(route, dynamicRouteAttributes);
        MediaDevice mediaDevice = createMediaDeviceFromRouteLocked(route, dynamicRouteAttributes);
        if (mediaDevice != null) {
            if (mediaDevice.isSelected()) {
                mediaDevice.setState(STATE_SELECTED);
@@ -918,8 +936,9 @@ public abstract class InfoMediaManager {
        }
    }

    @GuardedBy("mLock")
    @Nullable
    private MediaDevice createMediaDeviceFromRoute(@NonNull MediaRoute2Info route,
    private MediaDevice createMediaDeviceFromRouteLocked(@NonNull MediaRoute2Info route,
            @NonNull DynamicRouteAttributes dynamicRouteAttributes) {
        final int deviceType = route.getType();
        MediaDevice mediaDevice = null;
+7 −7
Original line number Diff line number Diff line
@@ -864,19 +864,19 @@ public class InfoMediaManagerTest {

        when(route2Info.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
        when(route2Info.getId()).thenReturn(TEST_ID);
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        assertThat(mInfoMediaManager.mMediaDevices.get(0) instanceof InfoMediaDevice).isTrue();

        when(route2Info.getType()).thenReturn(TYPE_USB_DEVICE);
        when(route2Info.getId()).thenReturn(TEST_ID);
        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        assertThat(mInfoMediaManager.mMediaDevices.get(0) instanceof PhoneMediaDevice).isTrue();

        when(route2Info.getType()).thenReturn(TYPE_WIRED_HEADSET);
        when(route2Info.getId()).thenReturn(TEST_ID);
        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        assertThat(mInfoMediaManager.mMediaDevices.get(0) instanceof PhoneMediaDevice).isTrue();

        when(route2Info.getType()).thenReturn(TYPE_BLUETOOTH_A2DP);
@@ -887,12 +887,12 @@ public class InfoMediaManagerTest {
        when(cachedBluetoothDeviceManager.findDevice(any(BluetoothDevice.class)))
                .thenReturn(cachedDevice);
        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        assertThat(mInfoMediaManager.mMediaDevices.get(0) instanceof BluetoothMediaDevice).isTrue();

        when(route2Info.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        assertThat(mInfoMediaManager.mMediaDevices.get(0) instanceof PhoneMediaDevice).isTrue();
    }

@@ -910,7 +910,7 @@ public class InfoMediaManagerTest {
                .thenReturn(null);

        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(route2Info, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(route2Info, TEST_SYSTEM_ROUTING_SESSION);

        assertThat(mInfoMediaManager.mMediaDevices.size()).isEqualTo(0);
    }
@@ -927,7 +927,7 @@ public class InfoMediaManagerTest {
        when(cachedBluetoothDeviceManager.findDevice(any(BluetoothDevice.class))).thenReturn(null);

        mInfoMediaManager.mMediaDevices.clear();
        mInfoMediaManager.addMediaDevice(bluetoothRoute, TEST_SYSTEM_ROUTING_SESSION);
        mInfoMediaManager.addMediaDeviceLocked(bluetoothRoute, TEST_SYSTEM_ROUTING_SESSION);

        assertThat(mInfoMediaManager.mMediaDevices.size()).isEqualTo(0);
    }