Merge changes Ibb968d5c,I38521e9a
* changes: [Media TTT] Add the #transferToReceiverTriggered callback. [Media TTT] Don't use futures for determining whether a transfer has succeeded or not.
This commit is contained in:
committed by
Android (Google) Code Review
commit
cbfc6f5891
@@ -60,6 +60,18 @@ interface IDeviceSenderCallback {
|
||||
oneway void closeToReceiverToEndCast(
|
||||
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 been started.
|
||||
*
|
||||
* Important notes:
|
||||
* - This callback is for *starting* a cast. It should be used when this device is currently
|
||||
* playing media locally and the media has started being transferred to the receiver device
|
||||
* instead.
|
||||
*/
|
||||
oneway void transferToReceiverTriggered(
|
||||
in MediaRoute2Info mediaInfo, in DeviceInfo otherDeviceInfo);
|
||||
|
||||
/**
|
||||
* Invoke to notify System UI that the attempted transfer has failed.
|
||||
*
|
||||
|
||||
@@ -21,8 +21,6 @@ import android.content.Context;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.media.MediaDataManager;
|
||||
import com.android.systemui.media.MediaHierarchyManager;
|
||||
import com.android.systemui.media.MediaHost;
|
||||
@@ -33,10 +31,8 @@ import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerR
|
||||
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender;
|
||||
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderService;
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
@@ -89,14 +85,11 @@ public interface MediaModule {
|
||||
static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender(
|
||||
MediaTttFlags mediaTttFlags,
|
||||
Context context,
|
||||
WindowManager windowManager,
|
||||
@Main Executor mainExecutor,
|
||||
@Background Executor backgroundExecutor) {
|
||||
WindowManager windowManager) {
|
||||
if (!mediaTttFlags.isMediaTttEnabled()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new MediaTttChipControllerSender(
|
||||
context, windowManager, mainExecutor, backgroundExecutor));
|
||||
return Optional.of(new MediaTttChipControllerSender(context, windowManager));
|
||||
}
|
||||
|
||||
/** */
|
||||
@@ -120,8 +113,7 @@ public interface MediaModule {
|
||||
CommandRegistry commandRegistry,
|
||||
Context context,
|
||||
MediaTttChipControllerSender mediaTttChipControllerSender,
|
||||
MediaTttChipControllerReceiver mediaTttChipControllerReceiver,
|
||||
@Main DelayableExecutor mainExecutor) {
|
||||
MediaTttChipControllerReceiver mediaTttChipControllerReceiver) {
|
||||
if (!mediaTttFlags.isMediaTttEnabled()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -130,8 +122,7 @@ public interface MediaModule {
|
||||
commandRegistry,
|
||||
context,
|
||||
mediaTttChipControllerSender,
|
||||
mediaTttChipControllerReceiver,
|
||||
mainExecutor));
|
||||
mediaTttChipControllerReceiver));
|
||||
}
|
||||
|
||||
/** Inject into MediaTttSenderService. */
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver
|
||||
import com.android.systemui.media.taptotransfer.receiver.ChipStateReceiver
|
||||
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender
|
||||
@@ -36,15 +35,13 @@ 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.TransferToReceiverTriggered
|
||||
import com.android.systemui.media.taptotransfer.sender.TransferSucceeded
|
||||
import com.android.systemui.shared.mediattt.DeviceInfo
|
||||
import com.android.systemui.shared.mediattt.IDeviceSenderCallback
|
||||
import com.android.systemui.statusbar.commandline.Command
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import java.io.PrintWriter
|
||||
import java.util.concurrent.FutureTask
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -57,7 +54,6 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
private val context: Context,
|
||||
private val mediaTttChipControllerSender: MediaTttChipControllerSender,
|
||||
private val mediaTttChipControllerReceiver: MediaTttChipControllerReceiver,
|
||||
@Main private val mainExecutor: DelayableExecutor,
|
||||
) {
|
||||
private var senderCallback: IDeviceSenderCallback? = null
|
||||
private val senderServiceConnection = SenderServiceConnection()
|
||||
@@ -97,22 +93,13 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
senderCallback.closeToReceiverToEndCast(mediaInfo, otherDeviceInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/203800643): Migrate other commands to invoke the service instead of the
|
||||
// controller.
|
||||
TRANSFER_INITIATED_COMMAND_NAME -> {
|
||||
val futureTask = FutureTask { fakeUndoRunnable }
|
||||
mediaTttChipControllerSender.displayChip(
|
||||
TransferInitiated(
|
||||
appIconDrawable,
|
||||
APP_ICON_CONTENT_DESCRIPTION,
|
||||
otherDeviceName,
|
||||
futureTask
|
||||
)
|
||||
)
|
||||
mainExecutor.executeDelayed({ futureTask.run() }, FUTURE_WAIT_TIME)
|
||||
|
||||
TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME -> {
|
||||
runOnService { senderCallback ->
|
||||
senderCallback.transferToReceiverTriggered(mediaInfo, otherDeviceInfo)
|
||||
}
|
||||
}
|
||||
// TODO(b/203800643): Migrate this command to invoke the service instead of the
|
||||
// controller.
|
||||
TRANSFER_SUCCEEDED_COMMAND_NAME -> {
|
||||
mediaTttChipControllerSender.displayChip(
|
||||
TransferSucceeded(
|
||||
@@ -132,7 +119,7 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
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_TO_RECEIVER_TRIGGERED_COMMAND_NAME, " +
|
||||
"$TRANSFER_SUCCEEDED_COMMAND_NAME, " +
|
||||
TRANSFER_FAILED_COMMAND_NAME
|
||||
)
|
||||
@@ -242,12 +229,11 @@ val MOVE_CLOSER_TO_START_CAST_COMMAND_NAME = MoveCloserToStartCast::class.simple
|
||||
@VisibleForTesting
|
||||
val MOVE_CLOSER_TO_END_CAST_COMMAND_NAME = MoveCloserToEndCast::class.simpleName!!
|
||||
@VisibleForTesting
|
||||
val TRANSFER_INITIATED_COMMAND_NAME = TransferInitiated::class.simpleName!!
|
||||
val TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME = TransferToReceiverTriggered::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"
|
||||
private const val TAG = "MediaTapToTransferCli"
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.StringRes
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttChipState
|
||||
import java.util.concurrent.Future
|
||||
|
||||
/**
|
||||
* A class that stores all the information necessary to display the media tap-to-transfer chip on
|
||||
@@ -72,18 +71,13 @@ class MoveCloserToEndCast(
|
||||
)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* If the transfer succeeded, the future can optionally return an undo runnable (see
|
||||
* [TransferSucceeded.undoRunnable]). [MediaTttChipControllerSender] is responsible for transitioning
|
||||
* the chip to the [TransferSucceeded] state if the future resolves successfully.
|
||||
* A state representing that a transfer to the receiver device has been initiated (but not
|
||||
* completed).
|
||||
*/
|
||||
class TransferInitiated(
|
||||
class TransferToReceiverTriggered(
|
||||
appIconDrawable: Drawable,
|
||||
appIconContentDescription: String,
|
||||
otherDeviceName: String,
|
||||
val future: Future<Runnable?>
|
||||
otherDeviceName: String
|
||||
) : ChipStateSender(
|
||||
appIconDrawable,
|
||||
appIconContentDescription,
|
||||
|
||||
@@ -23,11 +23,7 @@ import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -38,8 +34,6 @@ import javax.inject.Inject
|
||||
class MediaTttChipControllerSender @Inject constructor(
|
||||
context: Context,
|
||||
windowManager: WindowManager,
|
||||
@Main private val mainExecutor: Executor,
|
||||
@Background private val backgroundExecutor: Executor,
|
||||
) : MediaTttChipControllerCommon<ChipStateSender>(
|
||||
context, windowManager, R.layout.media_ttt_chip
|
||||
) {
|
||||
@@ -55,7 +49,7 @@ class MediaTttChipControllerSender @Inject constructor(
|
||||
}
|
||||
|
||||
// Loading
|
||||
val showLoading = chipState is TransferInitiated
|
||||
val showLoading = chipState is TransferToReceiverTriggered
|
||||
currentChipView.requireViewById<View>(R.id.loading).visibility =
|
||||
if (showLoading) { View.VISIBLE } else { View.GONE }
|
||||
|
||||
@@ -77,47 +71,5 @@ class MediaTttChipControllerSender @Inject constructor(
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the appropriate callbacks to [chipState.future] so that we update the chip correctly
|
||||
* when the future resolves.
|
||||
*/
|
||||
private fun addFutureCallback(chipState: TransferInitiated) {
|
||||
// Listen to the future on a background thread so we don't occupy the main thread while we
|
||||
// wait for it to complete.
|
||||
backgroundExecutor.execute {
|
||||
try {
|
||||
val undoRunnable = chipState.future.get(TRANSFER_TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||
// Make UI changes on the main thread
|
||||
mainExecutor.execute {
|
||||
displayChip(
|
||||
TransferSucceeded(
|
||||
chipState.appIconDrawable,
|
||||
chipState.appIconContentDescription,
|
||||
chipState.otherDeviceName,
|
||||
undoRunnable
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
mainExecutor.execute {
|
||||
displayChip(
|
||||
TransferFailed(
|
||||
chipState.appIconDrawable,
|
||||
chipState.appIconContentDescription,
|
||||
chipState.otherDeviceName,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val TRANSFER_TIMEOUT_SECONDS = 10L
|
||||
|
||||
@@ -55,6 +55,12 @@ class MediaTttSenderService @Inject constructor(
|
||||
) {
|
||||
this@MediaTttSenderService.transferFailed(mediaInfo, otherDeviceInfo)
|
||||
}
|
||||
|
||||
override fun transferToReceiverTriggered(
|
||||
mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
|
||||
) {
|
||||
this@MediaTttSenderService.transferToReceiverTriggered(mediaInfo, otherDeviceInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/203800643): Use the app icon from the media info instead of a fake one.
|
||||
@@ -93,4 +99,15 @@ class MediaTttSenderService @Inject constructor(
|
||||
)
|
||||
controller.displayChip(chipState)
|
||||
}
|
||||
|
||||
private fun transferToReceiverTriggered(
|
||||
mediaInfo: MediaRoute2Info, otherDeviceInfo: DeviceInfo
|
||||
) {
|
||||
val chipState = TransferToReceiverTriggered(
|
||||
appIconDrawable = fakeAppIconDrawable,
|
||||
appIconContentDescription = mediaInfo.name.toString(),
|
||||
otherDeviceName = otherDeviceInfo.name
|
||||
)
|
||||
controller.displayChip(chipState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,9 @@ import com.android.systemui.shared.mediattt.DeviceInfo
|
||||
import com.android.systemui.shared.mediattt.IDeviceSenderCallback
|
||||
import com.android.systemui.statusbar.commandline.Command
|
||||
import com.android.systemui.statusbar.commandline.CommandRegistry
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -75,7 +73,6 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
context,
|
||||
mediaTttChipControllerSender,
|
||||
mediaTttChipControllerReceiver,
|
||||
FakeExecutor(FakeSystemClock())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,10 +135,14 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sender_transferInitiated_chipDisplayWithCorrectState() {
|
||||
commandRegistry.onShellCommand(pw, getTransferInitiatedCommand())
|
||||
fun sender_transferToReceiverTriggered_chipDisplayWithCorrectState() {
|
||||
commandRegistry.onShellCommand(pw, getTransferToReceiverTriggeredCommand())
|
||||
|
||||
verify(mediaTttChipControllerSender).displayChip(any(TransferInitiated::class.java))
|
||||
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
|
||||
|
||||
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
|
||||
verify(mediaSenderService).transferToReceiverTriggered(any(), capture(deviceInfoCaptor))
|
||||
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -194,11 +195,11 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
MOVE_CLOSER_TO_END_CAST_COMMAND_NAME
|
||||
)
|
||||
|
||||
private fun getTransferInitiatedCommand(): Array<String> =
|
||||
private fun getTransferToReceiverTriggeredCommand(): Array<String> =
|
||||
arrayOf(
|
||||
ADD_CHIP_COMMAND_SENDER_TAG,
|
||||
DEVICE_NAME,
|
||||
TRANSFER_INITIATED_COMMAND_NAME
|
||||
TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME
|
||||
)
|
||||
|
||||
private fun getTransferSucceededCommand(): Array<String> =
|
||||
|
||||
@@ -26,26 +26,18 @@ import android.widget.TextView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.google.common.util.concurrent.SettableFuture
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.util.concurrent.Future
|
||||
|
||||
@SmallTest
|
||||
class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
private lateinit var appIconDrawable: Drawable
|
||||
private lateinit var fakeMainClock: FakeSystemClock
|
||||
private lateinit var fakeMainExecutor: FakeExecutor
|
||||
private lateinit var fakeBackgroundClock: FakeSystemClock
|
||||
private lateinit var fakeBackgroundExecutor: FakeExecutor
|
||||
|
||||
private lateinit var controllerSender: MediaTttChipControllerSender
|
||||
|
||||
@@ -56,13 +48,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
appIconDrawable = Icon.createWithResource(context, R.drawable.ic_cake).loadDrawable(context)
|
||||
fakeMainClock = FakeSystemClock()
|
||||
fakeMainExecutor = FakeExecutor(fakeMainClock)
|
||||
fakeBackgroundClock = FakeSystemClock()
|
||||
fakeBackgroundExecutor = FakeExecutor(fakeBackgroundClock)
|
||||
controllerSender = MediaTttChipControllerSender(
|
||||
context, windowManager, fakeMainExecutor, fakeBackgroundExecutor
|
||||
)
|
||||
controllerSender = MediaTttChipControllerSender(context, windowManager)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,13 +78,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferInitiated_futureNotResolvedYet_appIcon_loadingIcon_noUndo_noFailureIcon() {
|
||||
val future: SettableFuture<Runnable?> = SettableFuture.create()
|
||||
controllerSender.displayChip(transferInitiated(future))
|
||||
fun transferToReceiverTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
|
||||
// Don't resolve the future in any way and don't run our executors
|
||||
|
||||
// Assert we're still in the loading state
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconDrawable)
|
||||
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_ICON_CONTENT_DESC)
|
||||
@@ -108,71 +90,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
assertThat(chipView.getFailureIcon().visibility).isEqualTo(View.GONE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferInitiated_futureResolvedSuccessfully_switchesToTransferSucceeded() {
|
||||
val future: SettableFuture<Runnable?> = SettableFuture.create()
|
||||
val undoRunnable = Runnable { }
|
||||
|
||||
controllerSender.displayChip(transferInitiated(future))
|
||||
|
||||
future.set(undoRunnable)
|
||||
fakeBackgroundExecutor.advanceClockToLast()
|
||||
fakeBackgroundExecutor.runAllReady()
|
||||
fakeMainExecutor.advanceClockToLast()
|
||||
val numRun = fakeMainExecutor.runAllReady()
|
||||
|
||||
// Assert we ran the future callback
|
||||
assertThat(numRun).isEqualTo(1)
|
||||
// Assert that we've moved to the successful state
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getChipText()).contains(DEVICE_NAME)
|
||||
assertThat(chipView.getLoadingIconVisibility()).isEqualTo(View.GONE)
|
||||
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferInitiated_futureCancelled_switchesToTransferFailed() {
|
||||
val future: SettableFuture<Runnable?> = SettableFuture.create()
|
||||
|
||||
controllerSender.displayChip(transferInitiated(future))
|
||||
|
||||
future.cancel(true)
|
||||
fakeBackgroundExecutor.advanceClockToLast()
|
||||
fakeBackgroundExecutor.runAllReady()
|
||||
fakeMainExecutor.advanceClockToLast()
|
||||
val numRun = fakeMainExecutor.runAllReady()
|
||||
|
||||
// Assert we ran the future callback
|
||||
assertThat(numRun).isEqualTo(1)
|
||||
// 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_switchesToTransferFailed() {
|
||||
val future: SettableFuture<Runnable?> = SettableFuture.create()
|
||||
controllerSender.displayChip(transferInitiated(future))
|
||||
|
||||
// We won't set anything on the future, but we will still run the executors so that we're
|
||||
// waiting on the future resolving. If we have a bug in our code, then this test will time
|
||||
// out because we're waiting on the future indefinitely.
|
||||
fakeBackgroundExecutor.advanceClockToLast()
|
||||
fakeBackgroundExecutor.runAllReady()
|
||||
fakeMainExecutor.advanceClockToLast()
|
||||
val numRun = fakeMainExecutor.runAllReady()
|
||||
|
||||
// Assert we eventually decide to not wait for the future anymore
|
||||
assertThat(numRun).isEqualTo(1)
|
||||
// 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_deviceName_noLoadingIcon_noFailureIcon() {
|
||||
controllerSender.displayChip(transferSucceeded())
|
||||
@@ -227,24 +144,24 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromCloserToStartToTransferInitiated_loadingIconAppears() {
|
||||
fun changeFromCloserToStartToTransferTriggered_loadingIconAppears() {
|
||||
controllerSender.displayChip(moveCloserToStartCast())
|
||||
controllerSender.displayChip(transferInitiated())
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
|
||||
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferInitiatedToTransferSucceeded_loadingIconDisappears() {
|
||||
controllerSender.displayChip(transferInitiated())
|
||||
fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(transferSucceeded())
|
||||
|
||||
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferInitiatedToTransferSucceeded_undoButtonAppears() {
|
||||
controllerSender.displayChip(transferInitiated())
|
||||
fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(transferSucceeded { })
|
||||
|
||||
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.VISIBLE)
|
||||
@@ -259,8 +176,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferInitiatedToTransferFailed_failureIconAppears() {
|
||||
controllerSender.displayChip(transferInitiated())
|
||||
fun changeFromTransferTriggeredToTransferFailed_failureIconAppears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(transferFailed())
|
||||
|
||||
assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
|
||||
@@ -293,9 +210,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
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)
|
||||
private fun transferToReceiverTriggered() =
|
||||
TransferToReceiverTriggered(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
|
||||
|
||||
/** Helper method providing default parameters to not clutter up the tests. */
|
||||
private fun transferSucceeded(
|
||||
@@ -309,6 +225,3 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
|
||||
private const val DEVICE_NAME = "My Tablet"
|
||||
private const val APP_ICON_CONTENT_DESC = "Content description"
|
||||
// Use a settable future that hasn't yet been set so that we don't immediately switch to the success
|
||||
// state.
|
||||
private val TEST_FUTURE: SettableFuture<Runnable?> = SettableFuture.create()
|
||||
|
||||
@@ -36,7 +36,7 @@ class MediaTttSenderServiceTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun closeToReceiverToStartCast_controllerTriggeredWithMoveCloserToStartCastState() {
|
||||
fun closeToReceiverToStartCast_controllerTriggeredWithCorrectState() {
|
||||
val name = "Fake name"
|
||||
callback.closeToReceiverToStartCast(mediaInfo, DeviceInfo(name))
|
||||
|
||||
@@ -48,7 +48,7 @@ class MediaTttSenderServiceTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun closeToReceiverToEndCast_controllerTriggeredWithMoveCloserToEndCastState() {
|
||||
fun closeToReceiverToEndCast_controllerTriggeredWithCorrectState() {
|
||||
val name = "Fake name"
|
||||
callback.closeToReceiverToEndCast(mediaInfo, DeviceInfo(name))
|
||||
|
||||
@@ -59,6 +59,18 @@ class MediaTttSenderServiceTest : SysuiTestCase() {
|
||||
assertThat(chipState.otherDeviceName).isEqualTo(name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferToReceiverTriggered_controllerTriggeredWithCorrectState() {
|
||||
val name = "Fake name"
|
||||
callback.transferToReceiverTriggered(mediaInfo, DeviceInfo(name))
|
||||
|
||||
val chipStateCaptor = argumentCaptor<TransferToReceiverTriggered>()
|
||||
verify(controller).displayChip(capture(chipStateCaptor))
|
||||
|
||||
val chipState = chipStateCaptor.value!!
|
||||
assertThat(chipState.otherDeviceName).isEqualTo(name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferFailed_controllerTriggeredWithTransferFailedState() {
|
||||
callback.transferFailed(mediaInfo, DeviceInfo("Fake name"))
|
||||
|
||||
Reference in New Issue
Block a user