Merge "[Chipbar] Have MediaTttSenderCoordinator be responsible for not hiding in certain cases." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
668aee06a1
@@ -47,6 +47,8 @@ constructor(
|
|||||||
private val uiEventLogger: MediaTttSenderUiEventLogger,
|
private val uiEventLogger: MediaTttSenderUiEventLogger,
|
||||||
) : CoreStartable {
|
) : CoreStartable {
|
||||||
|
|
||||||
|
private var displayedState: ChipStateSender? = null
|
||||||
|
|
||||||
private val commandQueueCallbacks =
|
private val commandQueueCallbacks =
|
||||||
object : CommandQueue.Callbacks {
|
object : CommandQueue.Callbacks {
|
||||||
override fun updateMediaTapToTransferSenderDisplay(
|
override fun updateMediaTapToTransferSenderDisplay(
|
||||||
@@ -84,8 +86,27 @@ constructor(
|
|||||||
uiEventLogger.logSenderStateChange(chipState)
|
uiEventLogger.logSenderStateChange(chipState)
|
||||||
|
|
||||||
if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
|
if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
|
||||||
chipbarCoordinator.removeView(removalReason = ChipStateSender.FAR_FROM_RECEIVER.name)
|
// Return early if we're not displaying a chip anyway
|
||||||
|
val currentDisplayedState = displayedState ?: return
|
||||||
|
|
||||||
|
val removalReason = ChipStateSender.FAR_FROM_RECEIVER.name
|
||||||
|
if (
|
||||||
|
currentDisplayedState.transferStatus == TransferStatus.IN_PROGRESS ||
|
||||||
|
currentDisplayedState.transferStatus == TransferStatus.SUCCEEDED
|
||||||
|
) {
|
||||||
|
// Don't remove the chip if we're in progress or succeeded, since the user should
|
||||||
|
// still be able to see the status of the transfer.
|
||||||
|
logger.logRemovalBypass(
|
||||||
|
removalReason,
|
||||||
|
bypassReason = "transferStatus=${currentDisplayedState.transferStatus.name}"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
displayedState = null
|
||||||
|
chipbarCoordinator.removeView(removalReason)
|
||||||
} else {
|
} else {
|
||||||
|
displayedState = chipState
|
||||||
chipbarCoordinator.displayView(ChipSenderInfo(chipState, routeInfo, undoCallback))
|
chipbarCoordinator.displayView(ChipSenderInfo(chipState, routeInfo, undoCallback))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
|
|||||||
)
|
)
|
||||||
cancelViewTimeout?.run()
|
cancelViewTimeout?.run()
|
||||||
cancelViewTimeout = mainExecutor.executeDelayed(
|
cancelViewTimeout = mainExecutor.executeDelayed(
|
||||||
{ removeView(TemporaryDisplayRemovalReason.REASON_TIMEOUT) },
|
{ removeView(REMOVAL_REASON_TIMEOUT) },
|
||||||
timeout.toLong()
|
timeout.toLong()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -175,9 +175,6 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
|
|||||||
*/
|
*/
|
||||||
fun removeView(removalReason: String) {
|
fun removeView(removalReason: String) {
|
||||||
val currentDisplayInfo = displayInfo ?: return
|
val currentDisplayInfo = displayInfo ?: return
|
||||||
if (shouldIgnoreViewRemoval(currentDisplayInfo.info, removalReason)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentView = currentDisplayInfo.view
|
val currentView = currentDisplayInfo.view
|
||||||
animateViewOut(currentView) { windowManager.removeView(currentView) }
|
animateViewOut(currentView) { windowManager.removeView(currentView) }
|
||||||
@@ -192,13 +189,6 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
|
|||||||
cancelViewTimeout?.run()
|
cancelViewTimeout?.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a view removal request should be ignored and false otherwise.
|
|
||||||
*
|
|
||||||
* Allows subclasses to keep the view visible for longer in certain circumstances.
|
|
||||||
*/
|
|
||||||
open fun shouldIgnoreViewRemoval(info: T, removalReason: String): Boolean = false
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method implemented by subclasses to update [currentView] based on [newInfo].
|
* A method implemented by subclasses to update [currentView] based on [newInfo].
|
||||||
*/
|
*/
|
||||||
@@ -236,10 +226,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object TemporaryDisplayRemovalReason {
|
private const val REMOVAL_REASON_TIMEOUT = "TIMEOUT"
|
||||||
const val REASON_TIMEOUT = "TIMEOUT"
|
|
||||||
const val REASON_SCREEN_TAP = "SCREEN_TAP"
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class IconInfo(
|
private data class IconInfo(
|
||||||
val iconName: String,
|
val iconName: String,
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import com.android.systemui.media.taptotransfer.sender.MediaTttSenderUiEventLogg
|
|||||||
import com.android.systemui.media.taptotransfer.sender.TransferStatus
|
import com.android.systemui.media.taptotransfer.sender.TransferStatus
|
||||||
import com.android.systemui.plugins.FalsingManager
|
import com.android.systemui.plugins.FalsingManager
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason
|
|
||||||
import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
|
import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
|
||||||
import com.android.systemui.temporarydisplay.TemporaryViewInfo
|
import com.android.systemui.temporarydisplay.TemporaryViewInfo
|
||||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||||
@@ -185,23 +184,6 @@ open class ChipbarCoordinator @Inject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldIgnoreViewRemoval(info: ChipSenderInfo, removalReason: String): Boolean {
|
|
||||||
// Don't remove the chip if we're in progress or succeeded, since the user should still be
|
|
||||||
// able to see the status of the transfer. (But do remove it if it's finally timed out.)
|
|
||||||
val transferStatus = info.state.transferStatus
|
|
||||||
if (
|
|
||||||
(transferStatus == TransferStatus.IN_PROGRESS ||
|
|
||||||
transferStatus == TransferStatus.SUCCEEDED) &&
|
|
||||||
removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT
|
|
||||||
) {
|
|
||||||
logger.logRemovalBypass(
|
|
||||||
removalReason, bypassReason = "transferStatus=${transferStatus.name}"
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTouchableRegion(view: View, outRect: Rect) {
|
override fun getTouchableRegion(view: View, outRect: Rect) {
|
||||||
viewUtil.setRectToViewWindowLocation(view, outRect)
|
viewUtil.setRectToViewWindowLocation(view, outRect)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(true)
|
whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(true)
|
||||||
whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenReturn(1000)
|
whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenReturn(TIMEOUT)
|
||||||
|
|
||||||
fakeClock = FakeSystemClock()
|
fakeClock = FakeSystemClock()
|
||||||
fakeExecutor = FakeExecutor(fakeClock)
|
fakeExecutor = FakeExecutor(fakeClock)
|
||||||
@@ -316,7 +316,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transferToReceiverTriggeredThenFarFromReceiver_viewStillDisplayed() {
|
fun transferToReceiverTriggeredThenFarFromReceiver_viewStillDisplayedButStillTimesOut() {
|
||||||
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
||||||
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
|
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
|
||||||
routeInfo,
|
routeInfo,
|
||||||
@@ -332,10 +332,14 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
verify(windowManager, never()).removeView(any())
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
verify(logger).logRemovalBypass(any(), any())
|
||||||
|
|
||||||
|
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||||
|
|
||||||
|
verify(windowManager).removeView(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transferToThisDeviceTriggeredThenFarFromReceiver_viewStillDisplayed() {
|
fun transferToThisDeviceTriggeredThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
|
||||||
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
||||||
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
|
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
|
||||||
routeInfo,
|
routeInfo,
|
||||||
@@ -351,10 +355,14 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
verify(windowManager, never()).removeView(any())
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
verify(logger).logRemovalBypass(any(), any())
|
||||||
|
|
||||||
|
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||||
|
|
||||||
|
verify(windowManager).removeView(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayed() {
|
fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
|
||||||
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
||||||
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
|
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
|
||||||
routeInfo,
|
routeInfo,
|
||||||
@@ -370,10 +378,14 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
verify(windowManager, never()).removeView(any())
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
verify(logger).logRemovalBypass(any(), any())
|
||||||
|
|
||||||
|
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||||
|
|
||||||
|
verify(windowManager).removeView(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayed() {
|
fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayedButDoesTimeOut() {
|
||||||
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
commandQueueCallback.updateMediaTapToTransferSenderDisplay(
|
||||||
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
|
StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
|
||||||
routeInfo,
|
routeInfo,
|
||||||
@@ -389,6 +401,10 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
verify(windowManager, never()).removeView(any())
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
verify(logger).logRemovalBypass(any(), any())
|
||||||
|
|
||||||
|
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||||
|
|
||||||
|
verify(windowManager).removeView(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getChipView(): ViewGroup {
|
private fun getChipView(): ViewGroup {
|
||||||
@@ -434,6 +450,7 @@ class MediaTttSenderCoordinatorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private const val OTHER_DEVICE_NAME = "My Tablet"
|
private const val OTHER_DEVICE_NAME = "My Tablet"
|
||||||
|
private const val TIMEOUT = 10000
|
||||||
|
|
||||||
private val routeInfo =
|
private val routeInfo =
|
||||||
MediaRoute2Info.Builder("id", OTHER_DEVICE_NAME)
|
MediaRoute2Info.Builder("id", OTHER_DEVICE_NAME)
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var powerManager: PowerManager
|
private lateinit var powerManager: PowerManager
|
||||||
|
|
||||||
private var shouldIgnoreViewRemoval: Boolean = false
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
@@ -209,26 +207,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
|
|||||||
verify(windowManager, never()).removeView(any())
|
verify(windowManager, never()).removeView(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun removeView_shouldIgnoreRemovalFalse_viewRemoved() {
|
|
||||||
shouldIgnoreViewRemoval = false
|
|
||||||
underTest.displayView(getState())
|
|
||||||
|
|
||||||
underTest.removeView("reason")
|
|
||||||
|
|
||||||
verify(windowManager).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun removeView_shouldIgnoreRemovalTrue_viewNotRemoved() {
|
|
||||||
shouldIgnoreViewRemoval = true
|
|
||||||
underTest.displayView(getState())
|
|
||||||
|
|
||||||
underTest.removeView("reason")
|
|
||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getState(name: String = "name") = ViewInfo(name)
|
private fun getState(name: String = "name") = ViewInfo(name)
|
||||||
|
|
||||||
private fun getConfigurationListener(): ConfigurationListener {
|
private fun getConfigurationListener(): ConfigurationListener {
|
||||||
@@ -267,10 +245,6 @@ class TemporaryViewDisplayControllerTest : SysuiTestCase() {
|
|||||||
mostRecentViewInfo = newInfo
|
mostRecentViewInfo = newInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldIgnoreViewRemoval(info: ViewInfo, removalReason: String): Boolean {
|
|
||||||
return shouldIgnoreViewRemoval
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTouchableRegion(view: View, outRect: Rect) {
|
override fun getTouchableRegion(view: View, outRect: Rect) {
|
||||||
outRect.setEmpty()
|
outRect.setEmpty()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -434,92 +434,6 @@ class ChipbarCoordinatorTest : SysuiTestCase() {
|
|||||||
assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
|
assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToReceiverTriggeredThenRemoveView_viewStillDisplayed() {
|
|
||||||
underTest.displayView(transferToReceiverTriggered())
|
|
||||||
fakeClock.advanceTime(1000L)
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeExecutor.runAllReady()
|
|
||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToReceiverTriggeredThenRemoveView_eventuallyTimesOut() {
|
|
||||||
underTest.displayView(transferToReceiverTriggered())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
|
||||||
|
|
||||||
verify(windowManager).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToThisDeviceTriggeredThenRemoveView_viewStillDisplayed() {
|
|
||||||
underTest.displayView(transferToThisDeviceTriggered())
|
|
||||||
fakeClock.advanceTime(1000L)
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeExecutor.runAllReady()
|
|
||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToThisDeviceTriggeredThenRemoveView_eventuallyTimesOut() {
|
|
||||||
underTest.displayView(transferToThisDeviceTriggered())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
|
||||||
|
|
||||||
verify(windowManager).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToReceiverSucceededThenRemoveView_viewStillDisplayed() {
|
|
||||||
underTest.displayView(transferToReceiverSucceeded())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeExecutor.runAllReady()
|
|
||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToReceiverSucceededThenRemoveView_eventuallyTimesOut() {
|
|
||||||
underTest.displayView(transferToReceiverSucceeded())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
|
||||||
|
|
||||||
verify(windowManager).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToThisDeviceSucceededThenRemoveView_viewStillDisplayed() {
|
|
||||||
underTest.displayView(transferToThisDeviceSucceeded())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeExecutor.runAllReady()
|
|
||||||
|
|
||||||
verify(windowManager, never()).removeView(any())
|
|
||||||
verify(logger).logRemovalBypass(any(), any())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun transferToThisDeviceSucceededThenRemoveView_eventuallyTimesOut() {
|
|
||||||
underTest.displayView(transferToThisDeviceSucceeded())
|
|
||||||
|
|
||||||
underTest.removeView("fakeRemovalReason")
|
|
||||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
|
||||||
|
|
||||||
verify(windowManager).removeView(any())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
|
private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon)
|
||||||
|
|
||||||
private fun ViewGroup.getChipText(): String =
|
private fun ViewGroup.getChipText(): String =
|
||||||
|
|||||||
Reference in New Issue
Block a user