android: watchdog backs off whenever a live process owns recovery
Retrying, connecting or whitelist-blocked sessions kept the 60 s alarm and the 10 min Doze wakeup for hours although a live process makes the alarm useless. They now share the connected backoff (5 min / 60 min). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
24e536b9b9
commit
cf89cec20e
2 files changed
+46
-12
No files matched your search
+22
-12
@@ -150,6 +150,19 @@ public class WatchdogReceiver extends BroadcastReceiver
|
||||
return Action.RESTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a check counts towards the steady-state backoff of a live
|
||||
* process: connected, retrying/connecting, or held back by the ISP
|
||||
* whitelist. In all of these the in-process machinery owns recovery and
|
||||
* the alarm can only guard against the process dying - firing every
|
||||
* minute (and waking Doze every 10 minutes) for hours of failed retries
|
||||
* or whitelist blocking only burns battery.
|
||||
*/
|
||||
static boolean isAliveSteady(Action action, boolean processAlive, boolean parked)
|
||||
{
|
||||
return action == Action.NONE && processAlive && !parked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
@@ -164,27 +177,24 @@ public class WatchdogReceiver extends BroadcastReceiver
|
||||
return;
|
||||
}
|
||||
reschedule(context);
|
||||
if (WhiteListManager.getInstance(context).shouldBlockReconnect())
|
||||
{ /* the ISP whitelist blocks the server; the in-process retry
|
||||
* machinery parks itself in that case, so should we */
|
||||
DiagLog.i(TAG, "whitelist blocks the server, not restarting");
|
||||
return;
|
||||
}
|
||||
/* the ISP whitelist blocks the server; the in-process retry
|
||||
* machinery parks itself in that case, so should we */
|
||||
boolean whitelistBlocks = WhiteListManager.getInstance(context).shouldBlockReconnect();
|
||||
VpnStateService service = VpnStateService.getLiveInstance();
|
||||
boolean processAlive = service != null;
|
||||
boolean serviceTracking = processAlive && service.getState() != VpnStateService.State.DISABLED;
|
||||
boolean wifiPresent = isWifiPresent(context);
|
||||
boolean autoProfileConfigured = AutoConnectManager.getInstance(context).getCurrentConfig().getProfileUuid() != null;
|
||||
Action action = decideAction(enabled, uuid != null, autoExpected, false, serviceTracking,
|
||||
Action action = decideAction(enabled, uuid != null, autoExpected, whitelistBlocks, serviceTracking,
|
||||
processAlive, wifiPresent, autoProfileConfigured);
|
||||
boolean connected = serviceTracking && service.getState() == VpnStateService.State.CONNECTED;
|
||||
boolean parked = uuid == null && autoExpected && processAlive && !serviceTracking && action == Action.NONE;
|
||||
boolean alive = isAliveSteady(action, processAlive, parked);
|
||||
if (parked)
|
||||
{
|
||||
sParkedChecks++;
|
||||
sConnectedChecks = 0;
|
||||
}
|
||||
else if (connected && action == Action.NONE)
|
||||
else if (alive)
|
||||
{
|
||||
sConnectedChecks++;
|
||||
sParkedChecks = 0;
|
||||
@@ -195,8 +205,8 @@ public class WatchdogReceiver extends BroadcastReceiver
|
||||
sConnectedChecks = 0;
|
||||
}
|
||||
boolean parkedSteady = parked && sParkedChecks >= PARKED_BACKOFF_AFTER;
|
||||
boolean connectedSteady = connected && sConnectedChecks >= CONNECTED_BACKOFF_AFTER;
|
||||
String cadence = parkedSteady ? "parked" : connectedSteady ? "connected" : null;
|
||||
boolean connectedSteady = alive && sConnectedChecks >= CONNECTED_BACKOFF_AFTER;
|
||||
String cadence = parkedSteady ? "parked" : connectedSteady ? "alive" : null;
|
||||
if (cadence != null)
|
||||
{ /* steady state: log the transition once, then stay silent - a
|
||||
* per-fire line only floods diag.log and burns flash I/O */
|
||||
@@ -210,7 +220,7 @@ public class WatchdogReceiver extends BroadcastReceiver
|
||||
{
|
||||
DiagLog.i(TAG, "check: uuid=" + (uuid != null) + " autoExpected=" + autoExpected +
|
||||
" processAlive=" + processAlive + " tracking=" + serviceTracking +
|
||||
" wifi=" + wifiPresent + " -> " + action);
|
||||
" whitelist=" + whitelistBlocks + " wifi=" + wifiPresent + " -> " + action);
|
||||
}
|
||||
sLastCadence = cadence;
|
||||
switch (action)
|
||||
|
||||
+24
@@ -125,4 +125,28 @@ class WatchdogReceiverTest
|
||||
assertThat(decide(expectedProfileSet = true, autoExpected = true, processAlive = false, wifiPresent = false))
|
||||
.isEqualTo(Action.RESTART)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun liveProcessRetryingOrWhitelistedBacksOff()
|
||||
{
|
||||
/* retrying/connecting: the service tracks the connection */
|
||||
val retrying = decide(expectedProfileSet = true, serviceTracking = true, processAlive = true)
|
||||
assertThat(retrying).isEqualTo(Action.NONE)
|
||||
assertThat(WatchdogReceiver.isAliveSteady(retrying, true, false)).isTrue()
|
||||
/* whitelist blocks the server while the process is alive */
|
||||
val blocked = decide(expectedProfileSet = true, whitelistBlocks = true, processAlive = true)
|
||||
assertThat(WatchdogReceiver.isAliveSteady(blocked, true, false)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deadProcessOrRestartNeverBacksOff()
|
||||
{
|
||||
val restart = decide(expectedProfileSet = true, processAlive = false)
|
||||
assertThat(WatchdogReceiver.isAliveSteady(restart, false, false)).isFalse()
|
||||
/* whitelist blocks, but no live process: keep the fast cadence */
|
||||
val blocked = decide(expectedProfileSet = true, whitelistBlocks = true, processAlive = false)
|
||||
assertThat(WatchdogReceiver.isAliveSteady(blocked, false, false)).isFalse()
|
||||
/* parked sessions use their own backoff */
|
||||
assertThat(WatchdogReceiver.isAliveSteady(Action.NONE, true, true)).isFalse()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user