diff options
| author | 2022-06-16 00:44:24 +0000 | |
|---|---|---|
| committer | 2022-06-16 00:44:24 +0000 | |
| commit | 035386f4afbdeb272fe51638ae8e1a7cd3527fb1 (patch) | |
| tree | c4ae13bbdd5c7994f3ac906dcc06629507b03dbe | |
| parent | 2ecc0eee04a05dcb721ba72fcfa37401d87c08aa (diff) | |
| parent | a2b34c4c218ff76743a250a3b28b405c9e0edfdc (diff) | |
Merge "Forward device updates when info changes" into tm-dev am: a2b34c4c21
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18878115
Change-Id: I1290faf696e45a583be5f4212b5000aa99fe9fdc
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
3 files changed, 105 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index 360f86548e13..aeeef6b24a1c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -216,4 +216,20 @@ data class MediaDeviceData /** Unique id for this device */ val id: String? = null -) +) { + /** + * Check whether [MediaDeviceData] objects are equal in all fields except the icon. The icon + * is ignored because it can change by reference frequently depending on the device type's + * implementation, but this is not usually relevant unless other info has changed + */ + fun equalsWithoutIcon(other: MediaDeviceData?): Boolean { + if (other == null) { + return false + } + + return enabled == other.enabled && + name == other.name && + intent == other.intent && + id == other.id + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index 8558859638d5..baed1c4286e9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -155,8 +155,8 @@ class MediaDeviceManager @Inject constructor( private var playbackType = PLAYBACK_TYPE_UNKNOWN private var current: MediaDeviceData? = null set(value) { - val hasSameId = value?.id != null && value.id == field?.id - if (!started || (!hasSameId && value != field)) { + val sameWithoutIcon = value != null && value.equalsWithoutIcon(field) + if (!started || !sameWithoutIcon) { field = value fgExecutor.execute { processDevice(key, oldKey, value) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt index 18ee79138b52..187210a40b6d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt @@ -47,7 +47,9 @@ import org.mockito.Mockito.any import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset +import org.mockito.Mockito.times import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -55,6 +57,7 @@ private const val KEY = "TEST_KEY" private const val KEY_OLD = "TEST_KEY_OLD" private const val PACKAGE = "PKG" private const val SESSION_KEY = "SESSION_KEY" +private const val DEVICE_ID = "DEVICE_ID" private const val DEVICE_NAME = "DEVICE_NAME" private const val REMOTE_DEVICE_NAME = "REMOTE_DEVICE_NAME" @@ -457,6 +460,89 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test + fun deviceIdChanged_informListener() { + // GIVEN a notification is added, with a particular device connected + whenever(device.id).thenReturn(DEVICE_ID) + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + // and later the manager gets a new device ID + val deviceCallback = captureCallback() + val updatedId = DEVICE_ID + "_new" + whenever(device.id).thenReturn(updatedId) + deviceCallback.onDeviceListUpdate(mutableListOf(device)) + + // THEN the listener gets the updated info + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java) + verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture()) + + val firstDevice = dataCaptor.allValues.get(0) + assertThat(firstDevice.id).isEqualTo(DEVICE_ID) + + val secondDevice = dataCaptor.allValues.get(1) + assertThat(secondDevice.id).isEqualTo(updatedId) + } + + @Test + fun deviceNameChanged_informListener() { + // GIVEN a notification is added, with a particular device connected + whenever(device.id).thenReturn(DEVICE_ID) + whenever(device.name).thenReturn(DEVICE_NAME) + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + // and later the manager gets a new device name + val deviceCallback = captureCallback() + val updatedName = DEVICE_NAME + "_new" + whenever(device.name).thenReturn(updatedName) + deviceCallback.onDeviceListUpdate(mutableListOf(device)) + + // THEN the listener gets the updated info + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java) + verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture()) + + val firstDevice = dataCaptor.allValues.get(0) + assertThat(firstDevice.name).isEqualTo(DEVICE_NAME) + + val secondDevice = dataCaptor.allValues.get(1) + assertThat(secondDevice.name).isEqualTo(updatedName) + } + + @Test + fun deviceIconChanged_doesNotCallListener() { + // GIVEN a notification is added, with a particular device connected + whenever(device.id).thenReturn(DEVICE_ID) + whenever(device.name).thenReturn(DEVICE_NAME) + val firstIcon = mock(Drawable::class.java) + whenever(device.icon).thenReturn(firstIcon) + manager.onMediaDataLoaded(KEY, null, mediaData) + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + + val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java) + verify(listener).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture()) + + // and later the manager gets a callback with only the icon changed + val deviceCallback = captureCallback() + val secondIcon = mock(Drawable::class.java) + whenever(device.icon).thenReturn(secondIcon) + deviceCallback.onDeviceListUpdate(mutableListOf(device)) + + // THEN the listener is not called again + fakeBgExecutor.runAllReady() + fakeFgExecutor.runAllReady() + verifyNoMoreInteractions(listener) + } + + @Test fun testRemotePlaybackDeviceOverride() { whenever(route.name).thenReturn(DEVICE_NAME) val deviceData = MediaDeviceData(false, null, REMOTE_DEVICE_NAME, null) |