diff options
| author | 2022-12-06 16:39:10 +0000 | |
|---|---|---|
| committer | 2022-12-06 16:39:10 +0000 | |
| commit | b4734a2258b239df336823bada2f70aaa4747d2f (patch) | |
| tree | 690fe45f964572c8ca59f606a883f50ef610845e | |
| parent | 1a34eba3e28c0c9245455cfd1f3e57b19b9ad78f (diff) | |
| parent | d75a26d08161edba64f369e5acb68573fbe42b1a (diff) | |
Merge "[Media TTT] Handle invalid chip transitions" into tm-qpr-dev am: 88aec368d4 am: d75a26d081
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20609875
Change-Id: Ia5e35de4f1870d966fbd9ba4443beb43ef80e2cd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
5 files changed, 346 insertions, 19 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt index 120f7d673881..b55bedda2dc1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt @@ -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]. */ fun logPackageNotFound(packageName: String) { buffer.log( 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 af7317c208ab..1f27582cb7aa 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,7 +56,12 @@ enum class ChipStateSender( R.string.media_move_closer_to_start_cast, transferStatus = TransferStatus.NOT_STARTED, 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 @@ -70,7 +75,12 @@ enum class ChipStateSender( R.string.media_move_closer_to_end_cast, transferStatus = TransferStatus.NOT_STARTED, 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 @@ -83,7 +93,13 @@ enum class ChipStateSender( transferStatus = TransferStatus.IN_PROGRESS, endItem = SenderEndItem.Loading, 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 @@ -96,7 +112,13 @@ enum class ChipStateSender( transferStatus = TransferStatus.IN_PROGRESS, endItem = SenderEndItem.Loading, 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. @@ -112,7 +134,13 @@ enum class ChipStateSender( newState = 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. @@ -128,7 +156,13 @@ enum class ChipStateSender( newState = 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. */ TRANSFER_TO_RECEIVER_FAILED( @@ -137,7 +171,13 @@ enum class ChipStateSender( R.string.media_transfer_failed, transferStatus = TransferStatus.FAILED, 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. */ TRANSFER_TO_THIS_DEVICE_FAILED( @@ -146,7 +186,13 @@ enum class ChipStateSender( R.string.media_transfer_failed, transferStatus = TransferStatus.FAILED, 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. */ FAR_FROM_RECEIVER( @@ -162,6 +208,12 @@ enum class ChipStateSender( throw IllegalArgumentException("FAR_FROM_RECEIVER should never be displayed, " + "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)) } + abstract fun isValidNextState(nextState: ChipStateSender): Boolean + companion object { /** * Returns the sender state enum associated with the given [displayState] from @@ -197,6 +251,31 @@ enum class ChipStateSender( */ @StatusBarManager.MediaTransferSenderState 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) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt index bb7bc6fff99f..e34b0cbdbdc3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt @@ -52,6 +52,8 @@ constructor( ) : CoreStartable { private var displayedState: ChipStateSender? = null + // A map to store current chip state per id. + private var stateMap: MutableMap<String, ChipStateSender> = mutableMapOf() private val commandQueueCallbacks = object : CommandQueue.Callbacks { @@ -87,9 +89,22 @@ constructor( logger.logStateChangeError(displayState) 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) + stateMap.put(routeInfo.id, chipState) 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 val currentDisplayedState = displayedState ?: return @@ -119,7 +134,7 @@ constructor( context, logger, ) - ) + ) { stateMap.remove(routeInfo.id) } } } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt index a9d05d11dc00..ea4020861a09 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt @@ -105,8 +105,9 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora * * This method handles inflating and attaching the view, then delegates to [updateView] to * 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 // 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 = mainExecutor.executeDelayed( - { removeView(id, REMOVAL_REASON_TIMEOUT) }, + { + removeView(id, REMOVAL_REASON_TIMEOUT) + onViewTimeout?.run() + }, timeout.toLong() ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt index 4437394da943..311740e17310 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt @@ -265,6 +265,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() { + displayReceiverTriggered() + reset(vibratorHelper) commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -278,13 +280,15 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { .isEqualTo(ChipStateSender.TRANSFER_TO_RECEIVER_SUCCEEDED.getExpectedStateText()) assertThat(chipbarView.getLoadingIcon().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) verify(vibratorHelper, never()).vibrate(any<VibrationEffect>()) } @Test fun transferToReceiverSucceeded_nullUndoCallback_noUndo() { + displayReceiverTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -297,6 +301,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_withUndoRunnable_undoVisible() { + displayReceiverTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -313,6 +318,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() { var undoCallbackCalled = false + displayReceiverTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -325,8 +331,9 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { getChipbarView().getUndoButton().performClick() - // Event index 1 since initially displaying the succeeded chip would also log an event - assertThat(uiEventLoggerFake.eventId(1)) + // Event index 2 since initially displaying the triggered and succeeded chip would also log + // events. + assertThat(uiEventLoggerFake.eventId(2)) .isEqualTo(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED.id) assertThat(undoCallbackCalled).isTrue() assertThat(getChipbarView().getChipText()) @@ -335,6 +342,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() { + displayThisDeviceTriggered() + reset(vibratorHelper) commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -348,13 +357,15 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { .isEqualTo(ChipStateSender.TRANSFER_TO_THIS_DEVICE_SUCCEEDED.getExpectedStateText()) assertThat(chipbarView.getLoadingIcon().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) verify(vibratorHelper, never()).vibrate(any<VibrationEffect>()) } @Test fun transferToThisDeviceSucceeded_nullUndoCallback_noUndo() { + displayThisDeviceTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -367,6 +378,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_withUndoRunnable_undoVisible() { + displayThisDeviceTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -383,6 +395,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() { var undoCallbackCalled = false + displayThisDeviceTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -395,8 +408,9 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { getChipbarView().getUndoButton().performClick() - // Event index 1 since initially displaying the succeeded chip would also log an event - assertThat(uiEventLoggerFake.eventId(1)) + // Event index 2 since initially displaying the triggered and succeeded chip would also log + // events. + assertThat(uiEventLoggerFake.eventId(2)) .isEqualTo( MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED.id ) @@ -407,6 +421,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() { + displayReceiverTriggered() + reset(vibratorHelper) commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED, routeInfo, @@ -421,7 +437,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) 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) verify(vibratorHelper).vibrate(any<VibrationEffect>()) } @@ -429,6 +446,12 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() { commandQueueCallback.updateMediaTapToTransferSenderDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED, + routeInfo, + null + ) + reset(vibratorHelper) + commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED, routeInfo, null @@ -442,7 +465,8 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.GONE) assertThat(chipbarView.getUndoButton().visibility).isEqualTo(View.GONE) 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) verify(vibratorHelper).vibrate(any<VibrationEffect>()) } @@ -517,6 +541,166 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { } @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 fun receivesNewStateFromCommandQueue_isLogged() { commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST, @@ -575,6 +759,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() { + displayReceiverTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -598,6 +783,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() { + displayThisDeviceTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -621,6 +807,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() { + displayReceiverTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, routeInfo, @@ -660,6 +847,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_thenUndo_thenFar_viewStillDisplayedButDoesTimeOut() { + displayThisDeviceTriggered() commandQueueCallback.updateMediaTapToTransferSenderDisplay( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, routeInfo, @@ -717,6 +905,26 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() { private fun ChipStateSender.getExpectedStateText(): String? { 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" |