Loading components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt +19 −34 Original line number Diff line number Diff line Loading @@ -4,9 +4,6 @@ package mozilla.components.feature.media.focus import android.content.Context import android.media.AudioAttributes import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build import mozilla.components.feature.media.ext.getMedia Loading @@ -23,19 +20,34 @@ import mozilla.components.support.base.log.logger.Logger * https://developer.android.com/guide/topics/media-apps/audio-focus */ internal class AudioFocus( private val context: Context val audioManager: AudioManager ) : AudioManager.OnAudioFocusChangeListener { private val logger = Logger("AudioFocus") private var playDelayed = false private var resumeOnFocusGain = false private val audioFocusController = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { AudioFocusControllerV26(audioManager, this) } else { AudioFocusControllerV21(audioManager, this) } @Synchronized fun request(state: MediaState) { val result = requestAudioFocusCompat(context, this) val result = audioFocusController.request() processAudioFocusResult(state, result) } @Synchronized fun abandon() { audioFocusController.abandon() playDelayed = false resumeOnFocusGain = false } private fun processAudioFocusResult(state: MediaState, result: Int) { logger.debug("processAudioFocusResult($result)") when (result) { AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { // Granted: Gecko already started playing media. Loading @@ -60,6 +72,8 @@ internal class AudioFocus( @Synchronized override fun onAudioFocusChange(focusChange: Int) { logger.debug("onAudioFocusChange($focusChange)") val state = MediaStateMachine.state when (focusChange) { Loading Loading @@ -93,32 +107,3 @@ internal class AudioFocus( } } } private fun requestAudioFocusCompat( context: Context, listener: AudioManager.OnAudioFocusChangeListener ): Int { val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { @Suppress("DEPRECATION") audioManager.requestAudioFocus( listener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) } else { audioManager.requestAudioFocus( AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() ) .setWillPauseWhenDucked(false) .setOnAudioFocusChangeListener(listener) .build() ) } } components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusController.kt 0 → 100644 +13 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus /** * A controller that knows how to request and abandon audio focus. */ internal interface AudioFocusController { fun request(): Int fun abandon() } components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV21.kt 0 → 100644 +28 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus import android.media.AudioManager /** * [AudioFocusController] implementation for Android API 21+. */ @Suppress("DEPRECATION") internal class AudioFocusControllerV21( private val audioManager: AudioManager, private val listener: AudioManager.OnAudioFocusChangeListener ) : AudioFocusController { override fun request(): Int { return audioManager.requestAudioFocus( listener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) } override fun abandon() { audioManager.abandonAudioFocus(listener) } } components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV26.kt 0 → 100644 +40 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus import android.annotation.TargetApi import android.media.AudioAttributes import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build /** * [AudioFocusController] implementation for Android API 26+. */ @TargetApi(Build.VERSION_CODES.O) internal class AudioFocusControllerV26( private val audioManager: AudioManager, listener: AudioManager.OnAudioFocusChangeListener ) : AudioFocusController { private val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() ) .setWillPauseWhenDucked(false) .setOnAudioFocusChangeListener(listener) .build() override fun request(): Int { return audioManager.requestAudioFocus(request) } override fun abandon() { audioManager.abandonAudioFocusRequest(request) } } components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt +3 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import android.app.Service import android.content.ComponentName import android.content.Context import android.content.Intent import android.media.AudioManager import android.os.IBinder import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.session.MediaSessionCompat Loading Loading @@ -36,7 +37,7 @@ internal class MediaService : Service() { private val logger = Logger("MediaService") private val notification = MediaNotification(this) private val mediaSession by lazy { MediaSessionCompat(this, "MozacMedia") } private val audioFocus = AudioFocus(this) private val audioFocus by lazy { AudioFocus(getSystemService(Context.AUDIO_SERVICE) as AudioManager) } override fun onCreate() { super.onCreate() Loading Loading @@ -102,6 +103,7 @@ internal class MediaService : Service() { } private fun shutdown() { audioFocus.abandon() mediaSession.release() stopSelf() } Loading Loading
components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocus.kt +19 −34 Original line number Diff line number Diff line Loading @@ -4,9 +4,6 @@ package mozilla.components.feature.media.focus import android.content.Context import android.media.AudioAttributes import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build import mozilla.components.feature.media.ext.getMedia Loading @@ -23,19 +20,34 @@ import mozilla.components.support.base.log.logger.Logger * https://developer.android.com/guide/topics/media-apps/audio-focus */ internal class AudioFocus( private val context: Context val audioManager: AudioManager ) : AudioManager.OnAudioFocusChangeListener { private val logger = Logger("AudioFocus") private var playDelayed = false private var resumeOnFocusGain = false private val audioFocusController = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { AudioFocusControllerV26(audioManager, this) } else { AudioFocusControllerV21(audioManager, this) } @Synchronized fun request(state: MediaState) { val result = requestAudioFocusCompat(context, this) val result = audioFocusController.request() processAudioFocusResult(state, result) } @Synchronized fun abandon() { audioFocusController.abandon() playDelayed = false resumeOnFocusGain = false } private fun processAudioFocusResult(state: MediaState, result: Int) { logger.debug("processAudioFocusResult($result)") when (result) { AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { // Granted: Gecko already started playing media. Loading @@ -60,6 +72,8 @@ internal class AudioFocus( @Synchronized override fun onAudioFocusChange(focusChange: Int) { logger.debug("onAudioFocusChange($focusChange)") val state = MediaStateMachine.state when (focusChange) { Loading Loading @@ -93,32 +107,3 @@ internal class AudioFocus( } } } private fun requestAudioFocusCompat( context: Context, listener: AudioManager.OnAudioFocusChangeListener ): Int { val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { @Suppress("DEPRECATION") audioManager.requestAudioFocus( listener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) } else { audioManager.requestAudioFocus( AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() ) .setWillPauseWhenDucked(false) .setOnAudioFocusChangeListener(listener) .build() ) } }
components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusController.kt 0 → 100644 +13 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus /** * A controller that knows how to request and abandon audio focus. */ internal interface AudioFocusController { fun request(): Int fun abandon() }
components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV21.kt 0 → 100644 +28 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus import android.media.AudioManager /** * [AudioFocusController] implementation for Android API 21+. */ @Suppress("DEPRECATION") internal class AudioFocusControllerV21( private val audioManager: AudioManager, private val listener: AudioManager.OnAudioFocusChangeListener ) : AudioFocusController { override fun request(): Int { return audioManager.requestAudioFocus( listener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN ) } override fun abandon() { audioManager.abandonAudioFocus(listener) } }
components/feature/media/src/main/java/mozilla/components/feature/media/focus/AudioFocusControllerV26.kt 0 → 100644 +40 −0 Original line number Diff line number Diff line /* 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 mozilla.components.feature.media.focus import android.annotation.TargetApi import android.media.AudioAttributes import android.media.AudioFocusRequest import android.media.AudioManager import android.os.Build /** * [AudioFocusController] implementation for Android API 26+. */ @TargetApi(Build.VERSION_CODES.O) internal class AudioFocusControllerV26( private val audioManager: AudioManager, listener: AudioManager.OnAudioFocusChangeListener ) : AudioFocusController { private val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build() ) .setWillPauseWhenDucked(false) .setOnAudioFocusChangeListener(listener) .build() override fun request(): Int { return audioManager.requestAudioFocus(request) } override fun abandon() { audioManager.abandonAudioFocusRequest(request) } }
components/feature/media/src/main/java/mozilla/components/feature/media/service/MediaService.kt +3 −1 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import android.app.Service import android.content.ComponentName import android.content.Context import android.content.Intent import android.media.AudioManager import android.os.IBinder import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.session.MediaSessionCompat Loading Loading @@ -36,7 +37,7 @@ internal class MediaService : Service() { private val logger = Logger("MediaService") private val notification = MediaNotification(this) private val mediaSession by lazy { MediaSessionCompat(this, "MozacMedia") } private val audioFocus = AudioFocus(this) private val audioFocus by lazy { AudioFocus(getSystemService(Context.AUDIO_SERVICE) as AudioManager) } override fun onCreate() { super.onCreate() Loading Loading @@ -102,6 +103,7 @@ internal class MediaService : Service() { } private fun shutdown() { audioFocus.abandon() mediaSession.release() stopSelf() } Loading