MotorSignal-App/docs/qa-2026-10-01/permission.md

37 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 `<no ANR has occurred since boot>`; `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 `<no ANR has occurred since boot>`, 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.