[Media TTT] Update the sender view controller and the command line helper to

handle the sender @SystemApi states.

Bug: 216318437
Test: media.taptotransfer tests (still ignored because they were failing
on some cuttlefish builds, but they do pass locally)
Test: all adb commands work as expected (e.g. `adb shell cmd statusbar
media-ttt-chip-sender MyTablet TransferToThisDeviceSucceeded` shows the
succeeded chip)

Change-Id: Ic3fb31854bb1327b698a1a432dc8cad7513dfe35
This commit is contained in:
Caitlin Cassidy
2022-01-29 17:44:54 +00:00
parent 44386a5a2e
commit 623a9ccf55
6 changed files with 398 additions and 162 deletions

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.view.WindowManager;
import com.android.systemui.dagger.SysUISingleton;
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;
@@ -35,6 +36,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Named;
@@ -99,13 +101,13 @@ public interface MediaModule {
@SysUISingleton
static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender(
MediaTttFlags mediaTttFlags,
CommandQueue commandQueue,
Context context,
WindowManager windowManager,
CommandQueue commandQueue) {
WindowManager windowManager) {
if (!mediaTttFlags.isMediaTttEnabled()) {
return Optional.empty();
}
return Optional.of(new MediaTttChipControllerSender(context, windowManager, commandQueue));
return Optional.of(new MediaTttChipControllerSender(commandQueue, context, windowManager));
}
/** */
@@ -128,6 +130,7 @@ public interface MediaModule {
MediaTttFlags mediaTttFlags,
CommandRegistry commandRegistry,
Context context,
@Main Executor mainExecutor,
MediaTttChipControllerReceiver mediaTttChipControllerReceiver) {
if (!mediaTttFlags.isMediaTttEnabled()) {
return Optional.empty();
@@ -136,6 +139,7 @@ public interface MediaModule {
new MediaTttCommandLineHelper(
commandRegistry,
context,
mainExecutor,
mediaTttChipControllerReceiver));
}

View File

@@ -21,13 +21,15 @@ import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Icon
import android.media.MediaRoute2Info
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.MoveCloserToEndCast
import com.android.systemui.media.taptotransfer.sender.MoveCloserToStartCast
import com.android.systemui.media.taptotransfer.sender.AlmostCloseToEndCast
import com.android.systemui.media.taptotransfer.sender.AlmostCloseToStartCast
import com.android.systemui.media.taptotransfer.sender.TransferFailed
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverTriggered
import com.android.systemui.media.taptotransfer.sender.TransferToThisDeviceSucceeded
@@ -36,6 +38,7 @@ import com.android.systemui.media.taptotransfer.sender.TransferToReceiverSucceed
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
/**
@@ -46,13 +49,36 @@ import javax.inject.Inject
class MediaTttCommandLineHelper @Inject constructor(
commandRegistry: CommandRegistry,
private val context: Context,
@Main private val mainExecutor: Executor,
private val mediaTttChipControllerReceiver: MediaTttChipControllerReceiver,
) {
private val appIconDrawable =
private val appIconDrawable =
Icon.createWithResource(context, R.drawable.ic_avatar_user).loadDrawable(context).also {
it.setTint(Color.YELLOW)
}
/**
* A map from a display state string typed in the command line to the display int it represents.
*/
private val stateStringToStateInt: Map<String, Int> = mapOf(
AlmostCloseToStartCast::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
AlmostCloseToEndCast::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
TransferToReceiverTriggered::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
TransferToThisDeviceTriggered::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
TransferToReceiverSucceeded::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
TransferToThisDeviceSucceeded::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
TransferFailed::class.simpleName!!
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
FAR_FROM_RECEIVER_STATE
to StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER
)
init {
commandRegistry.registerCommand(SENDER_COMMAND) { SenderCommand() }
commandRegistry.registerCommand(
@@ -68,22 +94,59 @@ class MediaTttCommandLineHelper @Inject constructor(
.addFeature("feature")
.build()
@StatusBarManager.MediaTransferSenderState
val displayState = stateStringToStateInt[args[1]]
if (displayState == null) {
pw.println("Invalid command name")
return
}
val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)
as StatusBarManager
statusBarManager.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
displayState,
routeInfo,
/* undoExecutor= */ null,
/* undoCallback= */ null
getUndoExecutor(displayState),
getUndoCallback(displayState)
)
// TODO(b/216318437): Migrate the rest of the callbacks to StatusBarManager.
}
private fun getUndoExecutor(
@StatusBarManager.MediaTransferSenderState displayState: Int
): Executor? {
return if (isSucceededState(displayState)) {
mainExecutor
} else {
null
}
}
private fun getUndoCallback(
@StatusBarManager.MediaTransferSenderState displayState: Int
): Runnable? {
return if (isSucceededState(displayState)) {
Runnable { Log.i(CLI_TAG, "Undo triggered for $displayState") }
} else {
null
}
}
private fun isSucceededState(
@StatusBarManager.MediaTransferSenderState displayState: Int
): Boolean {
return displayState ==
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED ||
displayState ==
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED
}
override fun help(pw: PrintWriter) {
pw.println("Usage: adb shell cmd statusbar $SENDER_COMMAND <deviceName> <chipStatus>")
pw.println("Usage: adb shell cmd statusbar $SENDER_COMMAND <deviceName> <chipState>")
}
}
// TODO(b/216318437): Migrate the receiver callbacks to StatusBarManager.
/** A command to DISPLAY the media ttt chip on the RECEIVER device. */
inner class AddChipCommandReceiver : Command {
override fun execute(pw: PrintWriter, args: List<String>) {
@@ -110,29 +173,15 @@ class MediaTttCommandLineHelper @Inject constructor(
@VisibleForTesting
const val SENDER_COMMAND = "media-ttt-chip-sender"
@VisibleForTesting
const val REMOVE_CHIP_COMMAND_SENDER_TAG = "media-ttt-chip-remove-sender"
@VisibleForTesting
const val ADD_CHIP_COMMAND_RECEIVER_TAG = "media-ttt-chip-add-receiver"
@VisibleForTesting
const val REMOVE_CHIP_COMMAND_RECEIVER_TAG = "media-ttt-chip-remove-receiver"
@VisibleForTesting
val MOVE_CLOSER_TO_START_CAST_COMMAND_NAME = MoveCloserToStartCast::class.simpleName!!
@VisibleForTesting
val MOVE_CLOSER_TO_END_CAST_COMMAND_NAME = MoveCloserToEndCast::class.simpleName!!
@VisibleForTesting
val TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME = TransferToReceiverTriggered::class.simpleName!!
@VisibleForTesting
val TRANSFER_TO_THIS_DEVICE_TRIGGERED_COMMAND_NAME =
TransferToThisDeviceTriggered::class.simpleName!!
@VisibleForTesting
val TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME = TransferToReceiverSucceeded::class.simpleName!!
@VisibleForTesting
val TRANSFER_TO_THIS_DEVICE_SUCCEEDED_COMMAND_NAME =
TransferToThisDeviceSucceeded::class.simpleName!!
@VisibleForTesting
val TRANSFER_FAILED_COMMAND_NAME = TransferFailed::class.simpleName!!
@VisibleForTesting
val NO_LONGER_CLOSE_TO_RECEIVER_COMMAND_NAME = "NoLongerCloseToReceiver"
val FAR_FROM_RECEIVER_STATE = "FarFromReceiver"
private const val APP_ICON_CONTENT_DESCRIPTION = "Fake media app icon"
private const val TAG = "MediaTapToTransferCli"
private const val CLI_TAG = "MediaTransferCli"
private val routeInfo = MediaRoute2Info.Builder("id", "Test Name")
.addFeature("feature")
.build()

View File

@@ -59,7 +59,7 @@ sealed class ChipStateSender(
*
* @property otherDeviceName the name of the other device involved in the transfer.
*/
class MoveCloserToStartCast(
class AlmostCloseToStartCast(
appIconDrawable: Drawable,
appIconContentDescription: String,
private val otherDeviceName: String,
@@ -76,7 +76,7 @@ class MoveCloserToStartCast(
*
* @property otherDeviceName the name of the other device involved in the transfer.
*/
class MoveCloserToEndCast(
class AlmostCloseToEndCast(
appIconDrawable: Drawable,
appIconContentDescription: String,
private val otherDeviceName: String,

View File

@@ -21,6 +21,7 @@ import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Icon
import android.media.MediaRoute2Info
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
@@ -38,9 +39,9 @@ import javax.inject.Inject
*/
@SysUISingleton
class MediaTttChipControllerSender @Inject constructor(
commandQueue: CommandQueue,
context: Context,
windowManager: WindowManager,
private val commandQueue: CommandQueue
) : MediaTttChipControllerCommon<ChipStateSender>(
context, windowManager, R.layout.media_ttt_chip
) {
@@ -50,25 +51,80 @@ class MediaTttChipControllerSender @Inject constructor(
it.setTint(Color.YELLOW)
}
private val commandQueueCallback = object : CommandQueue.Callbacks {
private val commandQueueCallbacks = object : CommandQueue.Callbacks {
override fun updateMediaTapToTransferSenderDisplay(
@StatusBarManager.MediaTransferSenderState displayState: Int,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?
) {
// TODO(b/216318437): Trigger displayChip with the right state based on displayState.
displayChip(
MoveCloserToStartCast(
// TODO(b/217418566): This app icon content description is incorrect --
// routeInfo.name is the name of the device, not the name of the app.
fakeAppIconDrawable, routeInfo.name.toString(), routeInfo.name.toString()
)
this@MediaTttChipControllerSender.updateMediaTapToTransferSenderDisplay(
displayState, routeInfo, undoCallback
)
}
}
init {
commandQueue.addCallback(commandQueueCallback)
commandQueue.addCallback(commandQueueCallbacks)
}
private fun updateMediaTapToTransferSenderDisplay(
@StatusBarManager.MediaTransferSenderState displayState: Int,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?
) {
// TODO(b/217418566): This app icon content description is incorrect --
// routeInfo.name is the name of the device, not the name of the app.
val appIconContentDescription = routeInfo.name.toString()
val otherDeviceName = routeInfo.name.toString()
val chipState = when(displayState) {
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST ->
AlmostCloseToStartCast(
fakeAppIconDrawable, appIconContentDescription, otherDeviceName
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST ->
AlmostCloseToEndCast(
fakeAppIconDrawable, appIconContentDescription, otherDeviceName
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED ->
TransferToReceiverTriggered(
fakeAppIconDrawable, appIconContentDescription, otherDeviceName
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED ->
TransferToThisDeviceTriggered(
fakeAppIconDrawable, appIconContentDescription
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED ->
TransferToReceiverSucceeded(
fakeAppIconDrawable,
appIconContentDescription,
otherDeviceName,
undoCallback
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED ->
TransferToThisDeviceSucceeded(
fakeAppIconDrawable,
appIconContentDescription,
otherDeviceName,
undoCallback
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED ->
TransferFailed(
fakeAppIconDrawable, appIconContentDescription
)
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER -> {
removeChip()
null
}
else -> {
Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState")
null
}
}
chipState?.let {
displayChip(it)
}
}
/** Displays the chip view for the given state. */
@@ -97,3 +153,5 @@ class MediaTttChipControllerSender @Inject constructor(
if (showFailure) { View.VISIBLE } else { View.GONE }
}
}
const val SENDER_TAG = "MediaTapToTransferSender"

View File

@@ -16,24 +16,35 @@
package com.android.systemui.media.taptotransfer
import android.content.ComponentName
import android.app.StatusBarManager
import android.content.Context
import android.media.MediaRoute2Info
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.media.taptotransfer.receiver.ChipStateReceiver
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver
import com.android.systemui.media.taptotransfer.sender.AlmostCloseToEndCast
import com.android.systemui.media.taptotransfer.sender.AlmostCloseToStartCast
import com.android.systemui.media.taptotransfer.sender.TransferFailed
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverTriggered
import com.android.systemui.media.taptotransfer.sender.TransferToThisDeviceSucceeded
import com.android.systemui.media.taptotransfer.sender.TransferToThisDeviceTriggered
import com.android.systemui.media.taptotransfer.sender.TransferToReceiverSucceeded
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.mockito.eq
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.anyString
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
import java.io.PrintWriter
import java.io.StringWriter
@@ -49,16 +60,20 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
private lateinit var mediaTttCommandLineHelper: MediaTttCommandLineHelper
@Mock
private lateinit var statusBarManager: StatusBarManager
@Mock
private lateinit var mediaTttChipControllerReceiver: MediaTttChipControllerReceiver
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
context.addMockSystemService(Context.STATUS_BAR_SERVICE, statusBarManager)
mediaTttCommandLineHelper =
MediaTttCommandLineHelper(
commandRegistry,
context,
FakeExecutor(FakeSystemClock()),
mediaTttChipControllerReceiver,
)
}
@@ -88,91 +103,116 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
) { EmptyCommand() }
}
/* TODO(b/216318437): Revive these tests using the new SystemApis.
@Test
fun sender_moveCloserToStartCast_serviceCallbackCalled() {
commandRegistry.onShellCommand(pw, getMoveCloserToStartCastCommand())
fun sender_almostCloseToStartCast_serviceCallbackCalled() {
commandRegistry.onShellCommand(
pw, getSenderCommand(AlmostCloseToStartCast::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService).closeToReceiverToStartCast(any(), capture(deviceInfoCaptor))
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
val routeInfoCaptor = argumentCaptor<MediaRoute2Info>()
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST),
capture(routeInfoCaptor),
nullable(),
nullable())
assertThat(routeInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
fun sender_moveCloserToEndCast_serviceCallbackCalled() {
commandRegistry.onShellCommand(pw, getMoveCloserToEndCastCommand())
fun sender_almostCloseToEndCast_serviceCallbackCalled() {
commandRegistry.onShellCommand(
pw, getSenderCommand(AlmostCloseToEndCast::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService).closeToReceiverToEndCast(any(), capture(deviceInfoCaptor))
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
val routeInfoCaptor = argumentCaptor<MediaRoute2Info>()
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST),
capture(routeInfoCaptor),
nullable(),
nullable())
assertThat(routeInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
fun sender_transferToReceiverTriggered_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferToReceiverTriggeredCommand())
commandRegistry.onShellCommand(
pw, getSenderCommand(TransferToReceiverTriggered::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService).transferToReceiverTriggered(any(), capture(deviceInfoCaptor))
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
val routeInfoCaptor = argumentCaptor<MediaRoute2Info>()
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED),
capture(routeInfoCaptor),
nullable(),
nullable())
assertThat(routeInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
fun sender_transferToThisDeviceTriggered_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferToThisDeviceTriggeredCommand())
commandRegistry.onShellCommand(
pw, getSenderCommand(TransferToThisDeviceTriggered::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
verify(mediaSenderService).transferToThisDeviceTriggered(any(), any())
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED),
any(),
nullable(),
nullable())
}
@Test
fun sender_transferToReceiverSucceeded_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferToReceiverSucceededCommand())
commandRegistry.onShellCommand(
pw, getSenderCommand(TransferToReceiverSucceeded::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService)
.transferToReceiverSucceeded(any(), capture(deviceInfoCaptor), any())
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
val routeInfoCaptor = argumentCaptor<MediaRoute2Info>()
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED),
capture(routeInfoCaptor),
nullable(),
nullable())
assertThat(routeInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
fun sender_transferToThisDeviceSucceeded_chipDisplayWithCorrectState() {
commandRegistry.onShellCommand(pw, getTransferToThisDeviceSucceededCommand())
commandRegistry.onShellCommand(
pw, getSenderCommand(TransferToThisDeviceSucceeded::class.simpleName!!)
)
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
val deviceInfoCaptor = argumentCaptor<DeviceInfo>()
verify(mediaSenderService)
.transferToThisDeviceSucceeded(any(), capture(deviceInfoCaptor), any())
assertThat(deviceInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
val routeInfoCaptor = argumentCaptor<MediaRoute2Info>()
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED),
capture(routeInfoCaptor),
nullable(),
nullable())
assertThat(routeInfoCaptor.value!!.name).isEqualTo(DEVICE_NAME)
}
@Test
fun sender_transferFailed_serviceCallbackCalled() {
commandRegistry.onShellCommand(pw, getTransferFailedCommand())
commandRegistry.onShellCommand(pw, getSenderCommand(TransferFailed::class.simpleName!!))
assertThat(context.isBound(mediaSenderServiceComponentName)).isTrue()
verify(mediaSenderService).transferFailed(any(), any())
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED),
any(),
nullable(),
nullable())
}
@Test
fun sender_noLongerCloseToReceiver_serviceCallbackCalledAndServiceUnbound() {
commandRegistry.onShellCommand(pw, getNoLongerCloseToReceiverCommand())
fun sender_farFromReceiver_serviceCallbackCalled() {
commandRegistry.onShellCommand(pw, getSenderCommand(FAR_FROM_RECEIVER_STATE))
// Once we're no longer close to the receiver, we should unbind the service.
assertThat(context.isBound(mediaSenderServiceComponentName)).isFalse()
verify(mediaSenderService).noLongerCloseToReceiver(any(), any())
verify(statusBarManager).updateMediaTapToTransferSenderDisplay(
eq(StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER),
any(),
nullable(),
nullable())
}
*/
@Test
fun receiver_addCommand_chipAdded() {
commandRegistry.onShellCommand(pw, arrayOf(ADD_CHIP_COMMAND_RECEIVER_TAG))
@@ -187,61 +227,8 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
verify(mediaTttChipControllerReceiver).removeChip()
}
private fun getMoveCloserToStartCastCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
MOVE_CLOSER_TO_START_CAST_COMMAND_NAME
)
private fun getMoveCloserToEndCastCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
MOVE_CLOSER_TO_END_CAST_COMMAND_NAME
)
private fun getTransferToReceiverTriggeredCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
TRANSFER_TO_RECEIVER_TRIGGERED_COMMAND_NAME
)
private fun getTransferToThisDeviceTriggeredCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
TRANSFER_TO_THIS_DEVICE_TRIGGERED_COMMAND_NAME
)
private fun getTransferToReceiverSucceededCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
TRANSFER_TO_RECEIVER_SUCCEEDED_COMMAND_NAME
)
private fun getTransferToThisDeviceSucceededCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
TRANSFER_TO_THIS_DEVICE_SUCCEEDED_COMMAND_NAME
)
private fun getTransferFailedCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
TRANSFER_FAILED_COMMAND_NAME
)
private fun getNoLongerCloseToReceiverCommand(): Array<String> =
arrayOf(
SENDER_COMMAND,
DEVICE_NAME,
NO_LONGER_CLOSE_TO_RECEIVER_COMMAND_NAME
)
private fun getSenderCommand(displayState: String): Array<String> =
arrayOf(SENDER_COMMAND, DEVICE_NAME, displayState)
class EmptyCommand : Command {
override fun execute(pw: PrintWriter, args: List<String>) {

View File

@@ -16,8 +16,10 @@
package com.android.systemui.media.taptotransfer.sender
import android.app.StatusBarManager
import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.media.MediaRoute2Info
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
@@ -35,6 +37,7 @@ import org.junit.Ignore
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -49,17 +52,148 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
private lateinit var windowManager: WindowManager
@Mock
private lateinit var commandQueue: CommandQueue
private lateinit var commandQueueCallback: CommandQueue.Callbacks
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
appIconDrawable = Icon.createWithResource(context, R.drawable.ic_cake).loadDrawable(context)
controllerSender = MediaTttChipControllerSender(context, windowManager, commandQueue)
controllerSender = MediaTttChipControllerSender(commandQueue, context, windowManager)
val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
verify(commandQueue).addCallback(callbackCaptor.capture())
commandQueueCallback = callbackCaptor.value!!
}
@Test
fun moveCloserToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = moveCloserToStartCast()
fun commandQueueCallback_almostCloseToStartCast_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(almostCloseToStartCast().getChipTextString(context))
}
@Test
fun commandQueueCallback_almostCloseToEndCast_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(almostCloseToEndCast().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToReceiverTriggered_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferToReceiverTriggered().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToThisDeviceTriggered_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferToThisDeviceTriggered().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToReceiverSucceeded_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferToReceiverSucceeded().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToThisDeviceSucceeded_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferToThisDeviceSucceeded().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToReceiverFailed_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferFailed().getChipTextString(context))
}
@Test
fun commandQueueCallback_transferToThisDeviceFailed_triggersCorrectChip() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
routeInfo,
null
)
assertThat(getChipView().getChipText())
.isEqualTo(transferFailed().getChipTextString(context))
}
@Test
fun commandQueueCallback_farFromReceiver_noChipShown() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
routeInfo,
null
)
verify(windowManager, never()).addView(any(), any())
}
@Test
fun commandQueueCallback_almostCloseThenFarFromReceiver_chipShownThenHidden() {
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
routeInfo,
null
)
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
routeInfo,
null
)
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
verify(windowManager).removeView(viewCaptor.value)
}
@Test
fun almostCloseToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = almostCloseToStartCast()
controllerSender.displayChip(state)
val chipView = getChipView()
@@ -72,8 +206,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun moveCloserToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = moveCloserToEndCast()
fun almostCloseToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
val state = almostCloseToEndCast()
controllerSender.displayChip(state)
val chipView = getChipView()
@@ -250,8 +384,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun changeFromCloserToStartToTransferTriggered_loadingIconAppears() {
controllerSender.displayChip(moveCloserToStartCast())
fun changeFromAlmostCloseToStartToTransferTriggered_loadingIconAppears() {
controllerSender.displayChip(almostCloseToStartCast())
controllerSender.displayChip(transferToReceiverTriggered())
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
@@ -280,9 +414,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
fun changeFromTransferSucceededToMoveCloserToStart_undoButtonDisappears() {
fun changeFromTransferSucceededToAlmostCloseToStart_undoButtonDisappears() {
controllerSender.displayChip(transferToReceiverSucceeded())
controllerSender.displayChip(moveCloserToStartCast())
controllerSender.displayChip(almostCloseToStartCast())
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE)
}
@@ -314,12 +448,12 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
/** Helper method providing default parameters to not clutter up the tests. */
private fun moveCloserToStartCast() =
MoveCloserToStartCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
private fun almostCloseToStartCast() =
AlmostCloseToStartCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun moveCloserToEndCast() =
MoveCloserToEndCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
private fun almostCloseToEndCast() =
AlmostCloseToEndCast(appIconDrawable, APP_ICON_CONTENT_DESC, DEVICE_NAME)
/** Helper method providing default parameters to not clutter up the tests. */
private fun transferToReceiverTriggered() =
@@ -347,3 +481,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
private const val DEVICE_NAME = "My Tablet"
private const val APP_ICON_CONTENT_DESC = "Content description"
private val routeInfo = MediaRoute2Info.Builder("id", "Test Name")
.addFeature("feature")
.build()