Merge "[Media TTT] Handle invalid chip transitions" into tm-qpr-dev

This commit is contained in:
Michael Mikhail
2022-12-05 22:52:51 +00:00
committed by Android (Google) Code Review
5 changed files with 346 additions and 19 deletions

View File

@@ -58,6 +58,27 @@ class MediaTttLogger(
) )
} }
/**
* Logs an invalid sender state transition error in trying to update to [desiredState].
*
* @param currentState the previous state of the chip.
* @param desiredState the new state of the chip.
*/
fun logInvalidStateTransitionError(
currentState: String,
desiredState: String
) {
buffer.log(
tag,
LogLevel.ERROR,
{
str1 = currentState
str2 = desiredState
},
{ "Cannot display state=$str2 after state=$str1; invalid transition" }
)
}
/** Logs that we couldn't find information for [packageName]. */ /** Logs that we couldn't find information for [packageName]. */
fun logPackageNotFound(packageName: String) { fun logPackageNotFound(packageName: String) {
buffer.log( buffer.log(

View File

@@ -56,7 +56,12 @@ enum class ChipStateSender(
R.string.media_move_closer_to_start_cast, R.string.media_move_closer_to_start_cast,
transferStatus = TransferStatus.NOT_STARTED, transferStatus = TransferStatus.NOT_STARTED,
endItem = null, endItem = null,
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == TRANSFER_TO_RECEIVER_TRIGGERED
}
},
/** /**
* A state representing that the two devices are close but not close enough to *end* a cast * A state representing that the two devices are close but not close enough to *end* a cast
@@ -70,7 +75,12 @@ enum class ChipStateSender(
R.string.media_move_closer_to_end_cast, R.string.media_move_closer_to_end_cast,
transferStatus = TransferStatus.NOT_STARTED, transferStatus = TransferStatus.NOT_STARTED,
endItem = null, endItem = null,
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == TRANSFER_TO_THIS_DEVICE_TRIGGERED
}
},
/** /**
* A state representing that a transfer to the receiver device has been initiated (but not * A state representing that a transfer to the receiver device has been initiated (but not
@@ -83,7 +93,13 @@ enum class ChipStateSender(
transferStatus = TransferStatus.IN_PROGRESS, transferStatus = TransferStatus.IN_PROGRESS,
endItem = SenderEndItem.Loading, endItem = SenderEndItem.Loading,
timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == TRANSFER_TO_RECEIVER_SUCCEEDED ||
nextState == TRANSFER_TO_RECEIVER_FAILED
}
},
/** /**
* A state representing that a transfer from the receiver device and back to this device (the * A state representing that a transfer from the receiver device and back to this device (the
@@ -96,7 +112,13 @@ enum class ChipStateSender(
transferStatus = TransferStatus.IN_PROGRESS, transferStatus = TransferStatus.IN_PROGRESS,
endItem = SenderEndItem.Loading, endItem = SenderEndItem.Loading,
timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == TRANSFER_TO_THIS_DEVICE_SUCCEEDED ||
nextState == TRANSFER_TO_THIS_DEVICE_FAILED
}
},
/** /**
* A state representing that a transfer to the receiver device has been successfully completed. * A state representing that a transfer to the receiver device has been successfully completed.
@@ -112,7 +134,13 @@ enum class ChipStateSender(
newState = newState =
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED
), ),
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == ALMOST_CLOSE_TO_START_CAST ||
nextState == TRANSFER_TO_THIS_DEVICE_TRIGGERED
}
},
/** /**
* A state representing that a transfer back to this device has been successfully completed. * A state representing that a transfer back to this device has been successfully completed.
@@ -128,7 +156,13 @@ enum class ChipStateSender(
newState = newState =
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED
), ),
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == ALMOST_CLOSE_TO_END_CAST ||
nextState == TRANSFER_TO_RECEIVER_TRIGGERED
}
},
/** A state representing that a transfer to the receiver device has failed. */ /** A state representing that a transfer to the receiver device has failed. */
TRANSFER_TO_RECEIVER_FAILED( TRANSFER_TO_RECEIVER_FAILED(
@@ -137,7 +171,13 @@ enum class ChipStateSender(
R.string.media_transfer_failed, R.string.media_transfer_failed,
transferStatus = TransferStatus.FAILED, transferStatus = TransferStatus.FAILED,
endItem = SenderEndItem.Error, endItem = SenderEndItem.Error,
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == ALMOST_CLOSE_TO_START_CAST ||
nextState == TRANSFER_TO_THIS_DEVICE_TRIGGERED
}
},
/** A state representing that a transfer back to this device has failed. */ /** A state representing that a transfer back to this device has failed. */
TRANSFER_TO_THIS_DEVICE_FAILED( TRANSFER_TO_THIS_DEVICE_FAILED(
@@ -146,7 +186,13 @@ enum class ChipStateSender(
R.string.media_transfer_failed, R.string.media_transfer_failed,
transferStatus = TransferStatus.FAILED, transferStatus = TransferStatus.FAILED,
endItem = SenderEndItem.Error, endItem = SenderEndItem.Error,
), ) {
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState == ALMOST_CLOSE_TO_END_CAST ||
nextState == TRANSFER_TO_RECEIVER_TRIGGERED
}
},
/** A state representing that this device is far away from any receiver device. */ /** A state representing that this device is far away from any receiver device. */
FAR_FROM_RECEIVER( FAR_FROM_RECEIVER(
@@ -162,6 +208,12 @@ enum class ChipStateSender(
throw IllegalArgumentException("FAR_FROM_RECEIVER should never be displayed, " + throw IllegalArgumentException("FAR_FROM_RECEIVER should never be displayed, " +
"so its string should never be fetched") "so its string should never be fetched")
} }
override fun isValidNextState(nextState: ChipStateSender): Boolean {
return nextState == FAR_FROM_RECEIVER ||
nextState.transferStatus == TransferStatus.NOT_STARTED ||
nextState.transferStatus == TransferStatus.IN_PROGRESS
}
}; };
/** /**
@@ -175,6 +227,8 @@ enum class ChipStateSender(
return Text.Loaded(context.getString(stringResId!!, otherDeviceName)) return Text.Loaded(context.getString(stringResId!!, otherDeviceName))
} }
abstract fun isValidNextState(nextState: ChipStateSender): Boolean
companion object { companion object {
/** /**
* Returns the sender state enum associated with the given [displayState] from * Returns the sender state enum associated with the given [displayState] from
@@ -197,6 +251,31 @@ enum class ChipStateSender(
*/ */
@StatusBarManager.MediaTransferSenderState @StatusBarManager.MediaTransferSenderState
fun getSenderStateIdFromName(name: String): Int = valueOf(name).stateInt fun getSenderStateIdFromName(name: String): Int = valueOf(name).stateInt
/**
* Validates the transition from a chip state to another.
*
* @param currentState is the current state of the chip.
* @param desiredState is the desired state of the chip.
* @return true if the transition from [currentState] to [desiredState] is valid, and false
* otherwise.
*/
fun isValidStateTransition(
currentState: ChipStateSender?,
desiredState: ChipStateSender,
): Boolean {
// Far from receiver is the default state.
if (currentState == null) {
return FAR_FROM_RECEIVER.isValidNextState(desiredState)
}
// No change in state is valid.
if (currentState == desiredState) {
return true
}
return currentState.isValidNextState(desiredState)
}
} }
} }

View File

@@ -52,6 +52,8 @@ constructor(
) : CoreStartable { ) : CoreStartable {
private var displayedState: ChipStateSender? = null private var displayedState: ChipStateSender? = null
// A map to store current chip state per id.
private var stateMap: MutableMap<String, ChipStateSender> = mutableMapOf()
private val commandQueueCallbacks = private val commandQueueCallbacks =
object : CommandQueue.Callbacks { object : CommandQueue.Callbacks {
@@ -87,9 +89,22 @@ constructor(
logger.logStateChangeError(displayState) logger.logStateChangeError(displayState)
return return
} }
val currentState = stateMap[routeInfo.id]
if (!ChipStateSender.isValidStateTransition(currentState, chipState)) {
// ChipStateSender.FAR_FROM_RECEIVER is the default state when there is no state.
logger.logInvalidStateTransitionError(
currentState = currentState?.name ?: ChipStateSender.FAR_FROM_RECEIVER.name,
chipState.name
)
return
}
uiEventLogger.logSenderStateChange(chipState) uiEventLogger.logSenderStateChange(chipState)
stateMap.put(routeInfo.id, chipState)
if (chipState == ChipStateSender.FAR_FROM_RECEIVER) { if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
// No need to store the state since it is the default state
stateMap.remove(routeInfo.id)
// Return early if we're not displaying a chip anyway // Return early if we're not displaying a chip anyway
val currentDisplayedState = displayedState ?: return val currentDisplayedState = displayedState ?: return
@@ -119,7 +134,7 @@ constructor(
context, context,
logger, logger,
) )
) ) { stateMap.remove(routeInfo.id) }
} }
} }

View File

@@ -105,8 +105,9 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
* *
* This method handles inflating and attaching the view, then delegates to [updateView] to * This method handles inflating and attaching the view, then delegates to [updateView] to
* display the correct information in the view. * display the correct information in the view.
* @param onViewTimeout a runnable that runs after the view timeout.
*/ */
fun displayView(newInfo: T) { fun displayView(newInfo: T, onViewTimeout: Runnable? = null) {
val currentDisplayInfo = displayInfo val currentDisplayInfo = displayInfo
// Update our list of active devices by removing it if necessary, then adding back at the // Update our list of active devices by removing it if necessary, then adding back at the
@@ -173,7 +174,10 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
cancelViewTimeout?.run() cancelViewTimeout?.run()
} }
cancelViewTimeout = mainExecutor.executeDelayed( cancelViewTimeout = mainExecutor.executeDelayed(
{ removeView(id, REMOVAL_REASON_TIMEOUT) }, {
removeView(id, REMOVAL_REASON_TIMEOUT)
onViewTimeout?.run()
},
timeout.toLong() timeout.toLong()
) )
} }

View File

@@ -265,6 +265,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() { fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() {
displayReceiverTriggered()
reset(vibratorHelper)
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -278,13 +280,15 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
.isEqualTo(ChipStateSender.TRANSFER_TO_RECEIVER_SUCCEEDED.getExpectedStateText()) .isEqualTo(ChipStateSender.TRANSFER_TO_RECEIVER_SUCCEEDED.getExpectedStateText())
assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE)
assertThat(uiEventLoggerFake.eventId(0)) // Event index 1 since initially displaying the triggered chip would also log an event.
assertThat(uiEventLoggerFake.eventId(1))
.isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED.id) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED.id)
verify(vibratorHelper, never()).vibrate(any<VibrationEffect>()) verify(vibratorHelper, never()).vibrate(any<VibrationEffect>())
} }
@Test @Test
fun transferToReceiverSucceeded_nullUndoCallback_noUndo() { fun transferToReceiverSucceeded_nullUndoCallback_noUndo() {
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -297,6 +301,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToReceiverSucceeded_withUndoRunnable_undoVisible() { fun transferToReceiverSucceeded_withUndoRunnable_undoVisible() {
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -313,6 +318,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToReceiverSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() { fun transferToReceiverSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() {
var undoCallbackCalled = false var undoCallbackCalled = false
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -325,8 +331,9 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
getChipbarView().getUndoButton().performClick() getChipbarView().getUndoButton().performClick()
// Event index 1 since initially displaying the succeeded chip would also log an event // Event index 2 since initially displaying the triggered and succeeded chip would also log
assertThat(uiEventLoggerFake.eventId(1)) // events.
assertThat(uiEventLoggerFake.eventId(2))
.isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED.id) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED.id)
assertThat(undoCallbackCalled).isTrue() assertThat(undoCallbackCalled).isTrue()
assertThat(getChipbarView().getChipText()) assertThat(getChipbarView().getChipText())
@@ -335,6 +342,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() { fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() {
displayThisDeviceTriggered()
reset(vibratorHelper)
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -348,13 +357,15 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
.isEqualTo(ChipStateSender.TRANSFER_TO_THIS_DEVICE_SUCCEEDED.getExpectedStateText()) .isEqualTo(ChipStateSender.TRANSFER_TO_THIS_DEVICE_SUCCEEDED.getExpectedStateText())
assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE)
assertThat(uiEventLoggerFake.eventId(0)) // Event index 1 since initially displaying the triggered chip would also log an event.
assertThat(uiEventLoggerFake.eventId(1))
.isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED.id) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED.id)
verify(vibratorHelper, never()).vibrate(any<VibrationEffect>()) verify(vibratorHelper, never()).vibrate(any<VibrationEffect>())
} }
@Test @Test
fun transferToThisDeviceSucceeded_nullUndoCallback_noUndo() { fun transferToThisDeviceSucceeded_nullUndoCallback_noUndo() {
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -367,6 +378,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToThisDeviceSucceeded_withUndoRunnable_undoVisible() { fun transferToThisDeviceSucceeded_withUndoRunnable_undoVisible() {
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -383,6 +395,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToThisDeviceSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() { fun transferToThisDeviceSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() {
var undoCallbackCalled = false var undoCallbackCalled = false
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -395,8 +408,9 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
getChipbarView().getUndoButton().performClick() getChipbarView().getUndoButton().performClick()
// Event index 1 since initially displaying the succeeded chip would also log an event // Event index 2 since initially displaying the triggered and succeeded chip would also log
assertThat(uiEventLoggerFake.eventId(1)) // events.
assertThat(uiEventLoggerFake.eventId(2))
.isEqualTo( .isEqualTo(
MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED.id MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED.id
) )
@@ -407,6 +421,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() { fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() {
displayReceiverTriggered()
reset(vibratorHelper)
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
routeInfo, routeInfo,
@@ -421,13 +437,20 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getErrorIcon().visibility).isEqualTo(View.VISIBLE) assertThat(chipbarView.getErrorIcon().visibility).isEqualTo(View.VISIBLE)
assertThat(uiEventLoggerFake.eventId(0)) // Event index 1 since initially displaying the triggered chip would also log an event.
assertThat(uiEventLoggerFake.eventId(1))
.isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED.id) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED.id)
verify(vibratorHelper).vibrate(any<VibrationEffect>()) verify(vibratorHelper).vibrate(any<VibrationEffect>())
} }
@Test @Test
fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() { fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
routeInfo,
null
)
reset(vibratorHelper)
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
routeInfo, routeInfo,
@@ -442,7 +465,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE)
assertThat(chipbarView.getErrorIcon().visibility).isEqualTo(View.VISIBLE) assertThat(chipbarView.getErrorIcon().visibility).isEqualTo(View.VISIBLE)
assertThat(uiEventLoggerFake.eventId(0)) // Event index 1 since initially displaying the triggered chip would also log an event.
assertThat(uiEventLoggerFake.eventId(1))
.isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED.id) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED.id)
verify(vibratorHelper).vibrate(any<VibrationEffect>()) verify(vibratorHelper).vibrate(any<VibrationEffect>())
} }
@@ -516,6 +540,166 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
verify(windowManager, never()).addView(any(), any()) verify(windowManager, never()).addView(any(), any())
} }
@Test
fun commandQueueCallback_receiverTriggeredThenAlmostStart_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_thisDeviceTriggeredThenAlmostEnd_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_receiverSucceededThenReceiverTriggered_invalidTransitionLogged() {
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo,
null
)
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_thisDeviceSucceededThenThisDeviceTriggered_invalidTransitionLogged() {
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo,
null
)
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_almostStartThenReceiverSucceeded_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_almostEndThenThisDeviceSucceeded_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_AlmostStartThenReceiverFailed_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_almostEndThenThisDeviceFailed_invalidTransitionLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
routeInfo,
null
)
verify(windowManager).addView(any(), any())
reset(windowManager)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
routeInfo,
null
)
verify(logger).logInvalidStateTransitionError(any(), any())
verify(windowManager, never()).addView(any(), any())
}
@Test @Test
fun receivesNewStateFromCommandQueue_isLogged() { fun receivesNewStateFromCommandQueue_isLogged() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
@@ -575,6 +759,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() { fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -598,6 +783,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() { fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -621,6 +807,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToReceiverSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() { fun transferToReceiverSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() {
displayReceiverTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo, routeInfo,
@@ -660,6 +847,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
@Test @Test
fun transferToThisDeviceSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() { fun transferToThisDeviceSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() {
displayThisDeviceTriggered()
commandQueueCallback.updateMediaTapToTransferSenderDisplay( commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo, routeInfo,
@@ -717,6 +905,26 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
private fun ChipStateSender.getExpectedStateText(): String? { private fun ChipStateSender.getExpectedStateText(): String? {
return this.getChipTextString(context, OTHER_DEVICE_NAME).loadText(context) return this.getChipTextString(context, OTHER_DEVICE_NAME).loadText(context)
} }
// display receiver triggered state helper method to make sure we start from a valid state
// transition (FAR_FROM_RECEIVER -> TRANSFER_TO_RECEIVER_TRIGGERED).
private fun displayReceiverTriggered() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
routeInfo,
null
)
}
// display this device triggered state helper method to make sure we start from a valid state
// transition (FAR_FROM_RECEIVER -> TRANSFER_TO_THIS_DEVICE_TRIGGERED).
private fun displayThisDeviceTriggered() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
routeInfo,
null
)
}
} }
private const val APP_NAME = "Fake app name" private const val APP_NAME = "Fake app name"