ククログ

株式会社クリアコード > ククログ > AOSPエミュレーターイメージのカスタマイズ

AOSPエミュレーターイメージのカスタマイズ

弊社では組み込み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

参考:

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 OpenSSHAndroid用レシピを組み込む手順を紹介します。

既存のレシピがあればそれをマニフェストへと追加する

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を選択する
  • デバイスプロファイルTabletMidium Tabletを選択する(必要に応じて適切なものに変更)
  • 以下を選択すると、追加したイメージが表示される
    • API: API 34 "UpsideDownCake"; Android 14.0
    • Service: 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エミュレーターイメージのカスタマイズ方法について説明しました。

家電製品や、機械の制御パネルなどで多く使われる組み込み機器向けのソフトウェア開発に関して、ニーズに合わせた設計、開発、サポートなども提供しています。 詳しくは組み込み機器ソフトウェア開発 をご覧いただき、お問い合わせフォームよりお気軽にお問い合わせください。