0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AOSP カスタムビルドを Cuttlefish で起動する

0
Posted at

はじめに

AOSP のビルドが完了したあとに、取り急ぎ仮想環境で動作確認したいと思いました。
Emulator または Cuttlefish で起動できますが、Cuttlefish のほうが軽快らしいので Cuttlefish にチャレンジしました。

ただ、公式ドキュメントは微妙に情報が足りず、少々難儀しました。

  • Get Started ページは ci.android.com のビルド成果物を前提にしています。今回はローカルでビルドしたものを使いたいケースです。
  • カスタム デバイスを作成する ページは、独自にビルドをカスタマイズしたときの記述です。今回は既存の cuttlefish ターゲットをそのまま使いたかったです。

この記事では、ローカルでビルドした AOSP(aosp_cf_x86_64_tv-trunk_staging-userdebug)を Cuttlefish で起動するまでにハマったところと、その解消法を紹介します。

前提

  • 環境
    • Ubuntu 24.04
    • CPU: Intel Core i5-12400(VT-x 対応)
    • メモリ: 64GB
  • AOSP のビルド(aosp_cf_x86_64_tv-trunk_staging-userdebug)が完了していること
    • 他の Cuttlefish ターゲットでも同様の方法で起動できるはずなので、適宜読み替えてください

結論

最終的には、こんな感じの流れでCuttlefishを起動できました:

AOSP=/path/to/aosp-project

# 1. HOME として使う作業ディレクトリを作り、cvd-host_package を展開
mkdir -p /tmp/cvd_home
cp -r $AOSP/out/host/linux-x86/cvd-host_package/. /tmp/cvd_home/

# 2. assemble_cvd が参照する ~/etc/cvd_config を実ファイルで配置
#    (シンボリックリンクだと動かないので注意)
mkdir -p /tmp/cvd_home/etc/cvd_config
cp $AOSP/out/host/linux-x86/cvd-host_package/etc/cvd_config/*.json \
   /tmp/cvd_home/etc/cvd_config/

# 3. GPU アクセラレーション用のバイナリを配置
mkdir -p /tmp/cvd_home/bin/x86_64-linux-gnu
cp $AOSP/out/host/linux-x86/bin/x86_64-linux-gnu/gfxstream_graphics_detector \
   /tmp/cvd_home/bin/x86_64-linux-gnu/

# 4. 起動
cd /tmp/cvd_home
HOME=/tmp/cvd_home ./bin/launch_cvd \
  --config=tv \
  --daemon \
  --system_image_dir=$AOSP/out/target/product/vsoc_x86_64 \
  --x_res=1920 --y_res=1080 --dpi=320

以降のセクションは、このコマンドに辿り着くまでに潰した問題の記録です。

Step 1: Cuttlefish ホスト環境のセットアップ

Cuttlefish を動かすには、ホスト側に cuttlefish-base / cuttlefish-user という deb パッケージが必要です。
公式の Get Startedにも書いてありますが、これらは android-cuttlefish リポジトリをクローンして自前でビルドします。

sudo apt install -y git devscripts equivs config-package-dev debhelper-compat golang curl
git clone https://github.com/google/android-cuttlefish
cd android-cuttlefish
tools/buildutils/build_packages.sh
sudo dpkg -i ./cuttlefish-base_*_*64.deb || sudo apt-get install -f
sudo dpkg -i ./cuttlefish-user_*_*64.deb || sudo apt-get install -f
sudo usermod -aG kvm,cvdnetwork,render $USER
sudo reboot

これらのパッケージが提供するもの

  • capability_query.py(KVM / vhost-net / vhost-vsock の利用可否判定スクリプト)
  • /dev/vhost-vsock の udev ルール
  • cvdnetwork グループ(TAP インターフェース作成用)

reboot は必須

ユーザーのグループ反映、カーネルモジュールの読み込み、udev ルールの反映のために reboot が必要です。
これをスキップすると後続の起動ステップでエラーになります。

Step 2: launch_cvd してみる → エラー

ホスト環境が整ったら、launch_cvd で起動を試みます。
以下、実際に踏んだ罠を時系列で並べていきます。


罠1: cuttlefish-base の deb パッケージビルドに失敗していた

症状

tools/buildutils/build_packages.sh 実行時、次のようなエラーで失敗します。

Removing cuttlefish-common-build-deps:amd64 because I can't find bazel:amd64
mk-build-deps: Unable to install cuttlefish-common-build-deps at /usr/bin/mk-build-deps line 460.
mk-build-deps: Unable to install all build-dep packages

原因

恥ずかしながら気づいていませんでしたが、前段で cuttlefish-base のインストールが失敗していたことが原因でした。
cuttlefish-common-build-depsbazel に依存していますが、bazel は Ubuntu 標準の apt リポジトリには含まれていません。
しかも、公式の Get started ページに bazel のインストール手順は記載されていません。

対処

Google 公式 APT リポジトリから bazel をインストールします:

sudo apt install -y apt-transport-https curl gnupg
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel-archive-keyring.gpg
sudo mv bazel-archive-keyring.gpg /usr/share/keyrings/
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" \
  | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt install -y bazel

その後、tools/buildutils/build_packages.sh を再実行すると、エラーが解消されました。

関連して出るエラー(こちらで気づくケース)

cuttlefish-base のインストールが中途半端なまま launch_cvd を実行すると、次のエラーで起動失敗します:

sh: 1: /usr/lib/cuttlefish-common/bin/capability_query.py: not found
VM manager crosvm is not supported on this machine.
Invalid vm_manager: crosvm

capability_query.pycuttlefish-base パッケージが提供するファイルです。
このエラーが出たら、上記のパッケージビルド&インストールが完了しているか確認してください。


罠2: bootloader ファイルが見つからない

症状

crosvm E: exiting with error 1: failed to open bios ./out/target/product/vsoc_x86_64/bootloader
crosvm E: Caused by: No such file or directory (os error 2)
VIRTUAL_DEVICE_BOOT_FAILED

原因

bootloader ファイルは存在しているのに、crosvm から見えていません。
相対パスで --system_image_dir を指定したため、crosvm の作業ディレクトリからの相対パス解決に失敗しています。

対処

--system_image_dir 引数に絶対パスを指定することで、解消しました。

./bin/launch_cvd \
  --system_image_dir=$(pwd)/out/target/product/vsoc_x86_64 \
  ...

罠3: /dev/vhost-vsock Permission denied

症状

crosvm E: failed to set up virtual socket device
crosvm E: failed to open virtual socket device /dev/vhost-vsock
crosvm E: Permission denied (os error 13)

同時に TAP デバイスのエラーも出ます:

network.cpp: Unable to connect to cvd-wifiap-01 tap interface: Operation not permitted
crosvm_builder.cpp: Unable to connect to "cvd-wifiap-01": Bad file descriptor

原因

cuttlefish-base の udev ルールとグループ権限が反映されていません。つまり reboot していません。

対処

公式のサンプルにも記載されている通り、再起動が必要です。
再起動すると、その他のカーネル モジュールのインストールがトリガーされ、udev のルールが適用されます。(引用元

sudo reboot

罠4: Could not read from dir "/home/$USER/etc/cvd_config"

※ 以下、$USER と記載した部分は、実際にはユーザー名が入っていました。

症状

Could not read from dir "/home/$USER/etc/cvd_config"
zsh: IOT instruction (core dumped) ./bin/launch_cvd ...

原因

assemble_cvd$HOME/etc/cvd_config を参照しますが、ディレクトリが存在しません。

対処

$HOME/etc/cvd_config にディレクトリを作成します(中身は次の罠で配置します)。
後述の HOME=/tmp/cvd_home 方式を使う場合は:

mkdir -p /tmp/cvd_home/etc/cvd_config

罠5: invalid config preset: 'tv'phone にフォールバック

症状

config_flag.cpp: /path/to/android-info.txt contains invalid config preset: 'tv'.
config_flag.cpp: Launching CVD using --config='phone'.
Could not read config file "/home/$USER/etc/cvd_config/cvd_config_phone.json"

原因

~/etc/cvd_config/cvd_config_tv.json / cvd_config_phone.json が配置されていません。
AOSP のビルド成果物には含まれているので、そこから配置すればよいです。

対処

cvd-host_package 内の config ファイルを $HOME/etc/cvd_config/コピーします:

mkdir -p /tmp/cvd_home/etc/cvd_config
cp $AOSP/out/host/linux-x86/cvd-host_package/etc/cvd_config/*.json \
   /tmp/cvd_home/etc/cvd_config/
ls /tmp/cvd_home/etc/cvd_config/
# cvd_config_auto.json  cvd_config_phone.json  cvd_config_tv.json  ...

ハマりポイント:シンボリックリンクでは動かない

最初、ディレクトリごとシンボリックリンクにしてみましたが、assemble_cvd が config ファイルを読み込めず同じエラーが再発しました。
実ファイルとしてコピーするのが確実です。

(補足:既存ディレクトリに対して ln -sf ... dir/ を実行すると、既存ディレクトリの中にリンクが入って dir/dir という二重構造になる罠もあります。これもコピーにすれば回避できます。)


罠6: extract-ikconfig/home/$USER/bin/ を参照する

症状

Started (pid: xxxxx): /home/$USER/bin/extract-ikconfig
exec of /home/$USER/bin/extract-ikconfig failed (No such file or directory)
Failed to extract ikconfig from .../boot.img

~/bin/ は存在しないし、PATH にも入っていないのに、なぜか assemble_cvd はそこを見に行きます。

原因

assemble_cvd$HOME/bin/ 以下のヘルパーツールを探す設計になっています。
つまり、cvd-host_package を展開したディレクトリを HOME として認識させる必要があります。

対処

公式ドキュメントの HOME=$PWD 方式を使います:

cd $AOSP/out/host/linux-x86/cvd-host_package
HOME=$PWD ./bin/launch_cvd ...

公式 Get started ページに HOME=$PWD ./bin/launch_cvd --daemon と書いてある意味がここで腑に落ちました。
単なるおまじないではなく、assemble_cvd のパス解決の中核になっているわけです。


罠7: Unix socket のパス長超過 (namelen=121 > 108)

症状

Check failed: namelen <= sizeof(dest->sun_path) (namelen=121, sizeof(dest->sun_path)=108)
MakeAddress failed. Name=/media/$USER/.../cuttlefish/instances/cvd-1/internal/rotary.sock is longer than allowed.

原因

Linux の Unix domain socket のパスは 108 文字制限があります。
AOSP のビルドパスが深い(外付けストレージにマウントしていると特に)と、HOME=$PWD にした際に各種ソケットパスが 108 文字を超えてしまいます。

対処

HOME を短いパスに変えます。cvd-host_package/tmp 以下にコピーするのが簡単です:

mkdir -p /tmp/cvd_home
cp -r $AOSP/out/host/linux-x86/cvd-host_package/. /tmp/cvd_home/

cd /tmp/cvd_home
HOME=/tmp/cvd_home ./bin/launch_cvd ...

罠8: GPU アクセラレーションが効かない

症状

起動はしますが、描画が重いです。ログを見ると:

exec of .../bin/x86_64-linux-gnu/gfxstream_graphics_detector failed (No such file or directory)
Failed to get graphics availability ... Assuming none.
GPU auto mode: did not detect prerequisites for accelerated rendering support, enabling --gpu_mode=guest_swiftshader.

swiftshader(ソフトウェアレンダリング)にフォールバックしています。

原因

gfxstream_graphics_detector バイナリが $HOME/bin/x86_64-linux-gnu/ 配下にありません。
/tmp/cvd_homecvd-host_package をコピーした時にサブディレクトリが漏れている可能性があります。
あるいは、AOSP の out/host/linux-x86/bin/x86_64-linux-gnu/ にあって、cvd-host_package 側には含まれていないケースもあります。

対処

AOSP のビルド成果物から /tmp/cvd_home/bin/x86_64-linux-gnu/ に配置します:

mkdir -p /tmp/cvd_home/bin/x86_64-linux-gnu
cp $AOSP/out/host/linux-x86/bin/x86_64-linux-gnu/gfxstream_graphics_detector \
   /tmp/cvd_home/bin/x86_64-linux-gnu/

再起動すると、ログが次のように変わります:

GPU auto mode: detected prerequisites for accelerated rendering support.
Enabling --gpu_mode=gfxstream.

体感でレイテンシが明らかに改善します。


動作確認

WebRTC 経由で操作

ブラウザで https://localhost:8443 を開きます。
自己署名証明書の警告は「詳細設定」→「アクセスする」で進めます。

adb で接続

./bin/adb devices
# 0.0.0.0:6520   device

TV ターゲットの DPAD 操作

画面右側のコントロールパネルに DPAD ボタンがあります。キーボードショートカットも使えます:

キー 動作
↑↓←→ DPAD 上下左右
Enter DPAD 中央(決定)

WebUI の画面をクリックしてフォーカスを合わせてから操作してください。

停止

cd /tmp/cvd_home
HOME=/tmp/cvd_home ./bin/stop_cvd

まとめ

公式ドキュメントは、前提を満たせば素直に通る内容になっています。
ですが、前提のうち bazel のインストールHOME=$PWD の意図については明示されていないため、自前ビルドで始めると詰まります。

自前ビルドで詰まる本質的な理由をまとめると:

  • assemble_cvd$HOME/bin/$HOME/etc/cvd_config/ を参照する設計になっている
  • つまり、cvd-host_package を展開したディレクトリを HOME として認識させる必要がある
  • ビルドパスが深いと、HOME=$PWD ではソケットパス制限(108 文字)に当たる
  • GPU アクセラレーションには gfxstream_graphics_detector が別途必要

HOME=$PWD ./bin/launch_cvd」という公式のワンライナーは、おまじないではなくパス解決の核心だった、というのが一番の学びでした。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?