Files
NoGooleApps/replica/telefon/architecture.md
T

3.1 KiB
Raw Blame History

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.