Android 10 では、ルート ファイル システムが ramdisk.img
に含まれなくなった代わりに、system.img
にマージされています(BOARD_BUILD_SYSTEM_ROOT_IMAGE
が設定されているかのように、system.img
が常に作成されます)。Android 10 を搭載したデバイスでは、以下を行う必要があります。
- system-as-root パーティション レイアウトを使用します(ビルドにより自動的に適用され、この動作を変更するオプションはありません)。
- RAM ディスクを使用する必要があります。これは dm-linear では必須です。
BOARD_BUILD_SYSTEM_ROOT_IMAGE
をfalse
に設定する必要があります。 この設定は、RAM ディスクを使用するデバイスと使用しないデバイス(つまり、代わりにsystem.img
マウントを直接使用するデバイス)を区別する目的にのみ使用されます。
system-as-root 構成の意味は、Android 9 と Android 10 で異なります。Android 9 の system-as-root 構成では、BOARD_BUILD_SYSTEM_ROOT_IMAGE
は true
に設定されています。これにより、ビルドはルート ファイル システムを system.img
にマージし、system.img
をルート ファイル システム(rootfs)としてマウントします。この構成は、Android 9 でリリースするデバイスでは必須ですが、Android 9 にアップグレードするデバイスと、以前のバージョンの Android を実行しているデバイスでは任意です。Android 10 の system-as-root 構成では、ビルドは常に $TARGET_SYSTEM_OUT
と $TARGET_ROOT_OUT
を system.img
にマージします。この構成は、Android 10 を実行するすべてのデバイスのデフォルトの動作です。
Android 10 では、無線(OTA)アップデートによるパーティションの作成、サイズ変更、破棄を可能にするユーザー空間パーティショニング システムである動的パーティションをサポートするために、さらに変更が加えられています。この変更の一環として、Linux カーネルは Android 10 を実行するデバイスで論理システム パーティションをマウントできなくなったため、この操作は第 1 ステージの init で処理されます。
以下のセクションでは、システム専用 OTA の system-as-root 要件について説明し、デバイスをアップデートして system-as-root を使用できるようにするためのガイダンスを提供します(パーティション レイアウトの変更、dm-verity カーネルの要件を含む)。また、Android 10 における RAM ディスクへの変更の詳細について説明します。
システム専用 OTA について
システム専用 OTA を使用すると、Android のリリースで他のパーティションを変更せずに system.img
と product.img
をアップデートできますが、それには system-as-root パーティション レイアウトが必要です。Android 10 を実行するすべてのデバイスで、system-as-root パーティション レイアウトを使用してシステム専用 OTA を有効にする必要があります。
- A/B デバイスでは
system
パーティションを rootfs としてマウントしていますが、すでに system-as-root を使用しているため、システム OTA をサポートするための変更は必要ありません。 - 非 A/B デバイスでは
system
パーティションを/system
にマウントしていますが、システム OTA をサポートするには system-as-root パーティション レイアウトを使用するようにアップデートする必要があります。
A/B デバイスと非 A/B デバイスの詳細については、A/B(シームレス)システム アップデートをご覧ください。
ベンダー オーバーレイの使用
ベンダー オーバーレイを使用すると、デバイスの起動時に vendor
パーティションに変更をオーバーレイできます。ベンダー オーバーレイは、デバイスの起動時に vendor
パーティションにオーバーレイされるベンダー モジュールのセットで、product
パーティションにあり、既存のモジュールに置き換わって追加されます。
デバイスが起動すると、init
プロセスは第 1 ステージのマウントを完了し、デフォルトのプロパティを読み取ります。次に、/product/vendor_overlay/<target_vendor_version>
を検索し、以下の条件に一致する場合、対応する vendor
パーティション ディレクトリに各サブディレクトリをマウントします。
/vendor/<overlay_dir>
が存在する。/product/vendor_overlay/<target_vendor_version>/<overlay_dir>
に/vendor/<overlay_dir>
と同じファイル コンテキストがある。init
が/vendor/<overlay_dir>
のファイル コンテキストにマウントすることを許可されている。
ベンダー オーバーレイの実装
ベンダー オーバーレイ ファイルを /product/vendor_overlay/<target_vendor_version>
にインストールします。これらのファイルは、デバイスの起動時に vendor
パーティションにオーバーレイし、同じ名前のファイルを置き換えて新しいファイルを追加します。ベンダー オーバーレイは、vendor
パーティションからファイルを削除することはできません。
ベンダー オーバーレイ ファイルには、vendor
パーティションで置き換えるターゲット ファイルと同じファイル コンテキストが存在する必要があります。デフォルトでは、/product/vendor_overlay/<target_vendor_version>
ディレクトリのファイルには vendor_file
コンテキストが存在します。ベンダー オーバーレイ ファイルと置き換えるファイルのファイル コンテキストに不一致がある場合は、デバイス固有の sepolicy でファイル コンテキストを指定します。ファイル コンテキストはディレクトリ レベルで設定されます。ベンダー オーバーレイ ディレクトリのファイル コンテキストがターゲット ディレクトリと一致せず、デバイス固有の sepolicy で適切なファイル コンテキストが指定されていない場合、そのベンダーのオーバーレイ ディレクトリはターゲット ディレクトリにオーバーレイされません。
ベンダー オーバーレイを使用するには、カーネルで CONFIG_OVERLAY_FS=y
を設定して OverlayFS を有効にする必要があります。また、カーネルを共通のカーネル 4.4 以降からマージするか、"overlayfs:
override_creds=off option bypass creator_cred"
を使用してパッチを当てる必要があります。
ベンダー オーバーレイの実装例
次の手順は、/vendor/lib/*
、/vendor/etc/*
、/vendor/app/*
の各ディレクトリをオーバーレイするベンダー オーバーレイの実装を示しています。
-
プレビルドされたベンダー ファイルを
device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/
に追加します。device/google/device/vendor_overlay/28/lib/libfoo.so device/google/device/vendor_overlay/28/lib/libbar.so device/google/device/vendor_overlay/28/etc/baz.xml device/google/device/vendor_overlay/28/app/qux.apk
-
プレビルドされたベンダー ファイルを
device/google/device/device.mk
のproduct/vendor_overlay
にインストールします。PRODUCT_COPY_FILES += \ $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
-
ターゲットの
vendor
パーティション ファイルにvendor_file
以外のコンテキストが存在する場合、ファイル コンテキストを定義します。/vendor/lib/*
はvendor_file
コンテキストを使用するため、この例にはそのディレクトリは含まれていません。device/google/device-sepolicy/private/file_contexts
に以下を追加します。/(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)? u:object_r:vendor_configs_file:s0 /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)? u:object_r:vendor_app_file:s0
-
init
プロセスが、ベンダー オーバーレイをvendor_file
以外のファイル コンテキストにマウントすることを許可します。init
プロセスにはすでにvendor_file
コンテキストにマウントする権限があるため、この例ではvendor_file
のポリシーを定義しません。device/google/device-sepolicy/public/init.te
に以下を追加します。allow init vendor_configs_file:dir mounton; allow init vendor_app_file:dir mounton;
ベンダー オーバーレイの検証
ベンダーのオーバーレイ構成を検証するには、/product/vendor_overlay/<target_vendor_version>/<overlay_dir>
にファイルを追加し、ファイルが /vendor/<overlay_dir>
のファイルにオーバーレイされているかどうかを確認します。
userdebug
ビルドの場合、Atest のテスト モジュールがあります。
$ atest -v fs_mgr_vendor_overlay_test
system-as-root のアップデート
system-as-root を使用するように非 A/B デバイスをアップデートするには、boot.img
と system.img
のパーティショニング スキームをアップデートし、dm-verity を設定し、デバイス固有のルートフォルダへのブート依存関係を削除します。
パーティションのアップデート
/boot
をリカバリ パーティションとして再利用する A/B デバイスとは異なり、非 A/B デバイスにはフォールバック パーティションがないため、/recovery
パーティションを分離しておく必要があります(たとえば boot_a
から boot_b
)。/recovery
が非 A/B デバイスで削除され、A/B スキームと同様にされた場合、/boot
パーティションのアップデートが失敗している間にリカバリモードが中断する可能性があります。そのため非 A/B デバイスでは、/recovery
パーティションは必ず /boot
から分離されたパーティションである必要があります。これは、リカバリ イメージが引き続き遅れてアップデートされることを意味します(Android 8.1.0 以前を実行しているデバイスと同じ)。
次の表に、Android 9 以前と以降の非 A/B デバイスのイメージ パーティションの違いを示します。
イメージ | RAM ディスク(9 より前) | system-as-root(9 以降) |
---|---|---|
boot.img |
カーネルと ramdisk.img が含まれます。
ramdisk.img -/ - init.rc - init - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... |
通常のブートカーネルのみが含まれます。 |
recovery.img |
リカバリ カーネルとリカバリ ramdisk.img が含まれます。 |
|
system.img |
以下のものが含まれます。
system.img -/ - bin/ - etc - vendor -> /vendor - ... |
元の system.img と ramdisk.img のマージされたコンテンツが含まれます。
system.img -/ - init.rc - init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... |
パーティション自体は変更されません。RAM ディスクと system-as-root は次のパーティション スキームを使用します。
/boot
/system
/system
/recovery
/vendor
など
dm-verity の設定
system-as-root では、カーネルは dm-verity を使用して、/
(マウント ポイント)の下に system.img
をマウントする必要があります。AOSP は、system.img
用に次の dm-verity 実装をサポートしています。
vboot 1.0
vboot 1.0 の場合、カーネルは /system
上の Android 固有のメタデータを解析し、dm-verity パラメータに変換して、dm-verity を設定する必要があります(これらのカーネルパッチが必要)。
次の例は、カーネル コマンドラインの system-as-root 用の、dm-verity 関連の設定を示しています。
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="system none ro,0 1 android-verity /dev/sda34" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f
vboot 2.0
vboot 2.0(AVB)の場合、ブートローダーは external/avb/libavb を統合し、/system
のハッシュツリー記述子を解析し、dm-verity パラメータに変換し、最後にカーネル コマンドラインを介してパラメータをカーネルに渡す必要があります(/system
のハッシュツリー記述子は、/vbmeta
または /system
それ自体に存在する可能性があります)。
vboot 2.0 には、次のカーネルパッチが必要です。
次の例は、カーネル コマンドラインの system-as-root 用の、dm-verity 関連の設定を示しています。
ro root=/dev/dm-0 rootwait skip_initramfs init=/init dm="1 vroot none ro 1,0 5159992 verity 1 PARTUUID=00000016-0000-0000-0000-000000000000 PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999 sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2 8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks 650080 fec_start 650080"
デバイス固有のルートフォルダを使用する
system-as-root を使用すると、汎用システム イメージ(GSI)がデバイス上でフラッシュされた後(ベンダー テストスイート テストを実行する前)、ルート ディレクトリのコンテンツ全体が system-as-root GSI に置き換えられるため、BOARD_ROOT_EXTRA_FOLDERS
を使用して追加されたデバイス固有のルートフォルダはすべて削除されます。これらのフォルダが削除されることで、デバイス固有のルートフォルダへの依存が存在する場合、デバイスが起動できなくなる場合があります(マウント ポイントとして使用されている場合など)。
この問題を回避するには、デバイス固有のルートフォルダを追加する際に BOARD_ROOT_EXTRA_FOLDERS
を使用しないようにします。デバイス固有のマウント ポイントを指定する必要がある場合は、/mnt/vendor/<mount point>
を使用します(これらの変更リストに追加されています)。これらのベンダー固有のマウント ポイントは、fstab
デバイスツリー(第 1 ステージのマウントの場合)と /vendor/etc/fstab.{ro.hardware}
ファイルで追加設定なしで直接指定できます(fs_mgr
が /mnt/vendor/*
の下に自動的に作成するため)。
RAM ディスク
Android 10 では、第 1 ステージの RAM ディスクには、第 1 ステージの init バイナリ(fstab エントリで指定された初期マウントを実行)と、ベンダーの fstab ファイルが含まれています(Android 9 と同様に、system.img
には $TARGET_ROOT_OUT
の内容が含まれています)。
- 起動 RAM ディスク(非 A/B)を備えたデバイスの場合、第 1 ステージの init は、
/init
にある静的な実行可能ファイルです。これらのデバイスは、system.img
を/system
としてマウントしてから、ルート切り替え操作を実行して/system
のマウントを/
に移動します。マウントが完了すると、RAM ディスクの内容は解放されます。 - リカバリを RAM ディスクとして使用するデバイスの場合、第 1 ステージの init はリカバリ用の RAM ディスク内の
/init
にあります。これらのデバイスは、最初にルートを/first_stage_ramdisk
に切り替えてリカバリ コンポーネントを環境から削除します。次に、起動 RAM ディスクを備えたデバイスと同じ手順を実行します(system.img
を/system
としてマウントし、ルートを切り替えてそのマウントを/
に移動し、マウント後に RAM ディスクの内容を解放します)。androidboot.force_normal_boot=1
がカーネル コマンドラインに存在する場合、デバイスはリカバリモードではなく、通常どおり(Android で)起動します。
第 1 ステージの init が終了すると、selinux_setup
引数を指定して /system/bin/init
を実行し、SELinux をコンパイルしてシステムにロードします。最後に、init は second_stage
引数を指定して /system/bin/init
をもう一度実行します。この時点で、init のメインフェーズにより、init.rc
スクリプトを使用して起動プロセスが実行および続行されます。
パーティション レイアウト(非 A/B デバイス)
以降のセクションでは、Android 10 以前と以降の非 A/B デバイスの、パーティション レイアウトの違いについて説明します。
boot.img
RAM ディスク (Android 8.x 以前) |
System as root (Android 9) |
RAM ディスク (Android 10) |
---|---|---|
カーネルと ramdisk.img -/ - init.rc - init - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... |
通常のブートカーネルのみが含まれます。 | カーネルと ramdisk.img -/ - init - vendor fstab files - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... |
recovery.img
リカバリ カーネルとリカバリ ramdisk.img
が含まれます。
system.img
RAM ディスク (Android 8.x 以前) |
System as root (Android 9) |
RAM ディスク (Android 10) |
---|---|---|
system.img -/ - bin/ - etc - vendor -> /vendor - ... |
system.img -/ - init.rc - init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... |
system.img -/ - init.rc - init -> /system/bin/init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ... |
パーティション レイアウト(A/B デバイス)
以降のセクションでは、Android 10 以前と以降の A/B デバイスの、パーティション レイアウトの違いについて説明します。
boot.img
System as root (Android 9) |
RAM ディスク (Android 10) |
---|---|
通常のブートカーネルとリカバリ用 RAM ディスク(BOARD_USES_RECOVERY_AS_BOOT := true )が含まれます。リカバリ用 RAM ディスクは、リカバリを起動する場合にのみ使用します。 |
通常のブートカーネルとリカバリ用 RAM ディスク(BOARD_USES_RECOVERY_AS_BOOT := true )が含まれます。リカバリ用 RAM ディスクは、リカバリと Android の両方で起動します。 ramdisk.img -/ - init -> /system/bin/init - first_stage_ramdisk - vendor fstab files - etc -> /system/etc - system/ (mount point) - vendor/ (mount point) - odm/ (mount point) ... |
system.img
$TARGET_SYSTEM_OUT
と $TARGET_ROOT_OUT
のマージされたコンテンツが含まれます。
system.img -/ - init.rc - init -> /system/bin/init - etc -> /system/etc - system/ - bin/ - etc/ - vendor -> /vendor - ... - vendor/ (mount point) - odm/ (mount point) ...