fix(android): gate the wifi read on ACCESS_WIFI_STATE, and declare it

Reported from the phone's diag log:

  status: crashed: SecurityException: WifiService: Neither user 10519 nor
  current process has android.permission.ACCESS_WIFI_STATE.
  at android.os.Parcel.createExceptionOrNull

`PhoneSensors.wifiSsid` read `WifiManager.connectionInfo` behind nothing
but the location grant, but WifiService gates every WifiManager call on
ACCESS_WIFI_STATE — and it enforces that by throwing SecurityException,
not by answering null. The permission was never declared, so the read
always threw.

The cost is larger than the missing SSID: the throw travels out of
`readSnapshot` into the worker's catch, which logs "status: crashed" and
returns failure — so one undeclared permission took the battery, network,
DND and location topics down with it, and the fleet's rows went stale
while the app looked healthy.

Two halves, both needed:

- the manifest declares ACCESS_WIFI_STATE (a normal permission: declaring
  it is the whole grant, no runtime prompt). An install that predates the
  line keeps the grant set it was installed with, so this alone does not
  stop the crash on an existing phone;
- `wifiSsid` returns null unless the permission is actually held, and
  wraps the read in `runCatching`, so the status report degrades to "no
  wifi name" instead of dying whole. The check is a `hasWifiState` beside
  the existing `hasLocation`, same idiom.
This commit is contained in:
kosmos authored and Valentin Haudiquet committed 2026-11-08 17:54:15 +01:00
1 parent 52ee642eee
commit 6ae21568d0
2 files changed
+21 -2

No files matched your search

+7
View File
@@ -11,6 +11,13 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Every WifiManager call — including the connectionInfo that
names the joined network — is gated on ACCESS_WIFI_STATE, which
WifiService enforces by throwing SecurityException, not by
answering null. A normal permission, so declaring it is the
whole grant: an install that predates this line keeps the grant
set it was installed with. -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- DND control is a special-app grant, and this declaration is what
puts the app on the "Do Not Disturb access" screen's list: an
undeclared app opens that screen and finds nothing to flip. -->