Android 10 では、ユーザーデータ チェックポイント(UDC)が導入され、Android 無線(OTA)アップデートが失敗したときに以前の状態にロールバックできるようになりました。UDC を使用している場合、Android OTA アップデートが失敗すると、デバイスは以前の状態に安全にロールバックできます。この問題は A/B アップデートによりアーリーブートについては解決されていますが、ユーザーデータ パーティション(/data
にマウントされています)が変更された場合のロールバックはサポートされていません。
UDC により、デバイスはユーザーデータ パーティションが変更された後でも復元できます。UDC 機能がこれを実現する仕組みを支えているのは、ファイル システムに対するチェックポイント機能、ファイル システムがチェックポイントをサポートしていない場合の代替実装、ブートローダー A/B メカニズムの統合(非 A/B アップデートにも対応)、鍵バージョンのバインディングおよび鍵のロールバック防止のサポートです。
ユーザーへの影響
UDC 機能により、OTA アップデートが失敗してもユーザーがデータを失うことが少なくなるので、OTA アップデートの利便性が向上します。これにより、アップデート プロセス中に問題が発生したユーザーからのサポート依頼の電話を減らすことができます。ただし、OTA アップデートが失敗したとき、デバイスが何度も再起動されることにユーザーが気づく可能性があります。
仕組み
各種のファイル システムにおけるチェックポイント機能
F2FS ファイル システムの場合、UDC はアップストリームの 4.20 Linux カーネルにチェックポイント機能を追加し、Android 10 を搭載したデバイスでサポートされるすべての一般的なカーネルにバックポートします。
他のファイル システムでは、UDC は dm_bow
と呼ばれるデバイス マッパー仮想デバイスを使用してチェックポイント機能を提供します。dm_bow
は、デバイスとファイル システムの間で動作します。パーティションがマウントされると trim が発行され、それによりファイル システムはすべての空きブロックで trim コマンドを発行するようになります。dm_bow
は trim コマンドをインターセプトし、それを使用して空きブロックリストを設定します。読み取りと書き込みは変更されずにデバイスに送信されますが、書き込みが許可される前に、復元に必要なデータが空きブロックにバックアップされます。
チェックポイント処理
checkpoint=fs/block
フラグの付いたパーティションがマウントされると、Android はそのドライブ上で restoreCheckpoint
を呼び出して、デバイスが現在のチェックポイントを復元できるようにします。次に、init
が needsCheckpoint
関数を呼び出し、デバイスがブートローダー A/B 状態にあるか、アップデートの再試行回数が設定されているかを判定します。いずれかが true の場合、Android は createCheckpoint
を呼び出してマウントフラグを追加するか、dm_bow
デバイスをビルドします。
パーティションのマウントが完了すると、trim を発行するためにチェックポイント コードが呼び出されます。その後、起動プロセスが通常どおり続行されます。LOCKED_BOOT_COMPLETE
の際は、Android が commitCheckpoint
を呼び出して現在のチェックポイントを commit します。アップデートは通常どおり続行されます。
Keymaster キーを管理する
Keymaster キーはデバイスの暗号化などに使用されます。これらのキーを管理するため、チェックポイントが commit されるまで Android はキー削除呼び出しを遅延させます。
正常性をモニタリングする
ヘルスデーモンは、チェックポイントを作成するために十分なディスク容量があるかどうかを確認します。ヘルスデーモンは Checkpoint.cpp
内の cp_healthDaemon
にあります。
ヘルスデーモンには、次のような動作を設定できます。
ro.sys.cp_msleeptime
: デバイスがディスク使用量をチェックする頻度を制御します。ro.sys.cp_min_free_bytes
: ヘルスデーモンが検索する最小値を制御します。ro.sys.cp_commit_on_full
: ディスクがいっぱいになったときに、ヘルスデーモンがデバイスを再起動するか、チェックポイントを commit して続行するかを制御します。
チェックポイント API
チェックポイント API は UDC 機能で使用されます。UDC で使用されるその他の API については、IVold.aidl
をご覧ください。
void startCheckpoint(int retry)
チェックポイントを作成します。
フレームワークは、アップデートを開始する準備が整うと、このメソッドを呼び出します。チェックポイントは、再起動後にユーザーデータなどのチェックポイント付きファイル システムが R/W マウントされる前に、作成されます。retry の数値が正の場合、API は再試行回数のトラッキングを処理し、アップデータは needsRollback
を呼び出してアップデートのロールバックが必要かどうかを確認します。retry の数値が -1
の場合、API は A/B ブートローダーの判断に従います。
このメソッドは、通常の A/B アップデートを実行するときは呼び出されません。
void commitChanges()
変更を commit します。
変更が commit 可能になると、フレームワークは再起動後にこのメソッドを呼び出します。このメソッドは、画像、動画、SMS、サーバー受信などのデータがユーザーデータに書き込まれる前、および BootComplete
の前に呼び出されます。
有効なチェックポイント付きアップデートが存在しない場合、このメソッドは効力がありません。
abortChanges()
強制的に再起動し、チェックポイントに戻ります。最初の再起動以降に行われた、ユーザーデータのすべての変更を破棄します。
フレームワークは、再起動の後、commitChanges
の前にこのメソッドを呼び出します。このメソッドが呼び出されると、retry_counter
が減ります。ログエントリが生成されます。
bool needsRollback()
ロールバックが必要かどうかを判断します。
チェックポイントがないデバイスでは、false
を返します。チェックポイントがあるデバイスでは、チェックポイントがない起動の場合に true
を返します。
UDC を実装する
リファレンス実装
UDC を実装する方法の例については、dm-bow.c をご覧ください。この機能の詳細については、dm-bow.txt をご覧ください。
セットアップ
init.hardware.rc
ファイルの on fs
では次のようにしてください。
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early
init.hardware.rc
ファイルの on late-fs
では次のようにしてください。
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
fstab.hardware
ファイルでは /data
に latemount
のタグが付くようにしてください。
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs
メタデータ パーティションを追加する
UDC には、非ブートローダーの再試行回数とキーを格納するメタデータ パーティションが必要です。メタデータ パーティションを設定して、/metadata
に早期マウントします。
fstab.hardware
ファイルで、/metadata
に earlymount
または first_stage_mount
のタグを付けてください。
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
パーティションをすべてゼロに初期化します。
BoardConfig.mk
に、次の行を追加します。
BOARD_USES_METADATA_PARTITION := true BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata
システムを更新する
F2FS システム
データをフォーマットするために F2FS を使用しているシステムでは、F2FS のバージョンがチェックポイントに対応していることを確認してください。詳細については、各種のファイル システムにおけるチェックポイント機能をご覧ください。
/data
にマウントされているデバイスに対して、fstab の <fs_mgr_flags>
セクションに checkpoint=fs
フラグを追加します。
F2FS 以外のシステム
F2FS 以外のシステムでは、dm-bow
がカーネル構成で有効になっている必要があります。
/data
にマウントされているデバイスに対して、fstab の <fs_mgr_flags>
セクションに checkpoint=block
フラグを追加します。
ログを確認する
チェックポイント API が呼び出されると、ログエントリが生成されます。
検証
UDC の実装をテストするには、VTS テストの VtsKernelCheckpointTest
セットを実施します。