refactor on SignalAudioManager

This commit is contained in:
Ryan Zhao 2023-04-24 15:38:06 +10:00
parent 63d442584c
commit 51856138e3
4 changed files with 53 additions and 60 deletions

View File

@ -799,6 +799,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
wantsToAnswerReceiver?.let { receiver -> wantsToAnswerReceiver?.let { receiver ->
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver) LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
} }
callManager.shutDownAudioManager()
powerButtonReceiver = null powerButtonReceiver = null
wiredHeadsetStateReceiver = null wiredHeadsetStateReceiver = null
networkChangedReceiver = null networkChangedReceiver = null

View File

@ -93,6 +93,10 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
peerConnectionObservers.remove(listener) peerConnectionObservers.remove(listener)
} }
fun shutDownAudioManager() {
signalAudioManager.shutdown()
}
private val _audioEvents = MutableStateFlow(AudioEnabled(false)) private val _audioEvents = MutableStateFlow(AudioEnabled(false))
val audioEvents = _audioEvents.asSharedFlow() val audioEvents = _audioEvents.asSharedFlow()
private val _videoEvents = MutableStateFlow(VideoEnabled(false)) private val _videoEvents = MutableStateFlow(VideoEnabled(false))

View File

@ -9,6 +9,7 @@ import android.media.SoundPool
import android.os.HandlerThread import android.os.HandlerThread
import network.loki.messenger.R import network.loki.messenger.R
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.webrtc.AudioManagerCommand import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
import org.thoughtcrime.securesms.webrtc.audio.SignalBluetoothManager.State as BState import org.thoughtcrime.securesms.webrtc.audio.SignalBluetoothManager.State as BState
@ -32,10 +33,10 @@ class SignalAudioManager(private val context: Context,
private val eventListener: EventListener?, private val eventListener: EventListener?,
private val androidAudioManager: AudioManagerCompat) { private val androidAudioManager: AudioManagerCompat) {
private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio").apply { start() } private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio", ThreadUtils.PRIORITY_IMPORTANT_BACKGROUND_THREAD).apply { start() }
private var handler: SignalAudioHandler? = null private var handler: SignalAudioHandler? = SignalAudioHandler(commandAndControlThread!!.looper)
private var signalBluetoothManager: SignalBluetoothManager? = null private var signalBluetoothManager: SignalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!)
private var state: State = State.UNINITIALIZED private var state: State = State.UNINITIALIZED
@ -62,12 +63,9 @@ class SignalAudioManager(private val context: Context,
private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null
fun handleCommand(command: AudioManagerCommand) { fun handleCommand(command: AudioManagerCommand) {
if (command == AudioManagerCommand.Initialize) {
initialize()
return
}
handler?.post { handler?.post {
when (command) { when (command) {
is AudioManagerCommand.Initialize -> initialize()
is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState() is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState()
is AudioManagerCommand.Start -> start() is AudioManagerCommand.Start -> start()
is AudioManagerCommand.Stop -> stop(command.playDisconnect) is AudioManagerCommand.Stop -> stop(command.playDisconnect)
@ -84,34 +82,37 @@ class SignalAudioManager(private val context: Context,
Log.i(TAG, "Initializing audio manager state: $state") Log.i(TAG, "Initializing audio manager state: $state")
if (state == State.UNINITIALIZED) { if (state == State.UNINITIALIZED) {
commandAndControlThread = HandlerThread("call-audio").apply { start() } savedAudioMode = androidAudioManager.mode
handler = SignalAudioHandler(commandAndControlThread!!.looper) savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn
savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute
hasWiredHeadset = androidAudioManager.isWiredHeadsetOn
signalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!) androidAudioManager.requestCallAudioFocus()
handler!!.post { setMicrophoneMute(false)
savedAudioMode = androidAudioManager.mode audioDevices.clear()
savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn
savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute
hasWiredHeadset = androidAudioManager.isWiredHeadsetOn
androidAudioManager.requestCallAudioFocus() signalBluetoothManager.start()
setMicrophoneMute(false) updateAudioDeviceState()
audioDevices.clear() wiredHeadsetReceiver = WiredHeadsetReceiver()
context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG))
signalBluetoothManager!!.start() state = State.PREINITIALIZED
updateAudioDeviceState() Log.d(TAG, "Initialized")
}
}
wiredHeadsetReceiver = WiredHeadsetReceiver() fun shutdown() {
context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG)) handler!!.post {
stop(false)
state = State.PREINITIALIZED if (commandAndControlThread != null) {
Log.i(TAG, "Shutting down command and control")
Log.d(TAG, "Initialized") commandAndControlThread?.quitSafely()
commandAndControlThread = null
} }
} }
} }
@ -138,23 +139,11 @@ class SignalAudioManager(private val context: Context,
private fun stop(playDisconnect: Boolean) { private fun stop(playDisconnect: Boolean) {
Log.d(TAG, "Stopping. state: $state") Log.d(TAG, "Stopping. state: $state")
if (state == State.UNINITIALIZED) {
Log.i(TAG, "Trying to stop AudioManager in incorrect state: $state")
return
}
handler?.post { incomingRinger.stop()
incomingRinger.stop() outgoingRinger.stop()
outgoingRinger.stop()
stop(false)
if (commandAndControlThread != null) {
Log.i(TAG, "Shutting down command and control")
commandAndControlThread?.quitSafely()
commandAndControlThread = null
}
}
if (playDisconnect) { if (playDisconnect && state != State.UNINITIALIZED) {
val volume: Float = androidAudioManager.ringVolumeWithMinimum() val volume: Float = androidAudioManager.ringVolumeWithMinimum()
soundPool.play(disconnectedSoundId, volume, volume, 0, 0, 1.0f) soundPool.play(disconnectedSoundId, volume, volume, 0, 0, 1.0f)
} }
@ -170,7 +159,7 @@ class SignalAudioManager(private val context: Context,
} }
wiredHeadsetReceiver = null wiredHeadsetReceiver = null
signalBluetoothManager?.stop() signalBluetoothManager.stop()
setSpeakerphoneOn(savedIsSpeakerPhoneOn) setSpeakerphoneOn(savedIsSpeakerPhoneOn)
setMicrophoneMute(savedIsMicrophoneMute) setMicrophoneMute(savedIsMicrophoneMute)
@ -189,19 +178,19 @@ class SignalAudioManager(private val context: Context,
TAG, TAG,
"updateAudioDeviceState(): " + "updateAudioDeviceState(): " +
"wired: $hasWiredHeadset " + "wired: $hasWiredHeadset " +
"bt: ${signalBluetoothManager!!.state} " + "bt: ${signalBluetoothManager.state} " +
"available: $audioDevices " + "available: $audioDevices " +
"selected: $selectedAudioDevice " + "selected: $selectedAudioDevice " +
"userSelected: $userSelectedAudioDevice" "userSelected: $userSelectedAudioDevice"
) )
if (signalBluetoothManager!!.state.shouldUpdate()) { if (signalBluetoothManager.state.shouldUpdate()) {
signalBluetoothManager!!.updateDevice() signalBluetoothManager.updateDevice()
} }
val newAudioDevices = mutableSetOf(AudioDevice.SPEAKER_PHONE) val newAudioDevices = mutableSetOf(AudioDevice.SPEAKER_PHONE)
if (signalBluetoothManager!!.state.hasDevice()) { if (signalBluetoothManager.state.hasDevice()) {
newAudioDevices += AudioDevice.BLUETOOTH newAudioDevices += AudioDevice.BLUETOOTH
} }
@ -217,7 +206,7 @@ class SignalAudioManager(private val context: Context,
var audioDeviceSetUpdated = audioDevices != newAudioDevices var audioDeviceSetUpdated = audioDevices != newAudioDevices
audioDevices = newAudioDevices audioDevices = newAudioDevices
if (signalBluetoothManager!!.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) { if (signalBluetoothManager.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
userSelectedAudioDevice = AudioDevice.NONE userSelectedAudioDevice = AudioDevice.NONE
} }
@ -230,7 +219,7 @@ class SignalAudioManager(private val context: Context,
userSelectedAudioDevice = AudioDevice.NONE userSelectedAudioDevice = AudioDevice.NONE
} }
val btState = signalBluetoothManager!!.state val btState = signalBluetoothManager.state
val needBluetoothAudioStart = btState == BState.AVAILABLE && val needBluetoothAudioStart = btState == BState.AVAILABLE &&
(userSelectedAudioDevice == AudioDevice.NONE || userSelectedAudioDevice == AudioDevice.BLUETOOTH || autoSwitchToBluetooth) (userSelectedAudioDevice == AudioDevice.NONE || userSelectedAudioDevice == AudioDevice.BLUETOOTH || autoSwitchToBluetooth)
@ -238,27 +227,27 @@ class SignalAudioManager(private val context: Context,
(userSelectedAudioDevice != AudioDevice.NONE && userSelectedAudioDevice != AudioDevice.BLUETOOTH) (userSelectedAudioDevice != AudioDevice.NONE && userSelectedAudioDevice != AudioDevice.BLUETOOTH)
if (btState.hasDevice()) { if (btState.hasDevice()) {
Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager!!.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop") Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop")
} }
if (needBluetoothAudioStop) { if (needBluetoothAudioStop) {
signalBluetoothManager!!.stopScoAudio() signalBluetoothManager.stopScoAudio()
signalBluetoothManager!!.updateDevice() signalBluetoothManager.updateDevice()
} }
if (!autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.UNAVAILABLE) { if (!autoSwitchToBluetooth && signalBluetoothManager.state == BState.UNAVAILABLE) {
autoSwitchToBluetooth = true autoSwitchToBluetooth = true
} }
if (needBluetoothAudioStart && !needBluetoothAudioStop) { if (!needBluetoothAudioStop && needBluetoothAudioStart) {
if (!signalBluetoothManager!!.startScoAudio()) { if (!signalBluetoothManager.startScoAudio()) {
Log.e(TAG,"Failed to start sco audio") Log.e(TAG,"Failed to start sco audio")
audioDevices.remove(AudioDevice.BLUETOOTH) audioDevices.remove(AudioDevice.BLUETOOTH)
audioDeviceSetUpdated = true audioDeviceSetUpdated = true
} }
} }
if (autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.CONNECTED) { if (autoSwitchToBluetooth && signalBluetoothManager.state == BState.CONNECTED) {
userSelectedAudioDevice = AudioDevice.BLUETOOTH userSelectedAudioDevice = AudioDevice.BLUETOOTH
autoSwitchToBluetooth = false autoSwitchToBluetooth = false
} }

View File

@ -1,13 +1,12 @@
package org.session.libsignal.utilities package org.session.libsignal.utilities
import java.util.concurrent.ExecutorService import android.os.Process
import java.util.concurrent.Executors import java.util.concurrent.*
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
object ThreadUtils { object ThreadUtils {
const val PRIORITY_IMPORTANT_BACKGROUND_THREAD = Process.THREAD_PRIORITY_DEFAULT + Process.THREAD_PRIORITY_LESS_FAVORABLE
val executorPool: ExecutorService = Executors.newCachedThreadPool() val executorPool: ExecutorService = Executors.newCachedThreadPool()
@JvmStatic @JvmStatic