refactor: more bluetooth improvements

This commit is contained in:
jubb 2021-11-26 17:12:30 +11:00
parent 787fefc237
commit 644213ea32
8 changed files with 69 additions and 72 deletions

View File

@ -155,8 +155,8 @@ dependencies {
testImplementation 'org.robolectric:shadows-multidex:4.4'
}
def canonicalVersionCode = 236
def canonicalVersionName = "1.12.0-ALPHA3"
def canonicalVersionCode = 237
def canonicalVersionName = "1.12.0-ALPHA4"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,
@ -246,6 +246,7 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
debuggable true
minifyEnabled false
}
debug {

View File

@ -176,6 +176,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
@Synchronized
private fun terminate() {
sendBroadcast(Intent(WebRtcCallActivity.ACTION_END))
lockManager.updatePhoneState(LockManager.PhoneState.IDLE)
callManager.stop()
stopForeground(true)
}
@ -377,7 +378,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
callManager.startOutgoingRinger(OutgoingRinger.Type.RINGING)
setCallInProgressNotification(TYPE_OUTGOING_RINGING, callManager.recipient)
callManager.insertCallMessage(recipient.address.serialize(), CallMessageType.CALL_OUTGOING)
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 2, TimeUnit.MINUTES)
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 1, TimeUnit.MINUTES)
val expectedState = callManager.currentConnectionState
val expectedCallId = callManager.callId
@ -425,7 +426,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
return
}
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 2, TimeUnit.MINUTES)
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 1, TimeUnit.MINUTES)
callManager.initializeAudioForCall()
callManager.initializeVideo(this)
@ -490,11 +491,6 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
callManager.handleSetCameraFlip()
}
private fun handleBluetoothChange(intent: Intent) {
val bluetoothAvailable = intent.getBooleanExtra(EXTRA_AVAILABLE, false)
callManager.postBluetoothAvailable(bluetoothAvailable)
}
private fun handleWiredHeadsetChanged(intent: Intent) {
callManager.handleWiredHeadsetChanged(intent.getBooleanExtra(EXTRA_AVAILABLE, false))
}
@ -611,6 +607,7 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
System.currentTimeMillis() - intent.getLongExtra(EXTRA_TIMESTAMP, -1) > TimeUnit.MINUTES.toMillis(2)
override fun onDestroy() {
Log.d(TAG,"onDestroy()")
callManager.unregisterListener(this)
callReceiver?.let { receiver ->
unregisterReceiver(receiver)
@ -621,7 +618,6 @@ class WebRtcCallService: Service(), CallManager.WebRtcListener {
networkChangedReceiver = null
callReceiver = null
uncaughtExceptionHandlerManager?.unregister()
callManager.onDestroy()
super.onDestroy()
// shutdown audiomanager
// unregister network receiver

View File

@ -10,9 +10,6 @@ open class AudioManagerCommand: Parcelable {
@Parcelize
object Initialize: AudioManagerCommand()
@Parcelize
object Shutdown: AudioManagerCommand()
@Parcelize
object UpdateAudioDeviceState: AudioManagerCommand()

View File

@ -309,8 +309,6 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
} else if (json.containsKey("hangup")) {
peerConnectionObservers.forEach(WebRtcListener::onHangup)
}
val videoEnabled = Json.decodeFromString(VideoEnabledMessage.serializer(), byteArray.decodeToString())
_remoteVideoEvents.value = VideoEnabled(videoEnabled.video)
} catch (e: Exception) {
Log.e(TAG, "Failed to deserialize data channel message", e)
}
@ -519,7 +517,8 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
fun handleSetMuteVideo(muted: Boolean, lockManager: LockManager) {
_videoEvents.value = VideoEnabled(!muted)
peerConnection?.setVideoEnabled(!muted)
val connection = peerConnection ?: return
connection.setVideoEnabled(!muted)
dataChannel?.let { channel ->
val toSend = if (muted) VIDEO_DISABLED_JSON else VIDEO_ENABLED_JSON
val buffer = DataChannel.Buffer(ByteBuffer.wrap(toSend.toString().encodeToByteArray()), false)
@ -527,7 +526,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
}
if (currentConnectionState == CallState.STATE_CONNECTED) {
if (localCameraState.enabled) lockManager.updatePhoneState(LockManager.PhoneState.IN_VIDEO)
if (connection.isVideoEnabled()) lockManager.updatePhoneState(LockManager.PhoneState.IN_VIDEO)
else lockManager.updatePhoneState(LockManager.PhoneState.IN_CALL)
}
@ -548,10 +547,6 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
}
}
fun postBluetoothAvailable(available: Boolean) {
// TODO: _bluetoothEnabled.value = available
}
fun handleWiredHeadsetChanged(present: Boolean) {
if (currentConnectionState in arrayOf(CallState.STATE_CONNECTED,
CallState.STATE_DIALING,
@ -601,10 +596,6 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
}
}
fun onDestroy() {
signalAudioManager.handleCommand(AudioManagerCommand.Shutdown)
}
fun startIncomingRinger() {
signalAudioManager.handleCommand(AudioManagerCommand.StartIncomingRinger(true))
}
@ -612,7 +603,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
fun startCommunication(lockManager: LockManager) {
signalAudioManager.handleCommand(AudioManagerCommand.Start)
val connection = peerConnection ?: return
if (localCameraState.enabled) lockManager.updatePhoneState(LockManager.PhoneState.IN_VIDEO)
if (connection.isVideoEnabled()) lockManager.updatePhoneState(LockManager.PhoneState.IN_VIDEO)
else lockManager.updatePhoneState(LockManager.PhoneState.IN_CALL)
connection.setCommunicationMode()
setAudioEnabled(true)
@ -649,9 +640,6 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va
}
}
@Serializable
data class VideoEnabledMessage(val video: Boolean)
interface WebRtcListener: PeerConnection.Observer {
fun onHangup()
}

View File

@ -24,7 +24,7 @@ class PeerConnectionWrapper(context: Context,
private val videoTrack: VideoTrack?
val readyForIce
get() = peerConnection.localDescription != null && peerConnection.remoteDescription != null
get() = peerConnection.localDescription != null && peerConnection.remoteDescription != null
init {
val turn = PeerConnection.IceServer.builder("turn:freyr.getsession.org").setUsername("session").setPassword("session").createIceServer()
@ -269,6 +269,8 @@ class PeerConnectionWrapper(context: Context,
}
}
fun isVideoEnabled() = camera.enabled
fun flipCamera() {
camera.flip()
}

View File

@ -17,6 +17,9 @@ class IncomingRinger(private val context: Context) {
private val vibrator: Vibrator? = ServiceUtil.getVibrator(context)
var mediaPlayer: MediaPlayer? = null
val isRinging: Boolean
get() = mediaPlayer?.isPlaying ?: false
fun start(vibrate: Boolean) {
val audioManager = ServiceUtil.getAudioManager(context)
mediaPlayer?.release()
@ -31,16 +34,14 @@ class IncomingRinger(private val context: Context) {
}
mediaPlayer?.let { player ->
if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
try {
if (!player.isPlaying) {
player.prepare()
player.start()
Log.i(TAG,"Playing ringtone")
}
} catch (e: Exception) {
Log.e(TAG,"Failed to start mediaPlayer", e)
try {
if (!player.isPlaying) {
player.prepare()
player.start()
Log.i(TAG,"Playing ringtone")
}
} catch (e: Exception) {
Log.e(TAG,"Failed to start mediaPlayer", e)
}
} ?: run {
Log.w(TAG,"Not ringing, mediaPlayer: ${mediaPlayer?.let{"available"}}, mode: $ringerMode")

View File

@ -11,6 +11,7 @@ import android.os.HandlerThread
import network.loki.messenger.R
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
import org.thoughtcrime.securesms.webrtc.audio.SignalBluetoothManager.State as BState
private val TAG = Log.tag(SignalAudioManager::class.java)
@ -68,7 +69,6 @@ class SignalAudioManager(private val context: Context,
}
handler?.post {
when (command) {
is AudioManagerCommand.Shutdown -> shutdown()
is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState()
is AudioManagerCommand.Start -> start()
is AudioManagerCommand.Stop -> stop(command.playDisconnect)
@ -144,15 +144,23 @@ class SignalAudioManager(private val context: Context,
return
}
incomingRinger.stop()
outgoingRinger.stop()
handler?.post {
incomingRinger.stop()
outgoingRinger.stop()
stop(false)
if (commandAndControlThread != null) {
Log.i(TAG, "Shutting down command and control")
commandAndControlThread?.quitSafely()
commandAndControlThread = null
}
}
if (playDisconnect) {
val volume: Float = androidAudioManager.ringVolumeWithMinimum()
soundPool.play(disconnectedSoundId, volume, volume, 0, 0, 1.0f)
}
state = State.PREINITIALIZED
state = State.UNINITIALIZED
wiredHeadsetReceiver?.let { receiver ->
try {
@ -175,19 +183,6 @@ class SignalAudioManager(private val context: Context,
Log.d(TAG, "Stopped")
}
private fun shutdown() {
handler?.post {
incomingRinger.stop()
outgoingRinger.stop()
stop(false)
if (commandAndControlThread != null) {
Log.i(TAG, "Shutting down command and control")
commandAndControlThread?.quitSafely()
commandAndControlThread = null
}
}
}
private fun updateAudioDeviceState() {
handler!!.assertHandlerThread()
@ -223,7 +218,7 @@ class SignalAudioManager(private val context: Context,
var audioDeviceSetUpdated = audioDevices != newAudioDevices
audioDevices = newAudioDevices
if (signalBluetoothManager!!.state == SignalBluetoothManager.State.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
if (signalBluetoothManager!!.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
userSelectedAudioDevice = AudioDevice.NONE
}
@ -236,13 +231,14 @@ class SignalAudioManager(private val context: Context,
userSelectedAudioDevice = AudioDevice.NONE
}
val needBluetoothAudioStart = signalBluetoothManager!!.state == SignalBluetoothManager.State.AVAILABLE && signalBluetoothManager!!.state != SignalBluetoothManager.State.CONNECTING
val btState = signalBluetoothManager!!.state
val needBluetoothAudioStart = btState == BState.AVAILABLE &&
(userSelectedAudioDevice == AudioDevice.NONE || userSelectedAudioDevice == AudioDevice.BLUETOOTH || autoSwitchToBluetooth)
val needBluetoothAudioStop = (signalBluetoothManager!!.state == SignalBluetoothManager.State.CONNECTED || signalBluetoothManager!!.state != SignalBluetoothManager.State.CONNECTING) &&
val needBluetoothAudioStop = (btState == BState.CONNECTED || btState == BState.CONNECTING) &&
(userSelectedAudioDevice != AudioDevice.NONE && userSelectedAudioDevice != AudioDevice.BLUETOOTH)
if (signalBluetoothManager!!.state.hasDevice()) {
if (btState.hasDevice()) {
Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager!!.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop")
}
@ -251,18 +247,19 @@ class SignalAudioManager(private val context: Context,
signalBluetoothManager!!.updateDevice()
}
if (!autoSwitchToBluetooth && signalBluetoothManager!!.state == SignalBluetoothManager.State.UNAVAILABLE) {
if (!autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.UNAVAILABLE) {
autoSwitchToBluetooth = true
}
if (needBluetoothAudioStart && !needBluetoothAudioStop) {
if (!signalBluetoothManager!!.startScoAudio()) {
Log.e(TAG,"Failed to start sco audio")
audioDevices.remove(AudioDevice.BLUETOOTH)
audioDeviceSetUpdated = true
}
}
if (autoSwitchToBluetooth && signalBluetoothManager!!.state == SignalBluetoothManager.State.CONNECTED) {
if (autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.CONNECTED) {
userSelectedAudioDevice = AudioDevice.BLUETOOTH
autoSwitchToBluetooth = false
}
@ -342,7 +339,6 @@ class SignalAudioManager(private val context: Context,
private fun startIncomingRinger(vibrate: Boolean) {
Log.i(TAG, "startIncomingRinger(): vibrate: $vibrate")
androidAudioManager.mode = AudioManager.MODE_RINGTONE
setDefaultAudioDevice(AudioDevice.SPEAKER_PHONE, false)
incomingRinger.start(vibrate)
}

View File

@ -9,6 +9,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.media.AudioManager
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.webrtc.AudioManagerCommand
import java.util.concurrent.TimeUnit
@ -73,7 +74,7 @@ class SignalBluetoothManager(
val bluetoothHeadsetFilter = IntentFilter().apply {
addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)
addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)
}
bluetoothReceiver = BluetoothHeadsetBroadcastReceiver()
@ -134,7 +135,6 @@ class SignalBluetoothManager(
state = State.CONNECTING
androidAudioManager.startBluetoothSco()
androidAudioManager.isBluetoothScoOn = true
scoConnectionAttempts++
startTimer()
@ -165,7 +165,7 @@ class SignalBluetoothManager(
return
}
if (bluetoothAdapter!!.getProfileConnectionState(BluetoothProfile.HEADSET) !in arrayOf(BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED)) {
if (bluetoothAdapter!!.getProfileConnectionState(BluetoothProfile.HEADSET) !in arrayOf(BluetoothProfile.STATE_CONNECTED)) {
state = State.UNAVAILABLE
Log.i(TAG, "No connected bluetooth headset")
} else {
@ -216,6 +216,7 @@ class SignalBluetoothManager(
private fun onServiceConnected(proxy: BluetoothHeadset?) {
bluetoothHeadset = proxy
androidAudioManager.isBluetoothScoOn = true
updateAudioDeviceState()
}
@ -244,9 +245,9 @@ class SignalBluetoothManager(
private fun onAudioStateChanged(audioState: Int, isInitialStateChange: Boolean) {
Log.i(TAG, "onAudioStateChanged: state: $state audioState: ${audioState.toStateString()} initialSticky: $isInitialStateChange")
if (audioState == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
if (audioState == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
cancelTimer()
if (state === State.CONNECTING) {
if (state == State.CONNECTING) {
Log.d(TAG, "Bluetooth audio SCO is now connected")
state = State.CONNECTED
scoConnectionAttempts = 0
@ -254,9 +255,9 @@ class SignalBluetoothManager(
} else {
Log.w(TAG, "Unexpected state ${audioState.toStateString()}")
}
} else if (audioState == BluetoothHeadset.STATE_AUDIO_CONNECTING) {
} else if (audioState == AudioManager.SCO_AUDIO_STATE_CONNECTING) {
Log.d(TAG, "Bluetooth audio SCO is now connecting...")
} else if (audioState == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
} else if (audioState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
Log.d(TAG, "Bluetooth audio SCO is now disconnected")
if (isInitialStateChange) {
Log.d(TAG, "Ignore ${audioState.toStateString()} initial sticky broadcast.")
@ -298,10 +299,17 @@ class SignalBluetoothManager(
}
}
} else if (intent.action == BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED) {
val connectionState: Int = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED)
// val connectionState: Int = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED)
// handler.post {
// if (state != State.UNINITIALIZED) {
// onAudioStateChanged(connectionState, isInitialStickyBroadcast)
// }
// }
} else if (intent.action == AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) {
val scoState: Int = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.ERROR)
handler.post {
if (state != State.UNINITIALIZED) {
onAudioStateChanged(connectionState, isInitialStickyBroadcast)
onAudioStateChanged(scoState, isInitialStickyBroadcast)
}
}
}
@ -346,3 +354,11 @@ private fun Int.toStateString(): String {
else -> "UNKNOWN"
}
}
private fun Int.toScoString(): String = when (this) {
AudioManager.SCO_AUDIO_STATE_DISCONNECTED -> "DISCONNECTED"
AudioManager.SCO_AUDIO_STATE_CONNECTED -> "CONNECTED"
AudioManager.SCO_AUDIO_STATE_CONNECTING -> "CONNECTING"
AudioManager.SCO_AUDIO_STATE_ERROR -> "ERROR"
else -> "UNKNOWN"
}