--- id: "0161" title: "matrix-client-android foreground service: calls + lifecycle + lockscreen" status: pending priority: high created: 2026-05-24 related_flows: ["0011"] related_issues: ["0158", "0160"] dependencies: ["0158"] tags: [matrix, android, foreground-service, lifecycle, mediasession, wakelock] --- ## Objetivo `CallForegroundService` que mantiene call activa con app en background o pantalla bloqueada. Notification ongoing visible mientras dura la call. `MediaSession` para integrar con lockscreen controls + Bluetooth Car (mute, hangup desde audio device). Wakelock controlado para evitar drain excesivo. Notificaciones full-screen intent para incoming calls (despiertan pantalla). ## Tareas 1. `CallForegroundService` (`android.app.Service`): - `START_FOREGROUND_SERVICE` con type `MEDIA_PROJECTION` o `PHONE_CALL` (Android 14+ requiere type explicito). - `Notification.Builder` channel `calls` con: - Custom view con caller name, duration, mute/hangup buttons. - `setOngoing(true)`. - `setCategory(CATEGORY_CALL)`. - Lifecycle: `START_STICKY` para reiniciar si OS lo mata (raro con foreground). 2. `MediaSession` integration: - `MediaSessionCompat` con play/pause/stop actions mapeados a mute/unmute/hangup. - Bluetooth Car media controls. - Lockscreen controls visibles si dispositivo lo soporta. 3. Wakelock: - `PowerManager.PARTIAL_WAKE_LOCK` durante call activa. - `WAKE_LOCK_KEY = "matrix_client:call"` para audit en `dumpsys power`. - Liberar inmediato al hangup. - Proximity wakelock (`PROXIMITY_SCREEN_OFF_WAKE_LOCK`) si call solo audio + telefono pegado a oreja. 4. Incoming call full-screen intent: - `Notification` con `setFullScreenIntent(pendingIntent, true)`. - Activity `IncomingCallActivity` con `showWhenLocked(true)` + `turnScreenOn(true)`. - Compose UI fullscreen con accept/decline. 5. Doze mode handling: - `ACTION_IGNORE_BATTERY_OPTIMIZATIONS` solicitar al user en onboarding (no obligatorio, solo para calls fiables). - Documentar tradeoff en pantalla onboarding. 6. Battery monitoring: - Log custom: call duration + battery_drain_pct al hangup. - Visible en `Settings > Diagnostics` para debug. 7. Tests: - Manual `CallBackgroundTest` — start call + Home button -> notif visible + audio sigue. - Manual `CallLockscreenTest` — call + power button -> pantalla apaga + audio sigue + lockscreen controls visibles. - Manual `IncomingFullScreenTest` — device en lockscreen + incoming call -> pantalla despierta + UI accept/decline. - Manual `BluetoothCarTest` — Bluetooth Car connected + call active + mute desde steering wheel funciona. - Manual `BatteryTest` — call 30min en background + WiFi + AC -> drain <15%. ## Funciones del registry a crear - `CallForegroundService_kotlin_infra` — service completo. - `media_session_kotlin_infra` — wrapper MediaSessionCompat. - `wakelock_manager_kotlin_infra` — adquirir/liberar wakelocks de forma idempotente. - `IncomingCallActivity_kotlin_ui` — Compose fullscreen activity. - `battery_monitor_kotlin_infra` — log drain por session. ## Acceptance - [ ] Call activa + Home -> notif ongoing visible + audio sigue 30s. - [ ] Call + power button -> lockscreen muestra controls + audio sigue. - [ ] Incoming call con pantalla apagada -> despierta + UI accept/decline. - [ ] Bluetooth Car: mute/hangup desde steering wheel funciona. - [ ] Hangup libera wakelocks (verificar con `dumpsys power | grep matrix_client`). - [ ] Battery saver activo: call no se corta (foreground service exempt). - [ ] Call 30min background: drain <15% con WiFi+AC. ## Notas **Anti-criterios:** - NO marcar done si call se corta a los 5min en background (battery optimization kill). - NO marcar done si wakelock queda colgado tras hangup (battery leak). - NO marcar done si lockscreen no muestra controls (UX critico para calls largas). **Gotchas Android 14+:** - Foreground service type DEBE declararse en manifest + runtime: `phoneCall|mediaProjection`. - `POST_NOTIFICATIONS` runtime permission (Android 13+). - `USE_FULL_SCREEN_INTENT` runtime permission (Android 14+) — pedir explicito. **Decisiones:** - Telecom framework (ConnectionService): NO en esta iteracion. Pro: integracion dialer nativo. Con: bug-prone, requiere CALL_PHONE permission con justificacion Play Store. Post-DoD considerar. - Audio focus exclusivo durante call (issue 0158 ya lo cubre). **Battery optimization onboarding:** - Pantalla en primer launch: explicar por que pedimos exempt battery optimization (calls fiables). - Boton "Open settings" -> `Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS`. - Si user declina: app funciona pero documentar que calls largas pueden cortarse.