Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2403c96c authored by Caitlin Cassidy's avatar Caitlin Cassidy
Browse files

[Media TTT] Don't hide the chip if we're in a transfer triggered state.

Also give those states a longer timeout.

Fixes: 219766679
Test: manual (verify requesting a chip removal doesn't work if currently
in the transfer triggered state)
Test: media.taptotransfer tests

Change-Id: Ifbbb4fd28ba092f1c989ed31c21bed5e891ac3be
parent b1daf7f5
Loading
Loading
Loading
Loading
+9 −11
Original line number Original line Diff line number Diff line
@@ -95,8 +95,8 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>(
        // Cancel and re-set the chip timeout each time we get a new state.
        // Cancel and re-set the chip timeout each time we get a new state.
        cancelChipViewTimeout?.run()
        cancelChipViewTimeout?.run()
        cancelChipViewTimeout = mainExecutor.executeDelayed(
        cancelChipViewTimeout = mainExecutor.executeDelayed(
            { removeChip(REASON_TIMEOUT) },
            { removeChip(MediaTttRemovalReason.REASON_TIMEOUT) },
            TIMEOUT_MILLIS
            chipState.getTimeoutMs()
        )
        )
    }
    }


@@ -106,10 +106,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>(
     * @param removalReason a short string describing why the chip was removed (timeout, state
     * @param removalReason a short string describing why the chip was removed (timeout, state
     *     change, etc.)
     *     change, etc.)
     */
     */
    fun removeChip(removalReason: String) {
    open fun removeChip(removalReason: String) {
        // TODO(b/203800347): We may not want to hide the chip if we're currently in a
        //  TransferTriggered state: Once the user has initiated the transfer, they should be able
        //  to move away from the receiver device but still see the status of the transfer.
        if (chipView == null) { return }
        if (chipView == null) { return }
        logger.logChipRemoval(removalReason)
        logger.logChipRemoval(removalReason)
        tapGestureDetector.removeOnGestureDetectedCallback(TAG)
        tapGestureDetector.removeOnGestureDetectedCallback(TAG)
@@ -148,7 +145,7 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>(
        // If the tap is within the chip bounds, we shouldn't hide the chip (in case users think the
        // If the tap is within the chip bounds, we shouldn't hide the chip (in case users think the
        // chip is tappable).
        // chip is tappable).
        if (!viewUtil.touchIsWithinView(view, e.x, e.y)) {
        if (!viewUtil.touchIsWithinView(view, e.x, e.y)) {
            removeChip(REASON_SCREEN_TAP)
            removeChip(MediaTttRemovalReason.REASON_SCREEN_TAP)
        }
        }
    }
    }
}
}
@@ -157,8 +154,9 @@ abstract class MediaTttChipControllerCommon<T : MediaTttChipState>(
// UpdateMediaTapToTransferReceiverDisplayTest
// UpdateMediaTapToTransferReceiverDisplayTest
private const val WINDOW_TITLE = "Media Transfer Chip View"
private const val WINDOW_TITLE = "Media Transfer Chip View"
private val TAG = MediaTttChipControllerCommon::class.simpleName!!
private val TAG = MediaTttChipControllerCommon::class.simpleName!!
@VisibleForTesting
const val TIMEOUT_MILLIS = 3000L


private const val REASON_TIMEOUT = "TIMEOUT"
object MediaTttRemovalReason {
private const val REASON_SCREEN_TAP = "SCREEN_TAP"
    const val REASON_TIMEOUT = "TIMEOUT"
    const val REASON_SCREEN_TAP = "SCREEN_TAP"
}
+8 −0
Original line number Original line Diff line number Diff line
@@ -52,6 +52,14 @@ open class MediaTttChipState(
            null
            null
        }
        }
    }
    }

    /**
     * Returns the amount of time this chip should display on the screen before it times out and
     * disappears. [MediaTttChipControllerCommon] will ensure that the timeout resets each time we
     * receive a new state.
     */
    open fun getTimeoutMs(): Long = DEFAULT_TIMEOUT_MILLIS
}
}


private const val DEFAULT_TIMEOUT_MILLIS = 3000L
private val TAG = MediaTttChipState::class.simpleName!!
private val TAG = MediaTttChipState::class.simpleName!!
+7 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,7 @@ class TransferToReceiverTriggered(
    }
    }


    override fun showLoading() = true
    override fun showLoading() = true
    override fun getTimeoutMs() = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
}
}


/**
/**
@@ -111,6 +112,7 @@ class TransferToThisDeviceTriggered(
    }
    }


    override fun showLoading() = true
    override fun showLoading() = true
    override fun getTimeoutMs() = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
}
}


/**
/**
@@ -194,3 +196,8 @@ class TransferFailed(
        return context.getString(R.string.media_transfer_failed)
        return context.getString(R.string.media_transfer_failed)
    }
    }
}
}

// Give the Transfer*Triggered states a longer timeout since those states represent an active
// process and we should keep the user informed about it as long as possible (but don't allow it to
// continue indefinitely).
private const val TRANSFER_TRIGGERED_TIMEOUT_MILLIS = 15000L
 No newline at end of file
+17 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttRemovalReason
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.gesture.TapGestureDetector
import com.android.systemui.statusbar.gesture.TapGestureDetector
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -58,6 +59,8 @@ class MediaTttChipControllerSender @Inject constructor(
    tapGestureDetector,
    tapGestureDetector,
    R.layout.media_ttt_chip
    R.layout.media_ttt_chip
) {
) {
    private var currentlyDisplayedChipState: ChipStateSender? = null

    private val commandQueueCallbacks = object : CommandQueue.Callbacks {
    private val commandQueueCallbacks = object : CommandQueue.Callbacks {
        override fun updateMediaTapToTransferSenderDisplay(
        override fun updateMediaTapToTransferSenderDisplay(
                @StatusBarManager.MediaTransferSenderState displayState: Int,
                @StatusBarManager.MediaTransferSenderState displayState: Int,
@@ -115,6 +118,8 @@ class MediaTttChipControllerSender @Inject constructor(


    /** Displays the chip view for the given state. */
    /** Displays the chip view for the given state. */
    override fun updateChipView(chipState: ChipStateSender, currentChipView: ViewGroup) {
    override fun updateChipView(chipState: ChipStateSender, currentChipView: ViewGroup) {
        currentlyDisplayedChipState = chipState

        // App icon
        // App icon
        setIcon(chipState, currentChipView)
        setIcon(chipState, currentChipView)


@@ -139,6 +144,18 @@ class MediaTttChipControllerSender @Inject constructor(
            if (showFailure) { View.VISIBLE } else { View.GONE }
            if (showFailure) { View.VISIBLE } else { View.GONE }
    }
    }


    override fun removeChip(removalReason: String) {
        // Don't remove the chip if we're mid-transfer since the user should still be able to
        // see the status of the transfer. (But do remove it if it's finally timed out.)
        if ((currentlyDisplayedChipState is TransferToReceiverTriggered ||
                currentlyDisplayedChipState is TransferToThisDeviceTriggered)
            && removalReason != MediaTttRemovalReason.REASON_TIMEOUT) {
            return
        }
        super.removeChip(removalReason)
        currentlyDisplayedChipState = null
    }

    private fun stateIntToString(@StatusBarManager.MediaTransferSenderState state: Int): String {
    private fun stateIntToString(@StatusBarManager.MediaTransferSenderState state: Int): String {
        return when(state) {
        return when(state) {
            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST ->
            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST ->
+12 −8
Original line number Original line Diff line number Diff line
@@ -96,20 +96,22 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {


    @Test
    @Test
    fun displayChip_chipDoesNotDisappearsBeforeTimeout() {
    fun displayChip_chipDoesNotDisappearsBeforeTimeout() {
        controllerCommon.displayChip(getState())
        val state = getState()
        controllerCommon.displayChip(state)
        reset(windowManager)
        reset(windowManager)


        fakeClock.advanceTime(TIMEOUT_MILLIS - 1)
        fakeClock.advanceTime(state.getTimeoutMs() - 1)


        verify(windowManager, never()).removeView(any())
        verify(windowManager, never()).removeView(any())
    }
    }


    @Test
    @Test
    fun displayChip_chipDisappearsAfterTimeout() {
    fun displayChip_chipDisappearsAfterTimeout() {
        controllerCommon.displayChip(getState())
        val state = getState()
        controllerCommon.displayChip(state)
        reset(windowManager)
        reset(windowManager)


        fakeClock.advanceTime(TIMEOUT_MILLIS + 1)
        fakeClock.advanceTime(state.getTimeoutMs() + 1)


        verify(windowManager).removeView(any())
        verify(windowManager).removeView(any())
    }
    }
@@ -117,7 +119,8 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
    @Test
    @Test
    fun displayChip_calledAgainBeforeTimeout_timeoutReset() {
    fun displayChip_calledAgainBeforeTimeout_timeoutReset() {
        // First, display the chip
        // First, display the chip
        controllerCommon.displayChip(getState())
        val state = getState()
        controllerCommon.displayChip(state)


        // After some time, re-display the chip
        // After some time, re-display the chip
        val waitTime = 1000L
        val waitTime = 1000L
@@ -125,7 +128,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
        controllerCommon.displayChip(getState())
        controllerCommon.displayChip(getState())


        // Wait until the timeout for the first display would've happened
        // Wait until the timeout for the first display would've happened
        fakeClock.advanceTime(TIMEOUT_MILLIS - waitTime + 1)
        fakeClock.advanceTime(state.getTimeoutMs() - waitTime + 1)


        // Verify we didn't hide the chip
        // Verify we didn't hide the chip
        verify(windowManager, never()).removeView(any())
        verify(windowManager, never()).removeView(any())
@@ -134,14 +137,15 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
    @Test
    @Test
    fun displayChip_calledAgainBeforeTimeout_eventuallyTimesOut() {
    fun displayChip_calledAgainBeforeTimeout_eventuallyTimesOut() {
        // First, display the chip
        // First, display the chip
        controllerCommon.displayChip(getState())
        val state = getState()
        controllerCommon.displayChip(state)


        // After some time, re-display the chip
        // After some time, re-display the chip
        fakeClock.advanceTime(1000L)
        fakeClock.advanceTime(1000L)
        controllerCommon.displayChip(getState())
        controllerCommon.displayChip(getState())


        // Ensure we still hide the chip eventually
        // Ensure we still hide the chip eventually
        fakeClock.advanceTime(TIMEOUT_MILLIS + 1)
        fakeClock.advanceTime(state.getTimeoutMs() + 1)


        verify(windowManager).removeView(any())
        verify(windowManager).removeView(any())
    }
    }
Loading