Merge changes Ib59a5b8a,I814c0406 into tm-qpr-dev
* changes: [Chipbar] Rename "chip" -> "view" in the generic TemporaryViewDisplayController (and other affected places). [Chipbar] Move the controller that was common between the media ttt sender and media ttt receiver into a more generic TemporaryViewDisplayController class.
This commit is contained in:
committed by
Android (Google) Code Review
commit
0b401b1d76
@@ -240,8 +240,6 @@
|
||||
-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt
|
||||
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
|
||||
@@ -529,6 +527,8 @@
|
||||
-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
|
||||
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
|
||||
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
|
||||
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
|
||||
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
|
||||
-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
|
||||
-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
|
||||
-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
|
||||
@@ -677,7 +677,6 @@
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
|
||||
@@ -834,6 +833,7 @@
|
||||
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
|
||||
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
|
||||
|
||||
@@ -34,15 +34,14 @@ import com.android.settingslib.Utils
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.media.taptotransfer.common.ChipInfoCommon
|
||||
import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
|
||||
import com.android.systemui.statusbar.CommandQueue
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
|
||||
import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
|
||||
import com.android.systemui.temporarydisplay.TemporaryViewInfo
|
||||
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -56,18 +55,16 @@ class MediaTttChipControllerReceiver @Inject constructor(
|
||||
context: Context,
|
||||
@MediaTttReceiverLogger logger: MediaTttLogger,
|
||||
windowManager: WindowManager,
|
||||
viewUtil: ViewUtil,
|
||||
mainExecutor: DelayableExecutor,
|
||||
accessibilityManager: AccessibilityManager,
|
||||
configurationController: ConfigurationController,
|
||||
powerManager: PowerManager,
|
||||
@Main private val mainHandler: Handler,
|
||||
private val uiEventLogger: MediaTttReceiverUiEventLogger,
|
||||
) : MediaTttChipControllerCommon<ChipReceiverInfo>(
|
||||
) : TemporaryViewDisplayController<ChipReceiverInfo>(
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
mainExecutor,
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
@@ -119,18 +116,18 @@ class MediaTttChipControllerReceiver @Inject constructor(
|
||||
uiEventLogger.logReceiverStateChange(chipState)
|
||||
|
||||
if (chipState == ChipStateReceiver.FAR_FROM_SENDER) {
|
||||
removeChip(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!)
|
||||
removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!)
|
||||
return
|
||||
}
|
||||
if (appIcon == null) {
|
||||
displayChip(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName))
|
||||
displayView(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName))
|
||||
return
|
||||
}
|
||||
|
||||
appIcon.loadDrawableAsync(
|
||||
context,
|
||||
Icon.OnDrawableLoadedListener { drawable ->
|
||||
displayChip(ChipReceiverInfo(routeInfo, drawable, appName))
|
||||
displayView(ChipReceiverInfo(routeInfo, drawable, appName))
|
||||
},
|
||||
// Notify the listener on the main handler since the listener will update
|
||||
// the UI.
|
||||
@@ -138,19 +135,19 @@ class MediaTttChipControllerReceiver @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
override fun updateChipView(newChipInfo: ChipReceiverInfo, currentChipView: ViewGroup) {
|
||||
super.updateChipView(newChipInfo, currentChipView)
|
||||
override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) {
|
||||
super.updateView(newInfo, currentView)
|
||||
val iconName = setIcon(
|
||||
currentChipView,
|
||||
newChipInfo.routeInfo.clientPackageName,
|
||||
newChipInfo.appIconDrawableOverride,
|
||||
newChipInfo.appNameOverride
|
||||
currentView,
|
||||
newInfo.routeInfo.clientPackageName,
|
||||
newInfo.appIconDrawableOverride,
|
||||
newInfo.appNameOverride
|
||||
)
|
||||
currentChipView.contentDescription = iconName
|
||||
currentView.contentDescription = iconName
|
||||
}
|
||||
|
||||
override fun animateChipIn(chipView: ViewGroup) {
|
||||
val appIconView = chipView.requireViewById<View>(R.id.app_icon)
|
||||
override fun animateViewIn(view: ViewGroup) {
|
||||
val appIconView = view.requireViewById<View>(R.id.app_icon)
|
||||
appIconView.animate()
|
||||
.translationYBy(-1 * getTranslationAmount().toFloat())
|
||||
.setDuration(30.frames)
|
||||
@@ -160,8 +157,8 @@ class MediaTttChipControllerReceiver @Inject constructor(
|
||||
.setDuration(5.frames)
|
||||
.start()
|
||||
// Using withEndAction{} doesn't apply a11y focus when screen is unlocked.
|
||||
appIconView.postOnAnimation { chipView.requestAccessibilityFocus() }
|
||||
startRipple(chipView.requireViewById(R.id.ripple))
|
||||
appIconView.postOnAnimation { view.requestAccessibilityFocus() }
|
||||
startRipple(view.requireViewById(R.id.ripple))
|
||||
}
|
||||
|
||||
override fun getIconSize(isAppIcon: Boolean): Int? =
|
||||
@@ -216,7 +213,7 @@ data class ChipReceiverInfo(
|
||||
val routeInfo: MediaRoute2Info,
|
||||
val appIconDrawableOverride: Drawable?,
|
||||
val appNameOverride: CharSequence?
|
||||
) : ChipInfoCommon {
|
||||
) : TemporaryViewInfo {
|
||||
override fun getTimeoutMs() = DEFAULT_TIMEOUT_MILLIS
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import androidx.annotation.StringRes
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
import com.android.internal.statusbar.IUndoMediaTransferCallback
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS
|
||||
import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
|
||||
|
||||
/**
|
||||
* A class enumerating all the possible states of the media tap-to-transfer chip on the sender
|
||||
@@ -120,7 +120,7 @@ enum class ChipStateSender(
|
||||
// state, but that may take too long to go through the binder and the user may be
|
||||
// confused ast o why the UI hasn't changed yet. So, we immediately change the UI
|
||||
// here.
|
||||
controllerSender.displayChip(
|
||||
controllerSender.displayView(
|
||||
ChipSenderInfo(
|
||||
TRANSFER_TO_THIS_DEVICE_TRIGGERED, routeInfo, undoCallback
|
||||
)
|
||||
@@ -155,7 +155,7 @@ enum class ChipStateSender(
|
||||
// state, but that may take too long to go through the binder and the user may be
|
||||
// confused as to why the UI hasn't changed yet. So, we immediately change the UI
|
||||
// here.
|
||||
controllerSender.displayChip(
|
||||
controllerSender.displayView(
|
||||
ChipSenderInfo(
|
||||
TRANSFER_TO_RECEIVER_TRIGGERED, routeInfo, undoCallback
|
||||
)
|
||||
|
||||
@@ -33,14 +33,13 @@ import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.animation.ViewHierarchyAnimator
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.media.taptotransfer.common.ChipInfoCommon
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
|
||||
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.policy.ConfigurationController
|
||||
import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason
|
||||
import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
|
||||
import com.android.systemui.temporarydisplay.TemporaryViewInfo
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -53,17 +52,15 @@ class MediaTttChipControllerSender @Inject constructor(
|
||||
context: Context,
|
||||
@MediaTttSenderLogger logger: MediaTttLogger,
|
||||
windowManager: WindowManager,
|
||||
viewUtil: ViewUtil,
|
||||
@Main mainExecutor: DelayableExecutor,
|
||||
accessibilityManager: AccessibilityManager,
|
||||
configurationController: ConfigurationController,
|
||||
powerManager: PowerManager,
|
||||
private val uiEventLogger: MediaTttSenderUiEventLogger
|
||||
) : MediaTttChipControllerCommon<ChipSenderInfo>(
|
||||
) : TemporaryViewDisplayController<ChipSenderInfo>(
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
mainExecutor,
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
@@ -106,53 +103,52 @@ class MediaTttChipControllerSender @Inject constructor(
|
||||
uiEventLogger.logSenderStateChange(chipState)
|
||||
|
||||
if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
|
||||
removeChip(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!)
|
||||
removeView(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!)
|
||||
} else {
|
||||
displayChip(ChipSenderInfo(chipState, routeInfo, undoCallback))
|
||||
displayView(ChipSenderInfo(chipState, routeInfo, undoCallback))
|
||||
}
|
||||
}
|
||||
|
||||
/** Displays the chip view for the given state. */
|
||||
override fun updateChipView(
|
||||
newChipInfo: ChipSenderInfo,
|
||||
currentChipView: ViewGroup
|
||||
override fun updateView(
|
||||
newInfo: ChipSenderInfo,
|
||||
currentView: ViewGroup
|
||||
) {
|
||||
super.updateChipView(newChipInfo, currentChipView)
|
||||
super.updateView(newInfo, currentView)
|
||||
|
||||
val chipState = newChipInfo.state
|
||||
val chipState = newInfo.state
|
||||
|
||||
// App icon
|
||||
val iconName = setIcon(currentChipView, newChipInfo.routeInfo.clientPackageName)
|
||||
val iconName = setIcon(currentView, newInfo.routeInfo.clientPackageName)
|
||||
|
||||
// Text
|
||||
val otherDeviceName = newChipInfo.routeInfo.name.toString()
|
||||
val otherDeviceName = newInfo.routeInfo.name.toString()
|
||||
val chipText = chipState.getChipTextString(context, otherDeviceName)
|
||||
currentChipView.requireViewById<TextView>(R.id.text).text = chipText
|
||||
currentView.requireViewById<TextView>(R.id.text).text = chipText
|
||||
|
||||
// Loading
|
||||
currentChipView.requireViewById<View>(R.id.loading).visibility =
|
||||
currentView.requireViewById<View>(R.id.loading).visibility =
|
||||
chipState.isMidTransfer.visibleIfTrue()
|
||||
|
||||
// Undo
|
||||
val undoView = currentChipView.requireViewById<View>(R.id.undo)
|
||||
val undoView = currentView.requireViewById<View>(R.id.undo)
|
||||
val undoClickListener = chipState.undoClickListener(
|
||||
this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger
|
||||
this, newInfo.routeInfo, newInfo.undoCallback, uiEventLogger
|
||||
)
|
||||
undoView.setOnClickListener(undoClickListener)
|
||||
undoView.visibility = (undoClickListener != null).visibleIfTrue()
|
||||
|
||||
// Failure
|
||||
currentChipView.requireViewById<View>(R.id.failure_icon).visibility =
|
||||
currentView.requireViewById<View>(R.id.failure_icon).visibility =
|
||||
chipState.isTransferFailure.visibleIfTrue()
|
||||
|
||||
// For accessibility
|
||||
currentChipView.requireViewById<ViewGroup>(
|
||||
currentView.requireViewById<ViewGroup>(
|
||||
R.id.media_ttt_sender_chip_inner
|
||||
).contentDescription = "$iconName $chipText"
|
||||
}
|
||||
|
||||
override fun animateChipIn(chipView: ViewGroup) {
|
||||
val chipInnerView = chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner)
|
||||
override fun animateViewIn(view: ViewGroup) {
|
||||
val chipInnerView = view.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner)
|
||||
ViewHierarchyAnimator.animateAddition(
|
||||
chipInnerView,
|
||||
ViewHierarchyAnimator.Hotspot.TOP,
|
||||
@@ -165,14 +161,14 @@ class MediaTttChipControllerSender @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
override fun removeChip(removalReason: String) {
|
||||
override fun removeView(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 (chipInfo?.state?.isMidTransfer == true &&
|
||||
removalReason != MediaTttRemovalReason.REASON_TIMEOUT) {
|
||||
if (info?.state?.isMidTransfer == true &&
|
||||
removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT) {
|
||||
return
|
||||
}
|
||||
super.removeChip(removalReason)
|
||||
super.removeView(removalReason)
|
||||
}
|
||||
|
||||
private fun Boolean.visibleIfTrue(): Int {
|
||||
@@ -188,7 +184,7 @@ data class ChipSenderInfo(
|
||||
val state: ChipStateSender,
|
||||
val routeInfo: MediaRoute2Info,
|
||||
val undoCallback: IUndoMediaTransferCallback? = null
|
||||
) : ChipInfoCommon {
|
||||
) : TemporaryViewInfo {
|
||||
override fun getTimeoutMs() = state.timeout
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.media.taptotransfer.common
|
||||
package com.android.systemui.temporarydisplay
|
||||
|
||||
import android.annotation.LayoutRes
|
||||
import android.annotation.SuppressLint
|
||||
@@ -37,30 +37,30 @@ 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.media.taptotransfer.common.MediaTttLogger
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
|
||||
/**
|
||||
* A superclass controller that provides common functionality for showing chips on the sender device
|
||||
* and the receiver device.
|
||||
* A generic controller that can temporarily display a new view in a new window.
|
||||
*
|
||||
* Subclasses need to override and implement [updateChipView], which is where they can control what
|
||||
* Subclasses need to override and implement [updateView], which is where they can control what
|
||||
* gets displayed to the user.
|
||||
*
|
||||
* The generic type T is expected to contain all the information necessary for the subclasses to
|
||||
* display the chip in a certain state, since they receive <T> in [updateChipView].
|
||||
* display the view in a certain state, since they receive <T> in [updateView].
|
||||
*
|
||||
* TODO(b/245610654): Remove all the media-specific logic from this class.
|
||||
*/
|
||||
abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
|
||||
internal val context: Context,
|
||||
internal val logger: MediaTttLogger,
|
||||
internal val windowManager: WindowManager,
|
||||
private val viewUtil: ViewUtil,
|
||||
@Main private val mainExecutor: DelayableExecutor,
|
||||
private val accessibilityManager: AccessibilityManager,
|
||||
private val configurationController: ConfigurationController,
|
||||
private val powerManager: PowerManager,
|
||||
@LayoutRes private val chipLayoutRes: Int,
|
||||
abstract class TemporaryViewDisplayController<T : TemporaryViewInfo>(
|
||||
internal val context: Context,
|
||||
internal val logger: MediaTttLogger,
|
||||
internal val windowManager: WindowManager,
|
||||
@Main private val mainExecutor: DelayableExecutor,
|
||||
private val accessibilityManager: AccessibilityManager,
|
||||
private val configurationController: ConfigurationController,
|
||||
private val powerManager: PowerManager,
|
||||
@LayoutRes private val viewLayoutRes: Int,
|
||||
) {
|
||||
/**
|
||||
* Window layout params that will be used as a starting point for the [windowLayoutParams] of
|
||||
@@ -85,31 +85,31 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
|
||||
*/
|
||||
internal abstract val windowLayoutParams: WindowManager.LayoutParams
|
||||
|
||||
/** The chip view currently being displayed. Null if the chip is not being displayed. */
|
||||
private var chipView: ViewGroup? = null
|
||||
/** The view currently being displayed. Null if the view is not being displayed. */
|
||||
private var view: ViewGroup? = null
|
||||
|
||||
/** The chip info currently being displayed. Null if the chip is not being displayed. */
|
||||
internal var chipInfo: T? = null
|
||||
/** The info currently being displayed. Null if the view is not being displayed. */
|
||||
internal var info: T? = null
|
||||
|
||||
/** A [Runnable] that, when run, will cancel the pending timeout of the chip. */
|
||||
private var cancelChipViewTimeout: Runnable? = null
|
||||
/** A [Runnable] that, when run, will cancel the pending timeout of the view. */
|
||||
private var cancelViewTimeout: Runnable? = null
|
||||
|
||||
/**
|
||||
* Displays the chip with the provided [newChipInfo].
|
||||
* Displays the view with the provided [newInfo].
|
||||
*
|
||||
* This method handles inflating and attaching the view, then delegates to [updateChipView] to
|
||||
* display the correct information in the chip.
|
||||
* This method handles inflating and attaching the view, then delegates to [updateView] to
|
||||
* display the correct information in the view.
|
||||
*/
|
||||
fun displayChip(newChipInfo: T) {
|
||||
val currentChipView = chipView
|
||||
fun displayView(newInfo: T) {
|
||||
val currentView = view
|
||||
|
||||
if (currentChipView != null) {
|
||||
updateChipView(newChipInfo, currentChipView)
|
||||
if (currentView != null) {
|
||||
updateView(newInfo, currentView)
|
||||
} else {
|
||||
// The chip is new, so set up all our callbacks and inflate the view
|
||||
// The view is new, so set up all our callbacks and inflate the view
|
||||
configurationController.addCallback(displayScaleListener)
|
||||
// Wake the screen if necessary so the user will see the chip. (Per b/239426653, we want
|
||||
// the chip to show over the dream state, so we should only wake up if the screen is
|
||||
// Wake the screen if necessary so the user will see the view. (Per b/239426653, we want
|
||||
// the view to show over the dream state, so we should only wake up if the screen is
|
||||
// completely off.)
|
||||
if (!powerManager.isScreenOn) {
|
||||
powerManager.wakeUp(
|
||||
@@ -119,79 +119,79 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
|
||||
)
|
||||
}
|
||||
|
||||
inflateAndUpdateChip(newChipInfo)
|
||||
inflateAndUpdateView(newInfo)
|
||||
}
|
||||
|
||||
// Cancel and re-set the chip timeout each time we get a new state.
|
||||
// Cancel and re-set the view timeout each time we get a new state.
|
||||
val timeout = accessibilityManager.getRecommendedTimeoutMillis(
|
||||
newChipInfo.getTimeoutMs().toInt(),
|
||||
// Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but
|
||||
newInfo.getTimeoutMs().toInt(),
|
||||
// Not all views 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
|
||||
)
|
||||
cancelChipViewTimeout?.run()
|
||||
cancelChipViewTimeout = mainExecutor.executeDelayed(
|
||||
{ removeChip(MediaTttRemovalReason.REASON_TIMEOUT) },
|
||||
cancelViewTimeout?.run()
|
||||
cancelViewTimeout = mainExecutor.executeDelayed(
|
||||
{ removeView(TemporaryDisplayRemovalReason.REASON_TIMEOUT) },
|
||||
timeout.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
/** Inflates a new chip view, updates it with [newChipInfo], and adds the view to the window. */
|
||||
private fun inflateAndUpdateChip(newChipInfo: T) {
|
||||
val newChipView = LayoutInflater
|
||||
/** Inflates a new view, updates it with [newInfo], and adds the view to the window. */
|
||||
private fun inflateAndUpdateView(newInfo: T) {
|
||||
val newView = LayoutInflater
|
||||
.from(context)
|
||||
.inflate(chipLayoutRes, null) as ViewGroup
|
||||
chipView = newChipView
|
||||
updateChipView(newChipInfo, newChipView)
|
||||
windowManager.addView(newChipView, windowLayoutParams)
|
||||
animateChipIn(newChipView)
|
||||
.inflate(viewLayoutRes, null) as ViewGroup
|
||||
view = newView
|
||||
updateView(newInfo, newView)
|
||||
windowManager.addView(newView, windowLayoutParams)
|
||||
animateViewIn(newView)
|
||||
}
|
||||
|
||||
/** Removes then re-inflates the chip. */
|
||||
private fun reinflateChip() {
|
||||
val currentChipInfo = chipInfo
|
||||
if (chipView == null || currentChipInfo == null) { return }
|
||||
/** Removes then re-inflates the view. */
|
||||
private fun reinflateView() {
|
||||
val currentInfo = info
|
||||
if (view == null || currentInfo == null) { return }
|
||||
|
||||
windowManager.removeView(chipView)
|
||||
inflateAndUpdateChip(currentChipInfo)
|
||||
windowManager.removeView(view)
|
||||
inflateAndUpdateView(currentInfo)
|
||||
}
|
||||
|
||||
private val displayScaleListener = object : ConfigurationController.ConfigurationListener {
|
||||
override fun onDensityOrFontScaleChanged() {
|
||||
reinflateChip()
|
||||
reinflateView()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the chip.
|
||||
* Hides the view.
|
||||
*
|
||||
* @param removalReason a short string describing why the chip was removed (timeout, state
|
||||
* @param removalReason a short string describing why the view was removed (timeout, state
|
||||
* change, etc.)
|
||||
*/
|
||||
open fun removeChip(removalReason: String) {
|
||||
if (chipView == null) { return }
|
||||
open fun removeView(removalReason: String) {
|
||||
if (view == null) { return }
|
||||
logger.logChipRemoval(removalReason)
|
||||
configurationController.removeCallback(displayScaleListener)
|
||||
windowManager.removeView(chipView)
|
||||
chipView = null
|
||||
chipInfo = null
|
||||
// No need to time the chip out since it's already gone
|
||||
cancelChipViewTimeout?.run()
|
||||
windowManager.removeView(view)
|
||||
view = null
|
||||
info = null
|
||||
// No need to time the view out since it's already gone
|
||||
cancelViewTimeout?.run()
|
||||
}
|
||||
|
||||
/**
|
||||
* A method implemented by subclasses to update [currentChipView] based on [newChipInfo].
|
||||
* A method implemented by subclasses to update [currentView] based on [newInfo].
|
||||
*/
|
||||
@CallSuper
|
||||
open fun updateChipView(newChipInfo: T, currentChipView: ViewGroup) {
|
||||
chipInfo = newChipInfo
|
||||
open fun updateView(newInfo: T, currentView: ViewGroup) {
|
||||
info = newInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that can be implemented by subclcasses to do custom animations for when the chip
|
||||
* A method that can be implemented by subclasses to do custom animations for when the view
|
||||
* appears.
|
||||
*/
|
||||
open fun animateChipIn(chipView: ViewGroup) {}
|
||||
open fun animateViewIn(view: ViewGroup) {}
|
||||
|
||||
/**
|
||||
* Returns the size that the icon should be, or null if no size override is needed.
|
||||
@@ -209,12 +209,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
|
||||
* @return the content description of the icon.
|
||||
*/
|
||||
internal fun setIcon(
|
||||
currentChipView: ViewGroup,
|
||||
currentView: ViewGroup,
|
||||
appPackageName: String?,
|
||||
appIconDrawableOverride: Drawable? = null,
|
||||
appNameOverride: CharSequence? = null,
|
||||
): CharSequence {
|
||||
val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon)
|
||||
val appIconView = currentView.requireViewById<CachingIconView>(R.id.app_icon)
|
||||
val iconInfo = getIconInfo(appPackageName)
|
||||
|
||||
getIconSize(iconInfo.isAppIcon)?.let { size ->
|
||||
@@ -264,9 +264,9 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>(
|
||||
// Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and
|
||||
// UpdateMediaTapToTransferReceiverDisplayTest
|
||||
private const val WINDOW_TITLE = "Media Transfer Chip View"
|
||||
private val TAG = MediaTttChipControllerCommon::class.simpleName!!
|
||||
private val TAG = TemporaryViewDisplayController::class.simpleName!!
|
||||
|
||||
object MediaTttRemovalReason {
|
||||
object TemporaryDisplayRemovalReason {
|
||||
const val REASON_TIMEOUT = "TIMEOUT"
|
||||
const val REASON_SCREEN_TAP = "SCREEN_TAP"
|
||||
}
|
||||
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.media.taptotransfer.common
|
||||
package com.android.systemui.temporarydisplay
|
||||
|
||||
/**
|
||||
* A superclass chip state that will be subclassed by the sender chip and receiver chip.
|
||||
* A superclass view state used with [TemporaryViewDisplayController].
|
||||
*/
|
||||
interface ChipInfoCommon {
|
||||
interface TemporaryViewInfo {
|
||||
/**
|
||||
* Returns the amount of time the given chip state should display on the screen before it times
|
||||
* Returns the amount of time the given view state should display on the screen before it times
|
||||
* out and disappears.
|
||||
*/
|
||||
fun getTimeoutMs(): Long
|
||||
fun getTimeoutMs(): Long = DEFAULT_TIMEOUT_MILLIS
|
||||
}
|
||||
|
||||
const val DEFAULT_TIMEOUT_MILLIS = 10000L
|
||||
@@ -41,7 +41,6 @@ import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -74,8 +73,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var windowManager: WindowManager
|
||||
@Mock
|
||||
private lateinit var viewUtil: ViewUtil
|
||||
@Mock
|
||||
private lateinit var commandQueue: CommandQueue
|
||||
private lateinit var commandQueueCallback: CommandQueue.Callbacks
|
||||
private lateinit var fakeAppIconDrawable: Drawable
|
||||
@@ -102,7 +99,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
FakeExecutor(FakeSystemClock()),
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
@@ -182,7 +178,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun setIcon_isAppIcon_usesAppIconSize() {
|
||||
controllerReceiver.displayChip(getChipReceiverInfo())
|
||||
controllerReceiver.displayView(getChipReceiverInfo())
|
||||
val chipView = getChipView()
|
||||
|
||||
controllerReceiver.setIcon(chipView, PACKAGE_NAME)
|
||||
@@ -198,7 +194,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun setIcon_notAppIcon_usesGenericIconSize() {
|
||||
controllerReceiver.displayChip(getChipReceiverInfo())
|
||||
controllerReceiver.displayView(getChipReceiverInfo())
|
||||
val chipView = getChipView()
|
||||
|
||||
controllerReceiver.setIcon(chipView, appPackageName = null)
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -51,8 +50,8 @@ import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@@ -75,8 +74,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var windowManager: WindowManager
|
||||
@Mock
|
||||
private lateinit var viewUtil: ViewUtil
|
||||
@Mock
|
||||
private lateinit var commandQueue: CommandQueue
|
||||
private lateinit var commandQueueCallback: CommandQueue.Callbacks
|
||||
private lateinit var fakeAppIconDrawable: Drawable
|
||||
@@ -110,7 +107,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
fakeExecutor,
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
@@ -309,7 +305,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun almostCloseToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
|
||||
val state = almostCloseToStartCast()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -325,7 +321,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun almostCloseToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() {
|
||||
val state = almostCloseToEndCast()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -341,7 +337,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToReceiverTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() {
|
||||
val state = transferToReceiverTriggered()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -357,7 +353,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToThisDeviceTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() {
|
||||
val state = transferToThisDeviceTriggered()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -373,7 +369,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToReceiverSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
|
||||
val state = transferToReceiverSucceeded()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -387,7 +383,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun transferToReceiverSucceeded_nullUndoRunnable_noUndo() {
|
||||
controllerSender.displayChip(transferToReceiverSucceeded(undoCallback = null))
|
||||
controllerSender.displayView(transferToReceiverSucceeded(undoCallback = null))
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
|
||||
@@ -398,7 +394,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
|
||||
override fun onUndoTriggered() {}
|
||||
}
|
||||
controllerSender.displayChip(transferToReceiverSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
|
||||
@@ -414,7 +410,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
controllerSender.displayChip(transferToReceiverSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
|
||||
getChipView().getUndoButton().performClick()
|
||||
|
||||
assertThat(undoCallbackCalled).isTrue()
|
||||
@@ -425,7 +421,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
|
||||
override fun onUndoTriggered() {}
|
||||
}
|
||||
controllerSender.displayChip(transferToReceiverSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToReceiverSucceeded(undoCallback))
|
||||
|
||||
getChipView().getUndoButton().performClick()
|
||||
|
||||
@@ -440,7 +436,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToThisDeviceSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() {
|
||||
val state = transferToThisDeviceSucceeded()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -454,7 +450,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun transferToThisDeviceSucceeded_nullUndoRunnable_noUndo() {
|
||||
controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback = null))
|
||||
controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback = null))
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE)
|
||||
@@ -465,7 +461,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
|
||||
override fun onUndoTriggered() {}
|
||||
}
|
||||
controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE)
|
||||
@@ -481,7 +477,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
|
||||
getChipView().getUndoButton().performClick()
|
||||
|
||||
assertThat(undoCallbackCalled).isTrue()
|
||||
@@ -492,7 +488,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
|
||||
override fun onUndoTriggered() {}
|
||||
}
|
||||
controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback))
|
||||
controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback))
|
||||
|
||||
getChipView().getUndoButton().performClick()
|
||||
|
||||
@@ -507,7 +503,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToReceiverFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() {
|
||||
val state = transferToReceiverFailed()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -523,7 +519,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToThisDeviceFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() {
|
||||
val state = transferToThisDeviceFailed()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
|
||||
val chipView = getChipView()
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
|
||||
@@ -538,24 +534,24 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun changeFromAlmostCloseToStartToTransferTriggered_loadingIconAppears() {
|
||||
controllerSender.displayChip(almostCloseToStartCast())
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayView(almostCloseToStartCast())
|
||||
controllerSender.displayView(transferToReceiverTriggered())
|
||||
|
||||
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(transferToReceiverSucceeded())
|
||||
controllerSender.displayView(transferToReceiverTriggered())
|
||||
controllerSender.displayView(transferToReceiverSucceeded())
|
||||
|
||||
assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(
|
||||
controllerSender.displayView(transferToReceiverTriggered())
|
||||
controllerSender.displayView(
|
||||
transferToReceiverSucceeded(
|
||||
object : IUndoMediaTransferCallback.Stub() {
|
||||
override fun onUndoTriggered() {}
|
||||
@@ -568,26 +564,26 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun changeFromTransferSucceededToAlmostCloseToStart_undoButtonDisappears() {
|
||||
controllerSender.displayChip(transferToReceiverSucceeded())
|
||||
controllerSender.displayChip(almostCloseToStartCast())
|
||||
controllerSender.displayView(transferToReceiverSucceeded())
|
||||
controllerSender.displayView(almostCloseToStartCast())
|
||||
|
||||
assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeFromTransferTriggeredToTransferFailed_failureIconAppears() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
controllerSender.displayChip(transferToReceiverFailed())
|
||||
controllerSender.displayView(transferToReceiverTriggered())
|
||||
controllerSender.displayView(transferToReceiverFailed())
|
||||
|
||||
assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferToReceiverTriggeredThenRemoveChip_chipStillDisplayed() {
|
||||
controllerSender.displayChip(transferToReceiverTriggered())
|
||||
fun transferToReceiverTriggeredThenRemoveView_viewStillDisplayed() {
|
||||
controllerSender.displayView(transferToReceiverTriggered())
|
||||
fakeClock.advanceTime(1000L)
|
||||
|
||||
controllerSender.removeChip("fakeRemovalReason")
|
||||
controllerSender.removeView("fakeRemovalReason")
|
||||
fakeExecutor.runAllReady()
|
||||
|
||||
verify(windowManager, never()).removeView(any())
|
||||
@@ -596,9 +592,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToReceiverTriggeredThenFarFromReceiver_eventuallyTimesOut() {
|
||||
val state = transferToReceiverTriggered()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
fakeClock.advanceTime(1000L)
|
||||
controllerSender.removeChip("fakeRemovalReason")
|
||||
controllerSender.removeView("fakeRemovalReason")
|
||||
|
||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||
|
||||
@@ -606,11 +602,11 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun transferToThisDeviceTriggeredThenRemoveChip_chipStillDisplayed() {
|
||||
controllerSender.displayChip(transferToThisDeviceTriggered())
|
||||
fun transferToThisDeviceTriggeredThenRemoveView_viewStillDisplayed() {
|
||||
controllerSender.displayView(transferToThisDeviceTriggered())
|
||||
fakeClock.advanceTime(1000L)
|
||||
|
||||
controllerSender.removeChip("fakeRemovalReason")
|
||||
controllerSender.removeView("fakeRemovalReason")
|
||||
fakeExecutor.runAllReady()
|
||||
|
||||
verify(windowManager, never()).removeView(any())
|
||||
@@ -619,9 +615,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun transferToThisDeviceTriggeredThenFarFromReceiver_eventuallyTimesOut() {
|
||||
val state = transferToThisDeviceTriggered()
|
||||
controllerSender.displayChip(state)
|
||||
controllerSender.displayView(state)
|
||||
fakeClock.advanceTime(1000L)
|
||||
controllerSender.removeChip("fakeRemovalReason")
|
||||
controllerSender.removeView("fakeRemovalReason")
|
||||
|
||||
fakeClock.advanceTime(TIMEOUT + 1L)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.media.taptotransfer.common
|
||||
package com.android.systemui.temporarydisplay
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
@@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
@@ -38,7 +39,6 @@ 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.time.FakeSystemClock
|
||||
import com.android.systemui.util.view.ViewUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -52,8 +52,8 @@ import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
private lateinit var controllerCommon: TestControllerCommon
|
||||
class TemporaryViewDisplayControllerTest : SysuiTestCase() {
|
||||
private lateinit var underTest: TestController
|
||||
|
||||
private lateinit var fakeClock: FakeSystemClock
|
||||
private lateinit var fakeExecutor: FakeExecutor
|
||||
@@ -72,8 +72,6 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var windowManager: WindowManager
|
||||
@Mock
|
||||
private lateinit var viewUtil: ViewUtil
|
||||
@Mock
|
||||
private lateinit var powerManager: PowerManager
|
||||
|
||||
@Before
|
||||
@@ -97,11 +95,10 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
fakeClock = FakeSystemClock()
|
||||
fakeExecutor = FakeExecutor(fakeClock)
|
||||
|
||||
controllerCommon = TestControllerCommon(
|
||||
underTest = TestController(
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
fakeExecutor,
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
@@ -110,43 +107,43 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_chipAdded() {
|
||||
controllerCommon.displayChip(getState())
|
||||
fun displayView_viewAdded() {
|
||||
underTest.displayView(getState())
|
||||
|
||||
verify(windowManager).addView(any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_screenOff_screenWakes() {
|
||||
fun displayView_screenOff_screenWakes() {
|
||||
whenever(powerManager.isScreenOn).thenReturn(false)
|
||||
|
||||
controllerCommon.displayChip(getState())
|
||||
underTest.displayView(getState())
|
||||
|
||||
verify(powerManager).wakeUp(any(), any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_screenAlreadyOn_screenNotWoken() {
|
||||
fun displayView_screenAlreadyOn_screenNotWoken() {
|
||||
whenever(powerManager.isScreenOn).thenReturn(true)
|
||||
|
||||
controllerCommon.displayChip(getState())
|
||||
underTest.displayView(getState())
|
||||
|
||||
verify(powerManager, never()).wakeUp(any(), any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_twice_chipNotAddedTwice() {
|
||||
controllerCommon.displayChip(getState())
|
||||
fun displayView_twice_viewNotAddedTwice() {
|
||||
underTest.displayView(getState())
|
||||
reset(windowManager)
|
||||
|
||||
controllerCommon.displayChip(getState())
|
||||
underTest.displayView(getState())
|
||||
verify(windowManager, never()).addView(any(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_chipDoesNotDisappearsBeforeTimeout() {
|
||||
fun displayView_viewDoesNotDisappearsBeforeTimeout() {
|
||||
val state = getState()
|
||||
controllerCommon.displayChip(state)
|
||||
underTest.displayView(state)
|
||||
reset(windowManager)
|
||||
|
||||
fakeClock.advanceTime(TIMEOUT_MS - 1)
|
||||
@@ -155,9 +152,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_chipDisappearsAfterTimeout() {
|
||||
fun displayView_viewDisappearsAfterTimeout() {
|
||||
val state = getState()
|
||||
controllerCommon.displayChip(state)
|
||||
underTest.displayView(state)
|
||||
reset(windowManager)
|
||||
|
||||
fakeClock.advanceTime(TIMEOUT_MS + 1)
|
||||
@@ -166,176 +163,176 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_calledAgainBeforeTimeout_timeoutReset() {
|
||||
// First, display the chip
|
||||
fun displayView_calledAgainBeforeTimeout_timeoutReset() {
|
||||
// First, display the view
|
||||
val state = getState()
|
||||
controllerCommon.displayChip(state)
|
||||
underTest.displayView(state)
|
||||
|
||||
// After some time, re-display the chip
|
||||
// After some time, re-display the view
|
||||
val waitTime = 1000L
|
||||
fakeClock.advanceTime(waitTime)
|
||||
controllerCommon.displayChip(getState())
|
||||
underTest.displayView(getState())
|
||||
|
||||
// Wait until the timeout for the first display would've happened
|
||||
fakeClock.advanceTime(TIMEOUT_MS - waitTime + 1)
|
||||
|
||||
// Verify we didn't hide the chip
|
||||
// Verify we didn't hide the view
|
||||
verify(windowManager, never()).removeView(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayChip_calledAgainBeforeTimeout_eventuallyTimesOut() {
|
||||
// First, display the chip
|
||||
fun displayView_calledAgainBeforeTimeout_eventuallyTimesOut() {
|
||||
// First, display the view
|
||||
val state = getState()
|
||||
controllerCommon.displayChip(state)
|
||||
underTest.displayView(state)
|
||||
|
||||
// After some time, re-display the chip
|
||||
// After some time, re-display the view
|
||||
fakeClock.advanceTime(1000L)
|
||||
controllerCommon.displayChip(getState())
|
||||
underTest.displayView(getState())
|
||||
|
||||
// Ensure we still hide the chip eventually
|
||||
// Ensure we still hide the view eventually
|
||||
fakeClock.advanceTime(TIMEOUT_MS + 1)
|
||||
|
||||
verify(windowManager).removeView(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun displayScaleChange_chipReinflatedWithMostRecentState() {
|
||||
controllerCommon.displayChip(getState(name = "First name"))
|
||||
controllerCommon.displayChip(getState(name = "Second name"))
|
||||
fun displayScaleChange_viewReinflatedWithMostRecentState() {
|
||||
underTest.displayView(getState(name = "First name"))
|
||||
underTest.displayView(getState(name = "Second name"))
|
||||
reset(windowManager)
|
||||
|
||||
getConfigurationListener().onDensityOrFontScaleChanged()
|
||||
|
||||
verify(windowManager).removeView(any())
|
||||
verify(windowManager).addView(any(), any())
|
||||
assertThat(controllerCommon.mostRecentChipInfo?.name).isEqualTo("Second name")
|
||||
assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeChip_chipRemovedAndRemovalLogged() {
|
||||
// First, add the chip
|
||||
controllerCommon.displayChip(getState())
|
||||
fun removeView_viewRemovedAndRemovalLogged() {
|
||||
// First, add the view
|
||||
underTest.displayView(getState())
|
||||
|
||||
// Then, remove it
|
||||
val reason = "test reason"
|
||||
controllerCommon.removeChip(reason)
|
||||
underTest.removeView(reason)
|
||||
|
||||
verify(windowManager).removeView(any())
|
||||
verify(logger).logChipRemoval(reason)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeChip_noAdd_viewNotRemoved() {
|
||||
controllerCommon.removeChip("reason")
|
||||
fun removeView_noAdd_viewNotRemoved() {
|
||||
underTest.removeView("reason")
|
||||
|
||||
verify(windowManager, never()).removeView(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppIconDrawableAndNullPackageName_stillHasIcon() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null)
|
||||
underTest.setIcon(view, appPackageName = null, appIconDrawableOverride = null)
|
||||
|
||||
assertThat(chipView.getAppIconView().drawable).isNotNull()
|
||||
assertThat(view.getAppIconView().drawable).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(
|
||||
chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null
|
||||
underTest.setIcon(
|
||||
view, appPackageName = "fakePackageName", appIconDrawableOverride = null
|
||||
)
|
||||
|
||||
assertThat(chipView.getAppIconView().drawable).isNotNull()
|
||||
assertThat(view.getAppIconView().drawable).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppIconDrawable_iconIsFromPackageName() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(chipView, PACKAGE_NAME, appIconDrawableOverride = null, null)
|
||||
underTest.setIcon(view, PACKAGE_NAME, appIconDrawableOverride = null, null)
|
||||
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconFromPackageName)
|
||||
assertThat(view.getAppIconView().drawable).isEqualTo(appIconFromPackageName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_hasAppIconDrawable_iconIsDrawable() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
val drawable = context.getDrawable(R.drawable.ic_alarm)!!
|
||||
controllerCommon.setIcon(chipView, PACKAGE_NAME, drawable, null)
|
||||
underTest.setIcon(view, PACKAGE_NAME, drawable, null)
|
||||
|
||||
assertThat(chipView.getAppIconView().drawable).isEqualTo(drawable)
|
||||
assertThat(view.getAppIconView().drawable).isEqualTo(drawable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppNameAndNullPackageName_stillHasContentDescription() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null)
|
||||
underTest.setIcon(view, appPackageName = null, appNameOverride = null)
|
||||
|
||||
assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty()
|
||||
assertThat(view.getAppIconView().contentDescription.toString()).isNotEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppNameAndInvalidPackageName_stillHasContentDescription() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(
|
||||
chipView, appPackageName = "fakePackageName", appNameOverride = null
|
||||
underTest.setIcon(
|
||||
view, appPackageName = "fakePackageName", appNameOverride = null
|
||||
)
|
||||
|
||||
assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty()
|
||||
assertThat(view.getAppIconView().contentDescription.toString()).isNotEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_nullAppName_iconContentDescriptionIsFromPackageName() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appNameOverride = null)
|
||||
underTest.setIcon(view, PACKAGE_NAME, null, appNameOverride = null)
|
||||
|
||||
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_NAME)
|
||||
assertThat(view.getAppIconView().contentDescription).isEqualTo(APP_NAME)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_hasAppName_iconContentDescriptionIsAppNameOverride() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
val appName = "Override App Name"
|
||||
controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appName)
|
||||
underTest.setIcon(view, PACKAGE_NAME, null, appName)
|
||||
|
||||
assertThat(chipView.getAppIconView().contentDescription).isEqualTo(appName)
|
||||
assertThat(view.getAppIconView().contentDescription).isEqualTo(appName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setIcon_iconSizeMatchesGetIconSize() {
|
||||
controllerCommon.displayChip(getState())
|
||||
val chipView = getChipView()
|
||||
underTest.displayView(getState())
|
||||
val view = getView()
|
||||
|
||||
controllerCommon.setIcon(chipView, PACKAGE_NAME)
|
||||
chipView.measure(
|
||||
underTest.setIcon(view, PACKAGE_NAME)
|
||||
view.measure(
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
)
|
||||
|
||||
assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE)
|
||||
assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE)
|
||||
assertThat(view.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE)
|
||||
assertThat(view.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE)
|
||||
}
|
||||
|
||||
private fun getState(name: String = "name") = ChipInfo(name)
|
||||
private fun getState(name: String = "name") = ViewInfo(name)
|
||||
|
||||
private fun getChipView(): ViewGroup {
|
||||
private fun getView(): ViewGroup {
|
||||
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
|
||||
verify(windowManager).addView(viewCaptor.capture(), any())
|
||||
return viewCaptor.value as ViewGroup
|
||||
@@ -349,37 +346,35 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() {
|
||||
return callbackCaptor.value
|
||||
}
|
||||
|
||||
inner class TestControllerCommon(
|
||||
inner class TestController(
|
||||
context: Context,
|
||||
logger: MediaTttLogger,
|
||||
windowManager: WindowManager,
|
||||
viewUtil: ViewUtil,
|
||||
@Main mainExecutor: DelayableExecutor,
|
||||
accessibilityManager: AccessibilityManager,
|
||||
configurationController: ConfigurationController,
|
||||
powerManager: PowerManager,
|
||||
) : MediaTttChipControllerCommon<ChipInfo>(
|
||||
) : TemporaryViewDisplayController<ViewInfo>(
|
||||
context,
|
||||
logger,
|
||||
windowManager,
|
||||
viewUtil,
|
||||
mainExecutor,
|
||||
accessibilityManager,
|
||||
configurationController,
|
||||
powerManager,
|
||||
R.layout.media_ttt_chip,
|
||||
) {
|
||||
var mostRecentChipInfo: ChipInfo? = null
|
||||
var mostRecentViewInfo: ViewInfo? = null
|
||||
|
||||
override val windowLayoutParams = commonWindowLayoutParams
|
||||
override fun updateChipView(newChipInfo: ChipInfo, currentChipView: ViewGroup) {
|
||||
super.updateChipView(newChipInfo, currentChipView)
|
||||
mostRecentChipInfo = newChipInfo
|
||||
override fun updateView(newInfo: ViewInfo, currentView: ViewGroup) {
|
||||
super.updateView(newInfo, currentView)
|
||||
mostRecentViewInfo = newInfo
|
||||
}
|
||||
override fun getIconSize(isAppIcon: Boolean): Int = ICON_SIZE
|
||||
}
|
||||
|
||||
inner class ChipInfo(val name: String) : ChipInfoCommon {
|
||||
inner class ViewInfo(val name: String) : TemporaryViewInfo {
|
||||
override fun getTimeoutMs() = 1L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user