Merge "[Media TTT] Update the receiver view controller and the command line helper to handle the receiver @SystemApi states."
This commit is contained in:
committed by
Android (Google) Code Review
commit
4a88d27a9a
@@ -115,12 +115,14 @@ public interface MediaModule {
|
||||
@SysUISingleton
|
||||
static Optional<MediaTttChipControllerReceiver> providesMediaTttChipControllerReceiver(
|
||||
MediaTttFlags mediaTttFlags,
|
||||
CommandQueue commandQueue,
|
||||
Context context,
|
||||
WindowManager windowManager) {
|
||||
if (!mediaTttFlags.isMediaTttEnabled()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new MediaTttChipControllerReceiver(context, windowManager));
|
||||
return Optional.of(
|
||||
new MediaTttChipControllerReceiver(commandQueue, context, windowManager));
|
||||
}
|
||||
|
||||
/** */
|
||||
@@ -130,17 +132,12 @@ public interface MediaModule {
|
||||
MediaTttFlags mediaTttFlags,
|
||||
CommandRegistry commandRegistry,
|
||||
Context context,
|
||||
@Main Executor mainExecutor,
|
||||
MediaTttChipControllerReceiver mediaTttChipControllerReceiver) {
|
||||
@Main Executor mainExecutor) {
|
||||
if (!mediaTttFlags.isMediaTttEnabled()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(
|
||||
new MediaTttCommandLineHelper(
|
||||
commandRegistry,
|
||||
context,
|
||||
mainExecutor,
|
||||
mediaTttChipControllerReceiver));
|
||||
new MediaTttCommandLineHelper(commandRegistry, context, mainExecutor));
|
||||
}
|
||||
|
||||
/** Inject into NearbyMediaDevicesService. */
|
||||
|
||||
@@ -18,16 +18,11 @@ package com.android.systemui.media.taptotransfer
|
||||
|
||||
import android.app.StatusBarManager
|
||||
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.AlmostCloseToEndCast
|
||||
import com.android.systemui.media.taptotransfer.sender.AlmostCloseToStartCast
|
||||
import com.android.systemui.media.taptotransfer.sender.TransferFailed
|
||||
@@ -49,14 +44,8 @@ import javax.inject.Inject
|
||||
class MediaTttCommandLineHelper @Inject constructor(
|
||||
commandRegistry: CommandRegistry,
|
||||
private val context: Context,
|
||||
@Main private val mainExecutor: Executor,
|
||||
private val mediaTttChipControllerReceiver: MediaTttChipControllerReceiver,
|
||||
@Main private val mainExecutor: Executor
|
||||
) {
|
||||
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.
|
||||
*/
|
||||
@@ -81,10 +70,7 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
|
||||
init {
|
||||
commandRegistry.registerCommand(SENDER_COMMAND) { SenderCommand() }
|
||||
commandRegistry.registerCommand(
|
||||
ADD_CHIP_COMMAND_RECEIVER_TAG) { AddChipCommandReceiver() }
|
||||
commandRegistry.registerCommand(
|
||||
REMOVE_CHIP_COMMAND_RECEIVER_TAG) { RemoveChipCommandReceiver() }
|
||||
commandRegistry.registerCommand(RECEIVER_COMMAND) { ReceiverCommand() }
|
||||
}
|
||||
|
||||
/** All commands for the sender device. */
|
||||
@@ -94,10 +80,11 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
.addFeature("feature")
|
||||
.build()
|
||||
|
||||
val commandName = args[1]
|
||||
@StatusBarManager.MediaTransferSenderState
|
||||
val displayState = stateStringToStateInt[args[1]]
|
||||
val displayState = stateStringToStateInt[commandName]
|
||||
if (displayState == null) {
|
||||
pw.println("Invalid command name")
|
||||
pw.println("Invalid command name $commandName")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -145,27 +132,29 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
/** All commands for the receiver device. */
|
||||
inner class ReceiverCommand : Command {
|
||||
override fun execute(pw: PrintWriter, args: List<String>) {
|
||||
mediaTttChipControllerReceiver.displayChip(
|
||||
ChipStateReceiver(appIconDrawable, APP_ICON_CONTENT_DESCRIPTION)
|
||||
)
|
||||
val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)
|
||||
as StatusBarManager
|
||||
when(val commandName = args[0]) {
|
||||
CLOSE_TO_SENDER_STATE ->
|
||||
statusBarManager.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
FAR_FROM_SENDER_STATE ->
|
||||
statusBarManager.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
else ->
|
||||
pw.println("Invalid command name $commandName")
|
||||
}
|
||||
}
|
||||
override fun help(pw: PrintWriter) {
|
||||
pw.println("Usage: adb shell cmd statusbar $ADD_CHIP_COMMAND_RECEIVER_TAG")
|
||||
}
|
||||
}
|
||||
|
||||
/** A command to REMOVE the media ttt chip on the RECEIVER device. */
|
||||
inner class RemoveChipCommandReceiver : Command {
|
||||
override fun execute(pw: PrintWriter, args: List<String>) {
|
||||
mediaTttChipControllerReceiver.removeChip()
|
||||
}
|
||||
override fun help(pw: PrintWriter) {
|
||||
pw.println("Usage: adb shell cmd statusbar $REMOVE_CHIP_COMMAND_RECEIVER_TAG")
|
||||
pw.println("Usage: adb shell cmd statusbar $RECEIVER_COMMAND <chipState>")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,13 +162,13 @@ class MediaTttCommandLineHelper @Inject constructor(
|
||||
@VisibleForTesting
|
||||
const val SENDER_COMMAND = "media-ttt-chip-sender"
|
||||
@VisibleForTesting
|
||||
const val ADD_CHIP_COMMAND_RECEIVER_TAG = "media-ttt-chip-add-receiver"
|
||||
const val RECEIVER_COMMAND = "media-ttt-chip-receiver"
|
||||
@VisibleForTesting
|
||||
const val REMOVE_CHIP_COMMAND_RECEIVER_TAG = "media-ttt-chip-remove-receiver"
|
||||
const val FAR_FROM_RECEIVER_STATE = "FarFromReceiver"
|
||||
@VisibleForTesting
|
||||
val FAR_FROM_RECEIVER_STATE = "FarFromReceiver"
|
||||
|
||||
private const val APP_ICON_CONTENT_DESCRIPTION = "Fake media app icon"
|
||||
const val CLOSE_TO_SENDER_STATE = "CloseToSender"
|
||||
@VisibleForTesting
|
||||
const val FAR_FROM_SENDER_STATE = "FarFromSender"
|
||||
private const val CLI_TAG = "MediaTransferCli"
|
||||
|
||||
private val routeInfo = MediaRoute2Info.Builder("id", "Test Name")
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.android.systemui.media.taptotransfer.receiver
|
||||
|
||||
import android.app.StatusBarManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Icon
|
||||
import android.media.MediaRoute2Info
|
||||
import android.util.Log
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
|
||||
import com.android.systemui.statusbar.CommandQueue
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -31,13 +37,49 @@ import javax.inject.Inject
|
||||
*/
|
||||
@SysUISingleton
|
||||
class MediaTttChipControllerReceiver @Inject constructor(
|
||||
commandQueue: CommandQueue,
|
||||
context: Context,
|
||||
windowManager: WindowManager,
|
||||
) : MediaTttChipControllerCommon<ChipStateReceiver>(
|
||||
context, windowManager, R.layout.media_ttt_chip_receiver
|
||||
) {
|
||||
// TODO(b/216141279): Use app icon from media route info instead of this fake one.
|
||||
private val fakeAppIconDrawable =
|
||||
Icon.createWithResource(context, R.drawable.ic_avatar_user).loadDrawable(context).also {
|
||||
it.setTint(Color.YELLOW)
|
||||
}
|
||||
|
||||
private val commandQueueCallbacks = object : CommandQueue.Callbacks {
|
||||
override fun updateMediaTapToTransferReceiverDisplay(
|
||||
@StatusBarManager.MediaTransferReceiverState displayState: Int,
|
||||
routeInfo: MediaRoute2Info
|
||||
) {
|
||||
this@MediaTttChipControllerReceiver.updateMediaTapToTransferReceiverDisplay(
|
||||
displayState, routeInfo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
commandQueue.addCallback(commandQueueCallbacks)
|
||||
}
|
||||
|
||||
private fun updateMediaTapToTransferReceiverDisplay(
|
||||
@StatusBarManager.MediaTransferReceiverState displayState: Int,
|
||||
routeInfo: MediaRoute2Info
|
||||
) {
|
||||
when(displayState) {
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER ->
|
||||
displayChip(ChipStateReceiver(fakeAppIconDrawable, routeInfo.name.toString()))
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER -> removeChip()
|
||||
else ->
|
||||
Log.e(RECEIVER_TAG, "Unhandled MediaTransferReceiverState $displayState")
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateChipView(chipState: ChipStateReceiver, currentChipView: ViewGroup) {
|
||||
setIcon(chipState, currentChipView)
|
||||
}
|
||||
}
|
||||
|
||||
private const val RECEIVER_TAG = "MediaTapToTransferReceiver"
|
||||
|
||||
@@ -21,8 +21,6 @@ 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
|
||||
@@ -62,8 +60,6 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
private lateinit var statusBarManager: StatusBarManager
|
||||
@Mock
|
||||
private lateinit var mediaTttChipControllerReceiver: MediaTttChipControllerReceiver
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@@ -74,7 +70,6 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
commandRegistry,
|
||||
context,
|
||||
FakeExecutor(FakeSystemClock()),
|
||||
mediaTttChipControllerReceiver,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -86,21 +81,10 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun constructor_addReceiverCommandAlreadyRegistered() {
|
||||
// Since creating the chip controller should automatically register the add command, it
|
||||
fun constructor_receiverCommandAlreadyRegistered() {
|
||||
// Since creating the chip controller should automatically register the receiver command, it
|
||||
// should throw when registering it again.
|
||||
commandRegistry.registerCommand(
|
||||
ADD_CHIP_COMMAND_RECEIVER_TAG
|
||||
) { EmptyCommand() }
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun constructor_removeReceiverCommandAlreadyRegistered() {
|
||||
// Since creating the chip controller should automatically register the remove command, it
|
||||
// should throw when registering it again.
|
||||
commandRegistry.registerCommand(
|
||||
REMOVE_CHIP_COMMAND_RECEIVER_TAG
|
||||
) { EmptyCommand() }
|
||||
commandRegistry.registerCommand(RECEIVER_COMMAND) { EmptyCommand() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -214,22 +198,31 @@ class MediaTttCommandLineHelperTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiver_addCommand_chipAdded() {
|
||||
commandRegistry.onShellCommand(pw, arrayOf(ADD_CHIP_COMMAND_RECEIVER_TAG))
|
||||
fun receiver_closeToSender_serviceCallbackCalled() {
|
||||
commandRegistry.onShellCommand(pw, getReceiverCommand(CLOSE_TO_SENDER_STATE))
|
||||
|
||||
verify(mediaTttChipControllerReceiver).displayChip(any(ChipStateReceiver::class.java))
|
||||
verify(statusBarManager).updateMediaTapToTransferReceiverDisplay(
|
||||
eq(StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER),
|
||||
any()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun receiver_removeCommand_chipRemoved() {
|
||||
commandRegistry.onShellCommand(pw, arrayOf(REMOVE_CHIP_COMMAND_RECEIVER_TAG))
|
||||
fun receiver_farFromSender_serviceCallbackCalled() {
|
||||
commandRegistry.onShellCommand(pw, getReceiverCommand(FAR_FROM_SENDER_STATE))
|
||||
|
||||
verify(mediaTttChipControllerReceiver).removeChip()
|
||||
verify(statusBarManager).updateMediaTapToTransferReceiverDisplay(
|
||||
eq(StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER),
|
||||
any()
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSenderCommand(displayState: String): Array<String> =
|
||||
arrayOf(SENDER_COMMAND, DEVICE_NAME, displayState)
|
||||
|
||||
private fun getReceiverCommand(displayState: String): Array<String> =
|
||||
arrayOf(RECEIVER_COMMAND, displayState)
|
||||
|
||||
class EmptyCommand : Command {
|
||||
override fun execute(pw: PrintWriter, args: List<String>) {
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.systemui.media.taptotransfer.receiver
|
||||
|
||||
import android.app.StatusBarManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.media.MediaRoute2Info
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
@@ -24,6 +26,7 @@ import android.widget.ImageView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.CommandQueue
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
@@ -31,7 +34,8 @@ import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@@ -41,11 +45,55 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
private lateinit var windowManager: WindowManager
|
||||
@Mock
|
||||
private lateinit var commandQueue: CommandQueue
|
||||
private lateinit var commandQueueCallback: CommandQueue.Callbacks
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
controllerReceiver = MediaTttChipControllerReceiver(context, windowManager)
|
||||
controllerReceiver = MediaTttChipControllerReceiver(commandQueue, context, windowManager)
|
||||
|
||||
val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
|
||||
verify(commandQueue).addCallback(callbackCaptor.capture())
|
||||
commandQueueCallback = callbackCaptor.value!!
|
||||
}
|
||||
|
||||
@Test
|
||||
fun commandQueueCallback_closeToSender_triggersChip() {
|
||||
commandQueueCallback.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
|
||||
assertThat(getChipView().getAppIconView().contentDescription).isEqualTo(ROUTE_NAME)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun commandQueueCallback_farFromSender_noChipShown() {
|
||||
commandQueueCallback.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
|
||||
verify(windowManager, never()).addView(any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun commandQueueCallback_closeThenFar_chipShownThenHidden() {
|
||||
commandQueueCallback.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
|
||||
commandQueueCallback.updateMediaTapToTransferReceiverDisplay(
|
||||
StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER,
|
||||
routeInfo
|
||||
)
|
||||
|
||||
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
|
||||
verify(windowManager).addView(viewCaptor.capture(), any())
|
||||
verify(windowManager).removeView(viewCaptor.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,9 +109,14 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
|
||||
private fun getChipView(): ViewGroup {
|
||||
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
|
||||
Mockito.verify(windowManager).addView(viewCaptor.capture(), any())
|
||||
verify(windowManager).addView(viewCaptor.capture(), any())
|
||||
return viewCaptor.value as ViewGroup
|
||||
}
|
||||
|
||||
private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
|
||||
}
|
||||
|
||||
private const val ROUTE_NAME = "Test name"
|
||||
private val routeInfo = MediaRoute2Info.Builder("id", ROUTE_NAME)
|
||||
.addFeature("feature")
|
||||
.build()
|
||||
|
||||
Reference in New Issue
Block a user