弊社では組み込みLinux機器向けのソフトウェア開発案件を承っておりますが、その一環でAOSP(Android Open Source Project)のカスタマイズについても実績があります。
今回は、社内向け備忘録の意味も込めて、AOSPエミュレーターイメージのカスタマイズ方法について説明します。
ビルド環境の用意
まず、AOSPビルド用のOSを用意します。UbuntuのLTS版を使用するのが無難です。
参考: https://source.android.com/docs/setup/start/requirements
Ubuntu 24.04 LTS等の環境を用意し、以下コマンドにてビルド用のツールチェーンをインストールします。
$ sudo apt update
$ sudo apt install git-core gnupg flex bison build-essential zip curl zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig repo
AOSPエミュレーターイメージのビルド
最初に、ベースとなるAOSPのエミュレーターイメージをビルドします。
AOSP 14をビルドするコマンド実行例を以下に示します。
$ mkdir ~/aosp14
$ cd ~/aosp14
$ repo init --partial-clone --no-use-superproject -b android-14.0.0_r67 -u https://android.googlesource.com/platform/manifest
$ repo sync
$ source build/envsetup.sh
$ lunch sdk_tablet_x86_64-ap2a-userdebug
$ m
$ m emu_img_zip
エミュレーターイメージは以下に生成されます。
$ ls out/target/product/emu64x/sdk-repo-linux-system-images.zip
out/target/product/emu64x/sdk-repo-linux-system-images.zip
以下コマンドでエミュレーターを起動することができます。
$ emulator
参考:
- https://source.android.com/docs/setup/download
- https://source.android.com/docs/setup/build/building
- https://source.android.com/docs/setup/reference/build-numbers#source-code-tags-and-builds
- https://source.android.com/docs/setup/test/avd
AOSP用Linuxカーネルのビルド
AOSPのビルド時にはLinuxカーネルはプレビルドのものが使用されるため、カーネルをカスタマイズしたい場合は別途リビルドする必要があります。 最新のAOSP 14のビルドではAOSP 15用のLinuxカーネル6.6が使用されていますので、以下手順ではAOSP 15用のカーネルをビルドしています。
カーネルをビルドするためのコマンド実行例を以下に示します。
$ mkdir ~/aosp15-kernel
$ cd ~/aosp15-kernel
$ repo init -u https://android.googlesource.com/kernel/manifest -b common-android15-6.6
$ repo sync
$ tools/bazel run //common:kernel_x86_64_dist
$ tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist
カーネル本体およびエミュレーター用カーネルモジュールは以下に生成されます。
$ ls out/kernel_x86_64/dist/
6lowpan.ko
8021q.ko
...
bzImage
...
$ ls out/virtual_device_x86_64/dist/
System.map
boot-img.tar.gz
boot.img
btintel.ko
...
カーネルコンフィグを追加したい場合は、例えばcommon/およびcommon-modules/に以下のパッチを適用し、
project common/
diff --git a/BUILD.bazel b/BUILD.bazel
index 187540edc355..844b0db131bd 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -197,6 +197,7 @@ define_common_kernels(target_configs = {
"kmi_symbol_list_strict_mode": False,
"module_implicit_outs": get_gki_modules_list("x86_64") + get_kunit_modules_list("x86_64"),
"make_goals": _GKI_X86_64_MAKE_GOALS,
+ "defconfig_fragments": ["arch/x86/configs/myconfig.fragment"],
"extra_dist": [
":test_mappings_zip",
":tests_zip_x86_64",
project common-modules/virtual-device/
diff --git a/build.config.virtual_device.x86_64 b/build.config.virtual_device.x86_64
index 8942aab..5561e7c 100644
--- a/build.config.virtual_device.x86_64
+++ b/build.config.virtual_device.x86_64
@@ -12,6 +12,7 @@ PRE_DEFCONFIG_CMDS="mkdir -p \${OUT_DIR}/arch/x86/configs/ && \
KCONFIG_CONFIG=\${OUT_DIR}/arch/x86/configs/${DEFCONFIG} \
${ROOT_DIR}/${KERNEL_DIR}/scripts/kconfig/merge_config.sh -m -r \
${ROOT_DIR}/${KERNEL_DIR}/arch/x86/configs/gki_defconfig \
+ ${ROOT_DIR}/${KERNEL_DIR}/arch/x86/configs/myconfig.fragment \
${ROOT_DIR}/common-modules/virtual-device/virtual_device_core.fragment \
${ROOT_DIR}/common-modules/virtual-device/virtual_device.fragment && \
true"
common/arch/x86/configs/myconfig.fragment に設定を加えてビルドし直します。
common/arch/x86/configs/myconfig.fragmentの例:
CONFIG_PID_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_PIDS=y
CONFIG_BRIDGE_NETFILTER=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_IPVS=y
CONFIG_POSIX_MQUEUE=y
CONFIG_CGROUP_PERF=y
CONFIG_NET_CLS_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_IP_VS=y
CONFIG_IP_VS_NFCT=y
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
参考:
AOSPイメージのカーネル差し替え
AOSPのプレビルドカーネルは、AOSPビルドディレクト内の以下のパスに配置されています。
- kernel/prebuilts/6.6/x86_64/
- kernel/prebuilts/common-modules/virtual-device/6.6/x86-64/
上記ディレクトリ下のファイルを差し替えてイメージをビルドし直すことで、エミュレーターイメージ内のカーネルを差し替えることができます。ただし、それぞれのファイルを正しいパスに配置するための手順が公開されているか、現時点では把握することができていません。以下、弊社にて行った手順をスクリプト化したものを参考として示します。
#!/bin/bash
KERNEL_FEATURE_VERSION=6.6
KERNEL_ARCH=x86_64
KERNEL_OUT_DIR=~/aosp15-kernel/out
PREBUILT_KERNEL_DIR=~/aosp14/kernel/prebuilts
KERNEL_DIST_DIR=${KERNEL_OUT_DIR}/kernel_${KERNEL_ARCH}/dist
VIRTUAL_DEVICE_DIST_DIR=${KERNEL_OUT_DIR}/virtual_device_${KERNEL_ARCH}/dist/
PREBUILT_KERNEL_DEST_DIR=${PREBUILT_KERNEL_DIR}/${KERNEL_FEATURE_VERSION}/${KERNEL_ARCH}
PREBUILT_VIRTUAL_DEVICE_DEST_DIR=${PREBUILT_KERNEL_DIR}/common-modules/virtual-device/${KERNEL_FEATURE_VERSION}/$(echo ${KERNEL_ARCH} | sed -e "s/_/-/")
if test -d "${PREBUILT_KERNEL_DEST_DIR}-orig"; then
rm -rf "${PREBUILT_KERNEL_DEST_DIR}"
else
mv "${PREBUILT_KERNEL_DEST_DIR}" "${PREBUILT_KERNEL_DEST_DIR}-orig"
fi
if test -d "${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}-orig"; then
rm -rf "${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}"
else
mv "${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}" "${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}-orig"
fi
mkdir -p ${PREBUILT_KERNEL_DEST_DIR}/system_dlkm_staging
install --mode=664 ${KERNEL_DIST_DIR}/bzImage ${PREBUILT_KERNEL_DEST_DIR}/kernel-${KERNEL_FEATURE_VERSION}
install --mode=664 ${KERNEL_DIST_DIR}/System.map ${PREBUILT_KERNEL_DEST_DIR}/
install --mode=664 ${KERNEL_DIST_DIR}/*.ko ${PREBUILT_KERNEL_DEST_DIR}/
tar xf ${KERNEL_DIST_DIR}/system_dlkm_staging_archive.tar.gz -C ${PREBUILT_KERNEL_DEST_DIR}/system_dlkm_staging
mkdir -p ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}
install --mode=664 ${VIRTUAL_DEVICE_DIST_DIR}/*.ko ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/
install --mode=664 ${VIRTUAL_DEVICE_DIST_DIR}/initramfs.img ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/
mv ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/cfg80211.ko ${PREBUILT_KERNEL_DEST_DIR}/
mv ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/mac80211.ko ${PREBUILT_KERNEL_DEST_DIR}/
mv ${PREBUILT_KERNEL_DEST_DIR}/virtio_*.ko ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/
mv ${PREBUILT_KERNEL_DEST_DIR}/vmw_vsock_virtio_transport.ko ${PREBUILT_VIRTUAL_DEVICE_DEST_DIR}/
また、既定ではビルドされないモジュールを参照している箇所があったため、以下の修正も必要でした。
project device/generic/goldfish/
diff --git a/board/kernel/x86_64.mk b/board/kernel/x86_64.mk
index e07f0bab..13982048 100644
--- a/board/kernel/x86_64.mk
+++ b/board/kernel/x86_64.mk
@@ -32,9 +32,8 @@ RAMDISK_KERNEL_MODULES := \
virtio_pci_legacy_dev.ko \
virtio_pci_modern_dev.ko \
virtio-rng.ko \
- vmw_vsock_virtio_transport_common.ko \
vmw_vsock_virtio_transport.ko \
- vsock.ko \
BOARD_SYSTEM_KERNEL_MODULES := $(wildcard $(KERNEL_ARTIFACTS_PATH)/*.ko)
ソフトウェアの追加例
AOSPイメージに独自にソフトウェアを追加する場合の例を紹介します。
ソフトウェアを組み込む場合、おおむね次のような手順で行います。
- 既存のリポジトリがあればそれをrepoマニフェストに追加する
- 追加したマニフェストをもとにソースコードを同期する
- 追加したソフトウェアにAndroid.mkあるいはAndroid.bpがなければ追加する
- デバイスの定義ファイルに組み込むパッケージを明示する
今回は説明を簡単にするため、LineageOSプロジェクトが提供しているPortable OpenSSHのAndroid用レシピを組み込む手順を紹介します。
既存のレシピがあればそれをマニフェストへと追加する
LineageOSプロジェクトが提供するPortable OpenSSHのリポジトリをrepoマニフェストに追加するには、.repo/local_manifests/に以下のような内容のファイルを追加します。
.repo/local_manifests/manifest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="github" fetch="https://github.com/" />
<project path="external/openssh" name="LineageOS/android_external_openssh" remote="github" revision="lineage-22.2" />
</manifest>
追加したマニフェストをもとにソースコードを同期する
repoコマンドを実行してソースコードを同期します。
$ repo sync
追加したソフトウェアにAndroid.mkがなければ追加する
今回組み込む対象のLineageOSプロジェクトのPortable OpenSSHリポジトリにはすでにAndroid.bpが含まれているので不要ですが、Androidへの組み込みに対応していないソフトウェアの場合、Android.mkないしAndroid.bpを追加します。
デバイスの定義ファイルに組み込むパッケージを明示する
リポジトリの用意ができたら、デバイスに組み込むためにデバイス定義ファイルを修正します。
今回の例では、デバイス定義ファイルはdevice/generic/goldfish/64bitonly/product/sdk_tablet_x86_64.mkです。
# OpenSSH
PRODUCT_PACKAGES += \
libssh \
ssh \
sftp \
scp \
sshd \
ssh-keygen \
sshd_config \
start-ssh
PRODUCT_PACKAGESに何を指定したら良いかは、組み込む対象のAndroid.bp等のレシピによって異なります。
今回の場合は、Portable OpenSSHのレシピでcc_binary等として定義されているものを指定する必要がありました。
ここまでできたら、あとは手順に従って起動イメージをビルドすればOpenSSHがイメージに組み込まれます。
ビルドしたイメージのAndroid Studioでの利用
上記でビルドしたAOSPイメージはAndroid Studioのエミュレーターで利用可能です。 以下、GNU/Linux版のAndroid Studioを使用する場合の利用手順を示します。
- Android Studioをインストールする
~/Android/Sdk/system-images/android-34/を作成してエミュレーターイメージのzipファイルを展開するDevice Managerから+ボタン(Add a new device)を押下するCreate Virtual Deviceを選択する- デバイスプロファイル
Tablet→Midium Tabletを選択する(必要に応じて適切なものに変更) - 以下を選択すると、追加したイメージが表示される
API:API 34 "UpsideDownCake"; Android 14.0Service:Android Open Source
- 同イメージを選択して
Finishを押下する - Android Studioの
Device Managerで同デバイスを起動する- あるいは以下コマンドで実行することもできる
$ ~/Android/Sdk/emulator/emulator -list-avds Automotive_1408p_landscape_with_Google_Play Medium_Phone_API_36 Medium_Tablet New_Device $ ~/Android/Sdk/emulator/emulator -avd Medium_Tablet
- あるいは以下コマンドで実行することもできる
さいごに
クリアコードでは組み込み機器ソフトウェア開発事業の一環として、お客様からのご依頼でのAOSPのカスタマイズについても実績があります。今回はAOSPエミュレーターイメージのカスタマイズ方法について説明しました。
家電製品や、機械の制御パネルなどで多く使われる組み込み機器向けのソフトウェア開発に関して、ニーズに合わせた設計、開発、サポートなども提供しています。 詳しくは組み込み機器ソフトウェア開発 をご覧いただき、お問い合わせフォームよりお気軽にお問い合わせください。