Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Краб живёт внутри телефона

Daniel получил root на Xiaomi Mi 8, поместил OpenCrabs в Ubuntu chroot прямо на устройстве и подключил к нему приложение на Flutter по ACP. Дальше краб сам написал Android-приложение, собрал APK на телефоне через aapt2, javac, d8 и apksigner и установил его. Без ПК, без облака, без Gradle, без SDK.

Кто-то говорит, что Flutter отстой… ага (ирония) @opencrabs внутри телефона, связан по a2a с кастомным приложением на flutter. Он может менять ОС. Может написать android-приложение, скомпилировать и открыть… всё внутри этого чёртова телефона

Первое приложение, полностью собранное внутри телефона с помощью @opencrabs, да, код написан в телефоне, apk собран и открыт. Компьютер не нужен ;)

Устройство: Xiaomi Mi 8 (dipper), Android 10 / API 29, MIUI 12, aarch64, ядро 4.9.186, 5,6 ГБ ОЗУ. Root брался из самого boot-образа: Magisk патчит его на телефоне, fastboot прошивает, а верификатор распаковывает результат и смотрит на ramdisk вместо того, чтобы доверять логу патча. Прямо сейчас: magisk -c выдаёт 30.7:MAGISK:R.

Перенести Linux userland на Android удалось со второй попытки. Первое поколение ставило бинарник aarch64-linux-android как модуль Magisk со скриптом-супервизором, а это означало порт cfg из 59 файлов и борьбу glibc против musl. Второе поколение, то, что работает сегодня, это chroot с Ubuntu 24.04.5 на glibc 2.39, как раз то, что нужно выпущенному бинарнику linux-arm64. Ловушка, которая съела больше всего времени: /apex представляет собой tmpfs из отдельных bind-монтирований, поэтому один bind на /apex копирует пустой каталог, и любой Android-бинарник умирает с «required file not found», что выглядит как ошибка прав, а на деле означает отсутствующий интерпретатор. Лечится тем, что каждый элемент /apex/* монтируется отдельно.

Дальше приложение. Daniel хотел интерфейс диалога, который ему нравится в вебе, но собранный нативно на Flutter, а не в WebView. Поэтому приложение говорит по ACP (JSON-RPC 2.0 поверх stdio) с opencrabs acp, запущенным в chroot, тем же протоколом, что использует TUI: живые куски рассуждений, карточки инструментов, запросы разрешений, расход токенов. Без браузера, без сервера, без открытого порта.

  • Переживает перезагрузку, и телефон при этом никто не трогает: задача JobScheduler, которая безусловно перевзводит себя, сервисный хук, который ждёт sys.boot_completed и заново поднимает семь монтирований, и цикл, который повторно применяет appops MIUI для простоя и автозапуска, потому что powerkeeper снимает исключение из оптимизации батареи примерно через 20 с после загрузки
  • Доказательство, из logcat после настоящей перезагрузки: рукопожатие ok на 12 с, сервис поднят, исключение для батареи зафиксировано, затем headless-самотест 12 пройдено / 0 провалено, GREEN за 3,7 с, покрывающий версию бинарника, оболочку, сессии, обвязку загрузки, состояние сервиса, исключение батареи, распознавание голоса, разрешение на микрофон, привязку виджета, готовность ACP и реальный промпт
  • APK, собранный на телефоне: MIUI поставляет свою плитку записи экрана с заглушкой всего на 20 КБ, поэтому нажатие открывает магазин приложений и ничего не записывает. Краб написал настоящую плитку быстрых настроек, собрал её в шесть шагов без Gradle и без SDK manager и поставил в панель рядом с WiFi. 12 784 байта.
  • Цепочка сборки: aapt2 compile → aapt2 link → javac --release 8 против android.jar → d8 из R8 → заворачиваем dex в zip → zipalign → apksigner sign и verify
  • Установлено изнутри chroot, пакетный менеджер Android достигнут через nsenter -t 1 -m, затем выданы права root записью строки политики Magisk, а в шторку плитка добавлена через cmd statusbar add-tile
  • Одно тело, два мозга: ACP это stdio, и ssh -T тоже stdio, поэтому телефон может смотреть на Mac в локальной сети без моста и без открытого порта. Замерено: initialize за 1,2 с, удалённый список из 40 сессий, самотест 9/9 GREEN против удалённого мозга

Главное: плитка сама ничего не записывает. Она через su от Magisk вызывает тот же бинарник рекордера в chroot, который использует команда /rec в чате, так что рекордер один, файл состояния один, папка вывода одна. Краб написал Android-приложение, которое является рукояткой для Linux-инструмента внутри того же телефона. Приложение это палец, краб это мозг. Вот и вся архитектура проекта, в 13 КБ.

Лог рассуждений из той сессии это та деталь, которую стоит сохранить: краб остановился, чтобы проверить, действительно ли он на телефоне, и подтвердил это по среде выполнения, а не предположил.

Источник в X ↗

APK, собранный на телефоне ↗