Improved SIM card detection

Do not remove mobile account when role changes
This commit is contained in:
Juha Heinanen
2026-06-30 14:04:39 +03:00
parent 026e845d9b
commit 12e6f3eada
@@ -1,7 +1,6 @@
@file:Suppress("DEPRECATION") @file:Suppress("DEPRECATION")
package com.tutpro.baresip package com.tutpro.baresip
import android.Manifest
import android.Manifest.permission.RECORD_AUDIO import android.Manifest.permission.RECORD_AUDIO
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Notification import android.app.Notification
@@ -117,6 +116,7 @@ class BaresipService: Service() {
private lateinit var bluetoothReceiver: BroadcastReceiver private lateinit var bluetoothReceiver: BroadcastReceiver
private lateinit var hotSpotReceiver: BroadcastReceiver private lateinit var hotSpotReceiver: BroadcastReceiver
private lateinit var airplaneModeReceiver: BroadcastReceiver private lateinit var airplaneModeReceiver: BroadcastReceiver
private lateinit var simStateReceiver: BroadcastReceiver
private lateinit var androidContactsObserver: ContentObserver private lateinit var androidContactsObserver: ContentObserver
private lateinit var networkCallback: ConnectivityManager.NetworkCallback private lateinit var networkCallback: ConnectivityManager.NetworkCallback
private lateinit var stopState: String private lateinit var stopState: String
@@ -138,6 +138,7 @@ class BaresipService: Service() {
private var hotSpotReceiverRegistered = false private var hotSpotReceiverRegistered = false
private var bluetoothReceiverRegistered = false private var bluetoothReceiverRegistered = false
private var airplaneModeReceiverRegistered = false private var airplaneModeReceiverRegistered = false
private var simStateReceiverRegistered = false
private var telephonyCallbackRegistered = false private var telephonyCallbackRegistered = false
private var isNotificationInCall = false private var isNotificationInCall = false
private var isServiceClean = false private var isServiceClean = false
@@ -329,6 +330,22 @@ class BaresipService: Service() {
) )
airplaneModeReceiverRegistered = true airplaneModeReceiverRegistered = true
simStateReceiver = object : BroadcastReceiver() {
override fun onReceive(ctx: Context, intent: Intent) {
if (intent.action == "android.intent.action.SIM_STATE_CHANGED") {
Log.d(TAG, "SIM state changed")
updateMobileStatus()
}
}
}
ContextCompat.registerReceiver(
this,
simStateReceiver,
IntentFilter("android.intent.action.SIM_STATE_CHANGED"),
ContextCompat.RECEIVER_EXPORTED
)
simStateReceiverRegistered = true
tm = getSystemService(TELECOM_SERVICE) as TelecomManager tm = getSystemService(TELECOM_SERVICE) as TelecomManager
btm = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager btm = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
@@ -1738,6 +1755,7 @@ class BaresipService: Service() {
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
addMobileUserAgent() addMobileUserAgent()
updateMobileStatus()
val mobileUa = uas.value.find { it.account.isMobile } val mobileUa = uas.value.find { it.account.isMobile }
if (mobileUa != null) if (mobileUa != null)
@@ -2244,22 +2262,24 @@ class BaresipService: Service() {
val mobileAccountHandle = Utils.pstnAccountHandle(this) val mobileAccountHandle = Utils.pstnAccountHandle(this)
val existingMobileUa = uas.value.find { it.account.isMobile } 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()
CallHistoryNew.save()
Message.save()
updateStatusNotification()
}
return
}
val mobileAor = "sip:mobile@pstn" val mobileAor = "sip:mobile@pstn"
val isAirplaneModeOn = Utils.isAirplaneModeOn(this)
val status = if (mobileAccountHandle == null || isAirplaneModeOn || !isSimReady())
R.drawable.circle_white
else if (existingMobileUa?.status == circleGreen.getValue(colorblind))
circleGreen.getValue(colorblind)
else
circleRed.getValue(colorblind)
if (existingMobileUa != null) { if (existingMobileUa != null) {
if (existingMobileUa.status != status) {
Log.d(TAG, "Updating existing Mobile UA status to $status")
existingMobileUa.updateStatus(status)
updateStatusNotification()
if (isMainVisible)
registrationUpdate.postValue(System.currentTimeMillis())
}
return return
} }
@@ -2270,13 +2290,7 @@ class BaresipService: Service() {
account.regint = 0 account.regint = 0
account.telProvider = "" account.telProvider = ""
val mobileUa = UserAgent(0L, account) val mobileUa = UserAgent(0L, account)
val isAirplaneModeOn = Utils.isAirplaneModeOn(this) mobileUa.status = status
val hasSimCard = hasSimCard()
mobileUa.status = if (isAirplaneModeOn || !hasSimCard)
R.drawable.circle_white
else
circleRed.getValue(colorblind)
updateMobileStatus(mobileUa.status)
val updatedUas = uas.value.toMutableList() val updatedUas = uas.value.toMutableList()
updatedUas.add(mobileUa) updatedUas.add(mobileUa)
@@ -2298,11 +2312,7 @@ class BaresipService: Service() {
private fun updateMobileStatus(newStatus: Int? = null) { private fun updateMobileStatus(newStatus: Int? = null) {
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 hasSimCard = hasSimCard() val status = newStatus ?: if (isAirplaneModeOn || !isSimReady()) {
val status = newStatus ?: if (isAirplaneModeOn || !hasSimCard) {
if (ua.status == circleGreen.getValue(colorblind))
ua.status
else
R.drawable.circle_white R.drawable.circle_white
} }
else if (ua.status == R.drawable.circle_white) else if (ua.status == R.drawable.circle_white)
@@ -2324,10 +2334,10 @@ class BaresipService: Service() {
if (state == previousMobileServiceState) return if (state == previousMobileServiceState) return
previousMobileServiceState = state previousMobileServiceState = state
val isAirplaneModeOn = Utils.isAirplaneModeOn(this) val isAirplaneModeOn = Utils.isAirplaneModeOn(this)
val hasSimCard = hasSimCard() val isSimReady = isSimReady()
val status = if (state == ServiceState.STATE_IN_SERVICE) val status = if (state == ServiceState.STATE_IN_SERVICE && isSimReady)
circleGreen.getValue(colorblind) circleGreen.getValue(colorblind)
else if (isAirplaneModeOn || !hasSimCard) else if (isAirplaneModeOn || !isSimReady())
R.drawable.circle_white R.drawable.circle_white
else else
circleRed.getValue(colorblind) circleRed.getValue(colorblind)
@@ -2939,8 +2949,19 @@ class BaresipService: Service() {
tm.registerPhoneAccount(phoneAccount) tm.registerPhoneAccount(phoneAccount)
} }
fun isSimReady(): Boolean {
val tm = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
return tm.simState == TelephonyManager.SIM_STATE_READY
}
private fun cleanService() { private fun cleanService() {
if (!isServiceClean) { if (isServiceClean) return
if (simStateReceiverRegistered) {
try {
unregisterReceiver(simStateReceiver)
} catch (_: IllegalArgumentException) {}
simStateReceiverRegistered = false
}
if (hotSpotReceiverRegistered) { if (hotSpotReceiverRegistered) {
try { try {
unregisterReceiver(hotSpotReceiver) unregisterReceiver(hotSpotReceiver)
@@ -3006,7 +3027,6 @@ class BaresipService: Service() {
releaseAudioEffects() releaseAudioEffects()
isServiceClean = true isServiceClean = true
} }
}
private external fun baresipStart( private external fun baresipStart(
path: String, path: String,
@@ -3017,13 +3037,6 @@ class BaresipService: Service() {
external fun baresipStop(force: Boolean) external fun baresipStop(force: Boolean)
private fun hasSimCard(): Boolean {
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED)
return false
val sm = getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE) as android.telephony.SubscriptionManager
return sm.activeSubscriptionInfoList?.isNotEmpty() ?: false
}
@SuppressLint("MutableCollectionMutableState") @SuppressLint("MutableCollectionMutableState")
companion object { companion object {