Always use Android Telecom Framework
Automatically add/remove Mobile account when Default Phone App setting is turned on/off
This commit is contained in:
@ -285,7 +285,7 @@ class Account(val accp: Long, virtualAor: String? = null) {
|
||||
BaresipService.filesPath + "/accounts",
|
||||
accounts.toByteArray(Charsets.UTF_8)
|
||||
)
|
||||
Log.d(TAG, "Saved accounts '${accounts}' to '${BaresipService.filesPath}/accounts'")
|
||||
// Log.d(TAG, "Saved accounts '${accounts}' to '${BaresipService.filesPath}/accounts'")
|
||||
}
|
||||
|
||||
fun ofAor(aor: String): Account? {
|
||||
|
||||
@ -1677,7 +1677,7 @@ private fun checkOnClick(ctx: Context, viewModel: AccountViewModel, ua: UserAgen
|
||||
|
||||
if (viewModel.defaultAccount.value) ua.makeDefault()
|
||||
|
||||
Api.account_debug(acc.accp)
|
||||
// Api.account_debug(acc.accp)
|
||||
|
||||
Account.saveAccounts()
|
||||
|
||||
|
||||
@ -164,8 +164,6 @@ private var newOpusPacketLoss = oldOpusPacketLoss
|
||||
private var newAudioDelay = BaresipService.audioDelay.toString()
|
||||
private var newToneCountry = BaresipService.toneCountry
|
||||
private var newRingtoneUri = ""
|
||||
private var oldTelecom = BaresipService.telecom
|
||||
private var newTelecom = oldTelecom
|
||||
|
||||
private var save = false
|
||||
|
||||
@ -178,8 +176,6 @@ private fun AudioContent(contentPadding: PaddingValues) {
|
||||
|
||||
oldSpeakerPhone = Config.variable("speaker_phone") == "yes"
|
||||
newSpeakerPhone = oldSpeakerPhone
|
||||
oldTelecom = Config.variable("telecom") == "yes"
|
||||
newTelecom = oldTelecom
|
||||
oldAudioModules = Config.variables("module")
|
||||
oldOpusBitrate = Config.variable("opus_bitrate")
|
||||
oldOpusPacketLoss = Config.variable("opus_packet_loss")
|
||||
@ -206,7 +202,6 @@ private fun AudioContent(contentPadding: PaddingValues) {
|
||||
.verticalScroll(state = scrollState),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Telecom()
|
||||
Ringtone()
|
||||
ToneCountry()
|
||||
SpeakerPhone()
|
||||
@ -219,37 +214,6 @@ private fun AudioContent(contentPadding: PaddingValues) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Telecom() {
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start
|
||||
) {
|
||||
val telecomTitle = stringResource(R.string.telecom)
|
||||
val telecomHelp = stringResource(R.string.telecom_help)
|
||||
Text(text = telecomTitle,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.clickable {
|
||||
alertTitle.value = telecomTitle
|
||||
alertMessage.value = telecomHelp
|
||||
showAlert.value = true
|
||||
},
|
||||
fontSize = 18.sp)
|
||||
var telecom by remember { mutableStateOf(oldTelecom) }
|
||||
Switch(
|
||||
checked = telecom,
|
||||
onCheckedChange = {
|
||||
telecom = it
|
||||
newTelecom = telecom
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Ringtone() {
|
||||
val ringToneTitle = stringResource(R.string.ringtone)
|
||||
@ -629,13 +593,6 @@ private fun checkOnClick(ctx: Context): Result {
|
||||
|
||||
var restart = false
|
||||
|
||||
if (newTelecom != oldTelecom) {
|
||||
Config.replaceVariable("telecom", if (newTelecom) "yes" else "no")
|
||||
BaresipService.telecom = newTelecom
|
||||
restart = true
|
||||
save = true
|
||||
}
|
||||
|
||||
if (Preferences(ctx).ringtoneUri != newRingtoneUri) {
|
||||
Preferences(ctx).ringtoneUri = newRingtoneUri
|
||||
BaresipService.rt = RingtoneManager.getRingtone(ctx, newRingtoneUri.toUri())
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.Manifest
|
||||
import android.Manifest.permission.RECORD_AUDIO
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
@ -61,7 +60,6 @@ import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.MessagingStyle
|
||||
import androidx.core.app.Person
|
||||
@ -491,18 +489,7 @@ class BaresipService: Service() {
|
||||
activeNetwork = cm.activeNetwork
|
||||
Log.i(TAG, "Active network: $activeNetwork")
|
||||
|
||||
if (telecom)
|
||||
registerPhoneAccount()
|
||||
else
|
||||
if (btAdapter != null) {
|
||||
Log.i(TAG, "Registering bluetooth receiver")
|
||||
val filter = IntentFilter()
|
||||
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
|
||||
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)
|
||||
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)
|
||||
this.registerReceiver(bluetoothReceiver, filter)
|
||||
bluetoothReceiverRegistered = true
|
||||
}
|
||||
registerPhoneAccount()
|
||||
|
||||
Log.i(TAG, "AEC/AGC/NS available = $aecAvailable/$agcAvailable/$nsAvailable")
|
||||
|
||||
@ -551,8 +538,6 @@ class BaresipService: Service() {
|
||||
setCallVolume()
|
||||
proximitySensing(proximitySensing)
|
||||
call?.answer()
|
||||
if (!telecom)
|
||||
ensureCommunicationMode()
|
||||
}
|
||||
|
||||
"Call Reject" -> {
|
||||
@ -877,12 +862,10 @@ class BaresipService: Service() {
|
||||
proximitySensing(proximitySensing)
|
||||
}
|
||||
"call ringing" -> {
|
||||
if (!telecom) ensureCommunicationMode()
|
||||
playRingBack()
|
||||
return
|
||||
}
|
||||
"call progress" -> {
|
||||
if (!telecom) ensureCommunicationMode()
|
||||
if ((ev[1].toInt() and Api.SDP_RECVONLY) != 0)
|
||||
stopMediaPlayer()
|
||||
else {
|
||||
@ -926,7 +909,6 @@ class BaresipService: Service() {
|
||||
)
|
||||
if (resourceId != 0) {
|
||||
ensureCommunicationMode()
|
||||
if (!telecom) playUnInterrupted(resourceId, 1)
|
||||
} else {
|
||||
Log.e(TAG, "Callwaiting tone $name.wav not found")
|
||||
}
|
||||
@ -946,23 +928,14 @@ class BaresipService: Service() {
|
||||
Log.d(TAG, "Incoming call $uap/$callp/$peerUri")
|
||||
if (Call.ofCallp(callp) == null)
|
||||
Call(callp, ua, peerUri, "in", "incoming").add()
|
||||
if (telecom) {
|
||||
val extras = android.os.Bundle()
|
||||
extras.putLong("uap", uap)
|
||||
extras.putLong("callp", callp)
|
||||
extras.putString("peerUri", peerUri)
|
||||
try {
|
||||
tm.addNewIncomingCall(getPhoneAccountHandle(this), extras)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Telecom addNewIncomingCall failed: ${e.message}")
|
||||
}
|
||||
} else {
|
||||
if (!requestAudioFocus(applicationContext)) {
|
||||
Log.w(TAG, "Audio focus denied for incoming call")
|
||||
Api.ua_hangup(uap, callp, 486, "Busy Here")
|
||||
return
|
||||
}
|
||||
handleIncomingCall(Call.ofCallp(callp)!!)
|
||||
val extras = android.os.Bundle()
|
||||
extras.putLong("uap", uap)
|
||||
extras.putLong("callp", callp)
|
||||
extras.putString("peerUri", peerUri)
|
||||
try {
|
||||
tm.addNewIncomingCall(getPhoneAccountHandle(this), extras)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Telecom addNewIncomingCall failed: ${e.message}")
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1023,12 +996,6 @@ class BaresipService: Service() {
|
||||
if (call.state() == Api.CALL_STATE_EARLY) {
|
||||
if ((ev[1].toInt() and Api.SDP_RECVONLY) != 0)
|
||||
stopMediaPlayer()
|
||||
else {
|
||||
if (!telecom) {
|
||||
ConnectionService.connections[callp]?.setRinging()
|
||||
playRingBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (call.status.value == "connected" && !call.held && !call.onhold) {
|
||||
if (call.callOnHold.value || call.showOnHoldNotice.value) {
|
||||
@ -1160,13 +1127,8 @@ class BaresipService: Service() {
|
||||
val tone = ev[2]
|
||||
if (tone == "busy")
|
||||
playBusy()
|
||||
else {
|
||||
if (!telecom && !Call.inCall())
|
||||
abandonAudioFocus(applicationContext)
|
||||
else
|
||||
ensureCommunicationMode()
|
||||
}
|
||||
if (!telecom && !Call.inCall())
|
||||
abandonAudioFocus(applicationContext)
|
||||
if (call.dir == "out")
|
||||
call.rejected = call.startTime == null &&
|
||||
!reason.startsWith("408") &&
|
||||
@ -1500,7 +1462,7 @@ class BaresipService: Service() {
|
||||
fun started() {
|
||||
Log.d(TAG, "Received 'started' from baresip")
|
||||
isNativeReady = true
|
||||
if (telecom) addMobileUserAgent()
|
||||
addMobileUserAgent()
|
||||
Api.net_debug()
|
||||
postServiceEvent(ServiceEvent("started", arrayListOf(callActionUri), System.nanoTime()))
|
||||
callActionUri = ""
|
||||
@ -1849,23 +1811,41 @@ class BaresipService: Service() {
|
||||
messageUpdate.postValue(System.currentTimeMillis())
|
||||
}
|
||||
|
||||
private fun addMobileUserAgent() {
|
||||
if (!telecom || Utils.pstnAccountHandle(this) == null) return
|
||||
fun addMobileUserAgent() {
|
||||
if (VERSION.SDK_INT < 29) return
|
||||
|
||||
val mobileAccountHandle = Utils.pstnAccountHandle(this)
|
||||
val existingMobileUa = uas.value.find { it.account.isMobile }
|
||||
|
||||
// If mobile account should not exist (role lost or no SIM), remove it if it exists
|
||||
if (mobileAccountHandle == null) {
|
||||
if (existingMobileUa != null) {
|
||||
Log.d(TAG, "Removing Mobile account (role lost or SIM missing)")
|
||||
existingMobileUa.remove()
|
||||
Account.saveAccounts()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val userPart = Utils.getLine1Number(this) ?: "mobile"
|
||||
val mobileAor = "sip:$userPart@pstn"
|
||||
|
||||
val existingMobileUa = uas.value.find { it.account.isMobile }
|
||||
if (existingMobileUa != null) {
|
||||
// Replace previous sip:mobile@pstn with real number if available
|
||||
// Update AOR if it previously was sip:mobile@pstn but now a real number
|
||||
if (existingMobileUa.account.aor == "sip:mobile@pstn" && mobileAor != "sip:mobile@pstn") {
|
||||
val updatedUas = uas.value.toMutableList()
|
||||
updatedUas.remove(existingMobileUa)
|
||||
uas.value = updatedUas.toList()
|
||||
} else
|
||||
return
|
||||
Log.d(TAG, "Updating existing Mobile account AOR to $mobileAor")
|
||||
val aorField = Account::class.java.getDeclaredField("aor")
|
||||
aorField.isAccessible = true
|
||||
aorField.set(existingMobileUa.account, mobileAor)
|
||||
val luriField = Account::class.java.getDeclaredField("luri")
|
||||
luriField.isAccessible = true
|
||||
luriField.set(existingMobileUa.account, mobileAor)
|
||||
Account.saveAccounts()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Log.d(TAG, "Injecting new virtual Mobile account: $mobileAor")
|
||||
val account = Account(0L, mobileAor)
|
||||
account.isMobile = true
|
||||
account.nickName = "Mobile"
|
||||
@ -2515,7 +2495,6 @@ class BaresipService: Service() {
|
||||
var isRecOn = false
|
||||
var toneCountry = "us"
|
||||
var proximitySensing = true
|
||||
var telecom = true
|
||||
|
||||
val uas = mutableStateOf(emptyList<UserAgent>())
|
||||
val uasStatus = mutableStateOf(emptyMap<String, Int>())
|
||||
@ -2609,8 +2588,6 @@ class BaresipService: Service() {
|
||||
) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
||||
) {
|
||||
Log.d(TAG, "requestAudioFocus granted")
|
||||
if (!telecom && isBluetoothHeadsetConnected(ctx))
|
||||
startBluetoothSco(ctx, 250L, 3)
|
||||
}
|
||||
else {
|
||||
Log.w(TAG, "requestAudioFocus denied")
|
||||
@ -2619,39 +2596,6 @@ class BaresipService: Service() {
|
||||
return audioFocusRequest != null
|
||||
}
|
||||
|
||||
fun abandonAudioFocus(ctx: Context) {
|
||||
val am = ctx.getSystemService(AUDIO_SERVICE) as AudioManager
|
||||
if (audioFocusRequest != null) {
|
||||
Log.d(TAG, "Abandoning audio focus")
|
||||
if (androidx.media.AudioManagerCompat.abandonAudioFocusRequest(
|
||||
am,
|
||||
audioFocusRequest!!
|
||||
) ==
|
||||
AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
||||
) {
|
||||
audioFocusRequest = null
|
||||
if (!telecom && isBluetoothHeadsetConnected(ctx))
|
||||
stopBluetoothSco(ctx)
|
||||
}
|
||||
else
|
||||
Log.e(TAG, "Failed to abandon audio focus")
|
||||
}
|
||||
am.mode = MODE_NORMAL
|
||||
}
|
||||
|
||||
private fun isBluetoothHeadsetConnected(ctx: Context): Boolean {
|
||||
if (VERSION.SDK_INT >= 31 &&
|
||||
ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) == PackageManager.PERMISSION_DENIED
|
||||
)
|
||||
return false
|
||||
return btAdapter != null && btAdapter!!.isEnabled &&
|
||||
btAdapter!!.getProfileConnectionState(BluetoothHeadset.HEADSET) ==
|
||||
BluetoothAdapter.STATE_CONNECTED
|
||||
}
|
||||
|
||||
private fun isBluetoothScoOn(am: AudioManager): Boolean {
|
||||
return if (VERSION.SDK_INT < 31)
|
||||
@Suppress("DEPRECATION")
|
||||
|
||||
@ -151,15 +151,11 @@ open class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir
|
||||
}
|
||||
|
||||
open fun hangup(code: Int, reason: String) {
|
||||
if (BaresipService.telecom) {
|
||||
val connection = ConnectionService.connections[callp]
|
||||
if (connection != null)
|
||||
connection.onDisconnect()
|
||||
else
|
||||
Api.ua_hangup(ua.uap, callp, code, reason)
|
||||
} else {
|
||||
val connection = ConnectionService.connections[callp]
|
||||
if (connection != null)
|
||||
connection.onDisconnect()
|
||||
else
|
||||
Api.ua_hangup(ua.uap, callp, code, reason)
|
||||
}
|
||||
}
|
||||
|
||||
open fun answer() {
|
||||
|
||||
@ -226,13 +226,6 @@ object Config {
|
||||
BaresipService.toneCountry = toneCountry
|
||||
config = "${config}tone_country ${BaresipService.toneCountry}\n"
|
||||
|
||||
val telecom = previousVariable("telecom")
|
||||
if (telecom != "")
|
||||
BaresipService.telecom = telecom == "yes"
|
||||
else
|
||||
BaresipService.telecom = true
|
||||
config = "${config}telecom ${if (BaresipService.telecom) "yes" else "no"}\n"
|
||||
|
||||
save()
|
||||
BaresipService.isConfigInitialized = true
|
||||
|
||||
|
||||
@ -2116,60 +2116,49 @@ private fun makeCall(ctx: Context, viewModel: ViewModel, uriText: String,
|
||||
else {
|
||||
viewModel.dialerState.callButtonsEnabled.value = false
|
||||
var error = ""
|
||||
if (BaresipService.telecom) {
|
||||
val tm = ctx.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
|
||||
if (ua.account.isMobile) {
|
||||
val phoneAccountHandle = Utils.pstnAccountHandle(ctx)
|
||||
if (phoneAccountHandle != null) {
|
||||
val extras = Bundle().apply {
|
||||
putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
|
||||
}
|
||||
val callExtras = Bundle()
|
||||
callExtras.putBoolean("pstnCall", true)
|
||||
callExtras.putString("aor", aor)
|
||||
extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras)
|
||||
try {
|
||||
Log.i(TAG, "Placing Telecom PSTN call to $uri with uap=${ua.uap}")
|
||||
tm.placeCall(uri.toUri(), extras)
|
||||
} catch (e: SecurityException) {
|
||||
error = "placeCall failed: ${e.message}"
|
||||
}
|
||||
val tm = ctx.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
|
||||
if (ua.account.isMobile) {
|
||||
val phoneAccountHandle = Utils.pstnAccountHandle(ctx)
|
||||
if (phoneAccountHandle != null) {
|
||||
val extras = Bundle().apply {
|
||||
putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
|
||||
}
|
||||
else
|
||||
error = "no phone account"
|
||||
}
|
||||
else {
|
||||
val extras = Bundle()
|
||||
extras.putParcelable(
|
||||
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
|
||||
BaresipService.getPhoneAccountHandle(ctx)
|
||||
)
|
||||
val callExtras = Bundle()
|
||||
callExtras.putBoolean("conferenceCall", dialerState.showCallConferenceButton.value)
|
||||
callExtras.putLong("uap", ua.uap)
|
||||
if (onHoldCallp != 0L)
|
||||
callExtras.putLong("onHoldCallp", onHoldCallp)
|
||||
callExtras.putBoolean("pstnCall", true)
|
||||
callExtras.putString("aor", aor)
|
||||
extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras)
|
||||
try {
|
||||
Log.d(TAG, "Placing Telecom SIP call to $uri with uap=${ua.uap}")
|
||||
Log.i(TAG, "Placing Telecom PSTN call to $uri with uap=${ua.uap}")
|
||||
tm.placeCall(uri.toUri(), extras)
|
||||
} catch (e: SecurityException) {
|
||||
error = "placeCall failed: ${e.message}"
|
||||
}
|
||||
}
|
||||
if (error != "") {
|
||||
Log.e(TAG, error)
|
||||
viewModel.dialerState.callButtonsEnabled.value = true
|
||||
}
|
||||
else
|
||||
error = "no phone account"
|
||||
}
|
||||
else {
|
||||
val intent = Intent(ctx, BaresipService::class.java)
|
||||
intent.action = "Start Call"
|
||||
intent.putExtra("uap", ua.uap)
|
||||
intent.putExtra("uri", uri)
|
||||
intent.putExtra("conferenceCall", dialerState.showCallConferenceButton.value)
|
||||
intent.putExtra("onHoldCallp", onHoldCallp)
|
||||
ctx.startService(intent)
|
||||
val extras = Bundle()
|
||||
extras.putParcelable(
|
||||
TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
|
||||
BaresipService.getPhoneAccountHandle(ctx)
|
||||
)
|
||||
val callExtras = Bundle()
|
||||
callExtras.putBoolean("conferenceCall", dialerState.showCallConferenceButton.value)
|
||||
callExtras.putLong("uap", ua.uap)
|
||||
if (onHoldCallp != 0L)
|
||||
callExtras.putLong("onHoldCallp", onHoldCallp)
|
||||
extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras)
|
||||
try {
|
||||
Log.d(TAG, "Placing Telecom SIP call to $uri with uap=${ua.uap}")
|
||||
tm.placeCall(uri.toUri(), extras)
|
||||
} catch (e: SecurityException) {
|
||||
error = "placeCall failed: ${e.message}"
|
||||
}
|
||||
}
|
||||
if (error != "") {
|
||||
Log.e(TAG, error)
|
||||
viewModel.dialerState.callButtonsEnabled.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2392,8 +2381,6 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
||||
|
||||
when (ev[0]) {
|
||||
"call rejected" -> {
|
||||
if (!BaresipService.telecom)
|
||||
BaresipService.abandonAudioFocus(ctx)
|
||||
if (aor == viewModel.selectedAor.value)
|
||||
viewModel.triggerAccountUpdate()
|
||||
}
|
||||
|
||||
@ -80,6 +80,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.compose.composable
|
||||
import com.tutpro.baresip.BaresipService.Companion.uas
|
||||
import com.tutpro.baresip.CustomElements.AlertDialog
|
||||
import com.tutpro.baresip.CustomElements.verticalScrollbar
|
||||
import com.tutpro.baresip.Utils.copyInputStreamToFile
|
||||
@ -1031,6 +1032,7 @@ private fun SettingsContent(
|
||||
) { result ->
|
||||
Log.d(TAG, "dialerRoleRequest result: $result")
|
||||
viewModel.defaultDialer.value = roleManager.isRoleHeld(RoleManager.ROLE_DIALER)
|
||||
BaresipService.instance?.addMobileUserAgent()
|
||||
}
|
||||
Switch(
|
||||
checked = defaultDialer,
|
||||
@ -1181,14 +1183,14 @@ private fun SettingsContent(
|
||||
UserAgent()
|
||||
UniqueContactUri()
|
||||
AudioSettings(navController)
|
||||
if (VERSION.SDK_INT >= 29)
|
||||
DefaultDialer()
|
||||
BatteryOptimizations()
|
||||
DarkTheme()
|
||||
if (VERSION.SDK_INT >= 31)
|
||||
DynamicColors()
|
||||
ColorBlind()
|
||||
ProximitySensing()
|
||||
if (VERSION.SDK_INT >= 29)
|
||||
DefaultDialer()
|
||||
Debug()
|
||||
SipTrace()
|
||||
Reset(onRestartApp)
|
||||
|
||||
@ -4,8 +4,10 @@ import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.KeyguardManager
|
||||
import android.app.role.RoleManager
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Context.ROLE_SERVICE
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
@ -1335,15 +1337,16 @@ object Utils {
|
||||
return file
|
||||
}
|
||||
|
||||
@RequiresApi(29)
|
||||
fun pstnAccountHandle(ctx: Context): PhoneAccountHandle? {
|
||||
val roleManager = ctx.getSystemService(ROLE_SERVICE) as RoleManager
|
||||
if (ctx.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) ==
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
PackageManager.PERMISSION_GRANTED &&
|
||||
roleManager.isRoleHeld(RoleManager.ROLE_DIALER)) {
|
||||
val tm = ctx.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
val preferredHandle: PhoneAccountHandle? = tm.userSelectedOutgoingPhoneAccount
|
||||
if (preferredHandle != null)
|
||||
return preferredHandle
|
||||
}
|
||||
val preferredHandle: PhoneAccountHandle? = tm.userSelectedOutgoingPhoneAccount
|
||||
if (preferredHandle != null)
|
||||
return preferredHandle
|
||||
val baresipHandle = BaresipService.getPhoneAccountHandle(ctx)
|
||||
val phoneAccounts = tm.callCapablePhoneAccounts.filter { it != baresipHandle }
|
||||
return if (phoneAccounts.isNotEmpty())
|
||||
|
||||
@ -321,8 +321,7 @@
|
||||
to standby state.</string>
|
||||
<string name="default_phone_app">Default Phone App</string>
|
||||
<string name="dialer_role_not_available">Dialer role is not available</string>
|
||||
<string name="default_phone_app_help">If checked, baresip is the default phone app. Do not check
|
||||
if your device may need to handle also other than SIP calls or messages.</string>
|
||||
<string name="default_phone_app_help">If checked, baresip is the default phone app.</string>
|
||||
<string name="listen_address">Listen Address</string>
|
||||
<string name="listen_address_help">IP address and port of form \'address:port\' at which baresip listens
|
||||
for incoming SIP requests. If IP address is an IPv6 address, it must be written inside
|
||||
@ -408,9 +407,6 @@
|
||||
<string name="colorblind_help">Use colorblind friendly registration status icons</string>
|
||||
<string name="proximity_sensing">Proximity Sensing</string>
|
||||
<string name="proximity_sensing_help">If checked, proximity sensing is active during calls.</string>
|
||||
<string name="telecom">Telecom Framework</string>
|
||||
<string name="telecom_help">Use Android Telecom framework for calls. If you experience audio
|
||||
related issues, try if it helps when you turn Telecom Framework off.</string>
|
||||
<string name="video_size">Video Frame Size</string>
|
||||
<string name="video_size_help">Size of transmitted video frames (width x height)</string>
|
||||
<string name="video_fps">Video Frames Per Second</string>
|
||||
|
||||
Reference in New Issue
Block a user