Merge changes Ic4074394,I1be9f1ab
* changes:
[Media TTT] Add error state.
[Media TTT] Add the #closeToReceiverToEndCast callback.
diff --git a/packages/SystemUI/res/drawable/ic_warning.xml b/packages/SystemUI/res/drawable/ic_warning.xml
new file mode 100644
index 0000000..fbed779
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_warning.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
+ <path android:fillColor="@android:color/white" android:pathData="M12,12.5zM1,21L12,2l11,19zM11,15h2v-5h-2zM12,18q0.425,0 0.713,-0.288Q13,17.425 13,17t-0.287,-0.712Q12.425,16 12,16t-0.713,0.288Q11,16.575 11,17t0.287,0.712Q11.575,18 12,18zM4.45,19h15.1L12,6z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/media_ttt_chip.xml
index 2d082dc..a5fdcd9 100644
--- a/packages/SystemUI/res/layout/media_ttt_chip.xml
+++ b/packages/SystemUI/res/layout/media_ttt_chip.xml
@@ -28,8 +28,8 @@
<com.android.internal.widget.CachingIconView
android:id="@+id/app_icon"
- android:layout_width="@dimen/media_ttt_icon_size"
- android:layout_height="@dimen/media_ttt_icon_size"
+ android:layout_width="@dimen/media_ttt_app_icon_size"
+ android:layout_height="@dimen/media_ttt_app_icon_size"
android:layout_marginEnd="12dp"
/>
@@ -41,23 +41,34 @@
android:textColor="?android:attr/textColorPrimary"
/>
+ <!-- At most one of [loading, failure_icon, undo] will be visible at a time. -->
+
<ProgressBar
android:id="@+id/loading"
android:indeterminate="true"
- android:layout_width="@dimen/media_ttt_loading_size"
- android:layout_height="@dimen/media_ttt_loading_size"
- android:layout_marginStart="12dp"
+ android:layout_width="@dimen/media_ttt_status_icon_size"
+ android:layout_height="@dimen/media_ttt_status_icon_size"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
android:indeterminateTint="?androidprv:attr/colorAccentPrimaryVariant"
style="?android:attr/progressBarStyleSmall"
/>
+ <ImageView
+ android:id="@+id/failure_icon"
+ android:layout_width="@dimen/media_ttt_status_icon_size"
+ android:layout_height="@dimen/media_ttt_status_icon_size"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+ android:src="@drawable/ic_warning"
+ android:tint="@color/GM2_red_500"
+ />
+
<TextView
android:id="@+id/undo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/media_transfer_undo"
android:textColor="?androidprv:attr/textColorOnAccent"
- android:layout_marginStart="12dp"
+ android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
android:textSize="@dimen/media_ttt_text_size"
android:paddingStart="@dimen/media_ttt_chip_outer_padding"
android:paddingEnd="@dimen/media_ttt_chip_outer_padding"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b12db5d..ceaacfc 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -984,10 +984,11 @@
<!-- Media tap-to-transfer chip for sender device -->
<dimen name="media_ttt_chip_outer_padding">16dp</dimen>
<dimen name="media_ttt_text_size">16sp</dimen>
- <dimen name="media_ttt_icon_size">24dp</dimen>
- <dimen name="media_ttt_loading_size">20dp</dimen>
+ <dimen name="media_ttt_app_icon_size">24dp</dimen>
+ <dimen name="media_ttt_status_icon_size">20dp</dimen>
<dimen name="media_ttt_undo_button_vertical_padding">8dp</dimen>
<dimen name="media_ttt_undo_button_vertical_negative_margin">-8dp</dimen>
+ <dimen name="media_ttt_last_item_start_margin">12dp</dimen>
<!-- Media tap-to-transfer chip for receiver device -->
<dimen name="media_ttt_chip_size_receiver">100dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b22ad66..34e5aef 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2158,8 +2158,12 @@
<string name="media_transfer_undo">Undo</string>
<!-- Text to ask the user to move their device closer to a different device (deviceName) in order to play media on the different device. [CHAR LIMIT=75] -->
<string name="media_move_closer_to_start_cast">Move closer to play on <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g></string>
+ <!-- Text to ask the user to move their device closer to a different device (deviceName) in order to transfer media from the different device and back onto the current device. [CHAR LIMIT=75] -->
+ <string name="media_move_closer_to_end_cast">Move closer to <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g> to play here</string>
<!-- Text informing the user that their media is now playing on a different device (deviceName). [CHAR LIMIT=50] -->
<string name="media_transfer_playing">Playing on <xliff:g id="deviceName" example="My Tablet">%1$s</xliff:g></string>
+ <!-- Text informing the user that the media transfer has failed because something went wrong. [CHAR LIMIT=50] -->
+ <string name="media_transfer_failed">Something went wrong</string>
<!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
<string name="controls_error_timeout">Inactive, check app</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/mediattt/IDeviceSenderCallback.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/mediattt/IDeviceSenderCallback.aidl
index 484791d..9aae7d9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/mediattt/IDeviceSenderCallback.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/mediattt/IDeviceSenderCallback.aidl
@@ -43,4 +43,28 @@
*/
oneway void closeToReceiverToStartCast(
in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
+
+ /**
+ * Invoke to notify System UI that this device (the sender) is close to a receiver device, so
+ * the user can potentially *end* a cast on the receiver device if the user moves this device a
+ * bit closer.
+ *
+ * Important notes:
+ * - When this callback triggers, the device is close enough to inform the user that
+ * transferring is an option, but the device is *not* close enough to actually initiate a
+ * transfer yet.
+ * - This callback is for *ending* a cast. It should be used when media is currently being
+ * played on the receiver device and the media should be transferred to play locally
+ * instead.
+ */
+ oneway void closeToReceiverToEndCast(
+ in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
+
+ /**
+ * Invoke to notify System UI that the attempted transfer has failed.
+ *
+ * This callback will be used for both the transfer that should've *started* playing the media
+ * on the receiver and the transfer that should've *ended* the playing on the receiver.
+ */
+ oneway void transferFailed(in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
index 460d38f..613dfe0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
@@ -33,7 +33,9 @@
import com.android.systemui.media.taptotransfer.receiver.ChipStateReceiver
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderService
+import com.android.systemui.media.taptotransfer.sender.MoveCloserToEndCast
import com.android.systemui.media.taptotransfer.sender.MoveCloserToStartCast
+import com.android.systemui.media.taptotransfer.sender.TransferFailed
import com.android.systemui.media.taptotransfer.sender.TransferInitiated
import com.android.systemui.media.taptotransfer.sender.TransferSucceeded
import com.android.systemui.shared.mediattt.DeviceInfo
@@ -90,6 +92,11 @@
senderCallback.closeToReceiverToStartCast(mediaInfo, otherDeviceInfo)
}
}
+ MOVE_CLOSER_TO_END_CAST_COMMAND_NAME -> {
+ runOnService { senderCallback ->
+ senderCallback.closeToReceiverToEndCast(mediaInfo, otherDeviceInfo)
+ }
+ }
// TODO(b/203800643): Migrate other commands to invoke the service instead of the
// controller.
@@ -116,11 +123,18 @@
)
)
}
+ TRANSFER_FAILED_COMMAND_NAME -> {
+ runOnService { senderCallback ->
+ senderCallback.transferFailed(mediaInfo, otherDeviceInfo)
+ }
+ }
else -> {
pw.println("Chip type must be one of " +
"$MOVE_CLOSER_TO_START_CAST_COMMAND_NAME, " +
+ "$MOVE_CLOSER_TO_END_CAST_COMMAND_NAME, " +
"$TRANSFER_INITIATED_COMMAND_NAME, " +
- TRANSFER_SUCCEEDED_COMMAND_NAME
+ "$TRANSFER_SUCCEEDED_COMMAND_NAME, " +
+ TRANSFER_FAILED_COMMAND_NAME
)
}
}
@@ -226,9 +240,13 @@
@VisibleForTesting
val MOVE_CLOSER_TO_START_CAST_COMMAND_NAME = MoveCloserToStartCast::class.simpleName!!
@VisibleForTesting
+val MOVE_CLOSER_TO_END_CAST_COMMAND_NAME = MoveCloserToEndCast::class.simpleName!!
+@VisibleForTesting
val TRANSFER_INITIATED_COMMAND_NAME = TransferInitiated::class.simpleName!!
@VisibleForTesting
val TRANSFER_SUCCEEDED_COMMAND_NAME = TransferSucceeded::class.simpleName!!
+@VisibleForTesting
+val TRANSFER_FAILED_COMMAND_NAME = TransferFailed::class.simpleName!!
private const val FUTURE_WAIT_TIME = 2000L
private const val APP_ICON_CONTENT_DESCRIPTION = "Fake media app icon"
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index dd434e7..e6f4ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -56,6 +56,22 @@
)
/**
+ * A state representing that the two devices are close but not close enough to *end* a cast that's
+ * currently occurring the receiver device. The chip will instruct the user to move closer in order
+ * to initiate the transfer from the receiver and back onto this device (the original sender).
+ */
+class MoveCloserToEndCast(
+ appIconDrawable: Drawable,
+ appIconContentDescription: String,
+ otherDeviceName: String,
+) : ChipStateSender(
+ appIconDrawable,
+ appIconContentDescription,
+ R.string.media_move_closer_to_end_cast,
+ otherDeviceName
+)
+
+/**
* A state representing that a transfer has been initiated (but not completed).
*
* @property future a future that will be resolved when the transfer has either succeeded or failed.
@@ -91,3 +107,17 @@
R.string.media_transfer_playing,
otherDeviceName
)
+
+/** A state representing that a transfer has failed. */
+class TransferFailed(
+ appIconDrawable: Drawable,
+ appIconContentDescription: String,
+ // TODO(b/211493953): The failed chip doesn't need [otherDeviceName] so we may want to remove
+ // [otherDeviceName] from the superclass [ChipStateSender].
+ otherDeviceName: String,
+) : ChipStateSender(
+ appIconDrawable,
+ appIconContentDescription,
+ R.string.media_transfer_failed,
+ otherDeviceName
+)
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
index 77d3d70..6453b79 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
@@ -73,6 +73,11 @@
}
undoView.setOnClickListener(undoClickListener)
+ // Failure
+ val showFailure = chipState is TransferFailed
+ currentChipView.requireViewById<View>(R.id.failure_icon).visibility =
+ if (showFailure) { View.VISIBLE } else { View.GONE }
+
// Future handling
if (chipState is TransferInitiated) {
addFutureCallback(chipState)
@@ -101,9 +106,14 @@
)
}
} catch (ex: Exception) {
- // TODO(b/203800327): Maybe show a failure chip here if UX decides we need one.
mainExecutor.execute {
- removeChip()
+ displayChip(
+ TransferFailed(
+ chipState.appIconDrawable,
+ chipState.appIconContentDescription,
+ chipState.otherDeviceName,
+ )
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderService.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderService.kt
index b56a699..84794cb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderService.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderService.kt
@@ -43,6 +43,18 @@
) {
this@MediaTttSenderService.closeToReceiverToStartCast(mediaInfo, otherDeviceInfo)
}
+
+ override fun closeToReceiverToEndCast(
+ mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
+ ) {
+ this@MediaTttSenderService.closeToReceiverToEndCast(mediaInfo, otherDeviceInfo)
+ }
+
+ override fun transferFailed(
+ mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
+ ) {
+ this@MediaTttSenderService.transferFailed(mediaInfo, otherDeviceInfo)
+ }
}
// TODO(b/203800643): Use the app icon from the media info instead of a fake one.
@@ -63,4 +75,22 @@
)
controller.displayChip(chipState)
}
+
+ private fun closeToReceiverToEndCast(mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo) {
+ val chipState = MoveCloserToEndCast(
+ appIconDrawable = fakeAppIconDrawable,
+ appIconContentDescription = mediaInfo.name.toString(),
+ otherDeviceName = otherDeviceInfo.name
+ )
+ controller.displayChip(chipState)
+ }
+
+ private fun transferFailed(mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo) {
+ val chipState = TransferFailed(
+ appIconDrawable = fakeAppIconDrawable,
+ appIconContentDescription = mediaInfo.name.toString(),
+ otherDeviceName = otherDeviceInfo.name
+ )
+ controller.displayChip(chipState)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
index 4839bde..be082be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
@@ -127,6 +127,17 @@
}
@Test
+ fun sender_moveCloserToEndCast_serviceCallbackCalled() {
+ commandRegistry.onShellCommand(pw, getMoveCloserToEndCastCommand())
+
+ assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
+
+ val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
+ verify(mediaSenderService).closeToReceiverToEndCast(any(), capture(deviceInfoCaptor))
+ assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
+ }
+
+ @Test
fun sender_transferInitiated_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferInitiatedCommand())
@@ -141,6 +152,14 @@
}
@Test
+ fun sender_transferFailed_serviceCallbackCalled() {
+ commandRegistry.onShellCommand(pw, getTransferFailedCommand())
+
+ assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
+ verify(mediaSenderService).transferFailed(any(), any())
+ }
+
+ @Test
fun sender_removeCommand_chipRemoved() {
commandRegistry.onShellCommand(pw, arrayOf(REMOVE_CHIP_COMMAND_SENDER_TAG))
@@ -168,6 +187,13 @@
MOVE_CLOSER_TO_START_CAST_COMMAND_NAME
)
+ private fun getMoveCloserToEndCastCommand(): Array<String> =
+ arrayOf(
+ ADD_CHIP_COMMAND_SENDER_TAG,
+ DEVICE_NAME,
+ MOVE_CLOSER_TO_END_CAST_COMMAND_NAME
+ )
+
private fun getTransferInitiatedCommand(): Array<String> =
arrayOf(
ADD_CHIP_COMMAND_SENDER_TAG,
@@ -182,6 +208,13 @@
TRANSFER_SUCCEEDED_COMMAND_NAME
)
+ private fun getTransferFailedCommand(): Array<String> =
+ arrayOf(
+ ADD_CHIP_COMMAND_SENDER_TAG,
+ DEVICE_NAME,
+ TRANSFER_FAILED_COMMAND_NAME
+ )
+
class EmptyCommand : Command {
override fun execute(pw: PrintWriter, args: List<String>) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
index ecc4c46..937d221 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
@@ -66,7 +66,7 @@
}
@Test
- fun moveCloserToStartCast_appIcon_chipTextContainsDeviceName_noLoadingIcon_noUndo() {
+ fun moveCloserToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
controllerSender.displayChip(moveCloserToStartCast())
val chipView = getChipView()
@@ -75,10 +75,24 @@
assertThat(chipView.getChipText()).contains(DEVICE_NAME)
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
}
@Test
- fun transferInitiated_futureNotResolvedYet_appIcon_loadingIcon_noUndo() {
+ fun moveCloserToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
+ controllerSender.displayChip(moveCloserToEndCast())
+
+ val chipView = getChipView()
+ assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconDrawable)
+ assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
+ assertThat(chipView.getChipText()).contains(DEVICE_NAME)
+ assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
+ assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
+ }
+
+ @Test
+ fun transferInitiated_futureNotResolvedYet_appIcon_loadingIcon_noUndo_noFailureIcon() {
val future: SettableFuture<Runnable?> = SettableFuture.create()
controllerSender.displayChip(transferInitiated(future))
@@ -91,6 +105,7 @@
assertThat(chipView.getChipText()).contains(DEVICE_NAME)
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
}
@Test
@@ -116,7 +131,7 @@
}
@Test
- fun transferInitiated_futureCancelled_chipRemoved() {
+ fun transferInitiated_futureCancelled_switchesToTransferFailed() {
val future: SettableFuture<Runnable?> = SettableFuture.create()
controllerSender.displayChip(transferInitiated(future))
@@ -129,12 +144,15 @@
// Assert we ran the future callback
assertThat(numRun).isEqualTo(1)
- // Assert that we've hidden the chip
- verify(windowManager).removeView(any())
+ // Assert that we've moved to the failed state
+ val chipView = getChipView()
+ assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
+ assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.VISIBLE)
}
@Test
- fun transferInitiated_futureNotResolvedAfterTimeout_chipRemoved() {
+ fun transferInitiated_futureNotResolvedAfterTimeout_switchesToTransferFailed() {
val future: SettableFuture<Runnable?> = SettableFuture.create()
controllerSender.displayChip(transferInitiated(future))
@@ -148,12 +166,15 @@
// Assert we eventually decide to not wait for the future anymore
assertThat(numRun).isEqualTo(1)
- // Assert we've hidden the chip
- verify(windowManager).removeView(any())
+ // Assert that we've moved to the failed state
+ val chipView = getChipView()
+ assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
+ assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.VISIBLE)
}
@Test
- fun transferSucceeded_appIcon_chipTextContainsDeviceName_noLoadingIcon() {
+ fun transferSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
controllerSender.displayChip(transferSucceeded())
val chipView = getChipView()
@@ -161,6 +182,7 @@
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
assertThat(chipView.getChipText()).contains(DEVICE_NAME)
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
}
@Test
@@ -192,6 +214,19 @@
}
@Test
+ fun transferFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() {
+ controllerSender.displayChip(transferFailed())
+
+ val chipView = getChipView()
+ assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconDrawable)
+ assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
+ assertThat(chipView.getChipText()).doesNotContain(DEVICE_NAME)
+ assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
+ assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
+ assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
fun changeFromCloserToStartToTransferInitiated_loadingIconAppears() {
controllerSender.displayChip(moveCloserToStartCast())
controllerSender.displayChip(transferInitiated())
@@ -223,6 +258,14 @@
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE)
}
+ @Test
+ fun changeFromTransferInitiatedToTransferFailed_failureIconAppears() {
+ controllerSender.displayChip(transferInitiated())
+ controllerSender.displayChip(transferFailed())
+
+ assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
+ }
+
private fun LinearLayout.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
private fun LinearLayout.getChipText(): String =
@@ -233,6 +276,8 @@
private fun LinearLayout.getUndoButton(): View = this.requireViewById(R.id.undo)
+ private fun LinearLayout.getFailureIcon(): View = this.requireViewById(R.id.failure_icon)
+
private fun getChipView(): LinearLayout {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
@@ -244,6 +289,10 @@
MoveCloserToStartCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
+ private fun moveCloserToEndCast() =
+ MoveCloserToEndCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
private fun transferInitiated(
future: Future<Runnable?> = TEST_FUTURE
) = TransferInitiated(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME, future)
@@ -252,6 +301,10 @@
private fun transferSucceeded(
undoRunnable: Runnable? = null
) = TransferSucceeded(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME, undoRunnable)
+
+ /** Helper method providing default parameters to not clutter up the tests. */
+ private fun transferFailed() =
+ TransferFailed(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
}
private const val DEVICE_NAME = "My Tablet"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderServiceTest.kt
index 8f64698..66e3fe6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderServiceTest.kt
@@ -5,6 +5,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.shared.mediattt.DeviceInfo
import com.android.systemui.shared.mediattt.IDeviceSenderCallback
+import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.google.common.truth.Truth.assertThat
@@ -45,4 +46,23 @@
val chipState = chipStateCaptor.value!!
assertThat(chipState.otherDeviceName).isEqualTo(name)
}
+
+ @Test
+ fun closeToReceiverToEndCast_controllerTriggeredWithMoveCloserToEndCastState() {
+ val name = "Fake name"
+ callback.closeToReceiverToEndCast(mediaInfo, DeviceInfo(name))
+
+ val chipStateCaptor = argumentCaptor<MoveCloserToEndCast>()
+ verify(controller).displayChip(capture(chipStateCaptor))
+
+ val chipState = chipStateCaptor.value!!
+ assertThat(chipState.otherDeviceName).isEqualTo(name)
+ }
+
+ @Test
+ fun transferFailed_controllerTriggeredWithTransferFailedState() {
+ callback.transferFailed(mediaInfo, DeviceInfo("Fake name"))
+
+ verify(controller).displayChip(any<TransferFailed>())
+ }
}