Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +59 −28 Original line number Diff line number Diff line Loading @@ -33,11 +33,13 @@ import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT import androidx.annotation.CallSuper import com.android.internal.widget.CachingIconView import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil Loading @@ -58,11 +60,11 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( private val viewUtil: ViewUtil, @Main private val mainExecutor: DelayableExecutor, private val accessibilityManager: AccessibilityManager, private val configurationController: ConfigurationController, private val tapGestureDetector: TapGestureDetector, private val powerManager: PowerManager, @LayoutRes private val chipLayoutRes: Int @LayoutRes private val chipLayoutRes: Int, ) { /** * Window layout params that will be used as a starting point for the [windowLayoutParams] of * all subclasses. Loading @@ -89,42 +91,40 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( /** The chip view currently being displayed. Null if the chip is not being displayed. */ private var chipView: ViewGroup? = null /** The chip info currently being displayed. Null if the chip is not being displayed. */ internal var chipInfo: T? = null /** A [Runnable] that, when run, will cancel the pending timeout of the chip. */ private var cancelChipViewTimeout: Runnable? = null /** * Displays the chip with the current state. * Displays the chip with the provided [newChipInfo]. * * This method handles inflating and attaching the view, then delegates to [updateChipView] to * display the correct information in the chip. */ fun displayChip(chipInfo: T) { val oldChipView = chipView if (chipView == null) { chipView = LayoutInflater .from(context) .inflate(chipLayoutRes, null) as ViewGroup } val currentChipView = chipView!! fun displayChip(newChipInfo: T) { val currentChipView = chipView updateChipView(chipInfo, currentChipView) // Add view if necessary if (oldChipView == null) { if (currentChipView != null) { updateChipView(newChipInfo, currentChipView) } else { // The chip is new, so set up all our callbacks and inflate the view configurationController.addCallback(displayScaleListener) tapGestureDetector.addOnGestureDetectedCallback(TAG, this::onScreenTapped) windowManager.addView(chipView, windowLayoutParams) // Wake the screen so the user will see the chip powerManager.wakeUp( SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION, "com.android.systemui:media_tap_to_transfer_activated" ) animateChipIn(currentChipView) inflateAndUpdateChip(newChipInfo) } // Cancel and re-set the chip timeout each time we get a new state. val timeout = accessibilityManager.getRecommendedTimeoutMillis( chipInfo.getTimeoutMs().toInt(), newChipInfo.getTimeoutMs().toInt(), // Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but // include it just to be safe. FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS Loading @@ -136,6 +136,32 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( ) } /** Inflates a new chip view, updates it with [newChipInfo], and adds the view to the window. */ private fun inflateAndUpdateChip(newChipInfo: T) { val newChipView = LayoutInflater .from(context) .inflate(chipLayoutRes, null) as ViewGroup chipView = newChipView updateChipView(newChipInfo, newChipView) windowManager.addView(newChipView, windowLayoutParams) animateChipIn(newChipView) } /** Removes then re-inflates the chip. */ private fun reinflateChip() { val currentChipInfo = chipInfo if (chipView == null || currentChipInfo == null) { return } windowManager.removeView(chipView) inflateAndUpdateChip(currentChipInfo) } private val displayScaleListener = object : ConfigurationController.ConfigurationListener { override fun onDensityOrFontScaleChanged() { reinflateChip() } } /** * Hides the chip. * Loading @@ -145,17 +171,22 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( open fun removeChip(removalReason: String) { if (chipView == null) { return } logger.logChipRemoval(removalReason) configurationController.removeCallback(displayScaleListener) tapGestureDetector.removeOnGestureDetectedCallback(TAG) windowManager.removeView(chipView) chipView = null chipInfo = null // No need to time the chip out since it's already gone cancelChipViewTimeout?.run() } /** * A method implemented by subclasses to update [currentChipView] based on [chipInfo]. * A method implemented by subclasses to update [currentChipView] based on [newChipInfo]. */ abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup) @CallSuper open fun updateChipView(newChipInfo: T, currentChipView: ViewGroup) { chipInfo = newChipInfo } /** * A method that can be implemented by subclcasses to do custom animations for when the chip Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +28 −24 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCom import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.animation.AnimationUtil.Companion.frames import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil Loading @@ -61,6 +62,7 @@ class MediaTttChipControllerReceiver @Inject constructor( viewUtil: ViewUtil, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, @Main private val mainHandler: Handler, Loading @@ -72,9 +74,10 @@ class MediaTttChipControllerReceiver @Inject constructor( viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip_receiver R.layout.media_ttt_chip_receiver, ) { @SuppressLint("WrongConstant") // We're allowed to use LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS override val windowLayoutParams = commonWindowLayoutParams.apply { Loading Loading @@ -140,12 +143,13 @@ class MediaTttChipControllerReceiver @Inject constructor( ) } override fun updateChipView(chipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { override fun updateChipView(newChipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { super.updateChipView(newChipInfo, currentChipView) setIcon( currentChipView, chipInfo.routeInfo.packageName, chipInfo.appIconDrawableOverride, chipInfo.appNameOverride newChipInfo.routeInfo.packageName, newChipInfo.appIconDrawableOverride, newChipInfo.appNameOverride ) } Loading packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +33 −31 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ 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.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil import javax.inject.Inject Loading @@ -56,6 +57,7 @@ class MediaTttChipControllerSender @Inject constructor( viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, private val uiEventLogger: MediaTttSenderUiEventLogger Loading @@ -66,16 +68,15 @@ class MediaTttChipControllerSender @Inject constructor( viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip R.layout.media_ttt_chip, ) { override val windowLayoutParams = commonWindowLayoutParams.apply { gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL) } private var currentlyDisplayedChipState: ChipStateSender? = null private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferSenderDisplay( @StatusBarManager.MediaTransferSenderState displayState: Int, Loading Loading @@ -116,16 +117,18 @@ class MediaTttChipControllerSender @Inject constructor( /** Displays the chip view for the given state. */ override fun updateChipView( chipInfo: ChipSenderInfo, currentChipView: ViewGroup) { val chipState = chipInfo.state currentlyDisplayedChipState = chipState newChipInfo: ChipSenderInfo, currentChipView: ViewGroup ) { super.updateChipView(newChipInfo, currentChipView) val chipState = newChipInfo.state // App icon setIcon(currentChipView, chipInfo.routeInfo.packageName) setIcon(currentChipView, newChipInfo.routeInfo.packageName) // Text val otherDeviceName = chipInfo.routeInfo.name.toString() val otherDeviceName = newChipInfo.routeInfo.name.toString() currentChipView.requireViewById<TextView>(R.id.text).apply { text = chipState.getChipTextString(context, otherDeviceName) } Loading @@ -137,7 +140,7 @@ class MediaTttChipControllerSender @Inject constructor( // Undo val undoView = currentChipView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( this, chipInfo.routeInfo, chipInfo.undoCallback, uiEventLogger this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger ) undoView.setOnClickListener(undoClickListener) undoView.visibility = (undoClickListener != null).visibleIfTrue() Loading @@ -161,12 +164,11 @@ class MediaTttChipControllerSender @Inject constructor( 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?.isMidTransfer == true && removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { if (chipInfo?.state?.isMidTransfer == true && removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { return } super.removeChip(removalReason) currentlyDisplayedChipState = null } private fun Boolean.visibleIfTrue(): Int { Loading packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +45 −14 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any Loading @@ -53,7 +55,7 @@ import org.mockito.MockitoAnnotations @SmallTest class MediaTttChipControllerCommonTest : SysuiTestCase() { private lateinit var controllerCommon: MediaTttChipControllerCommon<ChipInfo> private lateinit var controllerCommon: TestControllerCommon private lateinit var fakeClock: FakeSystemClock private lateinit var fakeExecutor: FakeExecutor Loading @@ -68,6 +70,8 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock private lateinit var configurationController: ConfigurationController @Mock private lateinit var windowManager: WindowManager @Mock private lateinit var viewUtil: ViewUtil Loading Loading @@ -104,8 +108,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil, fakeExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager powerManager, ) } Loading Loading @@ -185,6 +190,19 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager).removeView(any()) } @Test fun displayScaleChange_chipReinflatedWithMostRecentState() { controllerCommon.displayChip(getState(name = "First name")) controllerCommon.displayChip(getState(name = "Second name")) reset(windowManager) getConfigurationListener().onDensityOrFontScaleChanged() verify(windowManager).removeView(any()) verify(windowManager).addView(any(), any()) assertThat(controllerCommon.mostRecentChipInfo?.name).isEqualTo("Second name") } @Test fun removeChip_chipRemovedAndGestureDetectionStoppedAndRemovalLogged() { // First, add the chip Loading Loading @@ -341,7 +359,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager, never()).removeView(any()) } private fun getState() = ChipInfo() private fun getState(name: String = "name") = ChipInfo(name) private fun getChipView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) Loading @@ -351,6 +369,12 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) private fun getConfigurationListener(): ConfigurationListener { val callbackCaptor = argumentCaptor<ConfigurationListener>() verify(configurationController).addCallback(capture(callbackCaptor)) return callbackCaptor.value } inner class TestControllerCommon( context: Context, logger: MediaTttLogger, Loading @@ -358,8 +382,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager powerManager: PowerManager, ) : MediaTttChipControllerCommon<ChipInfo>( context, logger, Loading @@ -367,16 +392,22 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip R.layout.media_ttt_chip, ) { var mostRecentChipInfo: ChipInfo? = null override val windowLayoutParams = commonWindowLayoutParams override fun updateChipView(chipInfo: ChipInfo, currentChipView: ViewGroup) {} override fun updateChipView(newChipInfo: ChipInfo, currentChipView: ViewGroup) { super.updateChipView(newChipInfo, currentChipView) mostRecentChipInfo = newChipInfo } override fun getIconSize(isAppIcon: Boolean): Int = ICON_SIZE } inner class ChipInfo : ChipInfoCommon { inner class ChipInfo(val name: String) : ChipInfoCommon { override fun getTimeoutMs() = 1L } } Loading packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +4 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq Loading Loading @@ -68,6 +69,8 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock private lateinit var configurationController: ConfigurationController @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var windowManager: WindowManager Loading Loading @@ -103,6 +106,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { viewUtil, FakeExecutor(FakeSystemClock()), accessibilityManager, configurationController, TapGestureDetector(context), powerManager, Handler.getMain(), Loading Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +59 −28 Original line number Diff line number Diff line Loading @@ -33,11 +33,13 @@ import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT import androidx.annotation.CallSuper import com.android.internal.widget.CachingIconView import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil Loading @@ -58,11 +60,11 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( private val viewUtil: ViewUtil, @Main private val mainExecutor: DelayableExecutor, private val accessibilityManager: AccessibilityManager, private val configurationController: ConfigurationController, private val tapGestureDetector: TapGestureDetector, private val powerManager: PowerManager, @LayoutRes private val chipLayoutRes: Int @LayoutRes private val chipLayoutRes: Int, ) { /** * Window layout params that will be used as a starting point for the [windowLayoutParams] of * all subclasses. Loading @@ -89,42 +91,40 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( /** The chip view currently being displayed. Null if the chip is not being displayed. */ private var chipView: ViewGroup? = null /** The chip info currently being displayed. Null if the chip is not being displayed. */ internal var chipInfo: T? = null /** A [Runnable] that, when run, will cancel the pending timeout of the chip. */ private var cancelChipViewTimeout: Runnable? = null /** * Displays the chip with the current state. * Displays the chip with the provided [newChipInfo]. * * This method handles inflating and attaching the view, then delegates to [updateChipView] to * display the correct information in the chip. */ fun displayChip(chipInfo: T) { val oldChipView = chipView if (chipView == null) { chipView = LayoutInflater .from(context) .inflate(chipLayoutRes, null) as ViewGroup } val currentChipView = chipView!! fun displayChip(newChipInfo: T) { val currentChipView = chipView updateChipView(chipInfo, currentChipView) // Add view if necessary if (oldChipView == null) { if (currentChipView != null) { updateChipView(newChipInfo, currentChipView) } else { // The chip is new, so set up all our callbacks and inflate the view configurationController.addCallback(displayScaleListener) tapGestureDetector.addOnGestureDetectedCallback(TAG, this::onScreenTapped) windowManager.addView(chipView, windowLayoutParams) // Wake the screen so the user will see the chip powerManager.wakeUp( SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_APPLICATION, "com.android.systemui:media_tap_to_transfer_activated" ) animateChipIn(currentChipView) inflateAndUpdateChip(newChipInfo) } // Cancel and re-set the chip timeout each time we get a new state. val timeout = accessibilityManager.getRecommendedTimeoutMillis( chipInfo.getTimeoutMs().toInt(), newChipInfo.getTimeoutMs().toInt(), // Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but // include it just to be safe. FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS Loading @@ -136,6 +136,32 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( ) } /** Inflates a new chip view, updates it with [newChipInfo], and adds the view to the window. */ private fun inflateAndUpdateChip(newChipInfo: T) { val newChipView = LayoutInflater .from(context) .inflate(chipLayoutRes, null) as ViewGroup chipView = newChipView updateChipView(newChipInfo, newChipView) windowManager.addView(newChipView, windowLayoutParams) animateChipIn(newChipView) } /** Removes then re-inflates the chip. */ private fun reinflateChip() { val currentChipInfo = chipInfo if (chipView == null || currentChipInfo == null) { return } windowManager.removeView(chipView) inflateAndUpdateChip(currentChipInfo) } private val displayScaleListener = object : ConfigurationController.ConfigurationListener { override fun onDensityOrFontScaleChanged() { reinflateChip() } } /** * Hides the chip. * Loading @@ -145,17 +171,22 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( open fun removeChip(removalReason: String) { if (chipView == null) { return } logger.logChipRemoval(removalReason) configurationController.removeCallback(displayScaleListener) tapGestureDetector.removeOnGestureDetectedCallback(TAG) windowManager.removeView(chipView) chipView = null chipInfo = null // No need to time the chip out since it's already gone cancelChipViewTimeout?.run() } /** * A method implemented by subclasses to update [currentChipView] based on [chipInfo]. * A method implemented by subclasses to update [currentChipView] based on [newChipInfo]. */ abstract fun updateChipView(chipInfo: T, currentChipView: ViewGroup) @CallSuper open fun updateChipView(newChipInfo: T, currentChipView: ViewGroup) { chipInfo = newChipInfo } /** * A method that can be implemented by subclcasses to do custom animations for when the chip Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +28 −24 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCom import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.animation.AnimationUtil.Companion.frames import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil Loading @@ -61,6 +62,7 @@ class MediaTttChipControllerReceiver @Inject constructor( viewUtil: ViewUtil, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, @Main private val mainHandler: Handler, Loading @@ -72,9 +74,10 @@ class MediaTttChipControllerReceiver @Inject constructor( viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip_receiver R.layout.media_ttt_chip_receiver, ) { @SuppressLint("WrongConstant") // We're allowed to use LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS override val windowLayoutParams = commonWindowLayoutParams.apply { Loading Loading @@ -140,12 +143,13 @@ class MediaTttChipControllerReceiver @Inject constructor( ) } override fun updateChipView(chipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { override fun updateChipView(newChipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { super.updateChipView(newChipInfo, currentChipView) setIcon( currentChipView, chipInfo.routeInfo.packageName, chipInfo.appIconDrawableOverride, chipInfo.appNameOverride newChipInfo.routeInfo.packageName, newChipInfo.appIconDrawableOverride, newChipInfo.appNameOverride ) } Loading
packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +33 −31 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ 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.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.view.ViewUtil import javax.inject.Inject Loading @@ -56,6 +57,7 @@ class MediaTttChipControllerSender @Inject constructor( viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager, private val uiEventLogger: MediaTttSenderUiEventLogger Loading @@ -66,16 +68,15 @@ class MediaTttChipControllerSender @Inject constructor( viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip R.layout.media_ttt_chip, ) { override val windowLayoutParams = commonWindowLayoutParams.apply { gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL) } private var currentlyDisplayedChipState: ChipStateSender? = null private val commandQueueCallbacks = object : CommandQueue.Callbacks { override fun updateMediaTapToTransferSenderDisplay( @StatusBarManager.MediaTransferSenderState displayState: Int, Loading Loading @@ -116,16 +117,18 @@ class MediaTttChipControllerSender @Inject constructor( /** Displays the chip view for the given state. */ override fun updateChipView( chipInfo: ChipSenderInfo, currentChipView: ViewGroup) { val chipState = chipInfo.state currentlyDisplayedChipState = chipState newChipInfo: ChipSenderInfo, currentChipView: ViewGroup ) { super.updateChipView(newChipInfo, currentChipView) val chipState = newChipInfo.state // App icon setIcon(currentChipView, chipInfo.routeInfo.packageName) setIcon(currentChipView, newChipInfo.routeInfo.packageName) // Text val otherDeviceName = chipInfo.routeInfo.name.toString() val otherDeviceName = newChipInfo.routeInfo.name.toString() currentChipView.requireViewById<TextView>(R.id.text).apply { text = chipState.getChipTextString(context, otherDeviceName) } Loading @@ -137,7 +140,7 @@ class MediaTttChipControllerSender @Inject constructor( // Undo val undoView = currentChipView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( this, chipInfo.routeInfo, chipInfo.undoCallback, uiEventLogger this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger ) undoView.setOnClickListener(undoClickListener) undoView.visibility = (undoClickListener != null).visibleIfTrue() Loading @@ -161,12 +164,11 @@ class MediaTttChipControllerSender @Inject constructor( 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?.isMidTransfer == true && removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { if (chipInfo?.state?.isMidTransfer == true && removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { return } super.removeChip(removalReason) currentlyDisplayedChipState = null } private fun Boolean.visibleIfTrue(): Int { Loading
packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +45 −14 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any Loading @@ -53,7 +55,7 @@ import org.mockito.MockitoAnnotations @SmallTest class MediaTttChipControllerCommonTest : SysuiTestCase() { private lateinit var controllerCommon: MediaTttChipControllerCommon<ChipInfo> private lateinit var controllerCommon: TestControllerCommon private lateinit var fakeClock: FakeSystemClock private lateinit var fakeExecutor: FakeExecutor Loading @@ -68,6 +70,8 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock private lateinit var configurationController: ConfigurationController @Mock private lateinit var windowManager: WindowManager @Mock private lateinit var viewUtil: ViewUtil Loading Loading @@ -104,8 +108,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil, fakeExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager powerManager, ) } Loading Loading @@ -185,6 +190,19 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager).removeView(any()) } @Test fun displayScaleChange_chipReinflatedWithMostRecentState() { controllerCommon.displayChip(getState(name = "First name")) controllerCommon.displayChip(getState(name = "Second name")) reset(windowManager) getConfigurationListener().onDensityOrFontScaleChanged() verify(windowManager).removeView(any()) verify(windowManager).addView(any(), any()) assertThat(controllerCommon.mostRecentChipInfo?.name).isEqualTo("Second name") } @Test fun removeChip_chipRemovedAndGestureDetectionStoppedAndRemovalLogged() { // First, add the chip Loading Loading @@ -341,7 +359,7 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager, never()).removeView(any()) } private fun getState() = ChipInfo() private fun getState(name: String = "name") = ChipInfo(name) private fun getChipView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) Loading @@ -351,6 +369,12 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) private fun getConfigurationListener(): ConfigurationListener { val callbackCaptor = argumentCaptor<ConfigurationListener>() verify(configurationController).addCallback(capture(callbackCaptor)) return callbackCaptor.value } inner class TestControllerCommon( context: Context, logger: MediaTttLogger, Loading @@ -358,8 +382,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, tapGestureDetector: TapGestureDetector, powerManager: PowerManager powerManager: PowerManager, ) : MediaTttChipControllerCommon<ChipInfo>( context, logger, Loading @@ -367,16 +392,22 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { viewUtil, mainExecutor, accessibilityManager, configurationController, tapGestureDetector, powerManager, R.layout.media_ttt_chip R.layout.media_ttt_chip, ) { var mostRecentChipInfo: ChipInfo? = null override val windowLayoutParams = commonWindowLayoutParams override fun updateChipView(chipInfo: ChipInfo, currentChipView: ViewGroup) {} override fun updateChipView(newChipInfo: ChipInfo, currentChipView: ViewGroup) { super.updateChipView(newChipInfo, currentChipView) mostRecentChipInfo = newChipInfo } override fun getIconSize(isAppIcon: Boolean): Int = ICON_SIZE } inner class ChipInfo : ChipInfoCommon { inner class ChipInfo(val name: String) : ChipInfoCommon { override fun getTimeoutMs() = 1L } } Loading
packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +4 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.gesture.TapGestureDetector import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq Loading Loading @@ -68,6 +69,8 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var accessibilityManager: AccessibilityManager @Mock private lateinit var configurationController: ConfigurationController @Mock private lateinit var powerManager: PowerManager @Mock private lateinit var windowManager: WindowManager Loading Loading @@ -103,6 +106,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { viewUtil, FakeExecutor(FakeSystemClock()), accessibilityManager, configurationController, TapGestureDetector(context), powerManager, Handler.getMain(), Loading