Ubuntu24.04を使ってAndroid Automotive OS15をGoogle Pixel Tablet(2023)に書き込む

# これは何
Androidはスマートフォン向けのOSだけではなく、例えばTV向けのビルドバリアントや、自動車のダッシュボード搭載向けのビルドバリアントがあります。

後者の自動車向けのビルドバリアントはAndroid Automotive OSと呼ばれています。 https://source.android.com/docs/automotive 

note: Android AutoとAndroid Automotive OSは別物です！Android AutoというのはAndroidスマホの画面をミラーリングできる機能を搭載していることを示します。Android Automotive OSはAndroidOSが乗っていることを示します。

じゃあAndroid Automotive OSっていうのはどんな感じなのか実機で試すとき、ちょっとお試しで車を買うのは大変なので、お試し用に市販のタブレットにAndroid Automotive OS を書き込むことができます。

Google Pixel Tablet(2023)が2025年現在、もっとも入手性が良いと思います。 https://developer.android.com/training/cars/testing/aaos-on-pixel
（他にはRaspberry Pi4B以降も広く使われています https://github.com/raspberry-vanilla/android_local_manifest ）

この文章は現時点で最新のAndroid Automotive OS15をGoogle Pixel Tablet(Tangorproというコードネームがついています)に書き込む手順を示します。
メモとして書いておくと `aosp_tangorpro_car-bp1a-userdebug` が今回のゴールです。

# 準備する物
- 4コア以上（できれば16コア以上）で、16GB以上（できれば64GB以上）のメモリを積んだ x64対応アーキテクチャのPC 
- ディスクの↑空き容量が400GBくらい必要です
- Ubuntu24.04 
- Google Pixel Tablet

# Pixel TabletのBootloader Unlock
 開発者設定を有効にした後
 
 Settings > System > Developer
 で**OEM unlocking**を有効にしておいてください。
 

# Ubuntuの準備
Dockerを使うことも可能ですが、素朴に新規PCを立ち上げてUbuntu24.04をインストールした、という想定で書きます。(なんらかの余っているPCを使う、というシチュエーションを想定しています）

## Android OS ビルドに必要なライブラリのインストール
### 必要なパッケージ
Ubuntu 24.04だとapt-getではなくてaptなことに注意しましょう。
```bash
sudo apt update && sudo apt install curl git gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386  x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig
```
### ncurses5
Ubuntu24.04 で Android Automotive OS のビルドを行う場合、Ubuntu24.04では ncurses5 が ncurses6 に置き換わってしまい存在しないためビルドエラーとなる。そこで古いUbuntuのパッケージを取得して手動インストールして解決する
```bash
#libncurses5と依存するlibtinfo5を手動インストールする
curl --output libtinfo5_6.4-4_amd64.deb http://ftp.us.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb
curl --output libncurses5_6.4-4_amd64.deb http://ftp.us.debian.org/debian/pool/main/n/ncurses/libncurses5_6.4-4_amd64.deb
sudo dpkg -i libtinfo5_6.4-4_amd64.deb 
sudo dpkg -i libncurses5_6.4-4_amd64.deb
```

### GitConfig
以下を参考にgitのnameとemailを設定しておきます。(checkout時に未設定では失敗するので)
```bash
git config --global user.name "My Name"
git config --global user.email myname@example.com
```

### Swapのメモリ領域を確保
64GB未満のRAMではAndroidのビルド中に失敗するため、明示的にSwapメモリを64GB確保しておきます。
```bash
sudo swapoff /swapfile
sudo fallocate -l 64G /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```

### Repoのインストール
Android OSのソースコードをチェックアウトするためのRepoをインストールします。
Ubuntu24.04にインストール済みのRepoはバージョンが古いため最新に更新します。

~/bin にrepoをインストールする場合
```bash
cd 
mkdir ~/bin
PATH=~/bin:$PATH 
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
```

### USB接続したAndroid端末を認識するためのudevルール追加
Pixel TabletをPCに繋いでも検出されないことがあります。udevルールファイルを作成して対処します。

https://qiita.com/momoto/items/f90302a07678706ce2f6

新しいudevルールファイルを作成
```bash
sudo vi /etc/udev/rules.d/51-android.rules
```

`/etc/udev/rules.d/51-android.rules`に対してUSBベンダーが18d1(Google製)の端末を検出するように記載
```bash
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="plugdev"
```
ファイルの権限を変更してudevルールを再読み込みする。

```bash
sudo chmod a+r /etc/udev/rules.d/51-android.rules
sudo udevadm control --reload-rules
sudo udevadm trigger
```

このあとにUSBケーブルでPixel TabletをPCに接続して
```bash
lsusb
```
を実行して、認識できていることを確認してください。

### AppArmorの無効化
AOSPビルド時に警告が出るため、一時的に無効化します。
```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
```

<details><summary>元に戻すのはこれです</summary>

`sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=1`
</details>

## AndroidOSのソースコードチェックアウト
自分のホームディレクトリの直下に`aosp`というディレクトリを作って、そこでビルドします。

ディレクトリ作成
```bash
mkdir -p ~/aosp
```

移動
```bash
cd ~/aosp
```

Repoの初期化
```bash
repo init -u https://android.googlesource.com/platform/manifest -b android-15.0.0_r23
```
<details><summary>android-15.0.0_r23をなぜ選んだか</summary>
https://source.android.com/docs/setup/reference/build-numbers ここでPixel Tabletが対象になっているAndroid15系で最新のリビジョンだったためです。 android-15.0.0_r23 と書いてあります。(android-15.0.0_r26ではうまく動かなかった…)
</details>

このとき**Build ID**が**BP1A.250305.020.T2** であることを覚えておいてください。


local-manifestsをまとめてくれているリポジトリから設定を取得
```bash
git clone https://github.com/alexanderwolz/android_device_whaleshark_manifest.git -b android-15 .repo/local_manifests
```

実際のAndroidのソースコードを取得
```bash
repo sync -c -j$(nproc --all)
```

## デバイス固有のドライバを取得
https://developers.google.com/android/drivers?hl=en 

ここからGoogle Pixel TabletのAndroid 15.0.0_r23向けのデバイスドライバをダウンロードします。
先ほどBuild IDとして**BP1A.250305.020.T2**というのを覚えていたので、ページ内を検索してPixel Tablet向けのものをダウンロードします。

```bash
cd ~/Downloads
```

解凍
```bash
tar -xvf google_devices-tangorpro-*.tgz
```
解凍してできた `extract-google_devices-tangorpro.sh`ファイルをhomeのaospにコピー
```bash
cp ~/Downloads/extract-google_devices-tangorpro.sh ~/aosp
```

aospフォルダにGoogle Pixel Tabletドライバの取得
```bash
cd ~/aosp
bash extract-google_devices-tangorpro.sh
```
ここで
`aosp/vendor/google_devices/tangorpro` というフォルダの中にファイルが作られていれば成功です。


## Android Automotive OSのビルド

```bash
cd ~/aosp
```

```bash
source build/envsetup.sh
```

ビルド設定の指定
```bash
lunch whaleshark_tangorpro-bp1a-userdebug
```

OS本体のビルド(１時間から、スペックによっては半日以上かかります）
```bash
m -j$(nproc --all)
```

ハードウェアのスタブ実装のビルド（CAN通信などを持っていない端末なので）
```bash
m -j$(nproc --all) android.hardware.automotive.vehicle@2.0-default-service
```

ここまでが無事完了していると
`~/aosp/out/target/product/tangorpro/` つまり、Home以下の`aosp/out/target`以下に機種名であるtangorproがあり、以下に書き込みイメージができているはずです。

## 実機への書き込み

ここが一番丁寧だとおもいました。Fastboot Modeの写真などものっている！

https://qiita.com/yamakentoc/items/564108cd5ad207193f0e#%E5%AE%9F%E6%A9%9F%E3%81%AB%E3%83%93%E3%83%AB%E3%83%89%E3%81%97%E3%81%9Fandroidos%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B

```bash
cd ~/aosp/out/target/product/tangorpro/
```

```bash
export ANDROID_PRODUCT_OUT=$(pwd)
```

```bash
adb reboot bootloader #再起動
fastboot flashing unlock
fastboot flash bootloader $ANDROID_PRODUCT_OUT/bootloader.img 
fastboot reboot bootloader
fastboot -w flashall #書き込み
```
`adb root` は一時 rootです。
この状態でPixel Tabletが再起動してロゴのまま進まなくなっていると思います。

```bash
adb root
#Temporary disable the userdata checkpoint 
adb wait-for-device root; sleep 3; adb shell vdc checkpoint commitChanges; sleep 2 
#Enable remount
adb remount && sleep 2 && adb reboot && echo "rebooting the device" && adb wait-for-device root && sleep 5 && adb remount
```

Automotive 固有のファイルをデバイスにコピーする
```bash
adb sync vendor && adb reboot
```
これで再起動した後、ロゴのまま進まないという症状は直ります。
（気になる方はブート中に`adb logcat *E`とかでエラーが出ていないか確認しておくといいかも）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40627/c8c0b7f2-17ee-4f43-a990-05815dc594c8.png)


## ADB経由で設定を書き換えて遊んでみよう
解像度のスケーリング変更
```bash
adb root && adb shell wm size 1600x2560 && adb shell wm density 300 && adb reboot
```

位置情報の偽装
```bash
adb unroot && adb shell cmd location set-location-enabled true && adb root && adb shell appops set 0 android:mock_location allow && adb shell cmd location providers add-test-provider gps && adb shell cmd location providers set-test-provider-enabled gps true && adb shell cmd location providers set-test-provider-location gps --location 34.37786100,132.50426700
```

https://developer.android.com/training/cars/testing/aaos-on-pixel#simulate_driving_using_adb 

運転中にするとき(つまり、運転中は危ないのでアプリが操作不能になってほしいですね！)
```bash
adb shell cmd car_service inject-vhal-event 0x11600207 30 -t 2000 \
&& adb shell cmd car_service inject-vhal-event 0x11400400 8 \
&& adb shell cmd car_service inject-vhal-event 0x11200402 false
```

駐車状態にするとき(このときはアプリが操作可能になってほしいですね！）
```bash
adb shell dumpsys car_service inject-vhal-event 0x11600207 0 \
&& adb shell dumpsys car_service inject-vhal-event 0x11400400 4
```

## 参考URL
Ubuntu24.04の環境でAndroid Automotive OSをビルドする
https://qiita.com/rairaii/items/a3fc4fca41d169d8a518

Android Automotive OS で動作する特権アプリ (Privileged App) の開発方法
https://qiita.com/rairaii/items/d00fc16da67b66534853

Repository Collection for Whale Shark AAOS
https://github.com/alexanderwolz/android_device_whaleshark_manifest/tree/android-15

Whale Shark - an AAOS device configuration for Google Pixel Tablet (tangorpro)
https://github.com/alexanderwolz/android_device_whaleshark_tangorpro