<commit_before>package com.example.android.uamp.media

import android.app.PendingIntent
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.support.v4.media.session.MediaControllerCompat
import android.support.v4.media.session.MediaSessionCompat
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import kotlinx.coroutines.*

const val NOW_PLAYING_CHANNEL: String = "com.example.android.uamp.media.NOW_PLAYING"
const val NOW_PLAYING_NOTIFICATION: Int = 0xb339

/**
 * A wrapper class for ExoPlayer's PlayerNotificationManager. It sets up the notification shown to
 * the user during audio playback and provides track metadata, such as track title and icon image.
 */
class UampNotificationManager(private val context: Context,
                              player: ExoPlayer,
                              sessionToken : MediaSessionCompat.Token,
                              notificationListener: PlayerNotificationManager.NotificationListener) {

    private val serviceJob = SupervisorJob()
    private val serviceScope = CoroutineScope(Dispatchers.Main + serviceJob)
    private val notificationManager : PlayerNotificationManager

    init {
        val mediaController = MediaControllerCompat(context, sessionToken)

        notificationManager = PlayerNotificationManager(
                context,
                NOW_PLAYING_CHANNEL,
                NOW_PLAYING_NOTIFICATION,
                DescriptionAdapter(mediaController),
                notificationListener).apply {

            setPlayer(player)
            setMediaSessionToken(sessionToken)
            setSmallIcon(R.drawable.ic_notification)

            // Don't display the rewind or fast-forward buttons.
            setRewindIncrementMs(0)
            setFastForwardIncrementMs(0)

            // Display the stop buton. This can be used to easily stop playback and dismiss the
            // notification.
            setUseStopAction(true)
        }
    }

    fun removeNotification(){
        notificationManager.setPlayer(null)
    }

    private inner class DescriptionAdapter(private val controller: MediaControllerCompat)
        : PlayerNotificationManager.MediaDescriptionAdapter {

        var currentIconUri: Uri? = null
        var currentBitmap: Bitmap? = null

        override fun createCurrentContentIntent(player: Player?): PendingIntent? = controller.sessionActivity

        override fun getCurrentContentText(player: Player?): String? = controller.metadata.description.subtitle.toString()

        override fun getCurrentContentTitle(player: Player?): String = controller.metadata.description.title.toString()

        override fun getCurrentLargeIcon(player: Player?,
                                         callback: PlayerNotificationManager.BitmapCallback?): Bitmap? {

            val iconUri = controller.metadata.description.iconUri
            return if (currentIconUri != iconUri || currentBitmap == null) {

                // Cache the bitmap for the current song so that successive calls to
                // `getCurrentLargeIcon` don't cause the bitmap to be recreated.
                currentIconUri = iconUri
                serviceScope.launch {
                    currentBitmap = iconUri?.let {
                        resolveUriAsBitmap(it)
                    }
                    callback?.onBitmap(currentBitmap)
                }
                null
            } else {
                currentBitmap
            }
        }

        private suspend fun resolveUriAsBitmap(uri: Uri): Bitmap? {
            return withContext(Dispatchers.IO) {
                val parcelFileDescriptor =
                        context.contentResolver.openFileDescriptor(uri, MODE_READ_ONLY)
                                ?: return@withContext null
                val fileDescriptor = parcelFileDescriptor.fileDescriptor
                BitmapFactory.decodeFileDescriptor(fileDescriptor).apply {
                    parcelFileDescriptor.close()
                }
            }
        }
    }
}

private const val MODE_READ_ONLY = "r"<commit_msg>Stop Android Studio from using import.*<commit_after>package com.example.android.uamp.media

import android.app.PendingIntent
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.support.v4.media.session.MediaControllerCompat
import android.support.v4.media.session.MediaSessionCompat
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

const val NOW_PLAYING_CHANNEL: String = "com.example.android.uamp.media.NOW_PLAYING"
const val NOW_PLAYING_NOTIFICATION: Int = 0xb339

/**
 * A wrapper class for ExoPlayer's PlayerNotificationManager. It sets up the notification shown to
 * the user during audio playback and provides track metadata, such as track title and icon image.
 */
class UampNotificationManager(private val context: Context,
                              player: ExoPlayer,
                              sessionToken : MediaSessionCompat.Token,
                              notificationListener: PlayerNotificationManager.NotificationListener) {

    private val serviceJob = SupervisorJob()
    private val serviceScope = CoroutineScope(Dispatchers.Main + serviceJob)
    private val notificationManager : PlayerNotificationManager

    init {
        val mediaController = MediaControllerCompat(context, sessionToken)

        notificationManager = PlayerNotificationManager(
                context,
                NOW_PLAYING_CHANNEL,
                NOW_PLAYING_NOTIFICATION,
                DescriptionAdapter(mediaController),
                notificationListener).apply {

            setPlayer(player)
            setMediaSessionToken(sessionToken)
            setSmallIcon(R.drawable.ic_notification)

            // Don't display the rewind or fast-forward buttons.
            setRewindIncrementMs(0)
            setFastForwardIncrementMs(0)

            // Display the stop buton. This can be used to easily stop playback and dismiss the
            // notification.
            setUseStopAction(true)
        }
    }

    fun removeNotification(){
        notificationManager.setPlayer(null)
    }

    private inner class DescriptionAdapter(private val controller: MediaControllerCompat)
        : PlayerNotificationManager.MediaDescriptionAdapter {

        var currentIconUri: Uri? = null
        var currentBitmap: Bitmap? = null

        override fun createCurrentContentIntent(player: Player?): PendingIntent? = controller.sessionActivity

        override fun getCurrentContentText(player: Player?): String? = controller.metadata.description.subtitle.toString()

        override fun getCurrentContentTitle(player: Player?): String = controller.metadata.description.title.toString()

        override fun getCurrentLargeIcon(player: Player?,
                                         callback: PlayerNotificationManager.BitmapCallback?): Bitmap? {

            val iconUri = controller.metadata.description.iconUri
            return if (currentIconUri != iconUri || currentBitmap == null) {

                // Cache the bitmap for the current song so that successive calls to
                // `getCurrentLargeIcon` don't cause the bitmap to be recreated.
                currentIconUri = iconUri
                serviceScope.launch {
                    currentBitmap = iconUri?.let {
                        resolveUriAsBitmap(it)
                    }
                    callback?.onBitmap(currentBitmap)
                }
                null
            } else {
                currentBitmap
            }
        }

        private suspend fun resolveUriAsBitmap(uri: Uri): Bitmap? {
            return withContext(Dispatchers.IO) {
                val parcelFileDescriptor =
                        context.contentResolver.openFileDescriptor(uri, MODE_READ_ONLY)
                                ?: return@withContext null
                val fileDescriptor = parcelFileDescriptor.fileDescriptor
                BitmapFactory.decodeFileDescriptor(fileDescriptor).apply {
                    parcelFileDescriptor.close()
                }
            }
        }
    }
}

private const val MODE_READ_ONLY = "r"
{'fraction_non_alphanumeric': 0.06298940580377706, 'fraction_numerical': 0.002533394748963611, 'mean_word_length': 2.349402236791361, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '378831', 'n_tokens_mistral': 2067, 'n_tokens_neox': 1947, 'n_words': 482}