Fix offline SecurityException from WorkManager network tracking

WorkManager's persisted work database and JobScheduler jobs survive an
upgrade from the free flavor (shared applicationId). On startup,
WorkManagerInitializer reschedules that stale network-constrained work,
and WorkManager 2.11.2 tracks it via
ConnectivityManager.registerDefaultNetworkCallback, which throws
SecurityException because the offline flavor removes
ACCESS_NETWORK_STATE. The flavor guards in Amber only prevent new
enqueues and cannot stop this.

WorkManager is unused in the offline flavor (all enqueues are
flavor-guarded and ConnectivityService never starts), so strip all of
its manifest components there: WorkManagerInitializer plus
SystemJobService, SystemForegroundService, ForceStopRunnable receiver,
RescheduleReceiver and DiagnosticsReceiver, which would otherwise crash
via stale jobs or BOOT_COMPLETED after initialization is disabled.

Also guard cancelBackupApplicationsAlarm (reachable from
ApplicationsBackupScreen) with isOfflineFlavor like its siblings, and
extend check-offline-permissions.yml to fail if WorkManagerInitializer
or SystemJobService reappear in the offline merged manifest.
This commit is contained in:
greenart7c3
2026-09-09 08:32:19 -03:00
parent b2c18344db
commit 6f4128c0f8
3 changed files with 54 additions and 0 deletions
@@ -60,5 +60,20 @@ jobs:
else
echo "OK: No $PERMISSION in offline build manifest"
fi
for COMPONENT in androidx.work.WorkManagerInitializer androidx.work.impl.background.systemjob.SystemJobService; do
if grep -q "$COMPONENT" "$MANIFEST"; then
echo ""
echo "ERROR: $COMPONENT found in offline build manifest!"
echo "WorkManager must never initialize in the offline flavor: it tracks"
echo "network-constrained work via ConnectivityManager, which crashes with"
echo "SecurityException because ACCESS_NETWORK_STATE is removed."
echo ""
echo "Offending lines:"
grep "$COMPONENT" "$MANIFEST"
FAILED=1
else
echo "OK: No $COMPONENT in offline build manifest"
fi
done
done
exit $FAILED
@@ -337,6 +337,7 @@ class Amber :
}
fun cancelBackupApplicationsAlarm() {
if (BuildFlavorChecker.isOfflineFlavor()) return
WorkManager.getInstance(this).cancelUniqueWork("BackupApplicationsWorker")
}
+38
View File
@@ -29,6 +29,44 @@
android:enabled="true"
android:exported="true" />
<!-- WorkManager is dead code in the offline flavor: every WorkManager enqueue is
flavor-guarded and ConnectivityService (the only startCleanLogsAlarm caller)
never runs here. Its auto-initialization must not run either: for any persisted
network-constrained work (e.g. state left by an installed free flavor), WorkManager
tracks it via ConnectivityManager.registerDefaultNetworkCallback, which throws
SecurityException because ACCESS_NETWORK_STATE is removed below. Strip every
WorkManager manifest component so it can never initialize or be invoked here. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
<service
android:name="androidx.work.impl.background.systemjob.SystemJobService"
tools:node="remove" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
tools:node="remove" />
<receiver
android:name="androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver"
tools:node="remove" />
<receiver
android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver"
tools:node="remove" />
<receiver
android:name="androidx.work.impl.diagnostics.DiagnosticsReceiver"
tools:node="remove" />
<activity
android:name=".MainActivity"
android:exported="true">