ベンダー APEX

APEX ファイル形式を使用して、下位レベルの Android OS モジュールをパッケージ化してインストールできます。これにより、ネイティブ サービスやライブラリ、HAL 実装、ファームウェア、構成ファイルなどのコンポーネントを独立して構築およびインストールできます。

ベンダー APEX は、ビルド システムによって/vendorパーティションに自動的にインストールされ、他のパーティションの APEX と同様に、実行時にapexdによってアクティブ化されます。

ユースケース

ベンダーイメージのモジュール化

APEX は、ベンダー イメージ上の機能実装の自然なバンドル化とモジュール化を促進します。

ベンダー イメージが独立して構築されたベンダー APEX の組み合わせとして構築される場合、デバイス メーカーは、自社のデバイスに必要な特定のベンダー実装を簡単に選択できます。メーカーは、提供された APEX がニーズに合わない場合、またはまったく新しいカスタム ハードウェアを持っている場合に、新しいベンダー APEX を作成することもできます。

たとえば、OEM は、AOSP Wi-Fi 実装 APEX、SoC Bluetooth 実装 APEX、およびカスタム OEM テレフォニー実装 APEX を使用してデバイスを構成することを選択できます。

ベンダー APEX がなければ、ベンダー コンポーネント間の依存関係が非常に多くなる実装では、慎重な調整と追跡が必要になります。機能間通信の任意の時点で、明確に定義されたインターフェイスを使用してすべてのコンポーネント (構成ファイルや追加のライブラリを含む) を APEX にラップすることで、さまざまなコンポーネントが交換可能になります。

開発者の反復

ベンダー APEX は、Wi-Fi HAL などの機能実装全体をベンダー APEX 内にバンドルすることで、開発者がベンダー モジュールを開発する際の反復作業を高速化するのに役立ちます。開発者は、ベンダー イメージ全体を再構築するのではなく、ベンダー APEX を構築して個別にプッシュして変更をテストできます。

これにより、主に 1 つの機能領域で作業し、その機能領域だけを反復処理したい開発者にとって、開発者の反復サイクルが簡素化され、高速化されます。

機能領域を APEX に自然にバンドルすることで、その機能領域の変更の構築、プッシュ、テストのプロセスも簡素化されます。たとえば、APEX を再インストールすると、APEX に含まれるバンドルされたライブラリまたは構成ファイルが自動的に更新されます。

機能領域を APEX にバンドルすると、デバイスの不正な動作が観察された場合のデバッグや元に戻す作業も簡素化されます。たとえば、新しいビルドでテレフォニーの動作が低下している場合、開発者は古いテレフォニー実装 APEX をデバイスにインストールして (完全なビルドをフラッシュする必要はありません)、良好な動作が復元されるかどうかを確認できます。

ワークフローの例:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

基本

デバイス要件、ファイル形式の詳細、インストール手順などの一般的な APEX 情報については、メインのAPEX ファイル形式ページを参照してください。

Android.bpでは、 vendor: trueプロパティを設定すると、APEX モジュールがベンダー APEX になります。

apex {
  ..
  vendor: true,
  ..
}

バイナリと共有ライブラリ

APEX には、安定したインターフェイスがない限り、APEX ペイロード内に推移的な依存関係が含まれます。

ベンダー APEX 依存関係の安定したネイティブ インターフェイスには、 stubs付きのcc_libraryndk_library 、またはllndk_libraryが含まれます。これらの依存関係はパッケージ化から除外され、依存関係は APEX マニフェストに記録されます。マニフェストはlinkerconfigによって処理されるため、実行時に外部のネイティブ依存関係が利用可能になります。

/systemパーティション内の APEX とは異なり、ベンダー APEX は通常、特定の VNDK バージョンに関連付けられています。 VNDK ライブラリはリリース内の ABI の安定性を保証するため、VNDK ライブラリを安定したものとして扱い、 use_vndk_as_stableプロパティを使用して APEX から除外することでベンダー APEX のサイズを削減できます。

以下のスニペットでは、APEX にはバイナリ ( my_service ) とその非安定な依存関係 ( *.soファイル) の両方が含まれます。 my_service libbaseなどの VNDK ライブラリを使用して構築されている場合でも、VNDK ライブラリは含まれません。代わりに、実行時にmy_serviceシステムによって提供される VNDK ライブラリのlibbaseを使用します。

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  binaries: ["my_service"],
  ..
}

以下のスニペットでは、APEX には共有ライブラリmy_standalone_libとその非安定な依存関係 (上記のとおり) が含まれます。

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

HALの実装

HAL 実装を定義するには、次の例のように、ベンダー APEX 内で対応するバイナリとライブラリを提供します。

HAL 実装を完全にカプセル化するには、APEX で関連する VINTF フラグメントと init スクリプトも指定する必要があります。

VINTF フラグメント

VINTF フラグメントは、フラグメントが APEX のetc/vintfにある場合、ベンダー APEX から提供できます。

prebuiltsプロパティを使用して、VINTF フラグメントを APEX に埋め込みます。

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

初期化スクリプト

APEX には、(A) APEX ペイロード内の事前構築済みテキスト ファイル、または (B) /vendor/etc内の通常の init スクリプトの 2 つの方法で init スクリプトを含めることができます。同じ APEX に対して両方を設定できます。

APEX の初期化スクリプト:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

APEX 内の Init スクリプトにはservice定義のみを含めることができます。ベンダー APEX の Init スクリプトには、 on <property>ディレクティブも含めることができます。

ディレクティブon使用する場合は注意してください。 APEX の init スクリプトは APEX がアクティブ化された後に解析されて実行されるため、一部のイベントまたはプロパティは使用できません。 apex.all.ready=trueを使用して、できるだけ早くアクションを起動します。

ファームウェア

例:

次のように、 prebuilt_firmwareモジュール タイプを使用してファームウェアをベンダー APEX に埋め込みます。

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

prebuilt_firmwareモジュールは、APEX の<apex name>/etc/firmwareディレクトリにインストールされます。 ueventd /apex/*/etc/firmwareディレクトリをスキャンしてファームウェア モジュールを見つけます。

APEX のfile_contexts 、ファームウェア ペイロード エントリに適切にラベルを付けて、実行時にueventdがこれらのファイルにアクセスできるようにする必要があります。通常、 vendor_fileラベルで十分です。例えば:

(/.*)? u:object_r:vendor_file:s0

カーネルモジュール

次のように、カーネル モジュールを事前構築モジュールとしてベンダー APEX に埋め込みます。

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

APEX のfile_contextsカーネル モジュール ペイロード エントリに適切にラベルを付ける必要があります。例えば:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

カーネル モジュールは明示的にインストールする必要があります。ベンダー パーティション内の次の init スクリプトの例は、 insmodによるインストールを示しています。

my_init.rc :

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

ランタイムリソースオーバーレイ

例:

rrosプロパティを使用して、ベンダー APEX にランタイム リソース オーバーレイを埋め込みます。

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

その他の設定ファイル

ベンダー APEX は、通常はベンダー APEX 内に事前構築されたものとしてベンダー パーティションに存在する他のさまざまな構成ファイルをサポートしており、さらに多くの構成ファイルが追加されています。

例:

追加の開発機能

起動時のAPEXの選択

例:

開発者は、同じ APEX 名とキーを共有する複数のバージョンのベンダー APEX をインストールし、永続的な sysprops を使用して各起動時にどのバージョンをアクティブ化するかを選択することもできます。特定の開発者のユースケースでは、 adb installを使用して APEX の新しいコピーをインストールするよりも簡単な場合があります。

ユースケースの例:

  • Wi-Fi HAL ベンダー APEX の 3 つのバージョンをインストールします。QAチームは、1 つのバージョンを使用して手動または自動テストを実行し、別のバージョンで再起動してテストを再実行し、最終結果を比較できます。
  • カメラ HAL ベンダー APEX の 2 つのバージョン (現行版実験版) をインストールします。Dogfoodersは、追加のファイルをダウンロードしてインストールすることなく実験版を使用できるため、簡単に元に戻すことができます。

起動中に、 apexd特定の形式に従って sysprops を検索し、適切な APEX バージョンをアクティブ化します。

プロパティ キーの予期される形式は次のとおりです。

  • ブートコンフィグ
    • BoardConfig.mkでデフォルト値を設定するために使用されます。
    • androidboot.vendor.apex.<apex name>
  • 永続的な sysprop
    • すでに起動されているデバイスに設定されているデフォルト値を変更するために使用されます。
    • bootconfig 値が存在する場合は、それをオーバーライドします。
    • persist.vendor.apex.<apex name>

プロパティの値は、アクティブ化する必要がある APEX のファイル名である必要があります。

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

デフォルト バージョンは、 BoardConfig.mkの bootconfig を使用して構成する必要もあります。

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

デバイスが起動したら、永続的な sysprop を設定してアクティブ化されたバージョンを変更します。

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

デバイスがフラッシュ後の bootconfig の更新 ( fastboot oemコマンドなど) をサポートしている場合、マルチインストールされた APEX の bootconfig プロパティを変更すると、起動時にアクティブ化されるバージョンも変更されます。

Cuttlefishに基づく仮想リファレンス デバイスの場合、 --extra_bootconfig_argsコマンドを使用して、起動時に bootconfig プロパティを直接設定できます。例えば:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";

APEX ファイル形式を使用して、下位レベルの Android OS モジュールをパッケージ化してインストールできます。これにより、ネイティブ サービスやライブラリ、HAL 実装、ファームウェア、構成ファイルなどのコンポーネントを独立して構築およびインストールできます。

ベンダー APEX は、ビルド システムによって/vendorパーティションに自動的にインストールされ、他のパーティションの APEX と同様に、実行時にapexdによってアクティブ化されます。

ユースケース

ベンダーイメージのモジュール化

APEX は、ベンダー イメージ上の機能実装の自然なバンドル化とモジュール化を促進します。

ベンダー イメージが独立して構築されたベンダー APEX の組み合わせとして構築される場合、デバイス メーカーは、自社のデバイスに必要な特定のベンダー実装を簡単に選択できます。メーカーは、提供された APEX がニーズに合わない場合、またはまったく新しいカスタム ハードウェアを持っている場合に、新しいベンダー APEX を作成することもできます。

たとえば、OEM は、AOSP Wi-Fi 実装 APEX、SoC Bluetooth 実装 APEX、およびカスタム OEM テレフォニー実装 APEX を使用してデバイスを構成することを選択できます。

ベンダー APEX がなければ、ベンダー コンポーネント間の依存関係が非常に多くなる実装では、慎重な調整と追跡が必要になります。機能間通信の任意の時点で、明確に定義されたインターフェイスを使用してすべてのコンポーネント (構成ファイルや追加のライブラリを含む) を APEX にラップすることで、さまざまなコンポーネントが交換可能になります。

開発者の反復

ベンダー APEX は、Wi-Fi HAL などの機能実装全体をベンダー APEX 内にバンドルすることで、開発者がベンダー モジュールを開発する際の反復作業を高速化するのに役立ちます。開発者は、ベンダー イメージ全体を再構築するのではなく、ベンダー APEX を構築して個別にプッシュして変更をテストできます。

これにより、主に 1 つの機能領域で作業し、その機能領域だけを反復処理したい開発者にとって、開発者の反復サイクルが簡素化され、高速化されます。

機能領域を APEX に自然にバンドルすることで、その機能領域の変更の構築、プッシュ、テストのプロセスも簡素化されます。たとえば、APEX を再インストールすると、APEX に含まれるバンドルされたライブラリまたは構成ファイルが自動的に更新されます。

機能領域を APEX にバンドルすると、デバイスの不正な動作が観察された場合のデバッグや元に戻す作業も簡素化されます。たとえば、新しいビルドでテレフォニーの動作が低下している場合、開発者は古いテレフォニー実装 APEX をデバイスにインストールして (完全なビルドをフラッシュする必要はありません)、良好な動作が復元されるかどうかを確認できます。

ワークフローの例:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

基本

デバイス要件、ファイル形式の詳細、インストール手順などの一般的な APEX 情報については、メインのAPEX ファイル形式ページを参照してください。

Android.bpでは、 vendor: trueプロパティを設定すると、APEX モジュールがベンダー APEX になります。

apex {
  ..
  vendor: true,
  ..
}

バイナリと共有ライブラリ

APEX には、安定したインターフェイスがない限り、APEX ペイロード内に推移的な依存関係が含まれます。

ベンダー APEX 依存関係の安定したネイティブ インターフェイスには、 stubs付きのcc_libraryndk_library 、またはllndk_libraryが含まれます。これらの依存関係はパッケージ化から除外され、依存関係は APEX マニフェストに記録されます。マニフェストはlinkerconfigによって処理されるため、実行時に外部のネイティブ依存関係が利用可能になります。

/systemパーティション内の APEX とは異なり、ベンダー APEX は通常、特定の VNDK バージョンに関連付けられています。 VNDK ライブラリはリリース内の ABI の安定性を保証するため、VNDK ライブラリを安定したものとして扱い、 use_vndk_as_stableプロパティを使用して APEX から除外することでベンダー APEX のサイズを削減できます。

以下のスニペットでは、APEX にはバイナリ ( my_service ) とその非安定な依存関係 ( *.soファイル) の両方が含まれます。 my_service libbaseなどの VNDK ライブラリを使用して構築されている場合でも、VNDK ライブラリは含まれません。代わりに、実行時にmy_serviceシステムによって提供される VNDK ライブラリのlibbaseを使用します。

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  binaries: ["my_service"],
  ..
}

以下のスニペットでは、APEX には共有ライブラリmy_standalone_libとその非安定な依存関係 (上記のとおり) が含まれます。

apex {
  ..
  vendor: true,
  use_vndk_as_stable: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

HALの実装

HAL 実装を定義するには、次の例のように、ベンダー APEX 内で対応するバイナリとライブラリを提供します。

HAL 実装を完全にカプセル化するには、APEX で関連する VINTF フラグメントと init スクリプトも指定する必要があります。

VINTF フラグメント

VINTF フラグメントは、フラグメントが APEX のetc/vintfにある場合、ベンダー APEX から提供できます。

prebuiltsプロパティを使用して、VINTF フラグメントを APEX に埋め込みます。

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

初期化スクリプト

APEX には、(A) APEX ペイロード内の事前構築済みテキスト ファイル、または (B) /vendor/etc内の通常の init スクリプトの 2 つの方法で init スクリプトを含めることができます。同じ APEX に対して両方を設定できます。

APEX の初期化スクリプト:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

APEX 内の Init スクリプトにはservice定義のみを含めることができます。ベンダー APEX の Init スクリプトには、 on <property>ディレクティブも含めることができます。

ディレクティブon使用する場合は注意してください。 APEX の init スクリプトは APEX がアクティブ化された後に解析されて実行されるため、一部のイベントまたはプロパティは使用できません。 apex.all.ready=trueを使用して、できるだけ早くアクションを起動します。

ファームウェア

例:

次のように、 prebuilt_firmwareモジュール タイプを使用してファームウェアをベンダー APEX に埋め込みます。

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

prebuilt_firmwareモジュールは、APEX の<apex name>/etc/firmwareディレクトリにインストールされます。 ueventd /apex/*/etc/firmwareディレクトリをスキャンしてファームウェア モジュールを見つけます。

APEX のfile_contexts 、ファームウェア ペイロード エントリに適切にラベルを付けて、実行時にueventdがこれらのファイルにアクセスできるようにする必要があります。通常、 vendor_fileラベルで十分です。例えば:

(/.*)? u:object_r:vendor_file:s0

カーネルモジュール

次のように、カーネル モジュールを事前構築モジュールとしてベンダー APEX に埋め込みます。

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

APEX のfile_contextsカーネル モジュール ペイロード エントリに適切にラベルを付ける必要があります。例えば:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

カーネル モジュールは明示的にインストールする必要があります。ベンダー パーティション内の次の init スクリプトの例は、 insmodによるインストールを示しています。

my_init.rc :

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

ランタイムリソースオーバーレイ

例:

rrosプロパティを使用して、ベンダー APEX にランタイム リソース オーバーレイを埋め込みます。

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

その他の設定ファイル

ベンダー APEX は、通常はベンダー APEX 内に事前構築されたものとしてベンダー パーティションに存在する他のさまざまな構成ファイルをサポートしており、さらに多くの構成ファイルが追加されています。

例:

追加の開発機能

起動時のAPEXの選択

例:

開発者は、同じ APEX 名とキーを共有する複数のバージョンのベンダー APEX をインストールし、永続的な sysprops を使用して各起動時にどのバージョンをアクティブ化するかを選択することもできます。特定の開発者のユースケースでは、 adb installを使用して APEX の新しいコピーをインストールするよりも簡単な場合があります。

ユースケースの例:

  • Wi-Fi HAL ベンダー APEX の 3 つのバージョンをインストールします。QAチームは、1 つのバージョンを使用して手動または自動テストを実行し、別のバージョンで再起動してテストを再実行し、最終結果を比較できます。
  • カメラ HAL ベンダー APEX の 2 つのバージョン (現行版実験版) をインストールします。Dogfoodersは、追加のファイルをダウンロードしてインストールすることなく実験版を使用できるため、簡単に元に戻すことができます。

起動中に、 apexd特定の形式に従って sysprops を検索し、適切な APEX バージョンをアクティブ化します。

プロパティ キーの予期される形式は次のとおりです。

  • ブートコンフィグ
    • BoardConfig.mkでデフォルト値を設定するために使用されます。
    • androidboot.vendor.apex.<apex name>
  • 永続的な sysprop
    • すでに起動されているデバイスに設定されているデフォルト値を変更するために使用されます。
    • bootconfig 値が存在する場合は、それをオーバーライドします。
    • persist.vendor.apex.<apex name>

プロパティの値は、アクティブ化する必要がある APEX のファイル名である必要があります。

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

デフォルト バージョンは、 BoardConfig.mkの bootconfig を使用して構成する必要もあります。

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

デバイスが起動したら、永続的な sysprop を設定してアクティブ化されたバージョンを変更します。

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

デバイスがフラッシュ後の bootconfig の更新 ( fastboot oemコマンドなど) をサポートしている場合、マルチインストールされた APEX の bootconfig プロパティを変更すると、起動時にアクティブ化されるバージョンも変更されます。

Cuttlefishに基づく仮想リファレンス デバイスの場合、 --extra_bootconfig_argsコマンドを使用して、起動時に bootconfig プロパティを直接設定できます。例えば:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";