Improved mobile account's airplane mode handling in APIs < 31

This commit is contained in:
Juha Heinanen
2026-06-03 17:57:48 +03:00
parent 28d9ea78af
commit 7a7ad4f02e
@@ -1,3 +1,4 @@
@file:Suppress("DEPRECATION")
package com.tutpro.baresip package com.tutpro.baresip
import android.Manifest.permission.RECORD_AUDIO import android.Manifest.permission.RECORD_AUDIO
@@ -55,6 +56,7 @@ import android.telecom.Connection
import android.telecom.DisconnectCause import android.telecom.DisconnectCause
import android.telecom.PhoneAccountHandle import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager import android.telecom.TelecomManager
import android.telephony.PhoneStateListener
import android.telephony.ServiceState import android.telephony.ServiceState
import android.telephony.TelephonyCallback import android.telephony.TelephonyCallback
import android.telephony.TelephonyManager import android.telephony.TelephonyManager
@@ -89,6 +91,7 @@ import java.util.Timer
import java.util.TimerTask import java.util.TimerTask
import kotlin.concurrent.schedule import kotlin.concurrent.schedule
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.time.Duration.Companion.milliseconds
class BaresipService: Service() { class BaresipService: Service() {
@@ -104,6 +107,8 @@ class BaresipService: Service() {
private lateinit var btm: BluetoothManager private lateinit var btm: BluetoothManager
private lateinit var telephonyManager: TelephonyManager private lateinit var telephonyManager: TelephonyManager
private lateinit var telephonyCallback: TelephonyCallback private lateinit var telephonyCallback: TelephonyCallback
@Suppress("DEPRECATION")
private lateinit var phoneStateListener: PhoneStateListener
private lateinit var vibrator: Vibrator private lateinit var vibrator: Vibrator
private lateinit var partialWakeLock: PowerManager.WakeLock private lateinit var partialWakeLock: PowerManager.WakeLock
private lateinit var proximityWakeLock: PowerManager.WakeLock private lateinit var proximityWakeLock: PowerManager.WakeLock
@@ -390,15 +395,15 @@ class BaresipService: Service() {
if (VERSION.SDK_INT >= 31) { if (VERSION.SDK_INT >= 31) {
telephonyCallback = object : TelephonyCallback(), TelephonyCallback.ServiceStateListener { telephonyCallback = object : TelephonyCallback(), TelephonyCallback.ServiceStateListener {
override fun onServiceStateChanged(serviceState: ServiceState) { override fun onServiceStateChanged(serviceState: ServiceState) {
val isAirplaneModeOn = Utils.isAirplaneModeOn(this@BaresipService) updateMobileStatusFromServiceState(serviceState.state)
val status = if (isAirplaneModeOn) }
R.drawable.circle_white }
else if (serviceState.state == ServiceState.STATE_IN_SERVICE) } else {
circleGreen.getValue(colorblind) @Suppress("DEPRECATION")
else phoneStateListener = object : PhoneStateListener() {
circleRed.getValue(colorblind) @Deprecated("Deprecated in Java")
Log.d(TAG, "Mobile service state changed: ${serviceState.state}, updating status to $status") override fun onServiceStateChanged(serviceState: ServiceState) {
updateMobileStatus(status) updateMobileStatusFromServiceState(serviceState.state)
} }
} }
} }
@@ -1064,7 +1069,7 @@ class BaresipService: Service() {
// transaction (the re-INVITE from the peer) finish // transaction (the re-INVITE from the peer) finish
// before trying to hold the other call and resume this one. // before trying to hold the other call and resume this one.
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
delay(100) delay(100.milliseconds)
call.resume() call.resume()
} }
} }
@@ -1260,7 +1265,7 @@ class BaresipService: Service() {
} }
history.add() history.add()
if (call.startTime != null && call.dumpfiles[0] != "") { if (call.startTime != null && call.dumpfiles[0] != "") {
delay(500) delay(500.milliseconds)
val rxFile = File(call.dumpfiles[0]) val rxFile = File(call.dumpfiles[0])
val txFile = File(call.dumpfiles[1]) val txFile = File(call.dumpfiles[1])
val mergedFileName = rxFile.name val mergedFileName = rxFile.name
@@ -1643,6 +1648,11 @@ class BaresipService: Service() {
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to register TelephonyCallback: ${e.message}") Log.e(TAG, "Failed to register TelephonyCallback: ${e.message}")
} }
} else if (!telephonyCallbackRegistered) {
@Suppress("DEPRECATION")
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE)
telephonyCallbackRegistered = true
Log.d(TAG, "Registered PhoneStateListener")
} }
Api.net_debug() Api.net_debug()
postServiceEvent( postServiceEvent(
@@ -2094,6 +2104,7 @@ class BaresipService: Service() {
Log.d(TAG, "Removing Mobile account (role lost or SIM missing)") Log.d(TAG, "Removing Mobile account (role lost or SIM missing)")
existingMobileUa.remove() existingMobileUa.remove()
Account.saveAccounts() Account.saveAccounts()
updateStatusNotification()
} }
return return
} }
@@ -2121,6 +2132,7 @@ class BaresipService: Service() {
uasStatus.value = UserAgent.statusMap() uasStatus.value = UserAgent.statusMap()
Account.saveAccounts() Account.saveAccounts()
updateStatusNotification()
} }
private fun toast(message: String, length: Int = Toast.LENGTH_SHORT) { private fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {
@@ -2133,10 +2145,16 @@ class BaresipService: Service() {
uas.value.find { it.account.isMobile }?.let { ua -> uas.value.find { it.account.isMobile }?.let { ua ->
val isAirplaneModeOn = Utils.isAirplaneModeOn(this) val isAirplaneModeOn = Utils.isAirplaneModeOn(this)
val status = newStatus val status = newStatus
?: if (isAirplaneModeOn) ?: if (isAirplaneModeOn) {
R.drawable.circle_white R.drawable.circle_white
else } else {
ua.status if (ua.status == R.drawable.circle_white) {
// Show "Red" (not yet in service)
circleRed.getValue(colorblind)
} else {
ua.status
}
}
if (ua.status != status) { if (ua.status != status) {
Log.d(TAG, "Updating Mobile status to $status") Log.d(TAG, "Updating Mobile status to $status")
ua.updateStatus(status) ua.updateStatus(status)
@@ -2147,6 +2165,18 @@ class BaresipService: Service() {
} }
} }
private fun updateMobileStatusFromServiceState(state: Int) {
val isAirplaneModeOn = Utils.isAirplaneModeOn(this)
val status = if (isAirplaneModeOn)
R.drawable.circle_white
else if (state == ServiceState.STATE_IN_SERVICE)
circleGreen.getValue(colorblind)
else
circleRed.getValue(colorblind)
Log.d(TAG, "Mobile service state changed: $state, updating status to $status")
updateMobileStatus(status)
}
@SuppressLint("FullScreenIntentPolicy") @SuppressLint("FullScreenIntentPolicy")
fun handleIncomingCall(call: Call) { fun handleIncomingCall(call: Call) {
val ua = call.ua val ua = call.ua
@@ -2751,6 +2781,9 @@ class BaresipService: Service() {
try { try {
telephonyManager.unregisterTelephonyCallback(telephonyCallback) telephonyManager.unregisterTelephonyCallback(telephonyCallback)
} catch (_: Exception) {} } catch (_: Exception) {}
} else {
@Suppress("DEPRECATION")
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
} }
telephonyCallbackRegistered = false telephonyCallbackRegistered = false
} }