Androidのリカバリシステム (Androidのシステムアップデート)

Post on 19-Jul-2015

3.117 views 3 download

Transcript of Androidのリカバリシステム (Androidのシステムアップデート)

Android のリカバリシステム(Android のシステムアップデート )

横浜 Android and モバイル OSプラットフォーム部

第 37 回勉強会

2015/2/22@l_b__

今日の内容

● ABS2012 の Intel Andrew Boie 氏のセッション、“ Android Software Updates” をベースに Android の OTA アップデート / リカバリシステムの解説をします

● Lollipop で の 新 機 能 、 SecureBoot/Block- Oriented OTA についても少々

自己紹介

● Twitter ID:@l_b__ ● PF 部の司会進行役 兼 懇親会手配役 兼 配信

係 兼 雑用係● フレームワーク周りが好物です● BeOS 好きだったのと Java-er なので Be 関係者

が多い ( 多かった )Android に惹かれました● 仕事は某 SIer で Android フレームワーク修正か

らアプリ作成までやっていましたが最近はAndroid やっていません

Android リカバリシステムの概要

OTA アップデートの手順OS ビルド・ OTA ファイル作成

OTA ファイル配布

アップデート更新通知

OTA ファイルダウンロード OTA アップデート アップデート完了

AOSP で対応しているのは?OS ビルド・ OTA ファイル作成

OTA ファイル配布

アップデート更新通知

OTA ファイルダウンロード OTA アップデート アップデート完了

ブロックで書くとOTA ファイル作成

サーバへデプロイ

アップデート存在チェック

OTA ファイルダウンロード

OTA ファイル署名検証

リカバリ再起動

RecoveryConsole起動

OTA ファイル署名検証

OTA ファイル展開

Updater 起動

アップデート適用

再起動し完了

配布側処理 Android

RecoveryConsole

OTA ファイル内Updater

RecoveryOS

赤線枠内がAOSP 対応部分

AOSP 内コンポーネントその1

● Releasetools– Target-files-package(TFP) からデジタル署名さ

れた OTA アップデートファイルを生成するツール– build/tools/releasetools 配下

● Android.os.RecoverySystem API– アップデートファイルの検証・インストールとファクト

リーデータリセットのための Android フレームワーク API

– frameworks/base/core/java/android/os/RecoverySystem.java

AOSP 内コンポーネントその2

● Recovery Console (RC)– Android 内の別ブート環境– システムアップデート処理を起動– ファクトリデータリセットを実行– bootable/recovery 配下

● Updater– アップデートファイル内のアップデートロジックと実

行形式バイナリ– RC から起動され、 Edify と呼ばれる独自スクリプ

トで実行– bootable/recovery 配下

AOSP に無い機能

● アップデートファイル配布サーバ側● システムアップデート更新チェックとダウンロード

処理● 更新の通知 UI

– android.settings.SYSTEM_UPDATE_SETTINGS のインテントを受け付けて設定画面から起動するようにする

リカバリシステムの制限事項

● 再パーティショニングは出来ない– /system が足りなくなったり boot 、 recovery

パーティションが足りなくなっても増やせないので最初に余裕を持った設定をする必要あり

– cache パーティションは system の 2/3程度あれば安全

● 1度に出来るのは 1 アップデート● アップデート中はデバイスの通常使用は出来な

ファイルシステムの設定

Android のパーティションレイアウト

● boot– Linuxカーネルと root ファイルシステムになる

RAM ディスク– init をはじめとした、 /system をマウントし

Android を起動するためのツールが含まれる● system

– 全ての Android のシステムアプリとライブラリを含む

– OTA アップデート時以外は常に Read-only でマウントされる

● ※Lollipop では OTA アップデート時も Read-onlyでマウント (後述 )

Android のパーティションレイアウト

● data– ダウンロードしたアプリ格納– アプリデータ格納– DalvikVM のキャッシュ– OTA アップデートでは何も変更されない– ファクトリデータリセットで消去される

Android のパーティションレイアウト

● recovery– リカバリ OS(互換起動イメージ )格納– RecoveryConsole(RC) の実装をはじめとした

recovery 機能を含む RAM ディスク● misc

– ファイルシステムを含まない非常に小さな領域● Bootloader Control Block(BCB) と呼ばれ、ブ

ロックデバイスとして直接読み書きされる– RC と Bootloader 、カーネル間のやり取りに使わ

れる

Android のパーティションレイアウト

● cache– 一時的なファイル置き場– 特殊な権限 (uid:system) を持つアプリによる一時ストレージやダウンロード領域として使用される

– OTA アップデートファイルもここに置かれる– applypatchが一時ストレージとして使用する– ファクトリデータリセットで消去される

Android Boot イメージ

● メタデータ (boot header) 、カーネルイメージ、 RAM ディスク、 2nd ブートローダー (オプション ) を格納したコンテナファイルフォーマット

● system/core/mkbootimg を使って生成– ファイルフォーマットは

system/core/mkbootimg/bootimg.hで定義– 通常ビルド時と OTA アップデートファイル生成時

に使用される

recovery.fstab

● デバイス上の全ファイルシステムを定義したファイル

– パーティションの定義ではない● RC と Releasetools が使用● デバイスノードのマウントポイントとファイルシステ

ムタイプを記述

Releasetools によるアップデートファイル生成

Targer-Files-Package(TFP)

● 'make target-files-package'で生成– out/target/product/[device]/obj/PACKAGING/target_files_intermediates/ に生成

● OTA アップデートファイル生成に必要な全てが含まれた zip アーカイブ

– フルイメージでのアップデートの場合は TFP は 1つだけ必要

– 差分アップデートの場合は差分の元となる TFP が2 つ必要

Targer-Files-Package(TFP)

● ”radio ファイル”としてデバイス固有 blob を追加可能

– 必ずしも無線に関する機能追加だけではない● bootloader等

– AndroidBoard.mk に以下を追加● $(call add-radio-file,myblob.dat)

– ただ、最近の Nexus デバイスでは使われていないよう

– デバイス向けの Releasetools追加定義で扱う

Android セキュリティ

● 全ての APKは電子署名される– 同じアプリのバージョンアップとして扱われるには同じ証明書で署名される必要がある

– 複数のアプリで同じユーザー ID を共有するのにもそれらのアプリが同じ証明書で署名される必要がある

– LOCAL_CERTIFICATE として定義された証明書を使用。

● デフォルトでは testkey を使用

Android セキュリティ

● AOSP は build/target/product/security に以下の 4つの証明書キーを持っている

– testkey:APK署名のデフォルトキー– platform: コアプラットフォーム署名向け– shared:ホームと連絡先アプリのプロセス間で共有されるプロバイダ向け

– media:メディア / ダウンロードプロバイダ向け

Android セキュリティ

● AOSP のキーでは製品版としては使えない– CTS を含む開発時のみ使用– Releasetools に含まれる

sign_target_files_apks を使って TFP 内のAPKを製品用キーで再署名する必要がある

● RC 内の OTA 検証キーも製品用キーに変換される

ota_from_target_files

● TFP から OTA アップデートファイルを生成するための Python スクリプト

– ota_from_target_files [flags] input_target_files output_ota_package

– (--incremental_from) <file>● 差分アップデート時に差分の元となる TFP を指定

– (--wipe_user_data)● OTA で /data を消去

– (--package_key) <key>● パッケージ署名に使うキーを指定

– デフォルトは testkey

ota_from_target_files

● Python の拡張としてデバイス独自のアップデートタスクを追加可能

● 全てのアップデートに必要なイメージ、 Updater実行バイナリ、アップデート時に使用されるedify スクリプトを含むパッケージを生成

アップデートファイル生成まとめ

Android ビルド

TFP( Test Key使用)

APK 再署名 TFP

差分アップデート元 TFP

アップデートファイル生成

アップデートファイル

make target-files-package

sign_target_files_apksota_from_target_files

差分アップデートファイルの生成場合必要

Releasetools拡張

● Releasetools を拡張するには以下のファンクションを実装した Python モジュールを作成する必要がある

– FullOTA_Assertion()– FullOTA_InstallEnd()– IncrementalOTA_Assertion()– IncrementalOTA_VerifyEnd()– IncrementalOTA_InstallEnd()

● モジュールを置いたパスを BoardConfig.mk にTARGET_RELEASETOOLS_EXTENSIONS として記述する

その他の Releasetools

● img_from_target_files– 'fastboot update' 向けの zip アーカイブを生成

● check_target_files_signature– TFP に含まれるパッケージの署名をチェックする– 差分アップデート用の 2 つの TFP の互換性チェッ

クに使用

RecoverySystem API

RecoverySystem API

● android.os.RecoverySystem としてアプリから使用可能な API

– REBOOT のパーミッションが必要– /cache の読み書き権限も必要なので systemユーザー向け API

● /cache/recovery/command にコマンド (OTAアップデート / ファクトリデータリセット ) 、アップデートファイルパスを書き込み、 OS 再起動後にRecovery Console へ伝える

● アップデートファイルの検証を実行– /system/etc/security/otacerts.zip をデフォル

トでは検証に使用

Recovery Console (RC)

Recovery Console

● リカバリ用の起動イメージ– シェルから’ reboot recovery’で起動– RecoverySystem API から起動– ベンダーが実装するブートローダーからの操作と

して起動● UI は画像ベース、ローカライゼーションにも対応● 手動操作向けの隠しメニュー

– ファクトリデータリセット– SD カードからのアップデート– UI プラグインでデバイス固有の機能追加可能

Recovery Console

● ログは /cache/recovery に保存される– RC と Updater の標準出力・エラーの出力先– Edify の ui_print() コマンド出力先

Recovery Console の制御

● RC 起動時は以下をコマンドライン引数としてチェックする

– recovery コマンドの引数 デバッグ用途のみ– BCB の recovery パラメータ– /cache/recovery/command ファイル

(RecoverySystem API が書き込み )● 起動時に引数を BCB に常に保存

– アップデート中の不意の電源断時に再度ブートローダーがリカバリ OS を起動するようにする

Recovery Console の制御

● finish_recovery()– アップデート、ファクトリデータリセットなど処理が

成功 /失敗に関わらず終了する時に実行– BCB をクリアして Android を起動するようにする– ログを /cache/recovery にコピー

ブートローダーとの調整

● カーネルは reboot() の引数として” recovery” が与えられたら、 BCB のcommand パラメータに” boot-recovery” を書き、 recovery パラメータを 0 クリアする

– ドライバの register_reboot_notifier() で実装する

● ブートローダーは起動イメージを BCB のcommand パラメータで判断する

– RC が command パラメータを消去するまでは RCを起動

– command が消去されていれば通常の Android起動

Recovery Console UI プラグイン

● RC へデバイス固有の拡張を追加可能– BoardConfig.mk の

TARGET_RECOVERY_UI_LIB にライブラリの$(LOCAL_MODULE) を定義する

– bootable/recovery/device.hで定義されるDevice クラスを実装することで独自拡張可能

– device/htc/fugu/recovery以下に実装サンプルあり

Recovery 画面

● GUI は画像ベース● bootable/recovery/ 配下の res-mdpi〜 res-xxxhdpi に標準の画像があり、差し替え可能

– RGB/RGBA フォーマットの 8bit PNG ファイル– ファイル名は同じままにしておく

● bootable/recovery/interlace-frames.py としてアニメーションの作成に使えるスクリプトが準備されている

– ベース画像とオーバーレイする複数フレームを一枚画像にする

Updater

Updater 実行バイナリ

● アップデートファイル内に含まれる– zip ファイルに含まれることで、アップデートの実装

コードが既存に存在している必要が無くなる● 必ずしも AOSP の Updater 実装を使用する必要

はない– RC は Updater を fork()/exec() で実行し、 pipe

で通信する– RC は引数を 3 つ渡す

● Android.mk で定義された RC API バージョン(Android2.2〜 5.0 でバージョン 3)

● pipe のファイルディスクリプタ● アップデート zip ファイルパス

Updater 実行バイナリ

– Updater は画面 ( 進捗表示 )表示制御や文字表示、 cache消去などの文字列コマンドを pipe経由で RC に送信する

● bootable/recovery/install.cpp参照● AOSP 実装Updater はアップデートファイル内の

Edify で記述されたスクリプトを実行する● デバイス固有の Updater 機能はプラグインとし

て実装可能● Updater の中断処理には注意 ! 正しく実装しな

いと文鎮化してしまう

起動からのリカバリ処理

● RC 自体は OTA アップデートの処理中はアップデートされない

– 不意の電源断後も同じ RC が使用されることを確実にするため

● flash_recovery– init.rc の oneshot service として実行– /system/etc/install-recovery.shを実行– recovery イメージの SHA1ハッシュをチェックして

パッチを当てる必要があるか判断– 必要があれば recovery パーティションの起動イメージにパッチを当てる

Applypatch

● 差分アップデート時に /system のファイルとboot イメージにパッチを当てるのに使用

● bootable/recovery/applypatch配下● 差分作成は bsdiff を使用● 安全に (望むタイミングまで元ファイルは touch

されない ) 、冪等に (1 回操作を行っても何度行っても同じ結果になる ) なるよう処理される

Edify スクリプト

● OTA アップデートのためのスクリプト言語● bootable/recovery/edify 配下● 文法など詳細は README ファイル参照● 全ての関数は C で実装、 Edify では関数定義出

来ない● 組み込み関数

は /bootable/recovery/updater/install.cに実装、プラグインとして関数追加可能

Updater プラグイン

● ライブラリとして複数の追加定義が可能– Static ライブラリとして作成– BoardConfig.mk に

TARGET_RECOVERY_UPDATE_LIBS としてライブラリ名を定義

– サンプル実装としてdevice/asus/fugu/recovery を参照

– TARGET_RECOVERY_UPDATE_EXTRA_LIBSとして Static ライブラリのバイナリ ( サポートライブラリ ) を追加定義可能

製品化タスク

● recovery.fstab の定義作成● デバイス独自 blob を” radio ファイル”として

AndroidBoard.mk に追加● RC UI プラグイン実装

– リカバリ時の画像を必要なら差し替え● Updater プラグイン実装

製品化タスク

● Releasetools拡張実装– OTA アップデートファイルへの RADIO イメージの追加・パッチのロジックを追加

– イメージを扱う Edify コマンドの Updater スクリプトへの追加

– 必要ならアサーション・ベリフィケーション処理を追加

● BoardConfig.mk にプラグイン、拡張、サポートライブラリの定義を追加

● 設定アプリから IntentFilter で OTA アップデートファイルダウンロード処理を呼べるようを実装

製品化タスク

● ブートローダーとカーネルで BCB を介してやり取りできるよう実装

● 製品用証明書キー生成● Android フレームワー

ク、 build/core 、 bootable/recovery は変更の必要なし

● 良い継続的なテストを計画しましょう

Lollipop での新機能

Secureboot

● 読み取り専用パーティションの整合性を保証する機能が Lollipop から有効化

– Linuxカーネルの DM-Verity を使用– パーティションを 4k バイトブロックに分け、各ブロッ

クのハッシュ値からハッシュツリーを生成

DM-Verity

● パーティションへの書き込み要求がある毎にカーネルモジュールがブロック単位でハッシュをチェック、不整合が発生したら I/Oエラーを返すことでパーティションを保護

● /system と /vendor に適用されている● system/extras/verity にユーティリティが追加● 詳細はhttps://source.android.com/devices/tech/security/secureboot/index.html

リカバリシステムへの影響

● リカバリ OS はファイルシステム経由で /systemを書き換える

– →DM-Verity が有効だと書き換えにより不整合が発生

– →文鎮化● 解決方法としてブロック指向の OTA(block-

oriented OTAs) を導入

ブロック指向OTA

● ファイルの差分ではなくブロックの差分を使用● ファイルシステムを介さず、ブロックデバイスを直接書き換える (MTD デバイスなら MTD サブシステム経由 )

● ファイルシステムを介さない分処理も高速化● リカバリ OS でも /system は Read-only としてマ

ウントされるようになり、書き込み直前にアンマウントされるよう変更されている

参考資料

● Android Builders Summit 2012 ”Android* Software Updates”

– https://events.linuxfoundation.org/images/stories/pdf/lf_abs12_boie.pdf

– http://free-electrons.com/blog/abs-2012-videos/

● Android Open Source Project “Android Core Technologies Secure Boot”

– https://source.android.com/devices/tech/security/secureboot/index.html

● Androidソースコード検索サービス

– https://sites.google.com/site/devcollaboration/codesearch