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:
Caitlin Shkuratov
2022-09-09 20:09:53 +00:00
committed by Android (Google) Code Review
9 changed files with 256 additions and 276 deletions

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
)

View File

@@ -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
}

View File

@@ -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"
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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
}
}