8.4 KiB
8.4 KiB
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, serialemulator-5556, Android 17 / API 37.emulator-5554stayed exclusively with the P1 owner and was not accessed. - Installed
app.motorsignal.motorcycle, versionCode 102 / versionName 1.0.2, APK SHA-256279F561D8DB91D01138321EE2666B2029D239BC6008809E802458FF835796AA2(root-confirmed build). - Wi-Fi, cellular data, and airplane-mode state were set offline before launch.
dumpsys connectivityreportedActive default network: none. No backend account was signed in or created. No production request/write was made. - Logcat captured with
adb logcat -candadb -s emulator-5556 logcat -v threadtimeto%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 appFATAL EXCEPTIONor 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 |
| 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-recovery-after-denial.png, and 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. 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. 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-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. The copy immediately after termination had SHA-256 D12108B8D77BD6294C2BC4FCFCB5B80EEBEE65406C3486E45B1A1A371726F5B4 and the same 704 samples; 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. |
| 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-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. 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 andPermission.locationWhenInUse, requests notifications, then calls_startListening()after a recognized grant. Exceptions are swallowed and reported asfalse. 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 onlocationPermissionGrantedProvider; 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 createdPixel8Pro_QAAVD config/data after preserving screenshots and SQLite evidence.emulator-5554was 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.