# P2 permission recovery / ANR investigation **Disposition:** permission denial, recovery, recording persistence, and Android revocation termination reproduced. No ANR occurred during this run. GPS re-acquisition after restoring global location could not be verified because the isolated emulator delivered no new fix after the toggle. No product files changed. ## Build, device, and isolation - Dedicated fresh Pixel 8 Pro AVD `Pixel8Pro_QA`, serial `emulator-5556`, Android 17 / API 37. `emulator-5554` stayed exclusively with the P1 owner and was not accessed. - Installed `app.motorsignal.motorcycle`, versionCode 102 / versionName 1.0.2, APK SHA-256 `279F561D8DB91D01138321EE2666B2029D239BC6008809E802458FF835796AA2` (root-confirmed build). - Wi-Fi, cellular data, and airplane-mode state were set offline before launch. `dumpsys connectivity` reported `Active default network: none`. No backend account was signed in or created. No production request/write was made. - Logcat captured with `adb logcat -c` and `adb -s emulator-5556 logcat -v threadtime` to `%TEMP%\MotorSignal-QA-2026-10-01-p2-permission.log` (3,747,443 bytes; stopped after tests). Permission state and activity state were sampled at each transition. Logcat contains the explicit system revocation kill below; no app `FATAL EXCEPTION` or ANR lines were found. ## Scenario results | Scenario | Result | Evidence | | --- | --- | --- | | Deny permission on first launch | **PASS — degraded UI verified** | At 06:24–06:25 EDT, denied the Android location and notification prompts. Fine/coarse permissions showed `granted=false`, `USER_SET|USER_FIXED`. Dashboard remained interactive with `Location permission needed for GPS speedometer`, `NO GPS`, and `STANDBY`: [permission-denied-before-launch.png](permission-denied-before-launch.png). | | Deny while app is open / retry | **PASS — denial handled; recovery route limited** | At 06:26 EDT, tapping Enable while open showed the separate notifications prompt; after denial, another Enable tap left fine/coarse location denied and returned to the app without a location prompt or Settings page. No hang/ANR. User can recover manually through Android Settings; the dashboard banner remained after returning from Settings until Enable was tapped again. See [permission-enable-prompt.png](permission-enable-prompt.png), [permission-recovery-after-denial.png](permission-recovery-after-denial.png), and [permission-recovery-settings.png](permission-recovery-settings.png). | | Grant through Settings | **PASS — permission state recovered after app action** | At 06:27–06:28 EDT, Android Settings showed MotorSignal Location as “Don’t allow”; changed to “Allow only while using the app.” Package manager then reported fine/coarse `granted=true`. Returning to the app alone left the banner stale; tapping Enable invalidated the cached permission result, removed the banner, and the dashboard showed `GPS 3D FIX`: [permission-recovery-app-button.png](permission-recovery-app-button.png). No external network was available. | | Revoke during recording | **PASS — Android termination classified; recording data persisted** | Started Ride 1 at 06:29:13 EDT; dashboard showed RECORDING and GPS 3D FIX: [permission-recording-before-revoke.png](permission-recording-before-revoke.png). Revoked fine then coarse location at 06:29:49. Logcat: `ActivityManager: Killing 5633:app.motorsignal.motorcycle/u0a230 (adj 0): permissions revoked`; Android removed MainActivity with `app died, no saved state`. This was expected OS process termination, not an app ANR or crash. `lastanr` returned ``; `dumpsys dropbox --print data_app_anr` returned `(No entries found)`. | | Relaunch after revocation | **PASS — local ride recovered** | Relaunched at 06:31:38, denied location again, and app reached STANDBY without ANR. Activity showed Ride 1: [permission-restart-after-revoke.png](permission-restart-after-revoke.png), [permission-recovered-ride-history.png](permission-recovered-ride-history.png). Read-only SQLite copy after restart: SHA-256 `FDCB156A688678AFF515898ECCE7422DFAAC2470D9678188C882ACFBC80D67E4`; ride 1 had `start_time=1790850553`, `end_time=1790850588`, 704 telemetry samples spanning those timestamps. The ride was ended/recovered at its last persisted sample; no sample loss across process termination was observed. DB artifact: [permission-recording-after-restart.sqlite](permission-recording-after-restart.sqlite). The copy immediately after termination had SHA-256 `D12108B8D77BD6294C2BC4FCFCB5B80EEBEE65406C3486E45B1A1A371726F5B4` and the same 704 samples; [permission-recording-after-revoke.sqlite](permission-recording-after-revoke.sqlite). | | GPS unavailable during recording | **PASS — degraded state visible** | Started Ride 2 at 06:34:52. With permission granted, turned global location off at 06:35:21 (`location_mode=0`). Android displayed “No location access.” After closing the dialog, recording remained active and dashboard showed `NO GPS` plus `DEGRADED`; package manager still showed fine/coarse `granted=true`: [permission-gps-off-recording.png](permission-gps-off-recording.png). | | GPS restoration during recording | **BLOCKED — no fresh emulator fix** | Restored global location to mode 3, confirmed Android Settings “Use location” was on, and sent `adb emu geo fix -122.4194 37.7749 15`; also toggled location off/on from Android Settings at 06:39:17. No `gps provider received location[1]` records appeared after 06:29:48, and dashboard remained `NO GPS` / `DEGRADED`: [permission-location-settings.png](permission-location-settings.png), [permission-gps-restored-recording.png](permission-gps-restored-recording.png). Stopped Ride 2 locally at 06:40:43. Final SQLite SHA-256 `4488B773924C9571E5DE681D6FA15177AC1EE2BFB81310B5D734B6E2A2074A0C`; Ride 2 persisted with 5,624 samples, all with null latitude/longitude/GPS accuracy. [permission-final.sqlite](permission-final.sqlite). Because the emulator provided no new fix, this does not establish whether app recovery works after a fresh fix; it is not marked PASS or a confirmed app defect. | ANR / hang classification | **PASS — no current-run ANR** | Throughout this run `dumpsys activity lastanr` stayed ``, Dropbox had no `data_app_anr`, and the app remained responsive. Revocation log explicitly attributes process death to Android permission revocation. This classifies the reproduced revocation event only. Root separately found a historical 2026-09-30 18:52:28 `data_app_anr` on 5554 with an input dispatch timeout and CPU saturation; its root cause remains uncertain and is not explained by this run. | ## Source inspection (code facts only) - `lib/services/location_service.dart`: startup initializes the location stream; `requestPermissions()` checks/requests Geolocator and `Permission.locationWhenInUse`, requests notifications, then calls `_startListening()` after a recognized grant. Exceptions are swallowed and reported as `false`. The watchdog attempts a current fix after the last accepted fix is older than two seconds; stream errors schedule a new subscription after two seconds. - `lib/features/dashboard/widgets/dashboard_alert_region.dart`: the banner depends on `locationPermissionGrantedProvider`; Enable calls the permission service and invalidates the provider. The observed stale banner after a Settings grant persisted until this action invalidated the provider. - `lib/services/telemetry_service.dart`: the authoritative 20 Hz sampler emits while GPS is null/stale; GPS age increases for retained positions. Runtime samples with GPS off were null in Ride 2; this alone does not validate stale-position behavior when a last fix exists. ## Cleanup and limits - Stopped the app's test recording, stopped the dedicated emulator with `adb -s emulator-5556 emu kill`, and removed the newly created `Pixel8Pro_QA` AVD config/data after preserving screenshots and SQLite evidence. `emulator-5554` was not touched. - Stopped the P2 logcat capture process. Raw log retained in `%TEMP%` for this session; useful extracted evidence is summarized above. - No accounts, fixtures, production settings, or backend data were changed. Permission/GPS tests ran entirely on the isolated emulator. - Remaining P2 blocker: emulator does not provide a fresh GPS fix after global location is toggled back on, so post-restoration GPS reacquisition remains unverified. Root should retain the independent historical ANR as unresolved pending its exact reproduction conditions.