docs(04-01): complete core GPS engine plan

- Created SUMMARY.md documenting lifecycle-aware GPS engine implementation
- Updated STATE.md to Phase 4 Plan 1 of 2 complete (70% progress)
- Added 6 key decisions to STATE.md decisions table
- Updated performance metrics: 7 plans, 4.9 min average for Phase 4
- Updated session continuity and blockers sections
- Documented self-check results: all files and commits verified

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikkeli Matlock
2026-02-12 09:04:59 +09:00
parent 1618cfeb26
commit 8bc1e392a5
2 changed files with 221 additions and 18 deletions
+30 -18
View File
@@ -9,19 +9,19 @@ See: .planning/PROJECT.md (updated 2026-02-09)
## Current Position ## Current Position
Phase: 3 of 4 (Overlay Refactor) Phase: 4 of 4 (GPS Power Optimization)
Plan: 2 of 2 complete Plan: 1 of 2 complete
Status: Phase complete Status: In progress
Last activity: 2026-02-11 — Completed 03-02-PLAN.md Last activity: 2026-02-12 — Completed 04-01-PLAN.md
Progress: [██████░░░░] 60% (Phase 3: 2/2 plans complete) Progress: [███████░░░] 70% (Phase 4: 1/2 plans complete)
## Performance Metrics ## Performance Metrics
**Velocity:** **Velocity:**
- Total plans completed: 6 - Total plans completed: 7
- Average duration: 6.3 minutes - Average duration: 6.0 minutes
- Total execution time: 0.63 hours - Total execution time: 0.71 hours
**By Phase:** **By Phase:**
@@ -30,10 +30,11 @@ Progress: [██████░░░░] 60% (Phase 3: 2/2 plans complete)
| 1. Foundation | 2 | 19.6 min | 9.8 min | | 1. Foundation | 2 | 19.6 min | 9.8 min |
| 2. Provider Migration | 2 | 11.5 min | 5.75 min | | 2. Provider Migration | 2 | 11.5 min | 5.75 min |
| 3. Overlay Refactor | 2 | 8.25 min | 4.1 min | | 3. Overlay Refactor | 2 | 8.25 min | 4.1 min |
| 4. GPS Optimization | 1 | 4.9 min | 4.9 min |
**Recent Trend:** **Recent Trend:**
- Last 5 plans: 02-01 (7.7 min), 02-02 (3.8 min), 03-01 (4.0 min), 03-02 (4.25 min) - Last 5 plans: 02-02 (3.8 min), 03-01 (4.0 min), 03-02 (4.25 min), 04-01 (4.9 min)
- Trend: Consistent sub-5-minute plans in Phase 3 - Trend: Consistent sub-5-minute plans continuing in Phase 4
*Updated after each plan completion* *Updated after each plan completion*
@@ -70,8 +71,12 @@ Recent decisions affecting current work:
| 03 | 02 | Error callback pattern for provider-to-screen comm | Implemented | | 03 | 02 | Error callback pattern for provider-to-screen comm | Implemented |
| 03 | 02 | Staleness opacity via withValues(alpha:) no animation | Implemented | | 03 | 02 | Staleness opacity via withValues(alpha:) no animation | Implemented |
| 03 | 02 | GPS grace period timer created (Phase 4 lifecycle) | Implemented | | 03 | 02 | GPS grace period timer created (Phase 4 lifecycle) | Implemented |
| 04 | TBD | Speed-adaptive GPS precision (~10 km/h threshold) | Pending | | 04 | 01 | Speed-adaptive GPS precision (8/12 km/h hysteresis) | Implemented |
| 04 | TBD | Background GPS only when overlay visible | Pending | | 04 | 01 | Precision switching gated until 5s after first fix | Implemented |
| 04 | 01 | Background grace period re-checks overlay at expiry | Implemented |
| 04 | 01 | Wake lock contextual: GPS + (overlay OR foreground) | Implemented |
| 04 | 01 | GPS stop preserves last data for staleness display | Implemented |
| 04 | 01 | BACKGROUND_GRACE_PERIOD (7s) replaces GPS_GRACE_PERIOD| Implemented |
### Pending Todos ### Pending Todos
@@ -125,13 +130,20 @@ Recent decisions affecting current work:
- INFO: Manual testing needed to verify overlay reliability improvements on physical device - INFO: Manual testing needed to verify overlay reliability improvements on physical device
- INFO: All OVRL-01 through OVRL-06 requirements satisfied - INFO: All OVRL-01 through OVRL-06 requirements satisfied
**Phase 4 (GPS Optimization):** **Phase 4 (GPS Optimization) - In Progress:**
- Speed thresholds (8/12 km/h) need field testing validation - RESOLVED: Core GPS engine complete with lifecycle awareness and precision switching
- Android OEM behavior varies (Samsung, Xiaomi duty-cycling differences) - RESOLVED: ProcessedGpsData timestamp field added for staleness detection
- RESOLVED: Background grace period (7s) with race condition protection
- RESOLVED: Conditional wake lock (GPS active + visible)
- INFO: Plan 04-01 complete (4.9 min) — ready for Plan 04-02 (UI Integration)
- PENDING: SpeedometerScreen needs gpsDataManager.setOverlayProvider() call
- PENDING: Background heartbeat (5s) may need adjustment vs 7s grace period
- FIELD TESTING: Speed thresholds (8/12 km/h) need validation on physical device
- FIELD TESTING: Android OEM behavior varies (Samsung, Xiaomi duty-cycling differences)
## Session Continuity ## Session Continuity
Last session: 2026-02-11 (Plan 03-02 execution complete) Last session: 2026-02-12 (Plan 04-01 execution complete)
Stopped at: Completed 03-02-PLAN.md — Phase 3 complete Stopped at: Completed 04-01-PLAN.md — Phase 4 in progress (1/2 plans)
Resume file: None Resume file: None
Next action: Begin Phase 4 (GPS Optimization) planning Next action: Execute Plan 04-02 (UI Integration)
@@ -0,0 +1,191 @@
---
phase: 04-gps-power-optimization
plan: 01
subsystem: gps
tags: [geolocator, wakelock, lifecycle, precision-switching]
requires:
- phase: 03-overlay-refactor
provides: OverlayProvider with isOverlayActive, OverlayService, staleness constants
provides:
- Lifecycle-aware GpsDataManager with WidgetsBindingObserver
- Speed-adaptive precision switching (8/12 km/h hysteresis)
- Background GPS management with 7s grace period
- Conditional wake lock (GPS active + visible)
- ProcessedGpsData with timestamp field
- Dynamic GPS stream via GpsService.createPositionStream()
affects: [04-02-ui-integration]
tech-stack:
added: [wakelock_plus (already dependency)]
patterns: [WidgetsBindingObserver for lifecycle, hysteresis threshold switching, race condition protection]
key-files:
created: []
modified:
- lib/models/processed_gps_data.dart
- lib/config/gps_constants.dart
- lib/config/timing_constants.dart
- lib/gps_service.dart
- lib/services/gps_data_manager.dart
key-decisions:
- "Speed-adaptive precision switching uses hysteresis (8/12 km/h) to prevent thrashing"
- "Precision switching gated until 5s after first GPS fix for stability"
- "Background grace period re-checks overlay state at expiry to handle race conditions"
- "Wake lock is contextual: enabled when GPS active AND (overlay visible OR app in foreground)"
- "GPS stop preserves last known data for staleness display (no data clearing)"
- "Deprecated GPS_GRACE_PERIOD (30s) in favor of BACKGROUND_GRACE_PERIOD (7s) for lifecycle"
duration: 4.9min
completed: 2026-02-12
---
# Phase 4 Plan 01: Core GPS Engine Summary
**Lifecycle-aware GPS manager with speed-adaptive precision switching, 7s background grace period, and conditional wake lock control**
## Performance
- **Duration:** 4.9 minutes
- **Start:** 2026-02-11 23:57:48 UTC
- **End:** 2026-02-12 00:02:42 UTC
- **Tasks completed:** 2
- **Files modified:** 5
- **Commits:** 2
## Accomplishments
Successfully transformed GpsDataManager into a fully lifecycle-aware GPS engine with intelligent power management:
1. **ProcessedGpsData Timestamp Field**
- Added `timestamp` field to enable staleness detection in overlay
- Updated `copyWith()` to support timestamp parameter
- Changed default initialization from `const` to non-const with `DateTime.now()`
2. **Precision Switching Constants**
- Added `PRECISION_UP_THRESHOLD_MPS` (3.33 m/s / 12 km/h) for high precision
- Added `PRECISION_DOWN_THRESHOLD_MPS` (2.22 m/s / 8 km/h) for balanced precision
- Added `PRECISION_SWITCH_FIRST_FIX_DELAY` (5s) safety gate
- Hysteresis prevents precision thrashing in 8-12 km/h range
3. **Lifecycle Constants**
- Added `BACKGROUND_GRACE_PERIOD` (7s) for responsive background management
- Deprecated `GPS_GRACE_PERIOD` (30s) with clear documentation
4. **Dynamic GPS Stream**
- Changed `GpsService.positionStream` from hardcoded `bestForNavigation` to `createPositionStream()`
- Accepts `LocationAccuracy` parameter for dynamic precision control
- Kept deprecated wrapper for backward compatibility during transition
5. **Lifecycle-Aware GPS Manager**
- Implemented `WidgetsBindingObserver` mixin for app lifecycle tracking
- Added overlay provider reference for background decision-making
- Tracks foreground/background state, GPS active state, current accuracy
- Registers/removes lifecycle observer in initialize()/dispose()
6. **Precision Switching Logic**
- Speed-based hysteresis switching (HIGH ↔ MEDIUM at 8/12 km/h boundaries)
- Gated until 5s after first GPS fix for stability
- Seamless stream recreation with new accuracy on switch
- Debug logging only (invisible to user per project decision)
7. **Background GPS Management**
- 7s grace period when app backgrounds without overlay visible
- Immediate GPS continuation when app backgrounds with overlay active
- Grace period re-checks overlay state at expiry (race condition protection)
- GPS restart on app foreground resume if previously stopped
8. **Conditional Wake Lock**
- Wake lock enabled when GPS active AND (overlay visible OR app in foreground)
- Wake lock disabled when GPS stops or app backgrounds without overlay
- Updated on all state transitions (GPS start/stop, lifecycle change)
- Disabled in dispose() as safety net
9. **State Preservation**
- GPS stop does NOT clear `_currentData` (preserves last known speed/heading)
- Staleness detection shows last data as stale per existing timer logic
- Fresh data immediately replaces stale display on GPS restart
## Task Commits
| Task | Name | Commit | Files Modified |
| ---- | ----------------------------------------------------- | ------- | -------------- |
| 1 | Add timestamp and precision/lifecycle constants | c4d4032 | 4 files |
| 2 | Implement lifecycle-aware GPS engine with wake lock | 1618cfe | 1 file |
## Files Created/Modified
**Modified:**
- `lib/models/processed_gps_data.dart` — Added timestamp field and copyWith support
- `lib/config/gps_constants.dart` — Added precision switching thresholds (3.33/2.22 m/s, 5s delay)
- `lib/config/timing_constants.dart` — Added BACKGROUND_GRACE_PERIOD (7s), deprecated GPS_GRACE_PERIOD
- `lib/gps_service.dart` — Added createPositionStream() with dynamic accuracy, deprecated static getter
- `lib/services/gps_data_manager.dart` — Added lifecycle awareness, precision switching, wake lock control
## Decisions Made
1. **Hysteresis Thresholds:** 8/12 km/h boundaries prevent precision thrashing in transition zone
2. **First-Fix Gate:** 5s delay before precision switching prevents instability during initial acquisition
3. **Race Condition Protection:** Background grace period re-checks overlay state at expiry (not just at start)
4. **Wake Lock Strategy:** Conditional on GPS active + visible (overlay OR foreground) for minimal battery impact
5. **Data Preservation:** GPS stop preserves last known data, relying on existing staleness timer for UI feedback
6. **Grace Period Duration:** 7s chosen for responsive UX (short enough to save battery, long enough for quick returns)
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Cleanup] Removed unnecessary flutter/foundation.dart import**
- **Found during:** Task 2 verification
- **Issue:** flutter analyze reported unnecessary import (flutter/widgets.dart provides ChangeNotifier)
- **Fix:** Removed `import 'package:flutter/foundation.dart';` from gps_data_manager.dart
- **Files modified:** lib/services/gps_data_manager.dart
- **Commit:** 1618cfe (included in Task 2 commit)
## Issues Encountered
None. Plan executed exactly as written with only one minor cleanup deviation (unnecessary import removal).
## Next Phase Readiness
**Ready for Plan 04-02 (UI Integration):**
- ✅ GpsDataManager implements full lifecycle awareness
- ✅ ProcessedGpsData carries timestamps for staleness detection
- ✅ Precision switching functional with hysteresis
- ✅ Background GPS management with grace period
- ✅ Wake lock contextual control implemented
- ✅ All timers properly canceled in dispose()
- ✅ Flutter analyze passes (only expected SCREAMING_SNAKE info warnings)
**Integration points for Plan 04-02:**
- SpeedometerScreen needs to call `gpsDataManager.setOverlayProvider(overlayProvider)` after provider wiring
- No UI changes needed for precision switching (silent/invisible per user decision)
- Background heartbeat may need adjustment (currently 5s, may conflict with 7s grace period)
- Staleness detection in overlay should consume `ProcessedGpsData.timestamp` field
**Testing considerations:**
- Field testing needed for 8/12 km/h hysteresis validation
- Android OEM behavior varies (Samsung, Xiaomi duty-cycling differences documented in research)
- Wake lock effectiveness depends on Android version and OEM power management
## Self-Check: PASSED
**Files exist:**
```
FOUND: lib/models/processed_gps_data.dart
FOUND: lib/config/gps_constants.dart
FOUND: lib/config/timing_constants.dart
FOUND: lib/gps_service.dart
FOUND: lib/services/gps_data_manager.dart
```
**Commits exist:**
```
FOUND: c4d4032
FOUND: 1618cfe
```
**Flutter analyze status:** 30 issues (all expected SCREAMING_SNAKE info warnings, no errors)
All claims verified. Plan execution complete.