[fenix] Closes https://github.com/mozilla-mobile/fenix/issues/16896: Integrate new MediaSession API to nightly or debug builds (https://github.com/mozilla-mobile/fenix/pull/16909)

pull/600/head
Roger Yang 4 years ago committed by GitHub
parent 32c0bbedc2
commit 30305ae436

@ -232,6 +232,9 @@
<service android:name=".media.MediaService" <service android:name=".media.MediaService"
android:exported="false" /> android:exported="false" />
<service android:name=".media.MediaSessionService"
android:exported="false" />
<service <service
android:name=".customtabs.CustomTabsService" android:name=".customtabs.CustomTabsService"
android:exported="true" android:exported="true"

@ -36,4 +36,9 @@ object FeatureFlags {
* all experiments. * all experiments.
*/ */
val nimbusExperiments = Config.channel.isNightlyOrDebug val nimbusExperiments = Config.channel.isNightlyOrDebug
/**
* Enables the new MediaSession API.
*/
val newMediaSessionApi = Config.channel.isNightlyOrDebug
} }

@ -58,7 +58,7 @@ import mozilla.components.feature.contextmenu.ContextMenuFeature
import mozilla.components.feature.downloads.DownloadsFeature import mozilla.components.feature.downloads.DownloadsFeature
import mozilla.components.feature.downloads.manager.FetchDownloadManager import mozilla.components.feature.downloads.manager.FetchDownloadManager
import mozilla.components.feature.intent.ext.EXTRA_SESSION_ID import mozilla.components.feature.intent.ext.EXTRA_SESSION_ID
import mozilla.components.feature.media.fullscreen.MediaFullscreenOrientationFeature import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature
import mozilla.components.feature.privatemode.feature.SecureWindowFeature import mozilla.components.feature.privatemode.feature.SecureWindowFeature
import mozilla.components.feature.prompts.PromptFeature import mozilla.components.feature.prompts.PromptFeature
import mozilla.components.feature.prompts.share.ShareDelegate import mozilla.components.feature.prompts.share.ShareDelegate
@ -123,6 +123,8 @@ import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import mozilla.components.feature.media.fullscreen.MediaFullscreenOrientationFeature
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
/** /**
* Base fragment extended by [BrowserFragment]. * Base fragment extended by [BrowserFragment].
@ -165,6 +167,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>() private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>()
private var fullScreenMediaFeature = private var fullScreenMediaFeature =
ViewBoundFeatureWrapper<MediaFullscreenOrientationFeature>() ViewBoundFeatureWrapper<MediaFullscreenOrientationFeature>()
private var fullScreenMediaSessionFeature =
ViewBoundFeatureWrapper<MediaSessionFullscreenFeature>()
private val searchFeature = ViewBoundFeatureWrapper<SearchFeature>() private val searchFeature = ViewBoundFeatureWrapper<SearchFeature>()
private var pipFeature: PictureInPictureFeature? = null private var pipFeature: PictureInPictureFeature? = null
@ -392,14 +396,25 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
view = view view = view
) )
fullScreenMediaFeature.set( if (newMediaSessionApi) {
feature = MediaFullscreenOrientationFeature( fullScreenMediaSessionFeature.set(
requireActivity(), feature = MediaSessionFullscreenFeature(
context.components.core.store requireActivity(),
), context.components.core.store
owner = this, ),
view = view owner = this,
) view = view
)
} else {
fullScreenMediaFeature.set(
feature = MediaFullscreenOrientationFeature(
requireActivity(),
context.components.core.store
),
owner = this,
view = view
)
}
val downloadFeature = DownloadsFeature( val downloadFeature = DownloadsFeature(
context.applicationContext, context.applicationContext,

@ -39,7 +39,6 @@ import mozilla.components.concept.fetch.Client
import mozilla.components.feature.customtabs.store.CustomTabsServiceStore import mozilla.components.feature.customtabs.store.CustomTabsServiceStore
import mozilla.components.feature.downloads.DownloadMiddleware import mozilla.components.feature.downloads.DownloadMiddleware
import mozilla.components.feature.logins.exceptions.LoginExceptionStorage import mozilla.components.feature.logins.exceptions.LoginExceptionStorage
import mozilla.components.feature.media.middleware.MediaMiddleware
import mozilla.components.feature.media.middleware.RecordingDevicesMiddleware import mozilla.components.feature.media.middleware.RecordingDevicesMiddleware
import mozilla.components.feature.pwa.ManifestStorage import mozilla.components.feature.pwa.ManifestStorage
import mozilla.components.feature.pwa.WebAppShortcutManager import mozilla.components.feature.pwa.WebAppShortcutManager
@ -74,7 +73,6 @@ import org.mozilla.fenix.downloads.DownloadService
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.fenix.perf.lazyMonitored
import org.mozilla.fenix.media.MediaService
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
import org.mozilla.fenix.search.telemetry.incontent.InContentTelemetry import org.mozilla.fenix.search.telemetry.incontent.InContentTelemetry
import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.settings.SupportUtils
@ -82,6 +80,11 @@ import org.mozilla.fenix.settings.advanced.getSelectedLocale
import org.mozilla.fenix.utils.Mockable import org.mozilla.fenix.utils.Mockable
import org.mozilla.fenix.utils.getUndoDelay import org.mozilla.fenix.utils.getUndoDelay
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import mozilla.components.feature.media.MediaSessionFeature
import mozilla.components.feature.media.middleware.MediaMiddleware
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import org.mozilla.fenix.media.MediaService
import org.mozilla.fenix.media.MediaSessionService
/** /**
* Component group for all core browser functionality. * Component group for all core browser functionality.
@ -179,10 +182,9 @@ class Core(
* The [BrowserStore] holds the global [BrowserState]. * The [BrowserStore] holds the global [BrowserState].
*/ */
val store by lazyMonitored { val store by lazyMonitored {
BrowserStore( val middlewareList =
middleware = listOf( mutableListOf(
RecentlyClosedMiddleware(context, RECENTLY_CLOSED_MAX, engine), RecentlyClosedMiddleware(context, RECENTLY_CLOSED_MAX, engine),
MediaMiddleware(context, MediaService::class.java),
DownloadMiddleware(context, DownloadService::class.java), DownloadMiddleware(context, DownloadService::class.java),
ReaderViewMiddleware(), ReaderViewMiddleware(),
TelemetryMiddleware( TelemetryMiddleware(
@ -199,7 +201,14 @@ class Core(
migration = SearchMigration(context) migration = SearchMigration(context)
), ),
RecordingDevicesMiddleware(context) RecordingDevicesMiddleware(context)
) + EngineMiddleware.create(engine, ::findSessionById) )
if (!newMediaSessionApi) {
middlewareList.add(MediaMiddleware(context, MediaService::class.java))
}
BrowserStore(
middleware = middlewareList + EngineMiddleware.create(engine, ::findSessionById)
) )
} }
@ -278,6 +287,10 @@ class Core(
context, engine, icons, R.drawable.ic_status_logo, context, engine, icons, R.drawable.ic_status_logo,
permissionStorage.permissionsStorage, HomeActivity::class.java permissionStorage.permissionsStorage, HomeActivity::class.java
) )
if (newMediaSessionApi) {
MediaSessionFeature(context, MediaSessionService::class.java, store).start()
}
} }
} }

@ -7,24 +7,26 @@ package org.mozilla.fenix.home.intent
import android.content.Intent import android.content.Intent
import androidx.navigation.NavController import androidx.navigation.NavController
import mozilla.components.feature.media.service.AbstractMediaService import mozilla.components.feature.media.service.AbstractMediaService
import mozilla.components.feature.media.service.AbstractMediaSessionService
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
/** /**
* When the media notification is clicked we need to switch to the tab where the audio/video is * When the media notification is clicked we need to switch to the tab where the audio/video is
* playing. This intent has the following informations: * playing. This intent has the following informations:
* action - [AbstractMediaService.Companion.ACTION_SWITCH_TAB] * action - [AbstractMediaSessionService.Companion.ACTION_SWITCH_TAB]
* extra string for the tab id - [AbstractMediaService.Companion.EXTRA_TAB_ID] * extra string for the tab id - [AbstractMediaSessionService.Companion.EXTRA_TAB_ID]
*/ */
class OpenSpecificTabIntentProcessor( class OpenSpecificTabIntentProcessor(
private val activity: HomeActivity private val activity: HomeActivity
) : HomeIntentProcessor { ) : HomeIntentProcessor {
override fun process(intent: Intent, navController: NavController, out: Intent): Boolean { override fun process(intent: Intent, navController: NavController, out: Intent): Boolean {
if (intent.action == AbstractMediaService.Companion.ACTION_SWITCH_TAB) { if (intent.action == getAction()) {
val sessionManager = activity.components.core.sessionManager val sessionManager = activity.components.core.sessionManager
val sessionId = intent.extras?.getString(AbstractMediaService.Companion.EXTRA_TAB_ID) val sessionId = intent.extras?.getString(getTabId())
val session = sessionId?.let { sessionManager.findSessionById(it) } val session = sessionId?.let { sessionManager.findSessionById(it) }
if (session != null) { if (session != null) {
sessionManager.select(session) sessionManager.select(session)
@ -36,3 +38,19 @@ class OpenSpecificTabIntentProcessor(
return false return false
} }
} }
private fun getAction(): String {
return if (newMediaSessionApi) {
AbstractMediaSessionService.Companion.ACTION_SWITCH_TAB
} else {
AbstractMediaService.Companion.ACTION_SWITCH_TAB
}
}
private fun getTabId(): String {
return if (newMediaSessionApi) {
AbstractMediaSessionService.Companion.EXTRA_TAB_ID
} else {
AbstractMediaService.Companion.EXTRA_TAB_ID
}
}

@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.media
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.media.service.AbstractMediaSessionService
import org.mozilla.fenix.ext.components
/**
* [AbstractMediaSessionService] implementation for injecting [BrowserStore] singleton.
*/
class MediaSessionService : AbstractMediaSessionService() {
override val store: BrowserStore by lazy { components.core.store }
}

@ -13,7 +13,7 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatImageButton
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.tab_tray_grid_item.view.* import kotlinx.android.synthetic.main.tab_tray_grid_item.view.*
import mozilla.components.browser.state.state.MediaState import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.browser.tabstray.TabViewHolder import mozilla.components.browser.tabstray.TabViewHolder
import mozilla.components.browser.tabstray.TabsTrayStyling import mozilla.components.browser.tabstray.TabsTrayStyling
@ -21,24 +21,27 @@ import mozilla.components.browser.tabstray.thumbnail.TabThumbnailView
import mozilla.components.browser.toolbar.MAX_URI_LENGTH import mozilla.components.browser.toolbar.MAX_URI_LENGTH
import mozilla.components.concept.base.images.ImageLoadRequest import mozilla.components.concept.base.images.ImageLoadRequest
import mozilla.components.concept.base.images.ImageLoader import mozilla.components.concept.base.images.ImageLoader
import mozilla.components.concept.engine.mediasession.MediaSession
import mozilla.components.concept.tabstray.Tab import mozilla.components.concept.tabstray.Tab
import mozilla.components.concept.tabstray.TabsTray import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.feature.media.ext.pauseIfPlaying
import mozilla.components.feature.media.ext.playIfPaused
import mozilla.components.support.base.observer.Observable import mozilla.components.support.base.observer.Observable
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getMediaStateForSession
import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.ext.removeAndDisable import org.mozilla.fenix.ext.removeAndDisable
import org.mozilla.fenix.ext.removeTouchDelegate import org.mozilla.fenix.ext.removeTouchDelegate
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.ext.showAndEnable
import org.mozilla.fenix.ext.toShortUrl import org.mozilla.fenix.ext.toShortUrl
import org.mozilla.fenix.utils.Do
import kotlin.math.max import kotlin.math.max
import mozilla.components.browser.state.state.MediaState
import mozilla.components.feature.media.ext.pauseIfPlaying
import mozilla.components.feature.media.ext.playIfPaused
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import org.mozilla.fenix.ext.getMediaStateForSession
import org.mozilla.fenix.utils.Do
/** /**
* A RecyclerView ViewHolder implementation for "tab" items. * A RecyclerView ViewHolder implementation for "tab" items.
@ -68,6 +71,7 @@ class TabTrayViewHolder(
/** /**
* Displays the data of the given session and notifies the given observable about events. * Displays the data of the given session and notifies the given observable about events.
*/ */
@Suppress("ComplexMethod", "LongMethod")
override fun bind( override fun bind(
tab: Tab, tab: Tab,
isSelected: Boolean, isSelected: Boolean,
@ -94,49 +98,98 @@ class TabTrayViewHolder(
// Media state // Media state
playPauseButtonView.increaseTapArea(PLAY_PAUSE_BUTTON_EXTRA_DPS) playPauseButtonView.increaseTapArea(PLAY_PAUSE_BUTTON_EXTRA_DPS)
with(playPauseButtonView) {
invalidate()
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) {
MediaState.State.PAUSED -> {
showAndEnable()
contentDescription =
context.getString(R.string.mozac_feature_media_notification_action_play)
setImageDrawable(
AppCompatResources.getDrawable(context, R.drawable.media_state_play)
)
}
MediaState.State.PLAYING -> { if (newMediaSessionApi) {
showAndEnable() with(playPauseButtonView) {
contentDescription = invalidate()
context.getString(R.string.mozac_feature_media_notification_action_pause) val sessionState = store.state.findTabOrCustomTab(tab.id)
setImageDrawable( when (sessionState?.mediaSessionState?.playbackState) {
AppCompatResources.getDrawable(context, R.drawable.media_state_pause) MediaSession.PlaybackState.PAUSED -> {
) showAndEnable()
contentDescription =
context.getString(R.string.mozac_feature_media_notification_action_play)
setImageDrawable(
AppCompatResources.getDrawable(context, R.drawable.media_state_play)
)
}
MediaSession.PlaybackState.PLAYING -> {
showAndEnable()
contentDescription =
context.getString(R.string.mozac_feature_media_notification_action_pause)
setImageDrawable(
AppCompatResources.getDrawable(context, R.drawable.media_state_pause)
)
}
else -> {
removeTouchDelegate()
removeAndDisable()
}
} }
MediaState.State.NONE -> { setOnClickListener {
removeTouchDelegate() when (sessionState?.mediaSessionState?.playbackState) {
removeAndDisable() MediaSession.PlaybackState.PLAYING -> {
metrics.track(Event.TabMediaPause)
sessionState.mediaSessionState?.controller?.pause()
}
MediaSession.PlaybackState.PAUSED -> {
metrics.track(Event.TabMediaPlay)
sessionState.mediaSessionState?.controller?.play()
}
else -> throw AssertionError(
"Play/Pause button clicked without play/pause state."
)
}
} }
} }
} } else {
with(playPauseButtonView) {
invalidate()
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) {
MediaState.State.PAUSED -> {
showAndEnable()
contentDescription =
context.getString(R.string.mozac_feature_media_notification_action_play)
setImageDrawable(
AppCompatResources.getDrawable(context, R.drawable.media_state_play)
)
}
playPauseButtonView.setOnClickListener { MediaState.State.PLAYING -> {
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) { showAndEnable()
MediaState.State.PLAYING -> { contentDescription =
metrics.track(Event.TabMediaPause) context.getString(R.string.mozac_feature_media_notification_action_pause)
store.state.media.pauseIfPlaying() setImageDrawable(
} AppCompatResources.getDrawable(context, R.drawable.media_state_pause)
)
}
MediaState.State.PAUSED -> { MediaState.State.NONE -> {
metrics.track(Event.TabMediaPlay) removeTouchDelegate()
store.state.media.playIfPaused() removeAndDisable()
}
} }
}
playPauseButtonView.setOnClickListener {
Do exhaustive when (store.state.getMediaStateForSession(tab.id)) {
MediaState.State.PLAYING -> {
metrics.track(Event.TabMediaPause)
store.state.media.pauseIfPlaying()
}
MediaState.State.NONE -> throw AssertionError( MediaState.State.PAUSED -> {
"Play/Pause button clicked without play/pause state." metrics.track(Event.TabMediaPlay)
) store.state.media.playIfPaused()
}
MediaState.State.NONE -> throw AssertionError(
"Play/Pause button clicked without play/pause state."
)
}
} }
} }

@ -14,12 +14,14 @@ import io.mockk.verifyOrder
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import mozilla.components.feature.media.service.AbstractMediaService import mozilla.components.feature.media.service.AbstractMediaService
import mozilla.components.feature.media.service.AbstractMediaSessionService
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -78,8 +80,13 @@ class OpenSpecificTabIntentProcessorTest {
@Test @Test
fun `GIVEN an intent with correct action and extra string, WHEN it is processed, THEN session should be selected and openToBrowser should be called`() { fun `GIVEN an intent with correct action and extra string, WHEN it is processed, THEN session should be selected and openToBrowser should be called`() {
val intent = Intent().apply { val intent = Intent().apply {
action = AbstractMediaService.Companion.ACTION_SWITCH_TAB if (newMediaSessionApi) {
putExtra(AbstractMediaService.Companion.EXTRA_TAB_ID, TEST_SESSION_ID) action = AbstractMediaSessionService.Companion.ACTION_SWITCH_TAB
putExtra(AbstractMediaSessionService.Companion.EXTRA_TAB_ID, TEST_SESSION_ID)
} else {
action = AbstractMediaService.Companion.ACTION_SWITCH_TAB
putExtra(AbstractMediaService.Companion.EXTRA_TAB_ID, TEST_SESSION_ID)
}
} }
val sessionManager: SessionManager = mockk(relaxed = true) val sessionManager: SessionManager = mockk(relaxed = true)
val session: Session = mockk(relaxed = true) val session: Session = mockk(relaxed = true)

@ -15,17 +15,23 @@ import io.mockk.just
import io.mockk.mockk import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.ContentState
import mozilla.components.browser.state.state.MediaSessionState
import mozilla.components.browser.state.state.MediaState import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.browser.toolbar.MAX_URI_LENGTH import mozilla.components.browser.toolbar.MAX_URI_LENGTH
import mozilla.components.concept.tabstray.Tab import mozilla.components.concept.tabstray.Tab
import mozilla.components.concept.base.images.ImageLoadRequest import mozilla.components.concept.base.images.ImageLoadRequest
import mozilla.components.concept.base.images.ImageLoader import mozilla.components.concept.base.images.ImageLoader
import mozilla.components.concept.engine.mediasession.MediaSession
import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.fenix.FeatureFlags.newMediaSessionApi
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -36,6 +42,8 @@ class TabTrayViewHolderTest {
private lateinit var view: View private lateinit var view: View
@MockK private lateinit var imageLoader: ImageLoader @MockK private lateinit var imageLoader: ImageLoader
@MockK private lateinit var store: BrowserStore @MockK private lateinit var store: BrowserStore
@MockK private lateinit var sessionState: SessionState
@MockK private lateinit var mediaSessionState: MediaSessionState
@MockK private lateinit var metrics: MetricController @MockK private lateinit var metrics: MetricController
private var state = BrowserState() private var state = BrowserState()
@ -74,14 +82,33 @@ class TabTrayViewHolderTest {
id = "123", id = "123",
url = "https://example.com" url = "https://example.com"
) )
state = state.copy(
media = MediaState( if (newMediaSessionApi) {
aggregate = MediaState.Aggregate( state = state.copy(
activeTabId = "123", tabs = listOf(
state = MediaState.State.PAUSED TabSessionState(
id = "123",
content = ContentState(
url = "https://example.com",
searchTerms = "search terms"
),
mediaSessionState = mediaSessionState
)
) )
) )
)
every { mediaSessionState.playbackState } answers { MediaSession.PlaybackState.PAUSED }
} else {
state = state.copy(
media = MediaState(
aggregate = MediaState.Aggregate(
activeTabId = "123",
state = MediaState.State.PAUSED
)
)
)
}
tabViewHolder.bind(tab, false, mockk(), mockk()) tabViewHolder.bind(tab, false, mockk(), mockk())
assertEquals("Play", playPauseButtonView.contentDescription) assertEquals("Play", playPauseButtonView.contentDescription)
@ -96,14 +123,33 @@ class TabTrayViewHolderTest {
id = "123", id = "123",
url = "https://example.com" url = "https://example.com"
) )
state = state.copy(
media = MediaState( if (newMediaSessionApi) {
aggregate = MediaState.Aggregate( state = state.copy(
activeTabId = "123", tabs = listOf(
state = MediaState.State.PLAYING TabSessionState(
id = "123",
content = ContentState(
url = "https://example.com",
searchTerms = "search terms"
),
mediaSessionState = mediaSessionState
)
) )
) )
)
every { mediaSessionState.playbackState } answers { MediaSession.PlaybackState.PLAYING }
} else {
state = state.copy(
media = MediaState(
aggregate = MediaState.Aggregate(
activeTabId = "123",
state = MediaState.State.PLAYING
)
)
)
}
tabViewHolder.bind(tab, false, mockk(), mockk()) tabViewHolder.bind(tab, false, mockk(), mockk())
assertEquals("Pause", playPauseButtonView.contentDescription) assertEquals("Pause", playPauseButtonView.contentDescription)

Loading…
Cancel
Save