From 85800eff1d231413c804ebb6a5ff0d431b3ae8ed Mon Sep 17 00:00:00 2001 From: Karl Schults Date: Tue, 5 Dec 2023 11:17:09 -0500 Subject: [PATCH] [APT-9543] Refactor common pieces for header-aware media --- .../com/scribd/armadillo/di/PlaybackModule.kt | 6 +++ .../mediasource/DashMediaSourceGenerator.kt | 50 +++--------------- .../mediasource/HeadersMediaSourceHelper.kt | 10 ++++ .../HeadersMediaSourceHelperImpl.kt | 52 +++++++++++++++++++ .../mediasource/HlsMediaSourceGenerator.kt | 47 +++-------------- 5 files changed, 80 insertions(+), 85 deletions(-) create mode 100644 Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelper.kt create mode 100644 Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelperImpl.kt diff --git a/Armadillo/src/main/java/com/scribd/armadillo/di/PlaybackModule.kt b/Armadillo/src/main/java/com/scribd/armadillo/di/PlaybackModule.kt index 092405a..9ecaa41 100644 --- a/Armadillo/src/main/java/com/scribd/armadillo/di/PlaybackModule.kt +++ b/Armadillo/src/main/java/com/scribd/armadillo/di/PlaybackModule.kt @@ -15,6 +15,8 @@ import com.scribd.armadillo.playback.MediaMetadataCompatBuilderImpl import com.scribd.armadillo.playback.PlaybackEngineFactoryHolder import com.scribd.armadillo.playback.PlaybackStateBuilderImpl import com.scribd.armadillo.playback.PlaybackStateCompatBuilder +import com.scribd.armadillo.playback.mediasource.HeadersMediaSourceHelper +import com.scribd.armadillo.playback.mediasource.HeadersMediaSourceHelperImpl import com.scribd.armadillo.playback.mediasource.MediaSourceRetriever import com.scribd.armadillo.playback.mediasource.MediaSourceRetrieverImpl import dagger.Module @@ -56,4 +58,8 @@ internal class PlaybackModule { @Provides @Singleton fun mediaSourceRetriever(mediaSourceRetrieverImpl: MediaSourceRetrieverImpl): MediaSourceRetriever = mediaSourceRetrieverImpl + + @Provides + @Singleton + fun mediaSourceHelper(mediaSourceHelperImpl: HeadersMediaSourceHelperImpl): HeadersMediaSourceHelper = mediaSourceHelperImpl } \ No newline at end of file diff --git a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/DashMediaSourceGenerator.kt b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/DashMediaSourceGenerator.kt index eeb593b..be5b637 100644 --- a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/DashMediaSourceGenerator.kt +++ b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/DashMediaSourceGenerator.kt @@ -6,69 +6,31 @@ import com.google.android.exoplayer2.offline.Download import com.google.android.exoplayer2.offline.DownloadHelper import com.google.android.exoplayer2.source.MediaSource import com.google.android.exoplayer2.source.dash.DashMediaSource -import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DefaultDataSource -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource -import com.scribd.armadillo.Constants -import com.scribd.armadillo.HeadersStore -import com.scribd.armadillo.download.CacheManager import com.scribd.armadillo.download.DownloadTracker import com.scribd.armadillo.extensions.toUri import com.scribd.armadillo.models.AudioPlayable import javax.inject.Inject internal class DashMediaSourceGenerator @Inject constructor( - private val cacheManager: CacheManager, - private val headersStore: HeadersStore, + private val mediaSourceHelper: HeadersMediaSourceHelper, private val downloadTracker: DownloadTracker) : MediaSourceGenerator { - private val previousRequests = mutableMapOf() - override fun generateMediaSource(context: Context, request: AudioPlayable.MediaRequest): MediaSource { + val dataSourceFactory = mediaSourceHelper.createDataSourceFactory(context, request) + downloadTracker.getDownload(request.url.toUri())?.let { if (it.state != Download.STATE_FAILED) { - return DownloadHelper.createMediaSource(it.request, buildDataSourceFactory(context, request)) + return DownloadHelper.createMediaSource(it.request, dataSourceFactory) } } val mediaItem = MediaItem.Builder() .setUri(request.url) - .build() - return DashMediaSource.Factory(buildDataSourceFactory(context, request)) + return DashMediaSource.Factory(dataSourceFactory) .createMediaSource(mediaItem) } - override fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) { - previousRequests[request.url]?.let { factory -> - if (request.headers.isNotEmpty()) { - headersStore.keyForUrl(request.url)?.let { - headersStore.setHeaders(it, request.headers) - } - // Updating the factory instance updates future requests generated from this factory by ExoPlayer - factory.setDefaultRequestProperties(request.headers) - } - } - } - - private fun buildDataSourceFactory(context: Context, request: AudioPlayable.MediaRequest): DataSource.Factory { - val httpDataSourceFactory = DefaultHttpDataSource.Factory() - .setUserAgent(Constants.getUserAgent(context)) - .setConnectTimeoutMs(DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS) - .setReadTimeoutMs(DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS) - .setAllowCrossProtocolRedirects(true) - - previousRequests[request.url] = httpDataSourceFactory - if (request.headers.isNotEmpty()) { - headersStore.keyForUrl(request.url)?.let { - headersStore.setHeaders(it, request.headers) - } - httpDataSourceFactory.setDefaultRequestProperties(request.headers) - } - - val upstreamFactory = DefaultDataSource.Factory(context, httpDataSourceFactory) - return cacheManager.playbackDataSourceFactory(context, upstreamFactory) - } - + override fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) = mediaSourceHelper.updateMediaSourceHeaders(request) } \ No newline at end of file diff --git a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelper.kt b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelper.kt new file mode 100644 index 0000000..accb10d --- /dev/null +++ b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelper.kt @@ -0,0 +1,10 @@ +package com.scribd.armadillo.playback.mediasource + +import android.content.Context +import com.google.android.exoplayer2.upstream.DataSource +import com.scribd.armadillo.models.AudioPlayable + +internal interface HeadersMediaSourceHelper { + fun createDataSourceFactory(context: Context, request: AudioPlayable.MediaRequest): DataSource.Factory + fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) +} \ No newline at end of file diff --git a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelperImpl.kt b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelperImpl.kt new file mode 100644 index 0000000..644333c --- /dev/null +++ b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HeadersMediaSourceHelperImpl.kt @@ -0,0 +1,52 @@ +package com.scribd.armadillo.playback.mediasource + +import android.content.Context +import com.google.android.exoplayer2.upstream.DataSource +import com.google.android.exoplayer2.upstream.DefaultDataSource +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource +import com.scribd.armadillo.Constants +import com.scribd.armadillo.HeadersStore +import com.scribd.armadillo.download.CacheManager +import com.scribd.armadillo.models.AudioPlayable +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class HeadersMediaSourceHelperImpl @Inject constructor( + private val cacheManager: CacheManager, + private val headersStore: HeadersStore +): HeadersMediaSourceHelper { + private val previousRequests = mutableMapOf() + + override fun createDataSourceFactory(context: Context, request: AudioPlayable.MediaRequest): DataSource.Factory { + val httpDataSourceFactory = DefaultHttpDataSource.Factory() + .setUserAgent(Constants.getUserAgent(context)) + .setConnectTimeoutMs(DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS) + .setReadTimeoutMs(DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS) + .setAllowCrossProtocolRedirects(true) + + previousRequests[request.url] = httpDataSourceFactory + if (request.headers.isNotEmpty()) { + headersStore.keyForUrl(request.url)?.let { + headersStore.setHeaders(it, request.headers) + } + httpDataSourceFactory.setDefaultRequestProperties(request.headers) + } + + val upstreamFactory = DefaultDataSource.Factory(context, httpDataSourceFactory) + return cacheManager.playbackDataSourceFactory(context, upstreamFactory) + + } + + override fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) { + previousRequests[request.url]?.let { factory -> + if (request.headers.isNotEmpty()) { + headersStore.keyForUrl(request.url)?.let { + headersStore.setHeaders(it, request.headers) + } + // Updating the factory instance updates future requests generated from this factory by ExoPlayer + factory.setDefaultRequestProperties(request.headers) + } + } + } +} \ No newline at end of file diff --git a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HlsMediaSourceGenerator.kt b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HlsMediaSourceGenerator.kt index 71b8c5c..a8b5ece 100644 --- a/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HlsMediaSourceGenerator.kt +++ b/Armadillo/src/main/java/com/scribd/armadillo/playback/mediasource/HlsMediaSourceGenerator.kt @@ -6,12 +6,6 @@ import com.google.android.exoplayer2.offline.Download import com.google.android.exoplayer2.offline.DownloadHelper import com.google.android.exoplayer2.source.MediaSource import com.google.android.exoplayer2.source.hls.HlsMediaSource -import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DefaultDataSource -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource -import com.scribd.armadillo.Constants -import com.scribd.armadillo.HeadersStore -import com.scribd.armadillo.download.CacheManager import com.scribd.armadillo.download.DownloadTracker import com.scribd.armadillo.extensions.toUri import com.scribd.armadillo.models.AudioPlayable @@ -22,50 +16,21 @@ import javax.inject.Inject * */ internal class HlsMediaSourceGenerator @Inject constructor( - private val cacheManager: CacheManager, - private val headersStore: HeadersStore, + private val mediaSourceHelper: HeadersMediaSourceHelper, private val downloadTracker: DownloadTracker) : MediaSourceGenerator { - private val previousRequests = mutableMapOf() override fun generateMediaSource(context: Context, request: AudioPlayable.MediaRequest): MediaSource { + val dataSourceFactory = mediaSourceHelper.createDataSourceFactory(context, request) + downloadTracker.getDownload(request.url.toUri())?.let { if (it.state != Download.STATE_FAILED) { - return DownloadHelper.createMediaSource(it.request, buildDataSourceFactory(context, request)) + return DownloadHelper.createMediaSource(it.request, dataSourceFactory) } } - return HlsMediaSource.Factory(buildDataSourceFactory(context, request)) + return HlsMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(request.url)) } - override fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) { - previousRequests[request.url]?.let { factory -> - if (request.headers.isNotEmpty()) { - headersStore.keyForUrl(request.url)?.let { - headersStore.setHeaders(it, request.headers) - } - // Updating the factory instance updates future requests generated from this factory by ExoPlayer - factory.setDefaultRequestProperties(request.headers) - } - } - } - - private fun buildDataSourceFactory(context: Context, request: AudioPlayable.MediaRequest): DataSource.Factory { - val httpDataSourceFactory = DefaultHttpDataSource.Factory() - .setUserAgent(Constants.getUserAgent(context)) - .setConnectTimeoutMs(DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS) - .setReadTimeoutMs(DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS) - .setAllowCrossProtocolRedirects(true) - - previousRequests[request.url] = httpDataSourceFactory - if (request.headers.isNotEmpty()) { - headersStore.keyForUrl(request.url)?.let { - headersStore.setHeaders(it, request.headers) - } - httpDataSourceFactory.setDefaultRequestProperties(request.headers) - } - - val upstreamFactory = DefaultDataSource.Factory(context, httpDataSourceFactory) - return cacheManager.playbackDataSourceFactory(context, upstreamFactory) - } + override fun updateMediaSourceHeaders(request: AudioPlayable.MediaRequest) = mediaSourceHelper.updateMediaSourceHeaders(request) } \ No newline at end of file