Все работы

Кейс · 2026

BMW iDrive Launcher

Собственный проект · Дизайн и разработка

В разработке

BMW iDrive Launcher

Заводской лаунчер на китайских магнитолах XTRONS тормозит и не умеет главного. Мы начали с малого — заменить его быстрым домашним экраном в эстетике современного iDrive и надёжно поднимать бортовой компьютер при старте машины. А выросло это в полноценную приборную панель: 3D-карусель плиток над живой картой, приборный янтарь на графите, музыка из Яндекса и собственный борткомпьютер, который читает шину I-Bus машины напрямую.

Всё на Kotlin и Jetpack Compose, со скриншот-тестами, без root. Обновляется по воздуху, исходный код открыт на GitHub. Машина — настоящая, ездит каждый день.

Как сделано

Чистый Kotlin + Jetpack Compose, без тяжёлых фреймворков. Инженерная часть — там же, где и «характер» интерфейса:

  • Логика отделена от UI и покрыта тестами — геометрия карусели, разбор кадров шины I-Bus, форматирование времени, маппинг воспроизведения, разрешение темы.
  • Скриншот-тесты Paparazzi рендерят каждый экран в родном разрешении головы: визуальная регрессия валит сборку, интерфейс не «уезжает» между версиями.
  • Лаунчер — это HOME, он не имеет права падать: все внешние вызовы, USB и карта обёрнуты в защиту и деградируют молча. Всё работает без root.
  • OTA-обновления по кнопке — правки прилетают на голову без флешки и без ADB.

История: решения и грабли

Проект интересен не фичами, а тем, с чем пришлось столкнуться — и как это обошли. Почти каждый шаг упирался в особенности дешёвой магнитолы.

Голова без разработчика. Стандартный трюк «семь тапов по номеру сборки» на этих XTRONS не работает — режим разработчика просто не появляется. Вечер ушёл на то, чтобы найти недокументированный вход: в заводских настройках пароль adbon открывает ADB. Написали отдельную инструкцию — таких голов в стране много.

Эквалайзер, который врал. Сначала на экране музыки крутился «живой» эквалайзер. Оказалось, ROM магнитолы блокирует захват аудио, поэтому любой анализатор был синтетическим — просто дёргался не в такт. Честнее убрать: оставили спокойную янтарную полосу прогресса.

Серый экран и зависания. Периодически лаунчер уходил в серый экран с ребутом. Добавили «сторожа» главного потока и отчёты о зависаниях, которые переживают перезагрузку и сами прилетают на сервер — так поймали причину, а не гадали.

Карта, которая капризничала. Хотелось живую карту фоном — в нашем стиле, а не дефолтный жёлтый Яндекс. Проприетарный формат стиля Яндекс.Карт молча не применялся. Перешли на открытый движок MapLibre + бесплатные тайлы OpenFreeMap со своим style.json на нашем сервере — теперь цвета карты правятся на сервере без пересборки приложения. А когда выяснилось, что провайдер магнитолы не пускает заграничный CDN тайлов, подняли прокси на своём сервере: голова ходит только к нам, мы тянем тайлы за неё.

Свой борткомпьютер вместо чужого приложения. Изначально лаунчер просто запускал стороннее i-Bus приложение. Оно глючило и дралось за единственный USB-порт адаптера. Решение — написать свой ридер шины I-Bus: подключаемся к адаптеру Resler (CP210x, 9600 8E1) по USB и сами разбираем сообщения приборной панели — скорость, обороты, температуры, зажигание. Протокол подтвердили декомпилом родного приложения. Собирали, по сути, вслепую — доступа к машине не было — но цифры на приборке сошлись с первого раза. Стороннее приложение удалили: порт теперь наш.

Кирпич — и воскрешение. Самый напряжённый эпизод: эксперимент с правами root залил на голову несовместимый загрузочный образ, и она ушла в вечный цикл «логотип → чёрный экран». Инструкции продавца (меню по кнопке, флешка) на этой Qualcomm-платформе не работают; предлагали возврат по почте — это месяцы без машины. Разобрались сами: нашли, что сервисный режим (fastboot) выходит только через один конкретный USB-разъём — четырёхпиновый OTG, а не «флешечные» порты, — и через него перезалили родной загрузочный образ, снятый с этой же головы. Всё восстановилось без потери данных и настроек. Заодно написали пошаговый разбор, чтобы такой кирпич больше не был приговором.

Кнопки, которые нельзя перехватить. Захотели, чтобы физические кнопки панели открывали наши экраны. Живой захват ввода показал: реальный код шлёт только «Назад» — остальные кнопки намертво зашиты в контроллер и сами запускают штатные приложения, не отдавая события. Перехватить нельзя — но можно перенаправить: сервис ловит запуск штатного приложения и мгновенно открывает наш экран. Теперь панельная «Музыка» открывает наш плеер.

Парктроник, который пищит поздно. Штатный парктроник E53 молчит, пока не подъедешь вплотную, — это ощущается как «тупит». Дистанции при этом есть на шине I-Bus (модуль отвечает на запрос). Добавили режим записи, который опрашивает датчики и логирует ответы, — чтобы раскодировать их и сделать более ранний, ступенчатый сигнал, чем штатный зуммер.

Разработка вслепую. Машины под рукой нет — итерации идут через OTA-кнопку «обновить» и диагностические логи с устройства. Логи стали нашими «глазами»: именно по ним настраивается разбор шины и добавляются новые показатели.

Уже добавили среднюю скорость поездки (со сбросом), считаемую прямо из шины. Дальше — топливо и расход в том же борткомпьютере и ранний сигнал парктроника.

Результат

Живой, ежедневно используемый лаунчер для головного устройства BMW X5 E53 — 3D-карусель в стиле iDrive над живой картой, собственный борткомпьютер (читает шину I-Bus машины напрямую по USB), музыка из Яндекса, OTA-обновления. Активная разработка, открытый код на GitHub.