diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 13e10017..307c41a4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -1,7 +1,6 @@ @file:Suppress("DEPRECATION") package com.tutpro.baresip -import android.Manifest import android.Manifest.permission.RECORD_AUDIO import android.annotation.SuppressLint import android.app.Notification @@ -117,6 +116,7 @@ class BaresipService: Service() { private lateinit var bluetoothReceiver: BroadcastReceiver private lateinit var hotSpotReceiver: BroadcastReceiver private lateinit var airplaneModeReceiver: BroadcastReceiver + private lateinit var simStateReceiver: BroadcastReceiver private lateinit var androidContactsObserver: ContentObserver private lateinit var networkCallback: ConnectivityManager.NetworkCallback private lateinit var stopState: String @@ -138,6 +138,7 @@ class BaresipService: Service() { private var hotSpotReceiverRegistered = false private var bluetoothReceiverRegistered = false private var airplaneModeReceiverRegistered = false + private var simStateReceiverRegistered = false private var telephonyCallbackRegistered = false private var isNotificationInCall = false private var isServiceClean = false @@ -329,6 +330,22 @@ class BaresipService: Service() { ) 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 btm = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager @@ -1738,6 +1755,7 @@ class BaresipService: Service() { Handler(Looper.getMainLooper()).post { addMobileUserAgent() + updateMobileStatus() val mobileUa = uas.value.find { it.account.isMobile } if (mobileUa != null) @@ -2244,22 +2262,24 @@ class BaresipService: Service() { 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() - CallHistoryNew.save() - Message.save() - updateStatusNotification() - } - return - } - 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.status != status) { + Log.d(TAG, "Updating existing Mobile UA status to $status") + existingMobileUa.updateStatus(status) + updateStatusNotification() + if (isMainVisible) + registrationUpdate.postValue(System.currentTimeMillis()) + } return } @@ -2270,13 +2290,7 @@ class BaresipService: Service() { account.regint = 0 account.telProvider = "" val mobileUa = UserAgent(0L, account) - val isAirplaneModeOn = Utils.isAirplaneModeOn(this) - val hasSimCard = hasSimCard() - mobileUa.status = if (isAirplaneModeOn || !hasSimCard) - R.drawable.circle_white - else - circleRed.getValue(colorblind) - updateMobileStatus(mobileUa.status) + mobileUa.status = status val updatedUas = uas.value.toMutableList() updatedUas.add(mobileUa) @@ -2298,12 +2312,8 @@ class BaresipService: Service() { private fun updateMobileStatus(newStatus: Int? = null) { uas.value.find { it.account.isMobile }?.let { ua -> val isAirplaneModeOn = Utils.isAirplaneModeOn(this) - val hasSimCard = hasSimCard() - val status = newStatus ?: if (isAirplaneModeOn || !hasSimCard) { - if (ua.status == circleGreen.getValue(colorblind)) - ua.status - else - R.drawable.circle_white + val status = newStatus ?: if (isAirplaneModeOn || !isSimReady()) { + R.drawable.circle_white } else if (ua.status == R.drawable.circle_white) // Show "Red" (not yet in service) @@ -2324,10 +2334,10 @@ class BaresipService: Service() { if (state == previousMobileServiceState) return previousMobileServiceState = state val isAirplaneModeOn = Utils.isAirplaneModeOn(this) - val hasSimCard = hasSimCard() - val status = if (state == ServiceState.STATE_IN_SERVICE) + val isSimReady = isSimReady() + val status = if (state == ServiceState.STATE_IN_SERVICE && isSimReady) circleGreen.getValue(colorblind) - else if (isAirplaneModeOn || !hasSimCard) + else if (isAirplaneModeOn || !isSimReady()) R.drawable.circle_white else circleRed.getValue(colorblind) @@ -2939,73 +2949,83 @@ class BaresipService: Service() { tm.registerPhoneAccount(phoneAccount) } + fun isSimReady(): Boolean { + val tm = getSystemService(TELEPHONY_SERVICE) as TelephonyManager + return tm.simState == TelephonyManager.SIM_STATE_READY + } + private fun cleanService() { - if (!isServiceClean) { - if (hotSpotReceiverRegistered) { - try { - unregisterReceiver(hotSpotReceiver) - } catch (_: IllegalArgumentException) {} - hotSpotReceiverRegistered = false - } - if (bluetoothReceiverRegistered) { - try { - unregisterReceiver(bluetoothReceiver) - } catch (_: IllegalArgumentException) {} - bluetoothReceiverRegistered = false - } - if (airplaneModeReceiverRegistered) { - try { - unregisterReceiver(airplaneModeReceiver) - } catch (_: IllegalArgumentException) {} - airplaneModeReceiverRegistered = false - } - if (telephonyCallbackRegistered) { - if (VERSION.SDK_INT >= 31) - try { - telephonyManager.unregisterTelephonyCallback(telephonyCallback) - } catch (_: Exception) {} - else { - @Suppress("DEPRECATION") - telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE) - } - telephonyCallbackRegistered = false - } - val callps = ConnectionService.connections.keys.toList() - for (callp in callps) - ConnectionService.onCallClosed(callp) - ConnectionService.pendingOutgoingConnection?.let { - it.setDisconnected(DisconnectCause(DisconnectCause.CANCELED)) - it.destroy() - ConnectionService.pendingOutgoingConnection = null - } - stopRinging() - stopMediaPlayer() - abandonAudioFocus(this) - uas.value = emptyList() - uasStatus.value = emptyMap() - callHistory.clear() - messages = emptyList() - if (this::nm.isInitialized) - nm.cancelAll() - if (this::partialWakeLock.isInitialized && partialWakeLock.isHeld) - partialWakeLock.release() - if (this::proximityWakeLock.isInitialized && proximityWakeLock.isHeld) - proximityWakeLock.release() - if (this::wifiLock.isInitialized) - wifiLock.release() - if (this::networkCallback.isInitialized) - try { - cm.unregisterNetworkCallback(networkCallback) - } catch (_: Exception) {} - if (androidContactsObserverRegistered) { - try { - contentResolver.unregisterContentObserver(androidContactsObserver) - } catch (_: Exception) {} - androidContactsObserverRegistered = false - } - releaseAudioEffects() - isServiceClean = true + if (isServiceClean) return + if (simStateReceiverRegistered) { + try { + unregisterReceiver(simStateReceiver) + } catch (_: IllegalArgumentException) {} + simStateReceiverRegistered = false } + if (hotSpotReceiverRegistered) { + try { + unregisterReceiver(hotSpotReceiver) + } catch (_: IllegalArgumentException) {} + hotSpotReceiverRegistered = false + } + if (bluetoothReceiverRegistered) { + try { + unregisterReceiver(bluetoothReceiver) + } catch (_: IllegalArgumentException) {} + bluetoothReceiverRegistered = false + } + if (airplaneModeReceiverRegistered) { + try { + unregisterReceiver(airplaneModeReceiver) + } catch (_: IllegalArgumentException) {} + airplaneModeReceiverRegistered = false + } + if (telephonyCallbackRegistered) { + if (VERSION.SDK_INT >= 31) + try { + telephonyManager.unregisterTelephonyCallback(telephonyCallback) + } catch (_: Exception) {} + else { + @Suppress("DEPRECATION") + telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE) + } + telephonyCallbackRegistered = false + } + val callps = ConnectionService.connections.keys.toList() + for (callp in callps) + ConnectionService.onCallClosed(callp) + ConnectionService.pendingOutgoingConnection?.let { + it.setDisconnected(DisconnectCause(DisconnectCause.CANCELED)) + it.destroy() + ConnectionService.pendingOutgoingConnection = null + } + stopRinging() + stopMediaPlayer() + abandonAudioFocus(this) + uas.value = emptyList() + uasStatus.value = emptyMap() + callHistory.clear() + messages = emptyList() + if (this::nm.isInitialized) + nm.cancelAll() + if (this::partialWakeLock.isInitialized && partialWakeLock.isHeld) + partialWakeLock.release() + if (this::proximityWakeLock.isInitialized && proximityWakeLock.isHeld) + proximityWakeLock.release() + if (this::wifiLock.isInitialized) + wifiLock.release() + if (this::networkCallback.isInitialized) + try { + cm.unregisterNetworkCallback(networkCallback) + } catch (_: Exception) {} + if (androidContactsObserverRegistered) { + try { + contentResolver.unregisterContentObserver(androidContactsObserver) + } catch (_: Exception) {} + androidContactsObserverRegistered = false + } + releaseAudioEffects() + isServiceClean = true } private external fun baresipStart( @@ -3017,13 +3037,6 @@ class BaresipService: Service() { 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") companion object {