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

Commit e5c5d375 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I669f379d,Idd5fb950

* changes:
  Fix ConcurrentModificationException
  Update output switch UI
parents 162e2b92 1045823b
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -31,12 +31,15 @@ import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;

import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settingslib.Utils;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.utils.ThreadUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * SliceBackgroundWorker for get MediaDevice list and handle MediaDevice state change event.
@@ -45,10 +48,13 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
        implements LocalMediaManager.DeviceCallback {

    private final Context mContext;
    private final List<MediaDevice> mMediaDevices = new ArrayList<>();
    private final Collection<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
    private final DevicesChangedBroadcastReceiver mReceiver;
    private final String mPackageName;

    private boolean mIsTouched;
    private MediaDevice mTopDevice;

    @VisibleForTesting
    LocalMediaManager mLocalMediaManager;

@@ -62,6 +68,7 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
    @Override
    protected void onSlicePinned() {
        mMediaDevices.clear();
        mIsTouched = false;
        if (mLocalMediaManager == null) {
            mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null);
        }
@@ -100,8 +107,13 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
        notifySliceChange();
    }

    public List<MediaDevice> getMediaDevices() {
        return new ArrayList<>(mMediaDevices);
    @Override
    public void onDeviceAttributesChanged() {
        notifySliceChange();
    }

    public Collection<MediaDevice> getMediaDevices() {
        return mMediaDevices;
    }

    public void connectDevice(MediaDevice device) {
@@ -111,18 +123,35 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
    }

    public MediaDevice getMediaDeviceById(String id) {
        return mLocalMediaManager.getMediaDeviceById(mMediaDevices, id);
        return mLocalMediaManager.getMediaDeviceById(new ArrayList<>(mMediaDevices), id);
    }

    public MediaDevice getCurrentConnectedMediaDevice() {
        return mLocalMediaManager.getCurrentConnectedDevice();
    }

    void setIsTouched(boolean isTouched) {
        mIsTouched = isTouched;
    }

    boolean getIsTouched() {
        return mIsTouched;
    }

    void setTopDevice(MediaDevice device) {
        mTopDevice = device;
    }

    MediaDevice getTopDevice() {
        return mTopDevice;
    }

    private class DevicesChangedBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (TextUtils.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION, action)) {
            if (TextUtils.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION, action)
                    && Utils.isAudioModeOngoingCall(mContext)) {
                notifySliceChange();
            }
        }
+17 −11
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settingslib.media.MediaDevice;

import java.util.List;
import java.util.Collection;

/**
 * Show the Media device that can be transfer the media.
@@ -61,7 +61,7 @@ public class MediaOutputSlice implements CustomSliceable {
    }

    @VisibleForTesting
    void init(String packageName, MediaDeviceUpdateWorker worker) {
    void init(MediaDeviceUpdateWorker worker) {
        mWorker = worker;
    }

@@ -78,16 +78,21 @@ public class MediaOutputSlice implements CustomSliceable {
            return listBuilder.build();
        }

        final List<MediaDevice> devices = getMediaDevices();
        final Collection<MediaDevice> devices = getMediaDevices();
        final MediaDeviceUpdateWorker worker = getWorker();
        final MediaDevice connectedDevice = worker.getCurrentConnectedMediaDevice();
        final boolean isTouched = worker.getIsTouched();
        // Fix the last top device when user press device to transfer.
        final MediaDevice topDevice = isTouched ? worker.getTopDevice() : connectedDevice;

        final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice();
        if (connectedDevice != null) {
            listBuilder.addRow(getActiveDeviceHeaderRow(connectedDevice));
        if (topDevice != null) {
            listBuilder.addRow(getActiveDeviceHeaderRow(topDevice));
            worker.setTopDevice(topDevice);
        }

        for (MediaDevice device : devices) {
            if (connectedDevice == null
                    || !TextUtils.equals(connectedDevice.getId(), device.getId())) {
            if (topDevice == null
                    || !TextUtils.equals(topDevice.getId(), device.getId())) {
                listBuilder.addRow(getMediaDeviceRow(device));
            }
        }
@@ -131,8 +136,8 @@ public class MediaOutputSlice implements CustomSliceable {
        return mWorker;
    }

    private List<MediaDevice> getMediaDevices() {
        final List<MediaDevice> devices = getWorker().getMediaDevices();
    private Collection<MediaDevice> getMediaDevices() {
        final Collection<MediaDevice> devices = getWorker().getMediaDevices();
        return devices;
    }

@@ -173,6 +178,7 @@ public class MediaOutputSlice implements CustomSliceable {
        final MediaDevice device = worker.getMediaDeviceById(id);
        if (device != null) {
            Log.d(TAG, "onNotifyChange() device name : " + device.getName());
            worker.setIsTouched(true);
            worker.connectDevice(device);
        }
    }
+35 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,6 +32,7 @@ import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;

import com.android.settings.testutils.shadow.ShadowAudioManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;

@@ -40,12 +42,14 @@ import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;

import java.util.ArrayList;
import java.util.List;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowAudioManager.class)
public class MediaDeviceUpdateWorkerTest {

    private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
@@ -61,6 +65,7 @@ public class MediaDeviceUpdateWorkerTest {
    private MediaDevice mMediaDevice1;
    private MediaDevice mMediaDevice2;
    private ShadowApplication mShadowApplication;
    private AudioManager mAudioManager;

    @Before
    public void setUp() {
@@ -69,6 +74,7 @@ public class MediaDeviceUpdateWorkerTest {
        mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, URI);
        mResolver = mock(ContentResolver.class);
        mShadowApplication = ShadowApplication.getInstance();
        mAudioManager = mContext.getSystemService(AudioManager.class);

        mMediaDevice1 = mock(MediaDevice.class);
        when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
@@ -94,6 +100,13 @@ public class MediaDeviceUpdateWorkerTest {
        verify(mResolver).notifyChange(URI, null);
    }

    @Test
    public void onDeviceAttributesChanged_shouldNotifyChange() {
        mMediaDeviceUpdateWorker.onDeviceAttributesChanged();

        verify(mResolver).notifyChange(URI, null);
    }

    @Test
    public void onDeviceListUpdate_sameDeviceList_shouldBeEqual() {
        mMediaDeviceUpdateWorker.onDeviceListUpdate(mMediaDevices);
@@ -103,7 +116,8 @@ public class MediaDeviceUpdateWorkerTest {
        newDevices.add(mMediaDevice2);

        mMediaDeviceUpdateWorker.onDeviceListUpdate(newDevices);
        final List<MediaDevice> devices = mMediaDeviceUpdateWorker.getMediaDevices();
        final List<MediaDevice> devices =
                new ArrayList<>(mMediaDeviceUpdateWorker.getMediaDevices());

        assertThat(devices.get(0).getId()).isEqualTo(newDevices.get(0).getId());
        assertThat(devices.get(1).getId()).isEqualTo(newDevices.get(1).getId());
@@ -121,7 +135,8 @@ public class MediaDeviceUpdateWorkerTest {
        newDevices.add(device3);

        mMediaDeviceUpdateWorker.onDeviceListUpdate(newDevices);
        final List<MediaDevice> devices = mMediaDeviceUpdateWorker.getMediaDevices();
        final List<MediaDevice> devices =
                new ArrayList<>(mMediaDeviceUpdateWorker.getMediaDevices());

        assertThat(devices.size()).isEqualTo(newDevices.size());
    }
@@ -134,14 +149,16 @@ public class MediaDeviceUpdateWorkerTest {
        newDevices.add(mMediaDevice1);

        mMediaDeviceUpdateWorker.onDeviceListUpdate(newDevices);
        final List<MediaDevice> devices = mMediaDeviceUpdateWorker.getMediaDevices();
        final List<MediaDevice> devices =
                new ArrayList<>(mMediaDeviceUpdateWorker.getMediaDevices());

        assertThat(devices.size()).isEqualTo(newDevices.size());
    }

    @Test
    public void onReceive_shouldNotifyChange() {
    public void onReceive_inCallState_shouldNotifyChange() {
        mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class);
        mAudioManager.setMode(AudioManager.MODE_IN_CALL);

        mMediaDeviceUpdateWorker.onSlicePinned();
        final Intent intent = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
@@ -151,4 +168,18 @@ public class MediaDeviceUpdateWorkerTest {

        verify(mResolver).notifyChange(URI, null);
    }

    @Test
    public void onReceive_notInCallState_doNothing() {
        mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class);
        mAudioManager.setMode(AudioManager.MODE_NORMAL);

        mMediaDeviceUpdateWorker.onSlicePinned();
        final Intent intent = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
        for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) {
            receiver.onReceive(mContext, intent);
        }

        verify(mResolver, never()).notifyChange(URI, null);
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ import java.util.List;
@Config(shadows = {ShadowBluetoothAdapter.class})
public class MediaOutputSliceTest {

    private static final String TEST_PACKAGE_NAME = "com.fake.android.music";
    private static final String TEST_DEVICE_1_ID = "test_device_1_id";
    private static final String TEST_DEVICE_1_NAME = "test_device_1_name";
    private static final int TEST_DEVICE_1_ICON =
@@ -100,12 +99,12 @@ public class MediaOutputSliceTest {
        mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, MEDIA_OUTPUT_SLICE_URI);
        mMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
        mMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
        mMediaOutputSlice.init(TEST_PACKAGE_NAME, mMediaDeviceUpdateWorker);
        mMediaOutputSlice.init(mMediaDeviceUpdateWorker);
    }

    @Test
    public void getSlice_workerIsNull_shouldReturnZeroRow() {
        mMediaOutputSlice.init(TEST_PACKAGE_NAME, null);
        mMediaOutputSlice.init(null);

        final Slice slice = mMediaOutputSlice.getSlice();