Files
NoGooleApps/replica/telefon/architecture.md
T

50 lines
3.1 KiB
Markdown
Raw 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.
# Architecture: Telefon (Android, ohne Google)
Same conventions as the other apps. **No network permission.** The app owns almost no data: it reads the system call log and contacts.
## Stack
| Schicht | Wahl | warum |
| --- | --- | --- |
| UI | Kotlin + Compose, M3 Expressive, dynamic colour | same as the others |
| Telefonie | `RoleManager.ROLE_DIALER` + own `InCallService` (BIND_INCALL_SERVICE, IN_CALL_SERVICE_UI) | the only official way to show the call UI and control calls |
| Anrufen | `TelecomManager.placeCall` | uses the default SIM/phone account, works for emergency numbers through the system |
| Daten | `CallLog.Calls` and `ContactsContract` via ContentResolver, observed with ContentObserver → Flow | no copy of personal data in our database |
| Eigene Daten | DataStore (quick replies, theme) | – |
| Audio | `InCallService.setMuted / setAudioRoute`, `CallEndpoint` on API 34+ | speaker, earpiece, Bluetooth |
| Näherungssensor | `PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK` while the earpiece is active | screen off at the ear |
## Permissions
READ_CALL_LOG, WRITE_CALL_LOG (delete entries), READ_CONTACTS, CALL_PHONE, READ_PHONE_STATE, MANAGE_OWN_CALLS no, USE_FULL_SCREEN_INTENT, POST_NOTIFICATIONS, WAKE_LOCK, SEND_SMS no (quick replies hand off to the SMS app with `smsto:`).
The dialer role grants most of these automatically once the user accepts it.
## Data
No schema. Own state in DataStore only. Access: single user; the system enforces the permissions.
## Interne API
| Aufruf | macht | Flow |
| --- | --- | --- |
| `CallLogRepo.observe(filter)` | query CallLog, join contact name/photo by number (PhoneLookup), group by day | F01 |
| `ContactsRepo.favorites()` / `search(q)` / `t9(digits)` | starred contacts; name/number search; T9 digit match on names and numbers | F02, F03, F06 |
| `Dialer.call(number)` | `placeCall(tel:)` | F01–F03 |
| `CallManager` (in `InCallService`) | StateFlow of calls; answer, reject (with SMS), hold, unhold, mute, route, DTMF, disconnect | F04, F05, F07 |
| `Role.request()` | role request intent | F08 |
## Was beißt
- **Wrong default dialer state**: without the role, calls still work through the system dialer; the app shows a banner instead of failing.
- **Lock screen**: incoming UI via full-screen-intent notification; `showWhenLocked` + `turnScreenOn` on the activity.
- **Ringtone**: the system rings for the default dialer? No: the InCallService app must play the ringtone itself only when `Call.Details` say so; on modern Android the platform `Ringer` plays it for the default dialer. We do not play our own.
- **Process death mid-call**: the InCallService is bound by the system as long as calls exist; UI state is rebuilt from `calls`.
- **Emergency numbers**: always via `placeCall`, never blocked by our UI.
- **Privacy**: no network, no analytics; call log stays in the system.
## Build-Reihenfolge
1. Slice: role request, InCallService, incoming + in-call screens, place a call from the keypad.
2. Must: call log with grouping and call back, favourites, search, notifications, mute/speaker/DTMF, proximity.
3. Should: filters, T9, hold, call waiting, quick reply SMS, details screen, voicemail, Bluetooth.