![](https://habrastorage.org/getpro/habr/upload_files/d46/60c/75e/d4660c75e2f565492fe3f7866300fa86.png)
Одной из проблем развития бортовых систем для автомобиля является создание качественного переносимого программного обеспечения, которое бы работало на бортовых системах разных автопроизводителей и может быть скомпилировано под разные аппаратные и программные архитектуры. Несмотря на очевидную актуальность, задача осложнялась прежде всего тем, что большинство автопроизводителей предпочитало создавать собственные проприетарные операционные системы, что затрудняло создание переносимого программного обеспечения. Ситуация изменилась со стартом проекта Automotive Grade Linux (AGL), поддерживаемыми крупными компаниями такими как Toyota, Mazda, Suzuki, Ford и Mercedes Benz и производителями медиасистем (например, Panasonic). И в планах развития проекта Flutter на 2022 год обозначено развитие поддержки AGL как целевой платформы для приложений. В этой статье мы рассмотрим основные идеи создания переносимых приложений для AGL на Flutter.
Прежде всего посмотрим на сам проект AGL и его архитектуру. AGL является специализированным дистрибутивом Linux, но в отличии от привычных нам Desktop-дистрибутивов, здесь используются наработки проекта Yocto для создания встраиваемых систем. Yocto позволяет собрать специализированный дистрибутив на основе слоев (bblayers.conf
), состоящих рецептов (recipes
, описывают правила сборки компонентов) и настроек конфигурации (local.conf
), которые компилируются утилитой bitbake
в двоичный образ для целевой платформы (которая может быть как одна из плат микрокомпьютеров, например Renesas M3 или Raspberry PI 4, так и образом для запуска в эмуляторе, например vmdk или ext4 для qemu). Для ознакомления с системой можно использовать образ виртуальной машины из agl-demo-platform-crosssdk-qemux86-64.ext4.xz (архив нужно распаковать) и загрузчик bzImage. После загрузки можно запустить образ AGL и познакомиться с интерфейсом системы следующей командой:
qemu-system-x86_64 -device virtio-net-pci,netdev=net0,mac=52:54:00:12:35:02 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 -drive \
file=agl-demo-platform-crosssdk-qemux86-64.ext4,if=virtio,format=raw \
-usb -usbdevice tablet -device virtio-rng-pci -snapshot -vga virtio \
-display gtk,show-cursor=on -device intel-hda -device hda-duplex \
-machine q35 -cpu kvm64 -cpu \ qemu64,+ssse3,+sse4.1,+sse4.2,+popcnt \
-enable-kvm -m 2048 -serial mon:vc -serial mon:stdio -serial null \
-kernel bzImage -append 'root=/dev/vda rw console=tty0 mem=2048M ip=dhcp oprofile.timer=1 console=ttyS0,115200n8 verbose fstab=no'
Интерфейс системы представлен на рисунке. Здесь можно увидеть общий интерфейс HomeScreen, который предоставляет доступ к Launcher (пиктограммы приложений), информации о климат-контроле, медиа-проигрывателю и навигатору.
![Интерфейс AGL Интерфейс AGL](https://habrastorage.org/getpro/habr/upload_files/2ab/5e6/962/2ab5e6962ea5d3cb14721cc08fbb2d46.png)
Система собрана из нескольких компонентов, для доступа к каждому из которых требуется запрашивать разрешения, которые могут быть реализованы одним из трех видов:
binding - связывание с нативной библиотекой;
api - доступ к API подсистемы;
permission - разрешение на общесистемное действие.
В системе реализованы следующие подсистемы:
платформа (управление ресурсами, мониторинг функционирования, межпроцессное взаимодействие) - на основе Linux;
сетевое взаимодействие и Bluetooth (Connectivity);
мультимедийная система (Multimedia) - радио (Tuner), камера (Camera), воспроизведение звука и видео;
голосовые сервисы (Speech Services);
геолокация и навигация (Navigation and Location-Based Services);
графическая подсистема (Graphics) - оконный менеджер, графические примитивы, 3D-графика (OpenGL-совместимая);
безопасность (Security);
система управления автомобилем (Automotive) - шина устройств (Vehicle Bus), диагностика (Diagnostics);
фреймворки для разработки приложений:
AGL Application Framework;
Native Application Framework (используется в том числе Flutter);
Web Application Framework (разработка на основе веб-технологий).
Разрешения и связывания приложения запрашивают через файл манифеста, структура которого зависит от используемого фреймворка для построения интерфейса. В настоящее время AGL работает поверх X11/DRM или Wayland и поддерживает как HTML5-приложения, так и нативные приложения (созданные в том числе с использованием Flutter).
Для реализации собственных приложений нам потребуется собрать собственный образ с использованием необходимых слоев и интеграции дополнительных инструментов разработчика. Начнем с варианта создания Flutter Web-приложения с использованием подсистем AGL для доступа к данным или управления системами автомобиля.
Web Application Framework for AGL
Веб-приложения для AGL реализуется в соответствии со стандартом Packaged Web Apps (Widgets), которая описана в стандартах W3C здесь. Для разработки приложений будет необходимо выполнить сборку собственного образа AGL, для этого установим инструмент repo (обертка вокруг git):
mkdir ~/bin export
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
и далее получим исходные тексты и выполним сборку:
repo init -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo
repo sync
source meta-agl/scripts/aglsetup.sh -m qemux86-64 agl-app-framework agl-demo\
agl-pipewire agl-package-management agl-flutter agl-basesystem agl-devel\
agl-app-framework agl-archiver agl-localdev agl-buildstats\
agl-weston-remoting agl-demo-preload agl-drm-lease
bitbake agl-ivi-demo-platform-html5
Сборка занимает более суток, поэтому для упрощения тестирования я подготовил образ для веб-разработки (под архитектуру процессора Intel Core i7 или более новую) и разместил его здесь (архив с образом файловой системы и загрузчиком). В опции -m можно указать сборку под аппаратное устройство (например, под Raspberry PI) и далее загрузить полученный образ на микрокомпьютер. В source мы перечислили необходимые компоненты (используется оконный менеджер weston над wayland, добавляем инструменты разработки и запуска приложений).
Для управления приложениями используется Application Framework Manager, который использует файл определения приложения appinfo.json (подробно структура описана здесь), содержащий метаданные и список запрашиваемых разрешений, API и связывания с нативными библиотеками (bindings). Пример appinfo.json для нашего приложения:
{
"id": "counter",
"title": "HTML5 Counter",
"description": "Counter application for AGL based on html5 technologies",
"version": "1.0.0",
"vendor": "Dmitrii Zolotov",
"type": "web",
"main": "index.html",
"uiRevision": "1",
"icon": "icon.svg",
"extensions": [ ]
}
Созданное веб-приложение может быть размещено в подкаталог /usr/lib/wam_apps/. При перезагрузке эмулятора будет доступна пиктограмма для запуска нового приложения. Приложение на Flutter собирается обычным образом для целевой платформы Web, но нужно отметить, что подсистемы AGL публикуются как JavaScript-объекты (используется реализация LG WebOS Open Source Edition platform, интегрированная в веб-вариант сборки AGL). Примеры web-приложений (не на Flutter) можно посмотреть здесь.
Для установки приложения через Web Application Manager также можно использовать формат архива Web Widget (.wgt), содержащего файл описания метаданных приложения и запрашиваемых разрешений. Например, можно обозначить необходимость доступа к списку установленных приложений и собрать веб-архив на Flutter. В этом случае метаданные определяются в файле config.xml, который может выглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="webapps-flutter-homescreen" version="1.0.0">
<name>Homescreen</name>
<icon src="icon.svg"/>
<content src="index.html" type="text/html"/>
<description>HTML5 Homescreen flutter demo</description>
<author>Igalia, S.L.</author>
<license>APL 2.0</license>
<feature name="urn:AGL:widget:required-permission">
<param name="urn:AGL:permission::public:no-htdocs" value="required" />
<param name="urn:AGL:permission::public:display" value="required" />
<param name="urn:AGL:permission:afm:system:widget" value="required" /> <!-- list available apps -->
<param name="urn:AGL:permission:afm:system:runner" value="required" /> <!-- run other apps -->
<param name="urn:AGL:permission::public:applications:read" value="required" /> <!-- get app icons -->
</feature>
<feature name="urn:AGL:widget:required-api">
<param name="homescreen" value="ws" />
<param name="afm-main" value="ws" />
</feature>
</widget>
Здесь запрашиваются API главного экрана и AFM (Application Framework Manager) и разрешение на запуск приложений и чтение списка установленных приложений. Также в API можно запросить доступ к gps, wifi и другим подсистемам AGL (список можно посмотреть здесь). Пример приложения на Flutter с доступом к системным ресурсам можно посмотреть в Github:
Для приложения счетчика файл конфигурации может выглядеть подобным образом:
<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="webapps-sample" version="0.0.0">
<name>Sample App</name>
<icon src="icon.svg"/>
<content src="index.html" type="text/html"/>
<description>Sample counter</description>
<author>Dmitrii Zolotov</author>
<license>GPL 2.0</license>
<feature name="urn:AGL:widget:required-permission">
<param name="urn:AGL:permission::public:no-htdocs" value="required" />
<param name="urn:AGL:permission::public:display" value="required" />
</feature>
<feature name="urn:AGL:widget:required-api">
<param name="homescreen" value="ws" />
</feature>
</widget>
Архив может быть установлен через afm-util install <name.wmgt>; aft-util start <appname>
Native Application Framework
Многоуровневая архитектура Flutter и разделение dart-фреймворка и низкоуровневой реализации Embedder представляет потенциальную возможность создания приложений на любую аппаратную архитектуру и программное окружение. Сейчас среди стабильных платформ для выполнения Flutter-приложений называется Android, iOS, Web, Windows, Linux и MacOS. Также экспериментально поддерживается разработка для Fuchsia OS. Но особый интерес для нас сейчас представляет проект компании Sony flutter-embedded-linux (и набор инструментов flutter-elinux), созданный на основе Flutter for Tizen SDK, расширений для инструментов Flutter, позволяющий выполнять сборку приложений для встраиваемых систем и по сути является является альтернативным решением для запуска Flutter-приложений на Linux-платформах без использования GTK (который используется в Flutter Desktop for Linux). В проекте реализуется альтернативный Embedder, который отвечает за реализацию цикла сообщений, платформенных каналов для использования C/C++ кода, работа с графикой, устройствами ввода и трансляцией запросов в Wayland или X11/DRM. Сгенерированный образ может быть выполнен как внутри эмулятора встраиваемого устройства (например, AGL на QEMU), так и на плате микрокомпьютера, которое может использоваться в реальном автомобиле.
![Архитектура eLinux Embedding Архитектура eLinux Embedding](https://habrastorage.org/getpro/habr/upload_files/bff/900/9fe/bff9009febc1f6f720965543dde509dd.png)
Инструмент устанавливается как обертка вокруг Flutter SDK и реализует полный набор команд утилиты командной строки flutter:
git clone https://github.com/sony/flutter-elinux.git
sudo mv flutter-elinux /opt/
export PATH=$PATH:/opt/flutter-elinux/bin
flutter-elinux --version
Можно увидеть, что в целевых платформах elinux поддерживается связывание с X11 или Wayland, что можно указать при запуске приложения. Запустим тестовое приложение для X11 elinux-x11
(для ubuntu можно использовать elinux-wayland
):
flutter create --platforms=elinux hello
cd hello
flutter-elinux run elinux-x11
Для создания запускаемых приложений на AGL нужно выполнить сборку flutter bundle и передать ее через scp на запущенную виртуальную машину (в нашем случае через порт 2222, пользователь root без пароля). Также можно подготовить файл ~/.flutter_custom_devices.json с описанием способа доставки артефактов на устройство, например:
{
"custom-devices": [
{
"id": "AGL",
"label": "AGL",
"sdkNameAndVersion": "Automative Grade Linux",
"enabled": true,
"platform": "x86_64",
"backend": "wayland",
"install": [
"scp", "-P", "2222", "-r", "${localPath}", "root@127.0.0.1:/tmp/${appName}"
],
"uninstall": [
"ssh", "-p", "2222", "root@127.0.0.1", "rm -rf \"/tmp/${appName}\""
],
"runDebug": [
"ssh", "-p", "2222", "root@127.0.0.1", "/tmp/${appName}/${appName}"
],
"forwardPort": [
"ssh", "-o", "ExitOnForwardFailure=yes",
"-p", "2222",
"-L", "127.0.0.1:${hostPort}:127.0.0.1:${devicePort}", "root@127.0.0.1"
],
"forwardPortSuccessRegex": "Linux"
}
]
}
Теперь в списке устройств (flutter-elinux devices) появится новое устройство AGL и можно будет запустить приложение непосредственно на нем: flutter-elinux run elinux-wayland -d AGL
Нужно отметить, что использование flutter-elinux не ограничивается только AGL, но может использоваться для разработки приложений для других встраиваемых устройств на основе Linux (а если дистрибутив допускает сборку образа Linux на Yocto, то можно использовать рецепты https://github.com/sony/meta-flutter для интеграции среды выполнения и сборки, если это явно указано при выполнении bitbake, приложений на Flutter на устройстве поверх Wayland или X11/DRM).
Более удобно для разработки и запуска приложений в виртуальном машине AGL выполнить сборку среды выполнения и SDK непосредственно внутри образа. Для этого в bitbake укажем целевую сборку agl-demo-platform и конфигурацию populate_sdk:
bitbake agl-demo-platform -c populate_sdk
В результаты мы получим возможность выполнять компиляцию приложений непосредственно внутри AGL (используется та же реализация Flutter eLinux). Для доступа к функциям операционной системы из кода используются механизмы платформенных каналов, которые на стороне системы принимаются через плагины.
Мы посмотрели основы разработки приложений на Flutter для операционной системы Automotive Grade Linux. В следующей статье мы рассмотрим примеры использования датчиков устройства на примере простого приложения для управления климатом в автомобиле.
В новой версии Flutter 3.0 была добавлена официальная поддержка игровых движков Flare и SpriteWidget и набор инструментов CasualGamingKit. Хочу пригласить вас на бесплатный урок, где мы изучим возможности Flutter для создания кроссплатформенных игр для мобильных устройств, веб и настольных компьютеров и создадим простую аркадную игру от начала и до подготовки к публикации в магазинах приложений.