🧑‍💻

自動車のスマホ化 - Android Automotive OS完全入門!

2023/06/13に公開
1

はじめに

Turing株式会社UX Engineeringチームでエンジニアをしています佐々木です。Turingは「We Overtake Tesla」をミッションに完全自動運転EVの開発をしています。UX Engineeringチームは、車載インフォテインメント (IVI : In-Vehicle Infotainment) システムの開発を担当しており、Android Open Source Project (AOSP) をベースに車載OSを開発しています。

本記事では、AOSPの枠組みに含まれるAndroid Automotive OS (AAOS)を概説し、また、実機でAAOSを体験するためにRaspberryPi 4BでAAOS13.0を実行する方法を紹介します。

Android Automotive OSの概要

Android Automotive OS (AAOS) は自動車特有の要件や機能を追加したAndroid OSであり、一般的なスマートフォンやタブレット端末と同じAOSPの枠組みで開発が行われています。AAOSは、2017年3月にGoogleによって発表され、2018年2月にAAOS搭載のVolvo Polestar 2が発表されました。他にもHonda Accord, Chevrolet Tahoe, Rivian R1Tなどの市販車に搭載されています。
Volvo EX30
AAOSを搭載したVolvo EX30は2023年夏頃に日本で発売予定
混乱しやすいのが、Android AutoAAOSの違いです。これらは似て非なるものです。Android Autoは、互換性のあるIVIシステムにユーザーのスマートフォン上で動作するアプリケーション等を反映するプラットフォームです。一方のAAOSは車載ハードウェア上で直接動作するオペレーティングシステムです。AAOSは、車両と密に連携することができ、エアコンの温度調節や窓の開閉などを行うことができます。さらに、Googleのアプリとサービスを提供するパッケージであるGoogle Automotive Services (GAS) に対応すれば、Google Playにアクセスでき、Google MapsやGoogle Assistantなどが利用できます。

それでは、スマホやタブレット端末向けのAndroidとAAOSの違いはどこにあるのでしょうか。以下では、実機でAAOSを体験し、主な違いを見ていきます。

AAOS13.0をRaspberryPi 4Bで実行する

それでは早速、実機でAAOSを体験してみましょう。ここでは、入手しやすいRaspberryPi 4BでAAOS13.0を実行します。
AAOS Home Screen
AAOSのホーム画面
通常、エッジデバイスでAndroidを実行するためには、ドライバやハードウェアのサポートが必要です。RaspberryVanillaはRaspberryPiでAndroidを実行するためにドライバやハードウェアの対応を行っているプロジェクトであり、定期的にアップデートされています。以下では、GrapeUp社が行っているRaspberryVanillaのAAOSカスタムプロジェクトを題材とします。

実行環境

Amazonのリンクを付与しますので、購入の参考にしてください。

  • PC(マシンスペックは下記のビルド要件を参照ください)

  • ディスプレイ
    操作のためタッチ機能が付いているとよいですが、お手持ちのHDMIポートが付いているモニターで問題ありません。タッチ機能がない場合は、別途マウスを用意してください。

  • RaspberryPi 4B
    RaspberryPi 4B
    RaspberryPi 4B

  • MicroSD
    16GBあれば十分です。
    MicroSD
    MicroSD

  • MicroHDMI-HDMIケーブル
    MicroHDMI-HDMI
    MicroHDMI-HDMIケーブル

  • USB-TTLシリアルアダプタ(デバッグ用)
    USB-TTL
    USB-TTLシリアルアダプタ

  • ジャンパ線メスーメス 3本(デバッグ用)
    cable of female-female
    ジャンパ線メスーメス

ビルド要件

Androidは大きなプロジェクトであり、ビルドにはマシンパワーが必要です。RAMは32GB以上(64GB以上を推奨)、ディスク容量は余裕を持って512GB以上であることが望ましいです。物理マシンが用意できない場合は、AWS EC2などを利用するとよいでしょう。筆者のマシンスペックは以下です。

  • OS : Ubuntu 20.04
  • CPU: Intel(R) Xeon(R) Gold 6226R (16コア、32スレッド)
  • RAM: 128GB
  • HD: 4TB

ビルド

それでは、ビルドしていきましょう。マシンスペックによりますが、通常フルビルドには1時間以上かかります。

  1. ビルド環境の構築

    sudo apt update
    sudo apt-get install git gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig
    sudo apt-get install bc coreutils dosfstools e2fsprogs fdisk kpartx mtools ninja-build pkg-config python3-pip
    sudo pip3 install meson mako jinja2 ply pyyaml
    
  2. repoのインストール

    Androidは巨大なプロジェクトであり、大量のGitリポジトリで開発が行われています。そこで、これら多くのリポジトリを一元的に管理するためにGoogleによって開発されたrepoというツールを用います。

    cd
    mkdir ~/bin
    PATH=~/bin:$PATH 
    curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    chmod a+x ~/bin/repo
    
  3. repoの初期化

    Androidプロジェクトを初期化します。今回はAndroid13.0 revision 35を指定します。

    repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r35 --depth=1
    
  4. local_manifestの追加

    git clone https://github.com/grapeup/aaos_local_manifest.git .repo/local_manifests
    

    AAOSは.repo/manifest.xmlというファイルを使用して、どのリポジトリをプロジェクトに含めるかを管理します。カスタムリポジトリを追加する場合は、.repo/local_manifests/にmanifestファイルを作成します。今回のプロジェクトでは        .repo/local_manifests/manifest_brcm_rpi4.xmlで追加するリポジトリを定義しています。

  5. local_manifestの変更

    公開されているリポジトリでは、dav1dが不足しています。そこで、
    .repo/local_manifests/manifest_brcm_rpi4.xmlの46行目<!-- FFmpeg -->以下にdav1dを追記します。https://github.com/grapeup/aaos_local_manifest/pull/5

    <!-- FFmpeg -->
      <project path="external/dav1d" name="raspberry-vanilla/android_external_dav1d" remote="github" revision="android-13.0" />
    

    また、以下の27行目のandroid_buildと35行目のandroid_build_soongのrevisionをandroid-13.0からandroid-13.0.0_r35に変更します。

    <project path="build/make" name="raspberry-vanilla/android_build" remote="github" revision="android-13.0.0_r35" >
    <project path="build/soong" name="raspberry-vanilla/android_build_soong" remote="github" revision="android-13.0.0_r35" >
    
  6. リポジトリの同期

    -jオプションで並列数を指定します。ネットワークを圧迫するため、並列数は大きくしすぎないようにしましょう。

    repo sync -j8
    
  7. コンパイル

    . build/envsetup.sh
    lunch aosp_rpi4-userdebug
    make bootimage systemimage vendorimage -j$(nproc)
    

イメージの書き込みとデプロイ

ビルドが完了したら、次はMicroSDにイメージを書き込み、RaspberryPi 4Bにデプロイしていきます。

  1. MicroSDをクリーン

    # MicroSDの認識を確認 
    lsblk
    
    # MicroSDをクリーン
    sudo umount /dev/sdb*
    sudo wipefs -a /dev/sdb*
    sudo wipefs -a /dev/sdb
    
  2. 4つのパーティションテーブルを作成

    # パーティションテーブルの作成
    echo -e "n\n\n\n\n+128M\na\nt\n0c\nn\n\n\n\n+2G\nn\n\n\n\n+256M\nn\np\n\n\nw\n" | sudo fdisk /dev/sdb
    
    # パーティションが4つに区切られたことを確認
    lsblk
    sdb           8:16   1 119.2G  0 disk 
    ├─sdb1        8:17   1   128M  0 part 
    ├─sdb2        8:18   1     2G  0 part 
    ├─sdb3        8:19   1   256M  0 part 
    └─sdb4        8:20   1 116.8G  0 part
    
  3. イメージ書き込み

    MicroSDに書き込むイメージはboot.img, system.img, vendor.imgの3つです。

    sudo dd if=boot.img of=/dev/sdb1 bs=1M
    sudo dd if=system.img of=/dev/sdb2 bs=1M
    sudo dd if=vendor.img of=/dev/sdb3 bs=1M
    sudo mkfs.ext4 -L userdata /dev/sdb4
    
    sudo umount /dev/sdb*
    
  4. MicroSDをRaspberryPiに挿入して起動

    無事に起動できると冒頭のホーム画面(Launcherアプリ)が表示されます。Launcherアプリには、地図表示やラジオ再生の機能があります。他にも車載アプリの代表例としてHVAC (Heating, Ventilation, and Air Conditioning)があります。
    HVAC
    HVACアプリ

デバッグ

AAOSの開発において、kernel logやAndroidコマンドラインツールのAndroid Debug Bridge (adb)でログが見れることは必須です。以下では、RaspberryPi 4Bでシリアル通信を行いkernel logを確認する方法とadbコマンドの有効化について紹介します。

シリアル通信でkernel logを確認

  1. RaspberryPi 4BとPCを接続する

    RaspberryPi 4Bのpin6: Ground、pin8: GPIO14 (TXD)、pin10: GPIO15 (RXD)とPCをUSB-TTLシリアルアダプタで接続します。

RaspberryPi Serial Communication
RaspberryPi 4Bとシリアル通信用USBデバイスの接続方法
(図:RaspberryPi Documentation, USB-TTLシリアルアダプタ

  1. シリアル通信を行う
    今回はgtktermというツールを用います。

    # gtktermのインストール
    sudo apt install gtkterm
    
    # gtktermの起動
    sudo gtkterm
    

    ConfigurationからPortを選択し、下記の設定画面を開きます。Baud Rateを115,200に設定し、接続します。
    gtkterm
    gtktermの設定

adbの有効化

  1. Wi-Fiの接続

    RaspberryPi 4Bをadb接続するPCと同じネットワークに接続してください。

  2. シリアル通信でAndroidコンソールにrootとしてログインし、TCP経由でadbを有効化

    su
    setprop service.adb.tcp.port 5555
    stop adbd
    start adbd
    
    # ipアドレスを確認
    ifconfig wlan0
    
  3. RaspberryPi 4Bにadbで接続

    cd platform-tools
    
    # 先程、確認したipアドレスを入力
    adb connect ipアドレス:5555
    
  4. logを確認

    adb logcat
    
    # log
    06-13 05:45:52.626   774  1023 D EglHelper: createEglContext start
    06-13 05:45:52.632   774  1023 D EglHelper: createEglContext done
    06-13 05:45:52.632   774  1023 D EglHelper: createEglSurface start
    06-13 05:45:52.632   774  1023 D EglHelper: createEglSurface done
    

    logを確認することができました。

Android Automotive OSとは何なのか?

こうしてRaspberryPi 4BでAAOSを動かしてみることで、スマホやタブレット端末向けのAndroidとAAOSでは、いくつかアプリの変更があることが確認できます。実際には、ここから自社開発の車両に合わせてアプリ(OEM Apps)を独自に開発していきます。そのためには、AAOSのシステムアーキテクチャ全体の理解が必要です。以下では、AAOSのアーキテクチャを確認しながら、スマホやタブレット端末向けのAndroidとAAOSの主要な違いについて見ていきます。
Android Automotive OS Architecture
Android Automotive OSのアーキテクチャ図

Apps

まずは、アプリケーションレイヤーを見てみましょう。AOSP Appsには、CalendarやCameraなどデフォルトアプリが含まれています。これらはpackages/apps/にあります。また、packages/apps/Car/を見ると、先ほどRaspberryPi 4Bで動かしたLauncherやHVACがあります。アプリ名はAndroid.bpで定義されており、例えばLauncherは    /packages/apps/Car/Launcher/Android.bpでCarLauncherとして定義されています。
OEM Appsは各社OEM(Original Equipment Manufacturing : ここでは自動車メーカーを指す)が開発したアプリです。例えば、Volvo EX30のLauncherアプリは下記のように、車速やテルテール、マップ、音楽アプリなどが含まれておりAOSPのデフォルトアプリとは大きく異なります。
Volvo EX30 Launcher
Volvo EX30のLauncherアプリ

3rd Party Appsは文字通り、GoogleやOEM以外が開発を行い、提供しているアプリです。AAOS向けのアプリは運転者の注意を妨げないように設計する必要があり、スマホやタブレット向けのアプリと異なる開発ガイドラインが設けられています。例えば、遅延時間について「ボタンは2秒以内に反応する」「アプリは10秒以内に起動する」「アプリのコンテンツは10秒以内に読み込まれる」といった条件が定められています。

これらアプリを最終的にビルドに含めるにはdevice/のmakefileで設定します。今回のプロジェクトでは、device/brcm/rpi4_car/rpi4_car.mkpackages/services/Car/car_product/build/car.mkを継承して設定を適用しています。

# device/brcm/rpi4_car/rpi4_car.mk line 112
$(call inherit-product, packages/services/Car/car_product/build/car.mk)
# packages/services/Car/car_product/build/car.mk line 122
PRODUCT_PACKAGES += \
    CarFrameworkPackageStubs \
    CarService \
    CarShell \
    CarDialerApp \
    CarRadioApp \
    OverviewApp \
    CarLauncher \
    CarSystemUI \
    LocalMediaPlayer \
    CarMediaApp \
    CarMessengerApp \
    CarHTMLViewer \
    CarHvacApp \
    CarMapsPlaceholder \
    CarLatinIME \
    CarSettings \
    CarUsbHandler \
    android.car \
    car-frameworks-service \
    com.android.car.procfsinspector \
    libcar-framework-service-jni \
    ScriptExecutor

System ServicesとVehicle HAL

次に、上図のCar API, CarService, VHAL(Vehicle Abstraction Layer)について確認してみましょう。これらは、アプリが車両情報を用いる場合に必要になります。以下では例としてHVACで運転席のエアコン温度を設定する場合を考えてみます。
HVAC Set temperature
HVACにおける通信

まず、HVACアプリのボタンでエアコン温度を設定すると、Car APIを使用してリクエストがCar Serviceに送られます。Car Serviceはリクエストを受け取ると、パーミッションやリクエストが妥当かを検証し承認します。例えば、走行中においてドア開閉のリクエストを受け取ったときは、リクエスト通りに実行すると危険なので拒否します。Car Serviceはリクエストを承認したらVHALを通じてECUに信号を送ります。VHALはCar Serviceから受け取った信号を車両プロトコル(CAN, LIN, FlexRayなど)を用いてECU(Electronic Control Unit)に伝達し、ECUがエアコン温度を変更します。変更が完了すると、ECUはVHALに車両プロトコルで信号を送ります。VHALはこの信号を適切な形式に変換し、Car Serviceに送ります。最終的に、Car ServiceからCar APIを通じてHVACアプリに変更が反映されます。

独自のAndroid Automotive OSを開発するためには?

ここまでの内容から、AAOSは自動車特有の要件や機能を追加したAndroid OSであり、AOSPの枠組みで開発されていることが確認できたかと思います。AOSPで車載アプリやVHALの参照実装、Car APIやCar Serviceが提供されているため、OEMはユーザー体験に注力して独自のAAOS開発を行うことができます。それでは、OEMが独自のAAOSを開発するためには何が必要でしょうか。大きく以下の3つに分けて考えることができるでしょう。

  1. OEM Apps

    ユーザー体験を考え、OEM独自のアプリを開発します。一般にAAOS搭載の市販車は、LauncherやHVAC、設定アプリを作り込んでいます。スマホ向けのAndroidアプリと同様にJava, Kotlin, Unityなどを用いて開発ができます。

  2. HAL (VHAL)

    車両ハードウェアに合わせてHALを実装し、OEM Appsが車両と連携できるようにします。通常はCやC++で実装されます。

  3. Device Configuration

    車載ハードウェアに合わせてWi-FiやBluetoothなどのデバイス設定ファイルを作成します。例えば、今回題材としたプロジェクトではdevice/rpi4_car/overlay/でRaspberryPi 4Bのデバイス設定の一部を行っています。

おわりに

本記事ではAAOSを概説し、実機でAAOS 13.0を体験しました。さらに、AAOSのアーキテクチャを見ながら主なコンポーネントの役割を理解し、独自のAAOSを開発に必要な3項目を整理しました。自動車特有の要件はありますが、AAOSの開発はスマホ(Android OS)開発と同等であり、Linux OSやAndroidアプリの開発知識を活かすことができます。

筆者が所属するTuring UX Engineeringチームでは独自のAAOSを開発しており、開発メンバーを募集しています。車載OS、音声認識、ナビゲーションなどIVIシステムの開発に興味がある方はぜひ、弊社求人一覧およびWantedlyをご覧ください。ソフトウェアの力でユーザ体験を向上させ、優しさと格好よさを兼ね備えた自動運転EVを作っていきましょう。
https://www.turing-motors.com/news/20230519

Tech Blog - Turing

Discussion

monakamonaka
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r35 --depth=1

手元環境で追試したところ、lunch コマンドの実行時にビルドエラーが発生し先に進めませんでした。
fork 元の raspberry-vanilla での更新に従って android-13.0.0_r52 を使用したところ、ビルドが走り出しました。ご参考まで。