[Media TTT] Add the #transferToReceiverSucceeded callback.

Bug: 203800643
Bug: 203800347
Test: verify `adb shell cmd statusbar media-ttt-chip-add-sender Device
TransferToReceiverSucceeded` shows the chip
Test: media.taptotransfer tests

Change-Id: Id5aef5c4f5fe61d26ad556b28f6d6cdb4d6ad31d
This commit is contained in:
Caitlin Cassidy
2022-01-14 19:05:23 +00:00
parent b3defd20a4
commit a6d18d89f9
8 changed files with 77 additions and 40 deletions

View File

@@ -84,6 +84,18 @@ interface IDeviceSenderCallback {
oneway void transferToThisDeviceTriggered(
in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
/**
* Invoke to notify System UI that a media transfer from this device (the sender) to a receiver
* device has finished successfully.
*
* Important notes:
* - This callback is for *starting* a cast. It should be used when this device had previously
* been playing media locally and the media has successfully been transferred to the
* receiver device instead.
*/
oneway void transferToReceiverSucceeded(
in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
/**
* Invoke to notify System UI that the attempted transfer has failed.
*

View File

@@ -37,7 +37,7 @@ import com.android.systemui.media.taptotransfer.sender.MoveCloserToStartCast
import com.android.systemui.media.taptotransfer.sender.TransferFailed
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverTriggered
import com.android.systemui.media.taptotransfer.sender.TransferToThisDeviceTriggered
import com.android.systemui.media.taptotransfer.sender.TransferSucceeded
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverSucceeded
import com.android.systemui.shared.mediattt.DeviceInfo
import com.android.systemui.shared.mediattt.IDeviceSenderCallback
import com.android.systemui.statusbar.commandline.Command
@@ -104,17 +104,10 @@ class MediaTttCommandLineHelper @Inject constructor(
senderCallback.transferToThisDeviceTriggered(mediaInfo, otherDeviceInfo)
}
}
// TODO(b/203800643): Migrate this command to invoke the service instead of the
// controller.
TRANSFER_SUCCEEDED_COMMAND_NAME -> {
mediaTttChipControllerSender.displayChip(
TransferSucceeded(
appIconDrawable,
APP_ICON_CONTENT_DESCRIPTION,
otherDeviceName,
fakeUndoRunnable
)
)
TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME -> {
runOnService { senderCallback ->
senderCallback.transferToReceiverSucceeded(mediaInfo, otherDeviceInfo)
}
}
TRANSFER_FAILED_COMMAND_NAME -> {
runOnService { senderCallback ->
@@ -127,7 +120,7 @@ class MediaTttCommandLineHelper @Inject constructor(
"$MOVE_CLOSER_TO_END_CAST_COMMAND_NAME, " +
"$TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME, " +
"$TRANSFER_TO_THIS_DEVICE_TRIGGERED_COMMAND_NAME, " +
"$TRANSFER_SUCCEEDED_COMMAND_NAME, " +
"$TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME, " +
TRANSFER_FAILED_COMMAND_NAME
)
}
@@ -217,10 +210,6 @@ class MediaTttCommandLineHelper @Inject constructor(
/** Runs the command on the provided [senderCallback]. */
fun run(senderCallback: IDeviceSenderCallback)
}
private val fakeUndoRunnable = Runnable {
Log.i(TAG, "Undo runnable triggered")
}
}
@VisibleForTesting
@@ -241,7 +230,7 @@ val TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME = TransferToReceiverTriggered::c
val TRANSFER_TO_THIS_DEVICE_TRIGGERED_COMMAND_NAME =
TransferToThisDeviceTriggered::class.simpleName!!
@VisibleForTesting
val TRANSFER_SUCCEEDED_COMMAND_NAME = TransferSucceeded::class.simpleName!!
val TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME = TransferToReceiverSucceeded::class.simpleName!!
@VisibleForTesting
val TRANSFER_FAILED_COMMAND_NAME = TransferFailed::class.simpleName!!

View File

@@ -111,13 +111,13 @@ class TransferToThisDeviceTriggered(
}
/**
* A state representing that a transfer has been successfully completed.
* A state representing that a transfer to the receiver device has been successfully completed.
*
* @property otherDeviceName the name of the other device involved in the transfer.
* @property undoRunnable if present, the runnable that should be run to undo the transfer. We will
* show an Undo button on the chip if this runnable is present.
*/
class TransferSucceeded(
class TransferToReceiverSucceeded(
appIconDrawable: Drawable,
appIconContentDescription: String,
private val otherDeviceName: String,

View File

@@ -54,7 +54,7 @@ class MediaTttChipControllerSender @Inject constructor(
// Undo
val undoClickListener: View.OnClickListener? =
if (chipState is TransferSucceeded && chipState.undoRunnable != null)
if (chipState is TransferToReceiverSucceeded && chipState.undoRunnable != null)
View.OnClickListener { chipState.undoRunnable.run() }
else
null

View File

@@ -67,6 +67,12 @@ class MediaTttSenderService @Inject constructor(
) {
this@MediaTttSenderService.transferToThisDeviceTriggered(mediaInfo)
}
override fun transferToReceiverSucceeded(
mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
) {
this@MediaTttSenderService.transferToReceiverSucceeded(mediaInfo, otherDeviceInfo)
}
}
// TODO(b/203800643): Use the app icon from the media info instead of a fake one.
@@ -123,4 +129,17 @@ class MediaTttSenderService @Inject constructor(
)
controller.displayChip(chipState)
}
private fun transferToReceiverSucceeded(
mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
) {
val chipState = TransferToReceiverSucceeded(
appIconDrawable = fakeAppIconDrawable,
appIconContentDescription = mediaInfo.name.toString(),
otherDeviceName = otherDeviceInfo.name
// TODO(b/203800643): Implement the undo API correctly so we can provide an undo
// callback here.
)
controller.displayChip(chipState)
}
}

View File

@@ -154,10 +154,14 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
}
@Test
fun sender_transferSucceeded_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferSucceededCommand())
fun sender_transferToReceiverSucceeded_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferToReceiverSucceededCommand())
verify(mediaTttChipControllerSender).displayChip(any(TransferSucceeded::class.java))
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService).transferToReceiverSucceeded(any(), capture(deviceInfoCaptor))
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
@@ -217,11 +221,11 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
TRANSFER_TO_THIS_DEVICE_TRIGGERED_COMMAND_NAME
)
private fun getTransferSucceededCommand(): Array<String> =
private fun getTransferToReceiverSucceededCommand(): Array<String> =
arrayOf(
ADD_CHIP_COMMAND_SENDER_TAG,
DEVICE_NAME,
TRANSFER_SUCCEEDED_COMMAND_NAME
TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME
)
private fun getTransferFailedCommand(): Array<String> =

View File

@@ -108,8 +108,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun transferSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
val state = transferSucceeded()
fun transferToReceiverSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
val state = transferToReceiverSucceeded()
controllerSender.displayChip(state)
val chipView = getChipView()
@@ -121,16 +121,16 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun transferSucceededNullUndoRunnable_noUndo() {
controllerSender.displayChip(transferSucceeded(undoRunnable = null))
fun transferToReceiverSucceeded_nullUndoRunnable_noUndo() {
controllerSender.displayChip(transferToReceiverSucceeded(undoRunnable = null))
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
}
@Test
fun transferSucceededWithUndoRunnable_undoWithClick() {
controllerSender.displayChip(transferSucceeded { })
fun transferToReceiverSucceeded_withUndoRunnable_undoWithClick() {
controllerSender.displayChip(transferToReceiverSucceeded { })
val chipView = getChipView()
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
@@ -138,11 +138,11 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun transferSucceededWithUndoRunnable_undoButtonClickRunsRunnable() {
fun transferToReceiverSucceeded_withUndoRunnable_undoButtonClickRunsRunnable() {
var runnableRun = false
val runnable = Runnable { runnableRun = true }
controllerSender.displayChip(transferSucceeded(undoRunnable = runnable))
controllerSender.displayChip(transferToReceiverSucceeded(undoRunnable = runnable))
getChipView().getUndoButton().performClick()
assertThat(runnableRun).isTrue()
@@ -173,7 +173,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() {
controllerSender.displayChip(transferToReceiverTriggered())
controllerSender.displayChip(transferSucceeded())
controllerSender.displayChip(transferToReceiverSucceeded())
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE)
}
@@ -181,14 +181,14 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
@Test
fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() {
controllerSender.displayChip(transferToReceiverTriggered())
controllerSender.displayChip(transferSucceeded { })
controllerSender.displayChip(transferToReceiverSucceeded { })
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.VISIBLE)
}
@Test
fun changeFromTransferSucceededToMoveCloserToStart_undoButtonDisappears() {
controllerSender.displayChip(transferSucceeded())
controllerSender.displayChip(transferToReceiverSucceeded())
controllerSender.displayChip(moveCloserToStartCast())
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE)
@@ -237,9 +237,10 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
TransferToThisDeviceTriggered(appIconDrawable, APP_ICON_CONTENT_DESC)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferSucceeded(
undoRunnable: Runnable? = null
) = TransferSucceeded(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME, undoRunnable)
private fun transferToReceiverSucceeded(undoRunnable: Runnable? = null) =
TransferToReceiverSucceeded(
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)

View File

@@ -78,6 +78,18 @@ class MediaTttSenderServiceTest : SysuiTestCase() {
assertThat(chipState.getChipTextString(context)).contains(name)
}
@Test
fun transferToReceiverSucceeded_controllerTriggeredWithCorrectState() {
val name = "Fake name"
callback.transferToReceiverSucceeded(mediaInfo, DeviceInfo(name))
val chipStateCaptor = argumentCaptor<TransferToReceiverSucceeded>()
verify(controller).displayChip(capture(chipStateCaptor))
val chipState = chipStateCaptor.value!!
assertThat(chipState.getChipTextString(context)).contains(name)
}
@Test
fun transferFailed_controllerTriggeredWithTransferFailedState() {
callback.transferFailed(mediaInfo, DeviceInfo("Fake name"))