# Домен G — Связь / телефон > Сетевой слой (WiFi/LTE-модем/tethering) **и** телефония (BT-паринг, HFP-звонки, контакты, > проекция). Две сущности: **Connectivity** — привилегированный core-сервис (владеет сетевым/BT- > железом); **Phone** — first-party ап на SDK (звонки/контакты). Транспорт для онлайн-ассистента > (D), OTA/телеметрии (L) и стриминга (H). Статус: **v2 (на ревью).** v2 — после adversarial-ревью (15 находок). Связано с: [architecture.md](../architecture.md) (§3 Connectivity/Phone, §5 карта связей, §6 boot-Stage) · [ipc.md](../contracts/ipc.md) (`Connectivity`, `Phone`) · [security-privacy.md](../contracts/security-privacy.md) (§3 `network`, §5 runtime-грант, §7 приватность/152-ФЗ) · [hardware.md](../contracts/hardware.md) (§4 модем/WiFi/BT/mic/amp, §3 load-shed) · [tech-stack.md](../tech-stack.md) (NM/MM/BlueZ) · домены **H** (§3 `phone_call`, §6 BT-аудио-шов), **D** (§3 online-LLM, §5 креды, §6/§10 интенты/AEC), **C** (§4 слоты, §7 distraction, §9 ввод), **K** (§3 руль-кнопки), **B** (§4 load-shed, §7 sleep/wake), **L** (облако/компаньон), **I** (нав/TMC) · [principles.md](../principles.md) (#1,#2,#3,#6,#7,#8,#11,#12,#13) --- ## 1. Назначение и границы - **Connectivity (core):** IP-связность для companion-слоя — WiFi-клиент, LTE-модем, tethering от телефона; приоритет/failover путей, статус сети; владелец сетевого и **BT-адаптера** (§3). - **Phone (first-party ап):** BT-паринг UX, **HFP-звонки** (hands-free), контакты/журнал (PBAP), опц. сообщения (MAP); звук звонка — роль `phone_call` в арбитре H (§4). - **Границы (красные линии):** - **Не safety-critical (#1):** **eCall / экстренный вызов — вне скоупа** (регулируемая safety-система). - **Голос — только HFP спаренного телефона; встроенный LTE-модем — data-only** (CS-voice / VoLTE — вне скоупа: отдельный крупный стек; усиливает границу eCall — головблок физически не голосовой узел сети). - **Модем — НЕ шлюз к машине (#2):** Connectivity даёт IP только companion-слою; **никакого моста модем↔CAN**, никакого удалённого управления узлами. Удалённый доступ к данным машины (если будет, через L) — **read-only + opt-in**, не через G. - **Проекция (CarPlay/Android Auto)** — тяжёлые лицензионные ограничения, не first-party, later (§8). - **Plane:** control/состояние — D-Bus (`Connectivity`/`Phone`); **звук звонка — PipeWire** (роль `phone_call`, политика — H §3); сам IP-трафик — вне D-Bus. ## 2. Connectivity (core-сервис) - **Пути данных (провайдер-агностично #8):** (1) **WiFi-клиент** (домашняя/известная сеть на стоянке); (2) **LTE-модем** (USB, SIM/APN — ModemManager); (3) **tethering** от телефона (BT-PAN / WiFi-hotspot телефона). - **Приоритет/failover:** политика выбора активного пути (напр. WiFi > tethering > metered-LTE), бесшовное переключение; **metered-aware** (крупные загрузки — OTA L/A — не тянуть по дорогой LTE без согласия). - **Состояние связности — НЕ бинарно на уровне источника правды:** NM connectivity-check различает `portal`/`limited` (ассоциация + IP есть, реального интернета нет — публичный WiFi за captive-portal) от настоящего `online`. **Портал не рапортуется как online** — иначе D (online-LLM) / L (OTA) ломаются на ложном «online». Прохождение портала — UX вне MVP, но детект обязателен (инвариант «не маскировать»). - **SIM/модем-стейты:** PIN-locked SIM на boot/вставке → состояние **`sim_locked`** (и `no_sim`/`no_service`), отличное от `offline` (как «сервис не поднят» ≠ offline); запрос **PIN — через слот Shell** (C §4, как входящий-оверлей §6), **PUK**-fallback после исчерпания попыток (ModemManager `Sim.SendPin`/`SendPuk`). - **Обёртка NetworkManager/ModemManager** (hardware §4); статус/состояния — `ru.shturman.Connectivity` (§11). - **Boot-Stage:** Connectivity поднимается на **Stage 2** (фоном, как Vehicle-Data/Assistant; architecture §6), не в Stage 1 → статус-бар C §3 до первого ответа = «unknown»; online-LLM (D §3, v1) до прихода Connectivity деградирует по #3 (offline-first), не виснет. - **Offline-first (#3):** сеть в движении нестабильна → потребители (D, H, L) **деградируют, не виснут**; Connectivity лишь честно сообщает состояние, не маскирует. Безопасность: модем — отдельный процесс (net-ns). - **Фаза:** WiFi-клиент + LTE-данные (+ SIM-unlock) — **v1** (нужно online-ассистенту D §3); hotspot/AP — later (§7). ## 3. Bluetooth (core: адаптер + паринг) *(резолв BT-шва H §6; синхронизировано в H §6/§15)* - **Владелец BlueZ-адаптера и паринга — Connectivity-core** (общий аппаратный радиоресурс → один привилегированный владелец, как сеть). 🟡 может выделиться в отдельный BT-сервис, если разрастётся (§15). - **Паринг:** BlueZ-Agent (PIN/just-works) — механизм в core; **UX выбора устройства/подтверждения — в Phone-апе/Shell** (слот C §4). Список спаренных, доверие, реконнект — здесь. **Сбой паринга** (неверный PIN / timeout / reject устройства) → видимая неблокирующая индикация + откат к списку устройств, без зависания. - **Активное устройство (мультипаринг):** одновременно активен **ровно один телефон для телефонии (HFP/PBAP)**; при нескольких спаренных — выбор active-устройства (last-connected / явный выбор в Phone-апе, слот C). A2DP-медиа может жить на **другом** устройстве (координация H §6). Это делает `Dial`/`CallStateChanged` (§11) однозначными. - **Диспетчеризация профилей** к потребителям спаренного устройства: - **HFP** (звонок) → **Phone-ап (G)**, §4; - **A2DP/AVRCP** (медиа) → **Media-ап (H §6)**; - **PBAP/MAP** (контакты/сообщения) → **Phone-ап (G)**, §5. - **HFP-аудио** идёт через PipeWire (bluez5-модуль, mSBC/CVSD) — H маршрутизирует по роли `phone_call`. - **Фаза:** v2 (вместе с Phone и A2DP H). ## 4. Телефония — HFP-звонки (Phone-ап) - **Состояния вызова:** `idle`/`incoming`/`dialing`/`active`/`held`(опц.)/**`audio_lost`** — публикуются на шине (§11), чтобы H проактивно корчил медиа (H §3 crash-safe: сигнал `Phone` → cork ДО появления аудио-ноды). - **Аудио:** downlink (голос собеседника) → усилитель; uplink — **салонный mic-массив** (hardware §4), тот же, что у ассистента → во время звонка mic отдан HFP-аплинку (политика арбитража H §3), ассистент подавлен. AEC/денойз на uplink — желателен (тот же тракт, что H §4 / D §10). - **Звонок — это телефона, не наш:** головблок — hands-free-периферия. - **Потеря HFP-аудио-линка в середине звонка** (SCO рвётся — телефон вышел из зоны, — но вызов жив на AG): **отдельное событие от hangup.** Phone эмитит `CallStateChanged → audio_lost` (§11), **синхронно снимая заявку роли `phone_call`** → H гарантированно опускает проактивный cork (медиа не залипает; H §3), mic освобождается, подавление ассистента снято. **Инвариант:** проактивный cork снят ⇔ оверлей не показывает hands-free-разговор (одно событие на обе оси). UI (§6) → «звонок продолжается на телефоне». - **Фаза:** v2. ## 5. Контакты / журнал / сообщения (PBAP/MAP) + приватность - **PBAP:** синхронизация контактов и журнала вызовов с телефона (имя вместо номера, набор по имени §6). **Синхронизация — фоновая/ленивая (#11)**, не блокирует UI и не задерживает доступность HFP; на общем BT-линке **голос (HFP) приоритетнее** фоновой PBAP-синхронизации. **MAP** (SMS) — later (чтение вслух §6). - **Приватность (#7, 152-ФЗ — высокочувствительно):** контакты, журнал, тексты SMS — **персональные данные**. **On-device, local-first**; **никогда** в облако/онлайн-LLM без явного согласия (как память водителя D §7). Доступ — audit-log (security-privacy §7 / a-base §9); at-rest — fscrypt-поддерево (a-base §3). Чистка — factory-reset (a-base §12) + при отвязке устройства. - **Фаза:** контакты v2; SMS/MAP v3. ## 6. Управление вызовом и distraction (#6) - **Ответ/сброс — аппаратно, не голосом:** кнопки **мультируля** (answer/hangup) и тач (C §9, K §3, uinput→Wayland-input) — крупная single-tap-аффорданс, доступна и на скорости (distraction блокирует *сложное*, не одно-действие; C §7). **Во время звонка mic занят HFP** → голосового «положи трубку» нет (явное решение, не пробел). - **Набор — голосом (до звонка):** «позвони <контакт>» — **assistant-интент** (Phone — first-party, регистрирует `assistant_intents`; роутинг/коллизии D §6 + plugin-sdk §5), резолв имени по PBAP active-устройства (§3/§5). - **Входящий вызов — оверлей** в слоте Shell (C §4), упрощённый на скорости (distraction — владелец C §7); `phone_call` прерывает ассистента (лестница H §3). **При активном реверс/парктроник-виде (J §6) входящий- оверлей НЕ перекрывает live-вид камеры** — деградирует до компактной формы (полоса/PiP), сохраняя answer/decline; z-order overlay-слота — у C (§15 → C). - **Имя не синхронизировано** по PBAP (реконнект/большая книга §5) → оверлей показывает **номер** (#3 graceful), имя подтянется позже. - **Фаза:** v2. ## 7. WiFi-hotspot / tethering *(later)* - **Головблок как AP** (раздать **текущий активный uplink** §2 — не обязательно LTE) и/или приём tethering от телефона (§2). NM-управление. - **Инвариант радио:** AP-раздача и приём WiFi-tether делят **одно WiFi-радио** → взаимоисключающие, если железо не поддерживает concurrent STA+AP (зависимость от hardware §4); конфигурация «AP-uplink = тот же телефон, что и tether-источник» — **запрещена (петля)**. - Энергобюджет/нагрев (hotspot тянет) — с B/hardware. **Фаза:** v3. ## 8. Проекция — CarPlay / Android Auto *(later, лицензионно-ограничено)* - 🟡 **Серьёзные ограничения (#12, юр.):** **CarPlay** требует Apple MFi-чип + лицензию (NDA, несовместимо с open-source); **Android Auto**-проекция — проприетарный протокол Google; открытые реализации (OpenAuto-класс) — реверс-инжиниринг, юридически серо, часто GPL. → **не first-party**; реалистично — community-плагин под ответственность интегратора **или** вне скоупа. - Если появится: аудио/видео проекции — роли `projection`/`phone_call` в арбитре H (§3); поверхность — слот C. - **Фаза:** v4/неопределённо; решение — отдельно (§15). ## 9. Lifecycle (шов с B) - **Load-shedding:** при power-loss модем/WiFi — среди сбрасываемых нагрузок (hardware §3, B §4) → Connectivity отрабатывает пропажу транспорта как обычный offline (#3), потребители деградируют (in-flight HTTP D — таймаут D §5; teardown через `ShutdownImminent`→`StopApp` оркестрирует B §4). - **Sleep/wake (B §7):** модем/радио выключены в `sleep`/`battery_cutoff` (бюджет АКБ #5); опц. wake по сети — later. - **Звонок при ACC-off:** головблок — лишь hands-free; на shutdown HFP-аудио прекращается, **звонок продолжается на телефоне** (как при потере SCO §4) — активный звонок shutdown не блокирует. - **Реконнект:** на boot/`accessory` Connectivity переподнимает известные WiFi/спаренные BT (resume медиа H §9 зависит от этого). ## 10. Приватность и безопасность (#7, #1, #2, #12) - **Local-first ПДн:** контакты/журнал/SMS — §5; никаких автоматических выгрузок. - **Модем ≠ шлюз к CAN (#2):** изоляция companion-IP от шины машины — нет пути модем→Vehicle-Data→CAN-write (его не существует). Удалённое — только read-only/opt-in через L. - **eCall/экстренный — вне скоупа (#1).** - **Лицензии (#12):** **BlueZ / ModemManager / NetworkManager** (и obexd для PBAP/MAP) — **GPL-2.0**; используем как **отдельные системные демоны через D-Bus** (не линкуем в наши Rust-бинари) → copyleft изолирован процессом (#12-допустимо). Наш код (`zbus`-обёртки) — MIT. ## 11. IPC / интерфейсы - **`ru.shturman.Connectivity`** (ipc §3, ядро): `GetStatus()`/`ListNetworks()`/`Connect(id)`/`Disconnect()`; сигналы `ConnectivityChanged(state)`/`NetworkChanged(...)`; properties `Online`(bool), **`State`** (`offline`/`portal`/`limited`/`online` + модем `sim_locked`/`no_sim`/`no_service`), `Type` (`wifi`/`modem`/**`tether`**), `SignalStrength`. Расширение enum `Type` (`tether`) + `State` + BT-устройства/ выбор active — **расширить ipc §3 (хвост)**. - **`ru.shturman.Phone`** (ipc §4, домен G): `Dial(number|contact)`/`Answer()`/`Hangup()` (адресуют active- устройство §3); сигнал **`CallStateChanged(state, peer)`** (`idle`/`incoming`/`dialing`/`active`/`held`/ **`audio_lost`** — SCO потерян, вызов на телефоне §4) — на него H проактивно корчит/раскорчивает медиа (H §3); property `CallState`, `Contacts`(read). Закрывает ipc §4-делегацию H/I/**G**. - **Гейтинг:** `network` (security-privacy §3/§5, runtime-грант); HFP-аудио — PipeWire-нода роли `phone_call` (H §3); контакты стороннему — **не отдаём** без явного грана (приватность §5/§10). - **UI:** входящий-оверлей/набор/PIN-запрос — слот Shell (C §4); статус сети — статус-бар (C §3). ## 12. Dev-симулятор (#13) - **Сеть/модем — управляемые состояния** (уже в dev-environment: online/offline/слабый сигнал/**portal**/ **sim_locked**, для offline-first тестов D/H/L). Добавить: **фейковый BT-стек** (паринг + **сбой паринга**, профили HFP/A2DP/PBAP, мульти-устройство), **сценарии вызова** (incoming/active/hangup/**SCO-loss** → проверка cork/un-cork медиа H §3), **мок-контакты** (PBAP без реального телефона). → dev-environment. ## 13. Функции | функция | MVP/later | зависит от | фаза | |---------|-----------|------------|------| | Connectivity-сервис (WiFi-клиент + LTE-данные + статус + SIM-unlock) | **MVP** | hardware §4, NM/MM | v1 | | Состояние связности (portal/limited детект, не ложный online) | **MVP** | NM connectivity-check | v1 | | Приоритет/failover путей + metered-aware | **MVP** | — | v1 | | BT-адаптер + паринг (core) + диспетчер профилей + active-устройство | **MVP** | hardware (BT), BlueZ | v2 | | HFP-звонки (состояния + аудио `phone_call` + SCO-loss) | **MVP** | H §3, mic/amp | v2 | | Отказ-пути (сбой паринга, no_sim/no_service) | **MVP** | — | v2 | | Контакты/журнал (PBAP, фоновый синк) + privacy | **MVP** | security-privacy, a-base §3 | v2 | | Управление вызовом (руль/тач) + входящий-оверлей (vs реверс) | **MVP** | C §4/§7/§9, K §3 | v2 | | Голосовой набор «позвони X» (assistant-интент) | later | D §6 | v2 | | tethering от телефона (BT-PAN / hotspot) | later | — | v2/v3 | | WiFi-hotspot (AP, раздача uplink) | later | hardware/B | v3 | | SMS/сообщения (MAP) + чтение вслух | later | D (TTS) | v3 | | Проекция (CarPlay/Android Auto) | later | лицензии (§8) | v4/неопр. | ## 14. Зависимости - **Вниз:** hardware (§4 модем/WiFi/**BT-адаптер**/mic/amp, §3 load-shed), NM/MM/BlueZ/obexd (tech-stack), PipeWire (HFP-аудио через H), a-base (§3 fscrypt контактов, §9 audit, §12 reset). - **Вбок:** **H** (роль `phone_call`, BT-аудио A2DP/AVRCP — H цепляет к нашему адаптеру; arbiter ducking), **D** (online-LLM поверх Connectivity; интенты «позвони»/«прочитай SMS»; AEC-тракт §10), **C** (слоты входящего/ набора/PIN, distraction, мультируль-ввод, z-order overlay), **K** (руль-кнопки answer/hangup), **B** (load-shed, sleep/wake), **L** (Connectivity — транспорт OTA/телеметрии/компаньона), **I** (RDS-TMC — задел H §7). - **Вверх:** статус сети/звонка для Shell; `network` — потребляют апы/плагины (гейтинг security-privacy). ## 15. Открытые вопросы - 🟡 **BT-адаптер в hardware §4:** добавить Bluetooth в периферию (резолвится этим коммитом). → hardware. - 🟡 **Владелец BlueZ:** Connectivity-core (рек., §3) vs выделенный BT-сервис — подтвердить. - 🟡 **Телефонный стек HFP:** PipeWire-bluez5 (аудио) + BlueZ-D-Bus (управление) — достаточно, или нужен **oFono** (richer call control: held/swap, call-waiting, 3-way, DTMF — тоже GPL-демон)? → реализация/tech-stack. - 🟡 **Проекция (CarPlay/Android Auto):** не-first-party / плагин / вне скоупа — решить (лицензии §8). → отдельно. - ◻️ **Z-order overlay-слота** (входящий-вызов vs реверс-вид vs ассистент vs уведомления) — общее правило «вид манёвра > уведомление». → C (§4 слот-модель) + J §6. - ◻️ **Политика приоритета путей** (WiFi/tether/LTE, metered-пороги, failover-гистерезис, пороги SIM-ретраев) — числа. → реализация. - ◻️ **Контакты/журнал/SMS в security-privacy §7** (потоки данных) — добавить строку local-first (резолвится этим коммитом). → security-privacy. - ◻️ **152-ФЗ для контактов/звонков** (оператор ПДн, основание) — legal-трек (как BYO-LLM, security-privacy §7). - ◻️ **Wake-on-network / входящий в sleep** — нужен ли, бюджет АКБ. → B. - ◻️ **tethering vs встроенный модем** — оба или приоритет одного (стоимость SIM vs зависимость от телефона). → later. --- ## Журнал решений (домен G) | Решение | Выбор | Дата | |---------|-------|------| | Структура | Connectivity (core, сетевое+BT-железо, Stage 2) + Phone (first-party ап); оба в домене G | 2026-06-22 | | Пути данных | провайдер-агностично: WiFi/LTE/tethering, приоритет+failover, metered-aware; связность не бинарна (portal/limited) | 2026-06-22 | | Голос | **только HFP спаренного телефона; встроенный модем — data-only** (VoLTE/CS вне скоупа); eCall вне скоупа (#1) | 2026-06-22 | | BlueZ | владелец — Connectivity-core; active-устройство = ровно один телефон для HFP/PBAP; профили HFP→Phone, A2DP/AVRCP→H, PBAP/MAP→Phone (**резолв H §6**) | 2026-06-22 | | Звонок | HFP hands-free; звук — роль `phone_call`; SCO-loss → `audio_lost` + снятие роли (раскорчивает H); звонок «телефона» | 2026-06-22 | | Управление | ответ/сброс — руль/тач single-tap (mic занят HFP → нет голос-hangup); набор — голосом (assistant-интент) | 2026-06-22 | | Приватность | контакты/журнал/SMS — local-first, fscrypt, не в облако без согласия (152-ФЗ); PBAP-синк фоновый | 2026-06-22 | | Красные линии | модем ≠ шлюз к CAN (#2); GPL-демоны (BlueZ/NM/MM/obexd) изолированы процессом (#12) | 2026-06-22 | | Проекция | CarPlay/AA — лицензионно тяжело → не-first-party/плагин/вне скоупа, v4-неопр. | 2026-06-22 | | Фазы | Connectivity-данные+SIM v1; BT/HFP/контакты v2; hotspot/SMS v3; проекция v4 | 2026-06-22 |