Embedded audio mode change to audio focus request

This commit is contained in:
Juha Heinanen
2023-02-15 21:10:23 +02:00
parent 392d7b725b
commit 2a836c02ef
3 changed files with 82 additions and 69 deletions

View File

@ -65,9 +65,7 @@ class BaresipService: Service() {
private var rt: Ringtone? = null
private var rtTimer: Timer? = null
private var audioFocusRequest: AudioFocusRequestCompat? = null
private var origVolume = mutableMapOf<Int, Int>()
private var btAdapter: BluetoothAdapter? = null
private var linkAddresses = mutableMapOf<String, String>()
private var activeNetwork: Network? = null
private var allNetworks = mutableSetOf<Network>()
@ -457,9 +455,7 @@ class BaresipService: Service() {
val vidMode = intent.getIntExtra("video", Api.VIDMODE_OFF)
stopRinging()
stopMediaPlayer()
if (am.mode != AudioManager.MODE_IN_COMMUNICATION)
am.mode = AudioManager.MODE_IN_COMMUNICATION
requestAudioFocus(AudioAttributes.CONTENT_TYPE_SPEECH)
requestAudioFocus(am, AudioAttributes.CONTENT_TYPE_SPEECH)
setCallVolume()
proximitySensing(true)
Api.ua_answer(uap, callp, vidMode)
@ -637,7 +633,6 @@ class BaresipService: Service() {
if (call!!.status == "transferring")
break
stopMediaPlayer()
requestAudioFocus(AudioAttributes.CONTENT_TYPE_SPEECH)
setCallVolume()
proximitySensing(true)
return
@ -879,7 +874,7 @@ class BaresipService: Service() {
resetCallVolume()
am.mode = AudioManager.MODE_NORMAL
am.stopBluetoothSco()
abandonAudioFocus()
abandonAudioFocus(am)
proximitySensing(false)
}
val missed = call.startTime == null && call.dir == "in" && !call.rejected
@ -1173,57 +1168,8 @@ class BaresipService: Service() {
return spannable
}
@SuppressLint("MissingPermission")
private fun isBluetoothHeadsetConnected(): Boolean {
return if (VERSION.SDK_INT < 31)
btAdapter != null && btAdapter!!.isEnabled &&
btAdapter!!.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothAdapter.STATE_CONNECTED
else
// getProfileConnectionState requires asking fot BLUETOOTH_CONNECT permission
true
}
private fun requestAudioFocus(type: Int) {
if (audioFocusRequest != null) {
if (audioFocusRequest!!.audioAttributesCompat.contentType == type)
return
else
abandonAudioFocus()
}
val attributes = AudioAttributesCompat.Builder()
.setUsage(AudioAttributesCompat.USAGE_VOICE_COMMUNICATION)
.setContentType(type)
.build()
audioFocusRequest = AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT)
.setAudioAttributes(attributes)
.setOnAudioFocusChangeListener { }
.build()
if (AudioManagerCompat.requestAudioFocus(am, audioFocusRequest!!) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.d(TAG, "Audio focus granted")
isAudioFocused = true
if (isBluetoothHeadsetConnected() && !am.isBluetoothScoOn) {
Log.d(TAG, "Starting Bluetooth SCO")
am.startBluetoothSco()
}
} else {
Log.d(TAG, "Audio focus denied")
audioFocusRequest = null
isAudioFocused = false
}
}
private fun abandonAudioFocus() {
if (audioFocusRequest != null) {
AudioManagerCompat.abandonAudioFocusRequest(am, audioFocusRequest!!)
audioFocusRequest = null
isAudioFocused = false
Log.d(TAG, "Audio focus abandoned")
}
}
private fun startRinging() {
requestAudioFocus(AudioAttributes.CONTENT_TYPE_MUSIC)
requestAudioFocus(am, AudioAttributes.CONTENT_TYPE_MUSIC)
am.mode = AudioManager.MODE_RINGTONE
if (rt == null) {
val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext,
@ -1248,7 +1194,7 @@ class BaresipService: Service() {
private fun stopRinging() {
if (am.mode == AudioManager.MODE_RINGTONE)
abandonAudioFocus()
abandonAudioFocus(am)
if (VERSION.SDK_INT < 28 && rtTimer != null) {
rtTimer!!.cancel()
rtTimer = null
@ -1485,7 +1431,7 @@ class BaresipService: Service() {
if (am.isBluetoothScoOn)
am.stopBluetoothSco()
am.mode = AudioManager.MODE_NORMAL
abandonAudioFocus()
abandonAudioFocus(am)
stopRinging()
stopMediaPlayer()
uas.clear()
@ -1541,6 +1487,59 @@ class BaresipService: Service() {
val serviceEvent = MutableLiveData<Event<Long>>()
val serviceEvents = mutableListOf<ServiceEvent>()
private var audioFocusRequest: AudioFocusRequestCompat? = null
private var btAdapter: BluetoothAdapter? = null
fun requestAudioFocus(am: AudioManager, type: Int): Boolean {
if (audioFocusRequest != null) {
if (audioFocusRequest!!.audioAttributesCompat.contentType == type)
return true
else
abandonAudioFocus(am)
}
val attributes = AudioAttributesCompat.Builder()
.setUsage(AudioAttributesCompat.USAGE_VOICE_COMMUNICATION)
.setContentType(type)
.build()
audioFocusRequest = AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT)
.setAudioAttributes(attributes)
.setOnAudioFocusChangeListener { }
.build()
if (AudioManagerCompat.requestAudioFocus(am, audioFocusRequest!!) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.d(TAG, "Audio focus granted")
isAudioFocused = true
if (isBluetoothHeadsetConnected() && !am.isBluetoothScoOn) {
Log.d(TAG, "Starting Bluetooth SCO")
am.startBluetoothSco()
}
if (type == AudioAttributes.CONTENT_TYPE_SPEECH)
am.mode = AudioManager.MODE_IN_COMMUNICATION
} else {
Log.d(TAG, "Audio focus denied")
audioFocusRequest = null
isAudioFocused = false
}
return isAudioFocused
}
private fun abandonAudioFocus(am: AudioManager) {
if (audioFocusRequest != null) {
AudioManagerCompat.abandonAudioFocusRequest(am, audioFocusRequest!!)
audioFocusRequest = null
isAudioFocused = false
Log.d(TAG, "Audio focus abandoned")
}
}
@SuppressLint("MissingPermission")
private fun isBluetoothHeadsetConnected(): Boolean {
return if (VERSION.SDK_INT < 31)
btAdapter != null && btAdapter!!.isEnabled &&
btAdapter!!.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothAdapter.STATE_CONNECTED
else
// getProfileConnectionState requires asking for BLUETOOTH_CONNECT permission
true
}
}

View File

@ -10,6 +10,7 @@ import android.content.*
import android.content.Intent.ACTION_CALL
import android.content.pm.PackageManager
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.media.AudioAttributes
import android.media.AudioDeviceInfo
import android.media.AudioManager
import android.net.Uri
@ -1816,17 +1817,24 @@ class MainActivity : AppCompatActivity() {
hangupButton.visibility = View.VISIBLE
hangupButton.isEnabled = true
if (Build.VERSION.SDK_INT < 31) {
am.mode = AudioManager.MODE_IN_COMMUNICATION
callRunnable = Runnable {
callRunnable = null
if (!call(ua, uri)) {
callButton.visibility = View.VISIBLE
callButton.isEnabled = true
hangupButton.visibility = View.INVISIBLE
hangupButton.isEnabled = false
if (!BaresipService.requestAudioFocus(am, AudioAttributes.CONTENT_TYPE_SPEECH)) {
Toast.makeText(
applicationContext,
"Audio focus denied",
Toast.LENGTH_SHORT
).show()
} else {
callRunnable = Runnable {
callRunnable = null
if (!call(ua, uri)) {
callButton.visibility = View.VISIBLE
callButton.isEnabled = true
hangupButton.visibility = View.INVISIBLE
hangupButton.isEnabled = false
}
}
callHandler.postDelayed(callRunnable!!, 1000)
}
callHandler.postDelayed(callRunnable!!, 1000)
} else {
audioModeChangedListener = AudioManager.OnModeChangedListener { mode ->
if (mode == AudioManager.MODE_IN_COMMUNICATION) {
@ -1849,7 +1857,12 @@ class MainActivity : AppCompatActivity() {
}
am.addOnModeChangedListener(mainExecutor, audioModeChangedListener!!)
Log.d(TAG, "Setting audio mode to MODE_IN_COMMUNICATION")
am.mode = AudioManager.MODE_IN_COMMUNICATION
if (!BaresipService.requestAudioFocus(am, AudioAttributes.CONTENT_TYPE_SPEECH))
Toast.makeText(
applicationContext,
"Audio focus denied",
Toast.LENGTH_SHORT
).show()
}
}
} else {

View File

@ -969,4 +969,5 @@ object Utils {
else
setSpeakerPhone(executor, am, !am.isSpeakerphoneOn)
}
}