Acquire PARTIAL_WAKE lock only during calls and briefly during registrations and network transitions

This commit is contained in:
Juha Heinanen
2026-04-12 18:52:04 +03:00
parent 71119f1c76
commit 97a31b5e31
6 changed files with 63 additions and 39 deletions

View File

@ -167,8 +167,10 @@ class BaresipService: Service() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
Log.d(TAG, "Network $network is available")
if (network !in allNetworks)
allNetworks.add(network)
synchronized(allNetworks) {
if (network !in allNetworks)
allNetworks.add(network)
}
}
override fun onLosing(network: Network, maxMsToLive: Int) {
@ -179,16 +181,20 @@ class BaresipService: Service() {
override fun onLost(network: Network) {
super.onLost(network)
Log.d(TAG, "Network $network is lost")
if (network in allNetworks)
allNetworks.remove(network)
synchronized(allNetworks) {
if (network in allNetworks)
allNetworks.remove(network)
}
if (isServiceRunning)
updateNetwork()
}
override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
super.onCapabilitiesChanged(network, caps)
if (network !in allNetworks)
allNetworks.add(network)
synchronized(allNetworks) {
if (network !in allNetworks)
allNetworks.add(network)
}
if (isServiceRunning)
updateNetwork()
}
@ -196,8 +202,10 @@ class BaresipService: Service() {
override fun onLinkPropertiesChanged(network: Network, props: LinkProperties) {
super.onLinkPropertiesChanged(network, props)
Log.d(TAG, "Network $network link properties changed: $props")
if (network !in allNetworks)
allNetworks.add(network)
synchronized(allNetworks) {
if (network !in allNetworks)
allNetworks.add(network)
}
if (isServiceRunning)
updateNetwork()
}
@ -740,6 +748,7 @@ class BaresipService: Service() {
if (uas.value[accountIndex].account.aor == aor) {
when (ev[0]) {
"registering", "unregistering" -> {
updatePartialWakeLock(brief = true)
ua.updateStatus(circleYellow.getValue(colorblind))
updateStatusNotification()
if (isMainVisible)
@ -747,6 +756,7 @@ class BaresipService: Service() {
return
}
"registered" -> {
updatePartialWakeLock(brief = true)
ua.updateStatus(
if (Api.account_regint(ua.account.accp) == 0)
R.drawable.circle_white
@ -759,6 +769,7 @@ class BaresipService: Service() {
return
}
"registering failed" -> {
updatePartialWakeLock(brief = true)
ua.updateStatus(if (Api.account_regint(ua.account.accp) == 0)
R.drawable.circle_white
else
@ -1408,6 +1419,7 @@ class BaresipService: Service() {
@Keep
fun started() {
Log.d(TAG, "Received 'started' from baresip")
isNativeReady = true
Api.net_debug()
postServiceEvent(ServiceEvent("started", arrayListOf(callActionUri), System.nanoTime()))
callActionUri = ""
@ -1422,6 +1434,7 @@ class BaresipService: Service() {
@Keep
fun stopped(error: String) {
Log.d(TAG, "Received 'stopped' from baresip with start error '$error'")
isNativeReady = false
quitTimer.cancel()
cleanService()
isServiceRunning = false
@ -1629,18 +1642,23 @@ class BaresipService: Service() {
}
@SuppressLint("WakelockTimeout")
private fun updatePartialWakeLock() {
val isAnyUaActive = uasStatus.value.values.any { it != R.drawable.circle_white }
val needsToStayAwake = isAnyUaActive || calls.isNotEmpty()
private fun updatePartialWakeLock(brief: Boolean = false) {
// Only hold a permanent wake lock during active calls.
// For registration standby, rely on the foreground service and kernel socket wakes.
// Also hold it briefly for registration events or network transitions.
val needsToStayAwake = calls.isNotEmpty()
try {
if (needsToStayAwake) {
if (!partialWakeLock.isHeld) {
Log.d(TAG, "Acquiring Partial Wake Lock (UA Active or Call in progress)")
Log.d(TAG, "Acquiring Partial Wake Lock (Call in progress)")
partialWakeLock.acquire()
}
} else if (brief) {
Log.d(TAG, "Acquiring Brief Partial Wake Lock (2s)")
partialWakeLock.acquire(2000L)
} else {
if (partialWakeLock.isHeld) {
Log.d(TAG, "Releasing Partial Wake Lock (All UAs idle and no calls)")
Log.d(TAG, "Releasing Partial Wake Lock (No calls in progress)")
partialWakeLock.release()
}
}
@ -1943,6 +1961,9 @@ class BaresipService: Service() {
}
private fun updateNetwork() {
if (!isNativeReady) return
updatePartialWakeLock(brief = true)
updateDnsServers()
val addresses = linkAddresses()
@ -1999,15 +2020,18 @@ class BaresipService: Service() {
private fun linkAddresses(): MutableMap<String, String> {
val addresses = mutableMapOf<String, String>()
for (n in allNetworks) {
val caps = cm.getNetworkCapabilities(n) ?: continue
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
val props = cm.getLinkProperties(n) ?: continue
for (la in props.linkAddresses)
if (la.scope == OsConstants.RT_SCOPE_UNIVERSE &&
synchronized(allNetworks) {
for (n in allNetworks) {
val caps = cm.getNetworkCapabilities(n) ?: continue
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) {
val props = cm.getLinkProperties(n) ?: continue
for (la in props.linkAddresses)
if (la.scope == OsConstants.RT_SCOPE_UNIVERSE &&
props.interfaceName != null && la.address.hostAddress != null &&
afMatch(la.address.hostAddress!!))
addresses[la.address.hostAddress!!] = props.interfaceName!!
afMatch(la.address.hostAddress!!)
)
addresses[la.address.hostAddress!!] = props.interfaceName!!
}
}
}
if (hotSpotIsEnabled) {
@ -2138,6 +2162,7 @@ class BaresipService: Service() {
var instance: BaresipService? = null
var isServiceRunning = false
var isNativeReady = false
var isStartReceived = false
var isConfigInitialized = false
var libraryLoaded = false

View File

@ -3,7 +3,7 @@ package com.tutpro.baresip
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.ContextCompat
import java.nio.charset.StandardCharsets
@ -17,14 +17,12 @@ class BootCompletedReceiver : BroadcastReceiver() {
val config = Utils.getFileContents(configPath) ?: return
val asCv = Utils.getNameValue(String(config, StandardCharsets.ISO_8859_1), "auto_start")
if ((asCv.isNotEmpty()) && (asCv[0] == "yes")) {
Log.i(TAG, "Start baresip upon boot completed")
val i = Intent(context, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val b = Bundle()
b.putBoolean("onStartup", true)
putExtras(b)
Log.i(TAG, "Start baresip service upon boot completed")
val baresipService = Intent(context, BaresipService::class.java).apply {
action = "Start"
putExtra("onStartup", true)
}
context.startActivity(i)
ContextCompat.startForegroundService(context, baresipService)
}
}

View File

@ -25,7 +25,6 @@ import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
@ -35,6 +34,7 @@ import androidx.lifecycle.Observer
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import androidx.core.content.ContextCompat
import kotlin.system.exitProcess
class MainActivity : ComponentActivity() {
@ -150,7 +150,7 @@ class MainActivity : ComponentActivity() {
if (BaresipService.isServiceRunning) {
restart = true
baresipService.action = "Stop"
startService(baresipService)
ContextCompat.startForegroundService(this, baresipService)
} else {
finishAndRemoveTask()
val pm = applicationContext.packageManager
@ -171,7 +171,7 @@ class MainActivity : ComponentActivity() {
if (BaresipService.isServiceRunning) {
restart = false
baresipService.action = "Stop"
startService(baresipService)
ContextCompat.startForegroundService(this, baresipService)
} else {
finishAndRemoveTask()
exitProcess(0)
@ -236,7 +236,7 @@ class MainActivity : ComponentActivity() {
else {
if (!BaresipService.isStartReceived) {
baresipService.action = "Start"
startService(baresipService)
ContextCompat.startForegroundService(this, baresipService)
if (atStartup)
moveTaskToBack(true)
}
@ -389,7 +389,7 @@ class MainActivity : ComponentActivity() {
if (BaresipService.isServiceRunning) {
restart = reStart
baresipService.action = "Stop"
startService(baresipService)
ContextCompat.startForegroundService(this, baresipService)
} else {
finishAndRemoveTask()
if (reStart)

View File

@ -2087,7 +2087,7 @@ private fun answer(ctx: Context, call: Call) {
intent.action = "Call Answer"
intent.putExtra("uap", call.ua.uap)
intent.putExtra("callp", call.callp)
ctx.startService(intent)
ContextCompat.startForegroundService(ctx, intent)
}
private fun reject(call: Call) {

View File

@ -21,6 +21,7 @@ import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -74,7 +75,6 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
@ -1499,7 +1499,7 @@ private fun checkOnClick(ctx: Context, viewModel: SettingsViewModel): Boolean {
}
}
Contact.contactsUpdate()
ctx.startService(baresipService)
ContextCompat.startForegroundService(ctx, baresipService)
save = true
}
@ -1535,7 +1535,7 @@ private fun checkOnClick(ctx: Context, viewModel: SettingsViewModel): Boolean {
UserAgent.updateColorblindStatus()
val baresipService = Intent(ctx, BaresipService::class.java)
baresipService.action = "Update Notification"
ctx.startService(baresipService)
ContextCompat.startForegroundService(ctx, baresipService)
save = true
}

View File

@ -3,6 +3,7 @@ package com.tutpro.baresip
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
class TaskReceiver : BroadcastReceiver() {
@ -46,7 +47,7 @@ class TaskReceiver : BroadcastReceiver() {
val baresipService = Intent(context, BaresipService::class.java)
if (BaresipService.isServiceRunning) {
baresipService.action = "Stop"
context.startService(baresipService)
ContextCompat.startForegroundService(context, baresipService)
}
}