Files
mobile-android/Architecture.md

383 lines
14 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.
# Rosetta Android — Architecture
> Документ описывает **текущую** архитектуру `rosetta-android` (ветка `dev`) по коду, без идеализаций.
## 1. Архитектурный стиль
Приложение построено как **layered + feature-oriented** архитектура:
- UI на Jetpack Compose (`MainActivity` + `ui/*`).
- Бизнес-оркестрация в singleton-сервисах (`ProtocolManager`, `CallManager`, `TransportManager`, `UpdateManager`).
- Data слой через репозитории (`MessageRepository`, `GroupRepository`, `AvatarRepository`, `AccountManager`).
- Persistence через Room (`RosettaDatabase`).
- Crypto изолирован в `crypto/*`.
DI-контейнера (Hilt/Koin) сейчас нет: зависимости поднимаются через `object`, `getInstance(...)`, singleton-инициализацию.
---
## 2. Слои и границы
```mermaid
flowchart TB
subgraph UI["UI Layer (Compose + ViewModel)"]
A1["MainActivity"]
A2["ui/chats/*"]
A3["ui/auth/*"]
A4["ui/settings/*"]
end
subgraph SVC["Service Layer (Singleton orchestrators)"]
B1["ProtocolManager"]
B2["CallManager"]
B3["TransportManager"]
B4["UpdateManager"]
B5["RosettaFirebaseMessagingService"]
end
subgraph DATA["Data Layer"]
C1["MessageRepository"]
C2["GroupRepository"]
C3["AvatarRepository"]
C4["AccountManager / PreferencesManager"]
C5["DraftManager / ForwardManager"]
end
subgraph DB["Persistence Layer"]
D1["Room: RosettaDatabase"]
D2["DAO: message/dialog/group/etc"]
end
subgraph NET["Network Layer"]
E1["Protocol (WebSocket)"]
E2["Packet* codec"]
E3["OkHttp HTTP (transport/update)"]
E4["WebRTC"]
end
subgraph CRYPTO["Crypto Layer"]
F1["CryptoManager"]
F2["MessageCrypto"]
F3["XChaCha20E2EE (calls)"]
end
UI --> SVC
UI --> DATA
SVC --> DATA
SVC --> NET
DATA --> DB
DATA --> CRYPTO
SVC --> CRYPTO
```
---
## 3. Главные модули и ответственность
### 3.1 `MainActivity` (composition root)
`MainActivity` — главный orchestration entrypoint приложения:
- поднимает `ProtocolManager.initialize(...)`, `CallManager.initialize(...)`;
- управляет auth-гейтингом, онбордингом и основным nav-stack (`Screen`);
- привязывает текущий аккаунт к runtime-сервисам;
- триггерит fast reconnect на `onResume`;
- следит за разрешениями (уведомления, fullscreen intent и т.д.).
### 3.2 `RosettaApplication`
На старте процесса инициализирует глобальные подсистемы:
- crash reporting,
- draft manager,
- transport manager,
- update manager.
### 3.3 Репозитории
#### `MessageRepository`
Ключевой data-центр для чатов:
- инициализация аккаунт-контекста (`publicKey/privateKey`);
- отправка сообщений (optimistic insert + сетевой send);
- обработка входящих `PacketMessage`/`PacketDelivery`/`PacketRead`;
- обновление `dialogs`, `messages`, `message_search_index`;
- синк timestamp (`accounts_sync_times`);
- шина событий для UI (`newMessageEvents`, `deliveryStatusEvents`).
#### `GroupRepository`
- хранение и операции по группам,
- интеграция с `PacketGroup*`.
#### `AvatarRepository`
- кэш/история аватаров (Room + file storage),
- реактивная выдача аватаров через `Flow`.
#### `AccountManager`
- хранение аккаунтов в DataStore,
- last logged public/private hash в SharedPreferences для быстрых синхронных чтений.
---
## 4. Сетевой стек
## 4.1 `Protocol` (низкий уровень)
`Protocol` отвечает за:
- WebSocket lifecycle (`DISCONNECTED/CONNECTING/CONNECTED/HANDSHAKING/DEVICE_VERIFICATION_REQUIRED/AUTHENTICATED`),
- heartbeat,
- reconnect/backoff,
- packet encode/decode,
- `waitPacket/unwaitPacket` обработчики,
- queue pre-handshake пакетов.
Ключевые механизмы устойчивости:
- `lifecycleMutex` для serialized lifecycle операций,
- `connectionGeneration` для игнора stale callbacks старых сокетов,
- guard `isConnecting` от параллельного `connect()`.
## 4.2 `ProtocolManager` (верхний уровень)
`ProtocolManager` — orchestration-слой над `Protocol`:
- единая точка для UI/Data слоёв (`send`, `authenticate`, `reconnect`, `waitPacket` и т.д.);
- bootstrap после auth (sync, own-profile resolve, push subscribe);
- маршрутизация входящих packet-ов в репозитории/подсистемы;
- call signaling bridge для `CallManager`;
- управление typed caches (`SearchUser`, user info cache).
Новый runtime-дизайн connection orchestration:
- `ProtocolConnectionModels.kt``ConnectionLifecycleState`, `ConnectionEvent`, bootstrap context;
- `ProtocolConnectionSupervisor.kt` — actor/event-loop для serialized событий;
- `ReadyPacketGate.kt` — очередь пакетов до состояния `READY` (TTL + max size).
---
## 5. Lifecycle состояния соединения (верхний уровень)
`ProtocolManager.connectionLifecycleState`:
- `DISCONNECTED`
- `CONNECTING`
- `HANDSHAKING`
- `AUTHENTICATED`
- `BOOTSTRAPPING`
- `READY`
- `DEVICE_VERIFICATION_REQUIRED`
Переход в `READY` происходит только когда одновременно выполнено:
- аккаунт инициализирован,
- протокол аутентифицирован,
- sync завершён,
- own-profile резолвнут (или истёк fallback timeout).
```mermaid
stateDiagram-v2
[*] --> DISCONNECTED
DISCONNECTED --> CONNECTING
CONNECTING --> HANDSHAKING
HANDSHAKING --> DEVICE_VERIFICATION_REQUIRED
HANDSHAKING --> AUTHENTICATED
AUTHENTICATED --> BOOTSTRAPPING
BOOTSTRAPPING --> READY
READY --> DISCONNECTED
DEVICE_VERIFICATION_REQUIRED --> CONNECTING
```
---
## 6. Поток auth / session bootstrap
```mermaid
sequenceDiagram
participant UI as AuthFlow/MainActivity
participant PM as ProtocolManager
participant P as Protocol
participant MR as MessageRepository
UI->>PM: initializeAccount(public, private)
UI->>PM: connect()
UI->>PM: authenticate(public, privateHash)
PM->>P: connect + startHandshake
P-->>PM: AUTHENTICATED
PM->>PM: onAuthenticated()
PM->>PM: subscribePushTokenIfAvailable()
PM->>PM: requestSynchronize()
PM->>MR: initialize(...)
PM-->>PM: SyncCompleted + OwnProfileResolved
PM-->>UI: connectionLifecycleState = READY
```
Критично: отправка пользовательских пакетов до `READY` не теряется, а попадает в `ReadyPacketGate`.
---
## 7. Поток сообщений (send/receive/delivery)
## 7.1 Отправка
1. UI (`ChatViewModel`) вызывает отправку через `MessageRepository.sendMessage(...)`.
2. Репозиторий делает optimistic insert в `messages` (`WAITING`).
3. Формируется `PacketMessage`.
4. Отправка идёт в `ProtocolManager.send(...)`.
5. Если состояние не `READY`, пакет ставится в `ReadyPacketGate`.
6. После `READY` очередь сбрасывается в `Protocol.sendPacket(...)`.
## 7.2 Подтверждение доставки
1. Сервер присылает `PacketDelivery (0x08)`.
2. `ProtocolManager` маршрутизирует в `MessageRepository.handleDelivery(...)`.
3. Репозиторий обновляет статус в Room.
4. UI получает апдейт через `Flow`/события.
## 7.3 Входящие
1. `PacketMessage (0x06)` приходит в `Protocol`.
2. `ProtocolManager` dispatch → `MessageRepository.handleIncomingMessage(...)`.
3. Сообщение сохраняется в Room, обновляется `dialogs` и индексы поиска.
4. UI реактивно перерисовывается.
---
## 8. Sync-пайплайн
Используется пакет `PacketSync (0x19)` и режимы:
- `BATCH_START`
- поток синк-пакетов (`MESSAGE/READ/DELIVERY/...`)
- `BATCH_END`
- `NOT_NEEDED`
Особенности:
- есть последовательная очередь inbound задач для сохранения порядка обработки;
- after-sync hooks: retry waiting messages, request missing user info;
- sync timestamp хранится в `accounts_sync_times`.
---
## 9. Calls (WebRTC + signaling)
`CallManager` использует:
- signaling пакеты: `PacketSignalPeer (0x1A)`, `PacketWebRTC (0x1B)`;
- ICE: `PacketIceServers (0x1C)`;
- WebRTC stack (`PeerConnectionFactory`, `PeerConnection`, audio track);
- E2EE голоса через `XChaCha20E2EE` обвязки sender/receiver.
Основные фазы звонка:
- `IDLE``INCOMING`/`OUTGOING``CONNECTING``ACTIVE``IDLE`.
```mermaid
stateDiagram-v2
[*] --> IDLE
IDLE --> OUTGOING
IDLE --> INCOMING
OUTGOING --> CONNECTING
INCOMING --> CONNECTING
CONNECTING --> ACTIVE
ACTIVE --> IDLE
OUTGOING --> IDLE
INCOMING --> IDLE
```
---
## 10. Transport (вложения)
`TransportManager`:
- получает transport server через `PacketRequestTransport (0x0F)` (desktop parity);
- upload/download через OkHttp;
- resumable download (HTTP Range);
- трекает состояния прогресса через `StateFlow` (`uploading`, `downloading`);
- поддерживает cancel/pause/resume через `FileDownloadManager`.
---
## 11. Push Notifications
`RosettaFirebaseMessagingService`:
- обрабатывает `onNewToken` и подписку токена через `ProtocolManager`;
- dedup пушей;
- маршрутизация типов (`personal_message`, `group_message`, `call`, `read`);
- очистка уведомлений по read events;
- wake-up reconnect при silent push.
---
## 12. Обновления (SDU)
`UpdateManager`:
1. запрашивает update server через `PacketRequestUpdate (0x0A)`;
2. ходит на SDU HTTP endpoint;
3. скачивает APK через `DownloadManager`;
4. ведёт update state machine (`Idle/Checking/UpdateAvailable/Downloading/ReadyToInstall/Error`).
---
## 13. Persistence (Room)
`RosettaDatabase` (version `17`) включает:
- `messages` — сообщения,
- `dialogs` — диалоги + денормализованные поля для быстрых списков,
- `message_search_index` — локальный индекс поиска,
- `groups` — группы,
- `pinned_messages` — закрепы,
- `avatar_cache` — аватары,
- `blacklist` — blacklist,
- `accounts_sync_times` — sync cursor,
- `encrypted_accounts` — аккаунты (legacy Room account storage).
Есть длинная цепочка миграций (4→17) с оптимизациями под производительность и денормализацию.
---
## 14. Crypto
- `CryptoManager`:
- seed phrase / keypair,
- PBKDF2-derived key caching,
- encrypt/decrypt для локального хранения.
- `MessageCrypto`:
- message-level XChaCha20-Poly1305,
- ECDH/AES-обмен ключом для payload,
- attachment decrypt logic.
Crypto и network связаны через `MessageRepository`/`ProtocolManager`.
---
## 15. Наблюдаемость и диагностика
- wire/protocol логи через `ProtocolManager.addLog(...)` + trace file;
- debug logs доступны в UI;
- отдельные диагностические логи для звонков (`CallManager` breadcrumbs).
---
## 16. Текущие архитектурные сильные стороны
- Реактивная модель состояния (`StateFlow`) на большинстве критических путей.
- Сильная декомпозиция packet протокола (`Packet*`).
- Наличие ready-gate и serialized supervisor снижает race-condition в соединении.
- Room + денормализация ускоряют списки чатов/поиск.
---
## 17. Текущие архитектурные риски
- `MainActivity` остаётся очень крупным composition root.
- `ProtocolManager` и `MessageRepository` всё ещё крупные “god objects”.
- Отсутствие DI усложняет управляемость зависимостей/тестируемость.
- Часть жизненного цикла связана через runtime singleton state, что повышает риск регрессий при эволюции.
---
## 18. Карта ключевых файлов
- `app/src/main/java/com/rosetta/messenger/MainActivity.kt`
- `app/src/main/java/com/rosetta/messenger/RosettaApplication.kt`
- `app/src/main/java/com/rosetta/messenger/network/Protocol.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolManager.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionModels.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionSupervisor.kt`
- `app/src/main/java/com/rosetta/messenger/network/ReadyPacketGate.kt`
- `app/src/main/java/com/rosetta/messenger/network/CallManager.kt`
- `app/src/main/java/com/rosetta/messenger/network/TransportManager.kt`
- `app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt`
- `app/src/main/java/com/rosetta/messenger/update/UpdateManager.kt`
- `app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt`
- `app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt`
- `app/src/main/java/com/rosetta/messenger/crypto/CryptoManager.kt`
- `app/src/main/java/com/rosetta/messenger/crypto/MessageCrypto.kt`