From c27d2d0d55587862777718f0eda186bbd61dae84 Mon Sep 17 00:00:00 2001
From: Ryan Harg <ryan.harg@mailbox.org>
Date: Mon, 5 Dec 2022 14:11:45 +0100
Subject: [PATCH] Update Exoplayer all the way to 2.18.1

---
 app/build.gradle.kts                          | 17 +++-------
 app/src/main/AndroidManifest.xml              |  9 ++++--
 .../funkwhale/ffa/activities/MainActivity.kt  |  6 ++--
 .../ffa/playback/MediaControlsManager.kt      |  3 +-
 .../funkwhale/ffa/playback/MediaSession.kt    | 14 ++++----
 .../funkwhale/ffa/playback/PinService.kt      |  5 ++-
 .../funkwhale/ffa/playback/PlayerService.kt   | 24 ++++++--------
 .../funkwhale/ffa/playback/QueueManager.kt    | 32 +++++++++++++++----
 .../ffa/repositories/SearchRepository.kt      |  2 +-
 .../ffa/repositories/TracksRepository.kt      |  2 +-
 .../audio/funkwhale/ffa/utils/Extensions.kt   |  3 --
 .../funkwhale/ffa/views/NowPlayingView.kt     |  8 ++---
 12 files changed, 68 insertions(+), 57 deletions(-)

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f93b57f1..bf4cabbb 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -52,7 +52,7 @@ android {
     disable += listOf("MissingTranslation", "ExtraTranslation")
   }
 
-  compileSdk = 31
+  compileSdk = 33
 
   defaultConfig {
 
@@ -62,7 +62,7 @@ android {
     versionName = androidGitVersion.name()
 
     minSdk = 24
-    targetSdk = 30
+    targetSdk = 33
 
     testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
 
@@ -167,21 +167,14 @@ dependencies {
   implementation("com.google.android.material:material:1.6.1")
   implementation("com.android.support.constraint:constraint-layout:2.0.4")
 
-  implementation("com.google.android.exoplayer:exoplayer-core:2.14.2")
-  implementation("com.google.android.exoplayer:exoplayer-ui:2.14.2")
-  implementation("com.google.android.exoplayer:extension-mediasession:2.14.2")
+  implementation("com.google.android.exoplayer:exoplayer-core:2.18.1")
+  implementation("com.google.android.exoplayer:exoplayer-ui:2.18.1")
+  implementation("com.google.android.exoplayer:extension-mediasession:2.18.1")
 
   implementation("io.insert-koin:koin-core:3.1.2")
   implementation("io.insert-koin:koin-android:3.1.2")
   testImplementation("io.insert-koin:koin-test:3.1.2")
 
-  implementation("com.github.PaulWoitaschek.ExoPlayer-Extensions:extension-opus:2.14.0") {
-    isTransitive = false
-  }
-  implementation("com.github.PaulWoitaschek.ExoPlayer-Extensions:extension-flac:2.14.0") {
-    isTransitive = false
-  }
-
   implementation("com.aliassadi:power-preference-lib:2.0.0")
   implementation("com.github.kittinunf.fuel:fuel:2.3.1")
   implementation("com.github.kittinunf.fuel:fuel-coroutines:2.3.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b6e41263..a417e9e8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,7 +22,8 @@
             android:name=".activities.SplashActivity"
             android:launchMode="singleInstance"
             android:noHistory="true"
-            android:screenOrientation="portrait">
+            android:screenOrientation="portrait"
+            android:exported="true">
 
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -61,7 +62,8 @@
 
         <service
             android:name=".playback.PlayerService"
-            android:foregroundServiceType="mediaPlayback">
+            android:foregroundServiceType="mediaPlayback"
+            android:exported="false">
 
             <intent-filter>
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
@@ -80,7 +82,8 @@
 
         </service>
 
-        <receiver android:name="androidx.media.session.MediaButtonReceiver">
+        <receiver android:name="androidx.media.session.MediaButtonReceiver"
+            android:exported="false">
             <intent-filter>
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
             </intent-filter>
diff --git a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
index 14d8939e..ee77457c 100644
--- a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt
@@ -228,8 +228,8 @@ class MainActivity : AppCompatActivity() {
           item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW)
           item.actionView = View(this)
           item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
-            override fun onMenuItemActionExpand(item: MenuItem?) = false
-            override fun onMenuItemActionCollapse(item: MenuItem?) = false
+            override fun onMenuItemActionExpand(item: MenuItem) = false
+            override fun onMenuItemActionCollapse(item: MenuItem) = false
           })
 
           item.isChecked = !item.isChecked
@@ -359,7 +359,7 @@ class MainActivity : AppCompatActivity() {
               .alpha(0.0f)
               .setDuration(400)
               .setListener(object : AnimatorListenerAdapter() {
-                override fun onAnimationEnd(animator: Animator?) {
+                override fun onAnimationEnd(animator: Animator) {
                   binding.nowPlaying.visibility = View.GONE
                 }
               })
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt b/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
index 36b5302f..73ee5b5a 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/MediaControlsManager.kt
@@ -2,6 +2,7 @@ package audio.funkwhale.ffa.playback
 
 import android.app.Notification
 import android.app.PendingIntent
+import android.app.PendingIntent.FLAG_MUTABLE
 import android.app.Service
 import android.content.Intent
 import android.support.v4.media.session.MediaSessionCompat
@@ -42,7 +43,7 @@ class MediaControlsManager(val context: Service, private val scope: CoroutineSco
 
       scope.launch(Default) {
         val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() }
-        val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0)
+        val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, FLAG_MUTABLE)
 
         val coverUrl = maybeNormalizeUrl(track.album?.cover())
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt b/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
index 8898309b..5e0a5d51 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt
@@ -9,7 +9,6 @@ import android.support.v4.media.session.MediaSessionCompat
 import android.support.v4.media.session.PlaybackStateCompat
 import audio.funkwhale.ffa.utils.Command
 import audio.funkwhale.ffa.utils.CommandBus
-import com.google.android.exoplayer2.ControlDispatcher
 import com.google.android.exoplayer2.Player
 import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
 
@@ -43,7 +42,7 @@ class MediaSession(private val context: Context) {
     MediaSessionConnector(session).also {
       it.setQueueNavigator(FFAQueueNavigator())
 
-      it.setMediaButtonEventHandler { _, _, intent ->
+      it.setMediaButtonEventHandler { _, intent ->
         if (!active) {
           Intent(context, PlayerService::class.java).let { player ->
             player.action = intent.action
@@ -67,13 +66,14 @@ class MediaSession(private val context: Context) {
 }
 
 class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
-  override fun onSkipToQueueItem(player: Player, controlDispatcher: ControlDispatcher, id: Long) {
+  override fun onSkipToQueueItem(player: Player, id: Long) {
     CommandBus.send(Command.PlayTrack(id.toInt()))
   }
 
-  override fun onCurrentWindowIndexChanged(player: Player) {}
+  override fun onCurrentMediaItemIndexChanged(player: Player) {}
 
-  override fun onCommand(player: Player, controlDispatcher: ControlDispatcher, command: String, extras: Bundle?, cb: ResultReceiver?) = true
+  override fun onCommand(player: Player, command: String, extras: Bundle?, cb: ResultReceiver?) =
+    true
 
   override fun getSupportedQueueNavigatorActions(player: Player): Long {
     return PlaybackStateCompat.ACTION_PLAY_PAUSE or
@@ -82,13 +82,13 @@ class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
       PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
   }
 
-  override fun onSkipToNext(player: Player, controlDispatcher: ControlDispatcher) {
+  override fun onSkipToNext(player: Player) {
     CommandBus.send(Command.NextTrack)
   }
 
   override fun getActiveQueueItemId(player: Player?) = player?.currentWindowIndex?.toLong() ?: 0
 
-  override fun onSkipToPrevious(player: Player, controlDispatcher: ControlDispatcher) {
+  override fun onSkipToPrevious(player: Player) {
     CommandBus.send(Command.PreviousTrack)
   }
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt b/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
index f3bd1cea..5993800a 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/PinService.kt
@@ -80,7 +80,10 @@ class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {
 
   override fun getScheduler(): Scheduler? = null
 
-  override fun getForegroundNotification(downloads: MutableList<Download>): Notification {
+  override fun getForegroundNotification(
+    downloads: MutableList<Download>,
+    notMetRequirements: Int
+  ): Notification {
     val description =
       resources.getQuantityString(R.plurals.downloads_description, downloads.size, downloads.size)
 
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt b/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
index 9c74da5c..f0bf3367 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/PlayerService.kt
@@ -31,11 +31,10 @@ import audio.funkwhale.ffa.utils.log
 import audio.funkwhale.ffa.utils.maybeNormalizeUrl
 import audio.funkwhale.ffa.utils.onApi
 import com.google.android.exoplayer2.C
-import com.google.android.exoplayer2.ExoPlaybackException
+import com.google.android.exoplayer2.PlaybackException
 import com.google.android.exoplayer2.Player
 import com.google.android.exoplayer2.SimpleExoPlayer
-import com.google.android.exoplayer2.source.TrackGroupArray
-import com.google.android.exoplayer2.trackselection.TrackSelectionArray
+import com.google.android.exoplayer2.Tracks
 import com.squareup.picasso.Picasso
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers.IO
@@ -43,7 +42,6 @@ import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.koin.java.KoinJavaComponent.inject
@@ -136,6 +134,7 @@ class PlayerService : Service() {
       playWhenReady = false
 
       playerEventListener = PlayerEventListener().also {
+
         addListener(it)
       }
     }
@@ -419,9 +418,9 @@ class PlayerService : Service() {
   }
 
   @SuppressLint("NewApi")
-  inner class PlayerEventListener : Player.EventListener {
+  inner class PlayerEventListener : Player.Listener {
     override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
-      super.onPlayerStateChanged(playWhenReady, playbackState)
+      super.onPlayWhenReadyChanged(playWhenReady, playbackState)
 
       EventBus.send(Event.StateChanged(playWhenReady))
 
@@ -469,14 +468,11 @@ class PlayerService : Service() {
       }
     }
 
-    override fun onTracksChanged(
-      trackGroups: TrackGroupArray,
-      trackSelections: TrackSelectionArray
-    ) {
-      super.onTracksChanged(trackGroups, trackSelections)
+    override fun onTracksChanged(tracks: Tracks) {
+      super.onTracksChanged(tracks)
 
-      if (queue.current != player.currentWindowIndex) {
-        queue.current = player.currentWindowIndex
+      if (queue.current != player.currentMediaItemIndex) {
+        queue.current = player.currentMediaItemIndex
         mediaControlsManager.updateNotification(queue.current(), player.playWhenReady)
       }
 
@@ -510,7 +506,7 @@ class PlayerService : Service() {
       }
     }
 
-    override fun onPlayerError(error: ExoPlaybackException) {
+    override fun onPlayerError(error: PlaybackException) {
       EventBus.send(Event.PlaybackError(getString(R.string.error_playback)))
 
       if (player.playWhenReady) {
diff --git a/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt b/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
index fe9bf315..c883390a 100644
--- a/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt
@@ -12,6 +12,7 @@ import audio.funkwhale.ffa.utils.FFACache
 import audio.funkwhale.ffa.utils.log
 import audio.funkwhale.ffa.utils.mustNormalizeUrl
 import com.github.kittinunf.fuel.gson.gsonDeserializerOf
+import com.google.android.exoplayer2.MediaItem
 import com.google.android.exoplayer2.source.ConcatenatingMediaSource
 import com.google.android.exoplayer2.source.ProgressiveMediaSource
 import com.google.gson.Gson
@@ -37,9 +38,12 @@ class QueueManager(val context: Context) {
         dataSources.addMediaSources(
           metadata.map { track ->
             val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
-
-            ProgressiveMediaSource.Factory(factory).setTag(track.title)
-              .createMediaSource(Uri.parse(url))
+            ProgressiveMediaSource.Factory(factory).createMediaSource(
+              MediaItem.Builder()
+                .setTag(track.title)
+                .setUri(Uri.parse(url))
+                .build()
+            )
           }
         )
       }
@@ -63,8 +67,12 @@ class QueueManager(val context: Context) {
     val factory = cacheDataSourceFactoryProvider.create(context)
     val sources = tracks.map { track ->
       val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
-
-      ProgressiveMediaSource.Factory(factory).setTag(track.title).createMediaSource(Uri.parse(url))
+      ProgressiveMediaSource.Factory(factory).createMediaSource(
+        MediaItem.Builder()
+          .setTag(track.title)
+          .setUri(Uri.parse(url))
+          .build()
+      )
     }
 
     metadata = tracks.toMutableList()
@@ -84,7 +92,12 @@ class QueueManager(val context: Context) {
     val sources = missingTracks.map { track ->
       val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
 
-      ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url))
+      ProgressiveMediaSource.Factory(factory).createMediaSource(
+        MediaItem.Builder()
+          .setTag(track.title) // was this missing on purpose?!
+          .setUri(Uri.parse(url))
+          .build()
+      )
     }
 
     metadata.addAll(tracks)
@@ -101,7 +114,12 @@ class QueueManager(val context: Context) {
     val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
 
     if (metadata.indexOf(track) == -1) {
-      ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url)).let {
+      ProgressiveMediaSource.Factory(factory).createMediaSource(
+        MediaItem.Builder()
+          .setTag(track.title) // was this missing on purpose?!
+          .setUri(Uri.parse(url))
+          .build()
+      ).let {
         dataSources.addMediaSource(current + 1, it)
         metadata.add(current + 1, track)
       }
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
index ee32d642..60021e16 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/SearchRepository.kt
@@ -11,8 +11,8 @@ import audio.funkwhale.ffa.model.Track
 import audio.funkwhale.ffa.model.TracksCache
 import audio.funkwhale.ffa.model.TracksResponse
 import audio.funkwhale.ffa.utils.OAuth
-import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import audio.funkwhale.ffa.utils.mustNormalizeUrl
+import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.android.exoplayer2.offline.DownloadManager
 import com.google.android.exoplayer2.upstream.cache.Cache
 import com.google.gson.reflect.TypeToken
diff --git a/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt b/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
index 7858bf00..7a224c61 100644
--- a/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/repositories/TracksRepository.kt
@@ -7,8 +7,8 @@ import audio.funkwhale.ffa.model.TracksCache
 import audio.funkwhale.ffa.model.TracksResponse
 import audio.funkwhale.ffa.utils.OAuth
 import audio.funkwhale.ffa.utils.getMetadata
-import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import audio.funkwhale.ffa.utils.mustNormalizeUrl
+import com.github.kittinunf.fuel.gson.gsonDeserializerOf
 import com.google.android.exoplayer2.offline.Download
 import com.google.android.exoplayer2.offline.DownloadManager
 import com.google.android.exoplayer2.upstream.cache.Cache
diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt b/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
index 7fb81232..fbd5e81c 100644
--- a/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/utils/Extensions.kt
@@ -10,10 +10,8 @@ import audio.funkwhale.ffa.model.DownloadInfo
 import audio.funkwhale.ffa.repositories.Repository
 import com.github.kittinunf.fuel.core.FuelError
 import com.github.kittinunf.fuel.core.Request
-import com.github.kittinunf.fuel.core.ResponseDeserializable
 import com.google.android.exoplayer2.offline.Download
 import com.google.gson.Gson
-import com.google.gson.reflect.TypeToken
 import com.squareup.picasso.Picasso
 import com.squareup.picasso.RequestCreator
 import kotlinx.coroutines.CompletableDeferred
@@ -23,7 +21,6 @@ import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import net.openid.appauth.ClientSecretPost
-import java.io.Reader
 import java.text.SimpleDateFormat
 import java.util.Date
 import kotlin.coroutines.CoroutineContext
diff --git a/app/src/main/java/audio/funkwhale/ffa/views/NowPlayingView.kt b/app/src/main/java/audio/funkwhale/ffa/views/NowPlayingView.kt
index d4133b0a..7ad73746 100644
--- a/app/src/main/java/audio/funkwhale/ffa/views/NowPlayingView.kt
+++ b/app/src/main/java/audio/funkwhale/ffa/views/NowPlayingView.kt
@@ -52,7 +52,7 @@ class NowPlayingView : MaterialCardView {
       viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
         override fun onGlobalLayout() {
           gestureDetectorCallback = OnGestureDetection()
-          gestureDetector = GestureDetector(context, gestureDetectorCallback)
+          gestureDetector = GestureDetector(context, gestureDetectorCallback!!)
 
           setOnTouchListener { _, motionEvent ->
             val ret = gestureDetector?.onTouchEvent(motionEvent) ?: false
@@ -128,8 +128,8 @@ class NowPlayingView : MaterialCardView {
     }
 
     override fun onFling(
-      firstMotionEvent: MotionEvent?,
-      secondMotionEvent: MotionEvent?,
+      firstMotionEvent: MotionEvent,
+      secondMotionEvent: MotionEvent,
       velocityX: Float,
       velocityY: Float
     ): Boolean {
@@ -195,7 +195,7 @@ class NowPlayingView : MaterialCardView {
       return true
     }
 
-    override fun onSingleTapUp(e: MotionEvent?): Boolean {
+    override fun onSingleTapUp(e: MotionEvent): Boolean {
       layoutParams.let {
         if (height != minHeight) return true
 
-- 
GitLab