Tuesday, March 5, 2024

Androidカスタムの核心:AOSPビルドからFastboot実装まで

Androidは、今日の世界で最も普及しているモバイルオペレーティングシステムですが、その真の力はオープンソースであるという点にあります。Android Open Source Project (AOSP) は、開発者、愛好家、そしてメーカーがAndroidの根幹に触れ、独自のバージョンを構築し、デバイスの可能性を最大限に引き出すことを可能にする基盤です。このカスタマイズと開発のプロセスにおいて、fastboot というツールは、AOSPでビルドされたソフトウェアと物理的なデバイスとを繋ぐ、不可欠な橋渡しの役割を果たします。

この記事では、AOSPの概念的な理解から、実際のビルド環境の構築、イメージの生成、そしてfastbootプロトコルを用いたデバイスへのフラッシュに至るまで、その全工程を詳細に解説します。これは単なるコマンドの羅列ではなく、各ステップの背後にある「なぜ」を理解し、トラブルシューティング能力を養い、最終的にはAndroidシステムの深層を理解するための一助となることを目的としています。

第1章 AOSP:Androidの魂と設計図

AOSPを理解することは、Android開発の第一歩です。多くのユーザーが日常的に触れるAndroidは、Googleのサービスや各メーカー独自のカスタマイズが施されたものであり、氷山の一角に過ぎません。その水面下には、巨大で強力なオープンソースの基盤、AOSPが存在します。

AOSPとは何か?その哲学と構造

AOSP (Android Open Source Project) は、Googleが主導するAndroidプラットフォームのオープンソース開発プロジェクトです。そのソースコードは、Apache License 2.0の下で公開されており、誰でも自由に閲覧、変更、再配布することが可能です。このオープン性が、Androidエコシステムの爆発的な成長と多様性を支える原動力となっています。

AOSPの哲学は、単一の企業による中央集権的な管理を避け、イノベーションを促進するための共通のプラットフォームを提供することにあります。これにより、無数のメーカーが独自のハードウェア上で動作するAndroidデバイスを開発でき、開発者はOSレベルでのカスタマイズや新しい機能の実験を行うことができます。

AOSPのソースツリー構造

AOSPのソースコードは、何百ものGitリポジトリの集合体であり、その全体構造を理解することは、ビルドやカスタマイズの際に極めて重要です。主要なディレクトリとその役割を以下に示します。

  • build/: ビルドシステムの中核。Android OS全体をコンパイルするためのMakefileやスクリプトが含まれています。envsetup.shsoongビルドシステム関連のファイルもここにあります。
  • frameworks/: Androidアプリケーションフレームワークの心臓部。Activity Manager、Window Manager、Package Managerなどのシステムサービスや、アプリケーションが使用するAPI(android.*パッケージ)が定義されています。
  • system/: Androidの基本的なシステムコンポーネント。コアライブラリ、ネイティブサービス、システムのユーザーインターフェースなどが含まれます。
  • bionic/: Android独自のCライブラリ。Linuxカーネルとユーザー空間の間のインターフェースを提供します。
  • art/: Androidランタイム(ART)。アプリケーションのDalvikバイトコードを実行する仮想マシンです。JIT (Just-In-Time) および AOT (Ahead-Of-Time) コンパイルを担当します。
  • kernel/: Linuxカーネルのソースコード。AOSPは特定のカーネルバージョンを直接含んでいるわけではなく、通常はデバイス固有のカーネルソースを別途取得して使用します。
  • device/: デバイス固有の構成ファイルが含まれるディレクトリ。特定のスマートフォンやタブレット(例:Pixelシリーズ)向けのビルド設定、ドライバ、カーネルのプリビルドなどが格納されています。カスタムROM開発では、このディレクトリに新しいデバイスのサポートを追加することが最初のステップとなります。
  • vendor/: ベンダー固有のプロプライエタリなライブラリやバイナリ(ハードウェア抽象化レイヤー、HAL)が格納されます。これらは多くの場合、クローズドソースであり、デバイスのハードウェアを動作させるために不可欠です。Project Treble以降、このディレクトリの重要性はさらに増しています。
  • packages/: システムアプリケーション(電話、連絡先、設定など)や壁紙、入力メソッドなどが含まれます。

AOSPと市販Androidの違い:GMSの役割

AOSPをビルドしてデバイスにインストールすると、多くのユーザーが「Androidらしくない」と感じるかもしれません。その理由は、Googleマップ、Gmail、PlayストアといったおなじみのGoogleアプリが存在しないためです。これらのアプリケーションと関連サービスは、Google Mobile Services (GMS) と呼ばれるプロプライエタリなパッケージであり、AOSPには含まれていません。

GMSを利用するには、デバイスメーカーがGoogleとのライセンス契約(MADA: Mobile Application Distribution Agreement)を締結し、互換性テストスイート(CTS: Compatibility Test Suite)に合格する必要があります。純粋なAOSPは、これらのサービスを含まない、オープンソースのみで構成された「骨格」としてのAndroidなのです。

第2章 AOSPビルド環境の構築

理論を学んだ後は、実践に移ります。AOSPをビルドするには、強力なハードウェアと適切に構成されたLinux環境が必要です。この章では、ビルドプロセスのための土台を固めます。

ハードウェアとソフトウェアの要件

AOSPのビルドは、計算資源とストレージを大量に消費するプロセスです。Googleが推奨する最小要件は年々増加しており、快適なビルド体験のためには以下のスペックが望ましいです。

  • OS: Ubuntu 20.04 (Focal Fossa) や 22.04 (Jammy Jellyfish) などの最新LTS版Linuxディストリビューション。macOSもサポートされていますが、Linuxがより一般的です。Windows Subsystem for Linux (WSL) 2も利用可能ですが、パフォーマンスや互換性の問題が発生する可能性があります。
  • CPU: 64ビットのマルチコアプロセッサ。8コア以上が推奨されます。コア数が多いほど、並列ビルド(-jオプション)の恩恵を受けられます。
  • RAM: 最低でも16GBが必要ですが、32GB以上を強く推奨します。RAMが不足すると、ビルド中にシステムがスワップを多用し、著しくパフォーマンスが低下します。
  • ストレージ: 高速なSSDを強く推奨します。ソースコードのチェックアウトだけで100GB以上、ビルド成果物を含めると400GB以上の空き容量が必要になる場合があります。余裕を持って500GB以上の空き容量を確保することが理想的です。

必要なパッケージのインストール

Ubuntu環境を例に、AOSPのビルドに必要なパッケージをインストールします。これらのパッケージには、コンパイラ、ビルドツール、各種ライブラリ、ソースコード管理ツールなどが含まれます。


sudo apt-get update
sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev \
gcc-multilib g++-multilib libc6-dev-i386 libncurses5-dev lib32ncurses5-dev \
x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils \
xsltproc unzip fontconfig

※注:必要なパッケージはAndroidのバージョンによって若干異なる場合があります。常に最新のAOSPドキュメント(source.android.com)を確認してください。

ソースコードの取得:Repoツールの活用

AOSPは数百のGitリポジトリから構成されているため、これらを手動で管理するのは非現実的です。そこで、Googleはrepoというツールを提供しています。repoは、複数のGitリポジトリを一つのプロジェクトとして管理するためのラッパーツールです。

1. Repoツールのインストール

まず、repoツール自体をダウンロードし、実行可能にします。


mkdir -p ~/.bin
PATH=~/.bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+x ~/.bin/repo

2. ソースコードの初期化と同期

次に、AOSPのソースコードを格納するディレクトリを作成し、repo initコマンドで特定バージョンのAOSPリポジトリを初期化します。


# AOSPソースを格納するディレクトリを作成
mkdir aosp
cd aosp

# Gitのユーザー名とメールアドレスを設定 (初回のみ)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

# AOSPリポジトリを初期化
# -u: マニフェストリポジトリのURLを指定
# -b: ブランチを指定 (例: android-13.0.0_r45)
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r45 --depth=1

# --depth=1 は履歴を浅くクローンし、ダウンロードサイズを削減しますが、
# コードの履歴を追いたい場合はこのオプションを外します。

初期化が完了したら、repo syncコマンドで全てのソースコードをダウンロードします。このプロセスはネットワーク速度とサーバーの負荷に依存し、数時間かかることがあります。


# -jオプションで並列ダウンロード数を指定できます (例: -j8)
# -cオプションは現在のブランチのみをダウンロードし、さらにサイズを削減します。
repo sync -c -j8

同期が完了すれば、あなたのローカルマシンにAOSPの完全なコピーが準備できたことになります。これで、ビルドプロセスに進む準備が整いました。

第3章 AOSPイメージのビルドと成果物の理解

ソースコードを手に入れたら、次はいよいよそれをコンパイルし、デバイスで実行可能なイメージファイル群を生成します。このプロセスは一見単純なコマンドの実行に見えますが、その背後では複雑なビルドシステムが動いています。

ビルドプロセスの開始

AOSPのルートディレクトリで、以下のコマンドを順に実行します。

1. ビルド環境の設定

まず、ビルドに必要な環境変数とシェル関数をセットアップするスクリプトを実行します。


source build/envsetup.sh

このコマンドを実行すると、lunch, m, croot, godirといった便利なヘルパー関数が現在のシェルセッションで利用可能になります。

2. ビルドターゲットの選択:lunch

次に、lunchコマンドを使用して、どのデバイスの、どの種類のビルドを行うかを選択します。lunchを引数なしで実行すると、選択可能なターゲットのリストが表示されます。

ターゲットの命名規則は通常 `[製品名]_[デバイス名]-[ビルドバリアント]` となっています。例えば、Pixel 7 Pro向けのuserdebugビルドは `aosp_cheetah-userdebug` となります。AOSPの汎用ターゲットとしては、エミュレータや特定のハードウェアに依存しない開発用の `aosp_arm64-eng` などがあります。


# ターゲットを直接指定する場合
lunch aosp_arm64-eng

ビルドバリアントの種類:

  • eng (Engineering): 開発者向けのビルド。デバッグツールが豊富に含まれ、デフォルトでrootアクセスが可能です。パフォーマンスの最適化は最小限です。
  • userdebug: userビルドに近いですが、rootアクセスと追加のデバッグ機能が有効になっています。デバッグとテストに適しています。
  • user: エンドユーザー向けのリリースビルド。rootアクセスは無効化され、デバッグ機能は制限されています。パフォーマンスとセキュリティが最も重視されます。

3. ビルドの実行:make

ターゲットを選択したら、make(または、より現代的なビルドシステムSoongを直接呼び出すm)コマンドでビルドを開始します。


# -jの後の数字は、並行して実行するジョブの数。
# 一般的に、CPUのコア数またはその1.5〜2倍の値を指定します。
make -j16

初回ビルドは数時間かかるのが普通です。2回目以降は、変更された部分のみが再コンパイルされるため、時間は大幅に短縮されます。ビルドが成功すると、ターミナルに成功メッセージが表示されます。

ビルド成果物の解剖

ビルドが完了すると、成果物は `out/target/product/[デバイス名]/` ディレクトリに生成されます。これらのイメージファイルが、デバイスに書き込む実体です。主要なイメージとその役割を理解することは、トラブルシューティングの鍵となります。

  • boot.img: デバイスの起動に不可欠なイメージ。LinuxカーネルとRAMディスク(initramfs)を結合したものです。RAMディスクには、システムの初期化に必要な最小限のファイルシステムとinitプロセスが含まれています。
  • system.img: Android OSの本体。システムのライブラリ、フレームワーク、システムアプリなどが含まれ、/systemパーティションにマウントされます。
  • userdata.img: ユーザーデータパーティションのイメージ。インストールされたアプリ、設定、写真などのユーザーデータが保存される/data領域の初期状態を定義します。通常、クリーンインストールの際は空のファイルシステムとしてフォーマットされます。
  • vendor.img: ハードウェア固有のバイナリやライブラリが含まれます。これらは、CPU、GPU、Wi-Fi、Bluetoothなどのハードウェアを制御するためのプロプライエタリなドライバやHAL(Hardware Abstraction Layer)です。Project Trebleの導入により、system.imgから分離されました。
  • vbmeta.img: Android Verified Boot (AVB) 2.0で使用されるメタデータイメージ。boot.imgsystem.imgなどの他のパーティションイメージのハッシュと署名情報を含み、システムの改ざんを防ぎます。
  • recovery.img: リカバリーモード用のイメージ。システムのアップデート、データのワイプ、バックアップなどを行うための最小限の環境です。
  • super.img (近年のデバイス): 動的パーティションをサポートするデバイス用の巨大なイメージ。system, vendor, productなどの複数の論理パーティションを内部に含んでいます。これにより、OTAアップデートなどでパーティションサイズを柔軟に変更できます。

これらのイメージファイルが、次の章で解説するFastbootツールによって、デバイスの対応するパーティションに一つずつ書き込まれていきます。

第4章 Fastboot:デバイスとPCを繋ぐ架け橋

Fastbootは、Androidデバイスのブートローダーと直接通信するためのプロトコルおよびコマンドラインツールです。OSが起動する前の低レベルな状態で動作するため、パーティションの書き換え、ブートローダーのアンロック、デバイス情報の取得など、強力な操作が可能です。ADB (Android Debug Bridge) が起動したOS上で動作するのに対し、Fastbootはブートローダーの段階で機能する、という点が根本的な違いです。

Fastbootの準備

Fastbootツールを使用するには、GoogleのSDK Platform-ToolsをPCにインストールする必要があります。これにはfastbootadbの両方が含まれています。公式サイトからダウンロードし、パスの通ったディレクトリに配置してください。

デバイス側では、以下の準備が必要です。

  1. USBデバッグの有効化: [設定] > [デバイス情報] に進み、[ビルド番号]を7回連続でタップして[開発者向けオプション]を有効にします。その後、[開発者向けオプション]内で[USBデバッグ]をオンにします。
  2. OEMロック解除の有効化: [開発者向けオプション]内で[OEMロック解除]をオンにします。これにより、ブートローダーのアンロックが可能になります。

ブートローダーのアンロック:最初の関門

ほとんどのデバイスは、セキュリティ上の理由からブートローダーがロックされた状態で出荷されます。カスタムイメージをフラッシュするには、まずこれをアンロックする必要があります。この操作はデバイス上の全データを消去するため、実行前に必ずバックアップを取ってください。また、メーカー保証が無効になる可能性があります。

  1. デバイスをPCに接続し、ターミナルでadb reboot bootloaderと入力してFastbootモードで再起動します。または、電源オフの状態から特定のキーの組み合わせ(例:音量ダウン+電源ボタン)を押すことでもFastbootモードに入れます。
  2. デバイスがFastbootモードで認識されているか確認します。
    
    fastboot devices
        
    シリアル番号が表示されれば成功です。
  3. ブートローダーをアンロックします。コマンドはデバイスによって異なりますが、多くの場合は以下の通りです。
    
    # Google Pixelや多くの最新デバイス
    fastboot flashing unlock
    
    # 一部の旧式デバイス
    fastboot oem unlock
        
  4. デバイスの画面に確認メッセージが表示されるので、音量ボタンで[Yes]を選択し、電源ボタンで決定します。デバイスは自動的に初期化され、再起動します。

Fastbootコマンドリファレンス

Fastbootには多くのコマンドがありますが、ここでは特に重要なものを紹介します。

情報取得系コマンド

  • fastboot devices: 接続されているデバイスを一覧表示します。
  • fastboot getvar [variable]: ブートローダーの変数を表示します。例えばfastboot getvar productは製品名を、fastboot getvar unlockedはブートローダーのロック状態を表示します。fastboot getvar allは全ての変数を表示し、デバッグに非常に役立ちます。

フラッシュ(書き込み)系コマンド

  • fastboot flash [partition] [filename.img]: 最も基本的なコマンド。指定したイメージファイルを指定したパーティションに書き込みます。
    
    fastboot flash boot boot.img
    fastboot flash system system.img
        
  • fastboot flashall: 現在のディレクトリにあるboot.img, system.img, vendor.imgなどを自動的にフラッシュする便利なスクリプトです。ただし、どのパーティションが書き込まれるかはデバイスの構成に依存するため、手動でのフラッシュがより確実です。
  • fastboot update [filename.zip]: OTAアップデートなどで使われる、イメージ一式をまとめたZIPファイルをフラッシュします。

パーティション操作コマンド

  • fastboot erase [partition]: パーティションのデータを消去します。fastboot erase userdataは、実質的にデバイスを初期化(ファクトリーリセット)します。
  • fastboot format [partition]: パーティションを特定のファイルシステムでフォーマットします。eraseよりも低レベルな操作です。

デバイス制御コマンド

  • fastboot reboot: デバイスを通常モードで再起動します。
  • fastboot reboot-bootloader: デバイスをFastbootモードで再起動します。フラッシュ作業の途中でブートローダーを再読み込みさせたい場合に便利です。

A/Bパーティション(シームレスアップデート)対応コマンド

近年のデバイスは、システムパーティションをA/Bの2つのスロットに持ち、アップデートの安全性を高めています。

  • fastboot getvar current-slot: 現在アクティブなスロット(aまたはb)を表示します。
  • fastboot --set-active=[slot]: アクティブなスロットを切り替えます。例えばfastboot --set-active=aとします。

第5章 実践:AOSPイメージのフラッシュワークフロー

理論とツールが揃ったところで、実際にAOSPビルドの成果物をデバイスにインストールする手順を見ていきましょう。ここでは、一般的なデバイスにおける標準的なフラッシュシーケンスを解説します。

ステップ1:準備と確認

  1. AOSPのビルドが正常に完了し、out/target/product/[デバイス名]/に必要なイメージファイル(boot.img, system.imgなど)が生成されていることを確認します。
  2. デバイスのブートローダーがアンロックされていることを確認します。
  3. デバイスをFastbootモードで起動し、PCに接続します。fastboot devicesで正しく認識されていることを確認します。

ステップ2:パーティションのフラッシュ

フラッシュの順序は重要になることがあります。一般的には、ブートローダーや無線通信関連のファームウェアを先に書き込み、その後で主要なシステムイメージを書き込むのが安全です。

以下は、動的パーティションを持たない、比較的古いデバイスの典型的な例です。


# ファームウェア関連(必要に応じて)
# fastboot flash bootloader bootloader-[device]-[version].img
# fastboot flash radio radio-[device]-[version].img
# fastboot reboot-bootloader  # 新しいブートローダーを読み込むために再起動

# 主要イメージのフラッシュ
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash vendor vendor.img
fastboot flash userdata userdata.img
fastboot flash recovery recovery.img

# キャッシュのクリア(推奨)
fastboot erase cache

一方、動的パーティション(superパーティション)を持つ現代のデバイスでは、手順が異なります。system, vendorなどを個別にフラッシュするのではなく、super.imgをフラッシュします。


# vbmetaのフラッシュ (Verified Boot)
fastboot flash vbmeta vbmeta.img

# superパーティションのフラッシュ
fastboot flash super super_empty.img # 一度空のイメージを書き込むのが安全な場合がある
fastboot flash super super.img

# その他のパーティション
fastboot flash boot boot.img

重要: 上記のコマンドはあくまで一例です。正しいパーティション名とフラッシュ手順は、必ず対象デバイスのドキュメントやコミュニティ(XDA-Developersなど)で確認してください。間違ったパーティションに誤ったイメージを書き込むと、デバイスが起動しなくなる(文鎮化する)危険があります。

ステップ3:クリーンインストールと再起動

メジャーバージョンのアップグレードや、異なるカスタムROMからの移行など、大幅な変更を行う場合は「クリーンインストール」が強く推奨されます。これにはユーザーデータの消去が含まれます。


fastboot erase userdata

すべてのイメージのフラッシュが完了したら、デバイスを再起動します。


fastboot reboot

PCからUSBケーブルを抜き、デバイスの初回起動を待ちます。初回起動は通常よりも時間がかかることがあります。数分から10分以上かかる場合もありますので、辛抱強く待ちましょう。AOSPのセットアップ画面が表示されれば、フラッシュは成功です。

第6章 トラブルシューティング:問題解決へのアプローチ

AOSPのビルドとフラッシュは、常にスムーズに進むとは限りません。問題が発生した際に、原因を特定し、解決策を見つけ出す能力は非常に重要です。ここでは、よくある問題とその対処法について解説します。

よくあるFastbootのエラー

  • < waiting for any device >:
    • 原因: PCがデバイスを認識していません。
    • 解決策:
      1. USBケーブルやポートを変更してみる。
      2. Windowsの場合、適切なUSBドライバ(Google USB Driverなど)がインストールされているか確認する。デバイスマネージャーで不明なデバイスとして表示されていないかチェックする。
      3. Linuxの場合、udevルールが正しく設定されているか確認する。/etc/udev/rules.d/にAndroidデバイス用のルールファイルを作成する必要がある場合があります。
      4. デバイスが確実にFastbootモードに入っているか再確認する。
  • FAILED (remote: '...'):
    • 原因: ブートローダー側でコマンドが拒否されました。remote:に続くメッセージがヒントになります。
    • 解決策:
      • 'flashing is not allowed in locked state': ブートローダーがロックされています。アンロック手順を先に行ってください。
      • 'partition does not exist': 指定したパーティション名が間違っています。fastboot getvar allで利用可能なパーティションを確認するか、デバイスのドキュメントを参照してください。
      • 'image not signed or invalid' or 'signature verification failed': Android Verified Boot (AVB) が有効なデバイスに、署名されていない、または不正な署名のイメージをフラッシュしようとしています。ブートローダーをアンロックするか、正しく署名されたイメージを使用する必要があります。

フラッシュ後の起動トラブル

  • ブートループ(Bootloop): 起動アニメーションが表示された後、すぐに再起動を繰り返す状態。
    • 原因:
      • カーネルパニック(boot.imgの問題)。
      • system.imgvendor.imgの不整合(HALのバージョンミスマッチなど)。
      • SELinuxポリシーの不備。
      • パーティションのフォーマットが不正。
    • 解決策:
      1. 再度Fastbootモードに入り、パーティション(特にuserdatacache)を消去して再試行する。
      2. イメージファイルが破損していないか確認し、必要であればAOSPを再ビルドする(make clean後に再ビルド)。
      3. 信頼できる公式のファクトリーイメージを一度フラッシュし、デバイスが正常な状態に戻るか確認する。
      4. 可能であれば、リカバリーモードからログ(logcatdmesg)を取得し、エラーメッセージを分析する。
  • 起動アニメーションから進まない:
    • 原因: システムサービスやアプリケーションフレームワークの初期化中に問題が発生しています。
    • 解決策:
      1. ブートループと同様に、クリーンインストールを試す。
      2. PCに接続し、adb logcatを実行してログをリアルタイムで監視する。致命的なエラー(FATAL EXCEPTION)が発生していないか探す。これにより、問題を引き起こしている特定のプロセスやサービスを特定できる場合があります。

問題解決のための心構え

トラブルシューティングは体系的なプロセスです。焦らず、以下のステップを試みてください。

  1. ログを確認する: ビルド時のエラーメッセージ、fastbootの出力、adb logcatなど、ログは問題の宝庫です。
  2. 変更を一つずつ適用する: 複数の変更を一度に行うと、何が原因かを特定するのが難しくなります。
  3. 検索を活用する: あなたが直面している問題は、他の誰かも経験している可能性が高いです。エラーメッセージをそのまま検索エンジンにかける、Stack OverflowやXDA-Developersなどのフォーラムで検索する、といった方法が有効です。
  4. 基本に戻る: 問題が複雑化した場合は、一度公式のファクトリーイメージに戻し、そこから再度カスタムビルドの適用を試みることで、問題の切り分けができます。

AOSPの世界は奥深く、挑戦的ですが、その分、成功したときの達成感は計り知れません。この記事が、あなたがAndroidシステムの深淵を覗き込み、自分だけのAndroidを創造する旅の一助となれば幸いです。


0 개의 댓글:

Post a Comment