From c770c9133a11db3f1a0f4a812ebc5623d644705f Mon Sep 17 00:00:00 2001 From: hughchen Date: Wed, 8 Jan 2020 19:38:40 +0800 Subject: [PATCH] Update output switch UI This CL include following update: 1. Add onDeviceAttributesChanged() callback to update UI when device attributes are changed. 2. Fix the top device when user press device to transfer. 3. Update UI when device is on goning call state and receive STREAM_DEVICES_CHANGED_ACTION intent. Bug: 144535188 Test: make -j42 RunSettingsRoboTests Change-Id: Idd5fb95054db30f8184faf4f6ab75d0b550907a1 --- .../media/MediaDeviceUpdateWorker.java | 29 +++++++++++++++++- .../settings/media/MediaOutputSlice.java | 18 +++++++---- .../media/MediaDeviceUpdateWorkerTest.java | 30 ++++++++++++++++++- .../settings/media/MediaOutputSliceTest.java | 5 ++-- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/media/MediaDeviceUpdateWorker.java b/src/com/android/settings/media/MediaDeviceUpdateWorker.java index a9c9086d6fd..3b67886e31e 100644 --- a/src/com/android/settings/media/MediaDeviceUpdateWorker.java +++ b/src/com/android/settings/media/MediaDeviceUpdateWorker.java @@ -31,6 +31,7 @@ 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; @@ -49,6 +50,9 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker private final DevicesChangedBroadcastReceiver mReceiver; private final String mPackageName; + private boolean mIsTouched; + private MediaDevice mTopDevice; + @VisibleForTesting LocalMediaManager mLocalMediaManager; @@ -62,6 +66,7 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker @Override protected void onSlicePinned() { mMediaDevices.clear(); + mIsTouched = false; if (mLocalMediaManager == null) { mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null); } @@ -100,6 +105,11 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker notifySliceChange(); } + @Override + public void onDeviceAttributesChanged() { + notifySliceChange(); + } + public List getMediaDevices() { return new ArrayList<>(mMediaDevices); } @@ -118,11 +128,28 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker 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(); } } diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java index fbdf01c48d2..3bb9ec85a03 100644 --- a/src/com/android/settings/media/MediaOutputSlice.java +++ b/src/com/android/settings/media/MediaOutputSlice.java @@ -61,7 +61,7 @@ public class MediaOutputSlice implements CustomSliceable { } @VisibleForTesting - void init(String packageName, MediaDeviceUpdateWorker worker) { + void init(MediaDeviceUpdateWorker worker) { mWorker = worker; } @@ -79,15 +79,20 @@ public class MediaOutputSlice implements CustomSliceable { } final List 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)); } } @@ -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); } } diff --git a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java index 2e9fa30498d..0b2850b94d0 100644 --- a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java @@ -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); @@ -140,8 +153,9 @@ public class MediaDeviceUpdateWorkerTest { } @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 +165,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); + } } diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java index 288c8e869d0..c9b9ff940c5 100644 --- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java @@ -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();