---
id: "0161"
title: "matrix-client-android foreground service: calls + lifecycle + lockscreen"
status: pendiente
priority: alta
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.
