序章

Android は、今日世界で最も人気のあるオペレーティングシステムです。 何百もの異なる相手先ブランド供給(OEM)は、無料でオープンソースであり、アプリとサービスの大規模なエコシステムが構築されているため、デバイスにインストールすることを選択します。 残念ながら、多くのOEMは、Androidの無線(OTA)アップデートを定期的にプッシュしていません。 また、他のOEMは、デバイスの発売後、限られた期間のみ更新を提供します。 さらに、OEMは、Androidを大幅にカスタマイズして、デバイスが独自のルックアンドフィールを備えていることを確認する傾向があります。 それらのカスタマイズには、代替ランチャー、テーマ別システムユーザーインターフェイス、およびプリインストールされたアプリが含まれます。

これらのカスタマイズをすべて削除する場合、またはデバイスで純粋なAndroidの最新バージョンを実行する場合は、新しいファームウェアを自分でビルドできます。 Androidの改造コミュニティでは、このようなファームウェアは通常ROMと呼ばれ、読み取り専用メモリの略です。

このチュートリアルでは、 Android Open Source Project 、または略してAOSPに基づくAndroidOreoROMを構築します。 このチュートリアルをデバイスに依存せず一般的なものにするために、AOSPエミュレーターのみを対象としますが、実際のデバイスにも同じ手法を適用できます。

前提条件

フォローできるようにするには、次のものが必要です。

  • Ubuntu 16.04初期サーバーセットアップガイドに従ってセットアップされた、少なくとも16 GBのRAM、4つのCPU、および120GBのストレージスペースを備えた1つのUbuntu16.04 x64サーバー(sudo非rootユーザーとファイアウォールを含む) 。 コンパイルプロセスには大量のRAMが必要であり、CPUが多いほどコンパイル時間が短縮されます。 さらに、ダウンロードしてビルドするファイルは非常に大きくなります。 DigitalOceanには高CPUドロップレットがあり、このプロジェクトに最適かもしれません。
  • Ubuntu16.04にGitをインストールする方法に従ってGitをインストールします。

ステップ1—スクリーンセッションを開始します

このチュートリアルで実行するコマンドの一部は、数時間実行される可能性があります。 コマンドの実行中にPCとサーバー間のSSH接続が中断されると、コマンドは突然終了します。 このような状況を回避するには、screenユーティリティを使用します。このユーティリティを使用すると、1つの端末で複数のコンソールセッションを実行できます。 screenを使用すると、実行中のセッションから切り離して、後で再接続できます。 Screenを初めて使用する場合は、UbuntuでのScreenの使用に関するこのチュートリアルで詳細を確認してください。

新しいscreenセッションを開始します。

  1. screen

画面を初めて実行すると、使用許諾契約が表示されます。 Enterを押してライセンスに同意します。

この時点から、SSH接続が失敗した場合でも、長時間実行されるコマンドはバックグラウンドで実行され続けます。 SSH接続を再確立すると、screen -rを実行してセッションを再開できるようになります。

次に、Androidをコンパイルするために必要なコンポーネントをインストールしましょう。

ステップ2—依存関係のインストール

AOSPソースコードは、いくつかの異なるGitリポジトリに分散しています。 ユーザーがこれらすべてのリポジトリを簡単にダウンロードできるようにするために、AOSPコミュニティはrepoと呼ばれるコマンドラインツールを作成しました。

wgetを使用してツールの最新バージョンをダウンロードし、~/binディレクトリに保存します。 まず、~/binディレクトリを作成します。

  1. mkdir -p ~/bin

次に、repoスクリプトをダウンロードします。

  1. wget 'https://storage.googleapis.com/git-repo-downloads/repo' -P ~/bin

:別のサイトからダウンロードしたマシンでスクリプトを実行する際のセキュリティが心配な場合は、スクリプトの内容を調べてください。

  1. less ~/bin/repo

スクリプトの内容に慣れたら、このチュートリアルを続けてください。

chmodを使用して、現在のユーザーにrepoを実行する権限を付与します。

  1. chmod +x ~/bin/repo

repoツールは内部でGitを使用し、ユーザー名とメールアドレスを指定してGit構成を作成する必要があります。 これを行うには、次のコマンドを実行します。

  1. git config --global user.name "your name"
  2. git config --global user.email "[email protected]_domain.com"

Androidのソースコードは、主にJava、C ++、およびXMLファイルで構成されています。 ソースコードをコンパイルするには、OpenJDK 8、GNUCおよびC++コンパイラ、XML解析ライブラリ、ImageMagick、およびその他のいくつかの関連パッケージをインストールする必要があります。 幸い、aptを使用してすべてをインストールできます。 その前に、サーバーのパッケージリストを更新してください。

  1. sudo apt-get update

リストが更新されたら、依存関係をインストールします。

  1. sudo apt-get install openjdk-8-jdk android-tools-adb bc bison build-essential curl flex g++-multilib gcc-multilib gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev libesd0-dev liblz4-tool libncurses5-dev libsdl1.2-dev libssl-dev libwxgtk3.0-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc yasm zip zlib1g-dev

依存関係がダウンロードされたら、repoスクリプトを使用してAndroidソースを取得できます。

ステップ3—ソースコードをダウンロードする

repoスクリプトを使用して、ワークスペースを準備するためのいくつかのタスクを実行します。 ダウンロードするAndroidソースを保存するための新しいディレクトリを作成します。

  1. mkdir -p ~/aosp/oreo

このチュートリアルの残りの部分ではこのディレクトリで作業するので、今すぐこのディレクトリに切り替えてください。

  1. cd ~/aosp/oreo

ディレクトリは、AOSP マニフェストリポジトリで初期化する必要があります。これは、default.xmlという名前のXMLファイルを含む特別なGitリポジトリであり、AOSPコードベースを形成する他のすべてのGitリポジトリのパスを指定します。

AOSPコードツリー全体を操作するのは面倒な場合があります。 したがって、関心のある特定のリビジョンまたはブランチの名前を追加で指定する必要があります。 このチュートリアルでは、Oreo ROMをビルドしているため、ビルドIDがOPD1.170816.025であるandroid-8.0.0_r33ブランチを使用します。 利用可能なすべてのビルドIDとブランチ名のリストは、AOSPの公式コードネーム、タグ、およびビルド番号ページから入手できます。

さらに、このチュートリアルでは、コードツリーのコミット履歴全体は必要ありません。 履歴を1の深さまで切り捨てることで、時間とストレージスペースの両方を節約できます。

したがって、repo initコマンドを使用してディレクトリを初期化し、次のオプションを指定します。

  1. repo init -u https://android.googlesource.com/platform/manifest -b android-8.0.0_r33 --depth=1

カラー表示を有効にするように求められたら、 Y を押してから、Enterを押します。

最後に、repo syncコマンドを実行して、さまざまなリポジトリから実際のAOSPファイルをダウンロードします。

  1. repo sync

上記のコマンドは30GBを超えるデータをダウンロードするため、完了するまでしばらくお待ちください。 それが完了したら、コンパイルを高速化するためにキャッシュを設定します。

ステップ4—コンパイラキャッシュの準備

ビルドを高速化するために、コンパイラキャッシュを使用できます。 その名前が示すように、コンパイラキャッシュは、すでにコンパイルされているROMの部分の再コンパイルを回避するのに役立ちます。

コンパイラキャッシュの使用を有効にするには、USE_CCACHEという名前の環境変数を設定します。

  1. export USE_CCACHE=1

十分な空きディスク容量がない限り、キャッシュが大きくなりすぎないようにするため、キャッシュのサイズを制限できます。 単一のデバイス用にROMを構築している場合は、15GBに制限できます。 これを行うには、ccacheコマンドを使用します。

  1. prebuilts/misc/linux-x86/ccache/ccache -M 15G

この変更を行ったことを確認する出力が表示されます。

Output
Set cache size limit to 15.0 Gbytes

コンパイルする前に、もう1つ最適化を行う必要があります。 次にそれをしましょう。

ステップ5—ジャックの構成

ROMのほとんどのJavaベースの部分の構築を担当するJackサーバーは、大量のメモリを必要とします。 メモリ割り当てエラーを回避するために、ANDROID_JACK_VM_ARGSという名前の環境変数を使用して、ジャックが使用できるメモリの量を指定できます。 通常、サーバーのRAMの約50% ofを割り当てるだけで十分です。 この環境変数は、他のコンパイル設定も指定します。

次のコマンドを実行して、8 GBのRAMをJackサーバーに割り当て、Jackが必要とするデフォルトのコンパイルオプションを保持します。

  1. export ANDROID_JACK_VM_ARGS="-Xmx8g -Dfile.encoding=UTF-8 -XX:+TieredCompilation"

これで、AndroidROMを構築する準備が整いました。

ステップ6—ビルドを開始する

AOSPコードツリーには、envsetup.shという名前のスクリプトが含まれています。このスクリプトには、ビルド関連のヘルパー関数がいくつかあります。 mmmmammmなどのヘルパー関数の多くは、makeコマンドのショートカットとして機能しますが、lunch特に、ROMのCPUアーキテクチャ、およびビルドのタイプを決定する重要な環境変数を設定します。

スクリプトを入手して、ヘルパー関数にアクセスします。

  1. source build/envsetup.sh
Output
including device/asus/fugu/vendorsetup.sh including device/generic/car/car-arm64/vendorsetup.sh including device/generic/car/car-armv7-a-neon/vendorsetup.sh including device/generic/car/car-x86_64/vendorsetup.sh including device/generic/car/car-x86/vendorsetup.sh including device/generic/mini-emulator-arm64/vendorsetup.sh including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh including device/generic/mini-emulator-mips64/vendorsetup.sh including device/generic/mini-emulator-mips/vendorsetup.sh including device/generic/mini-emulator-x86_64/vendorsetup.sh including device/generic/mini-emulator-x86/vendorsetup.sh including device/google/dragon/vendorsetup.sh including device/google/marlin/vendorsetup.sh including device/google/muskie/vendorsetup.sh including device/google/taimen/vendorsetup.sh including device/huawei/angler/vendorsetup.sh including device/lge/bullhead/vendorsetup.sh including device/linaro/hikey/vendorsetup.sh including sdk/bash_completion/adb.bash

次に、lunchを実行し、デバイスのコードネームを、enguserdebug、またはuserのいずれかのビルドタイプの接尾辞としてデバイスに渡します。 。 engおよびuserdebugビルドタイプはテスト目的に最適なROMになりますが、userビルドタイプは実稼働での使用をお勧めします。

AOSP ARMエミュレータで実行できるテストROMを構築するには、aosp_arm-englunchコマンドに渡します。

  1. lunch aosp_arm-eng

この出力が表示され、環境設定が示されます。

Output
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=8.0.0 TARGET_PRODUCT=aosp_arm TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_PLATFORM_VERSION=OPD1 TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_2ND_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=Linux-4.4.0-104-generic-x86_64-with-Ubuntu-16.04-xenial HOST_CROSS_OS=windows HOST_CROSS_ARCH=x86 HOST_CROSS_2ND_ARCH=x86_64 HOST_BUILD_TYPE=release BUILD_ID=OPD1.170816.025 OUT_DIR=out AUX_OS_VARIANT_LIST= ============================================

最後に、makeを実行してビルドを開始します。 makeは並列ジョブをサポートしているため、-jオプションを使用して、サーバーで使用可能なCPUの数と同じ数の並列ジョブを設定することでビルドを大幅に高速化できます。

nprocコマンドを使用して、使用しているCPUの数を確認します。

  1. nproc

このコマンドは、CPUの数を返します。

Output
8

次に、この番号をmakeとともに使用して、並列実行を指定できます。

  1. make -j8

8つのCPUを使用している場合でも、サーバー上でアクティブなCPUを集中的に使用するプロセスが他にない場合は、ビルドが完了するまで1時間以上待つ必要があります。 ビルドの期間は、RAMの量とCPUの数に正比例します。 より高速なビルドが必要な場合は、最大32個のCPUと48GBのメモリをサポートする専用の高CPUドロップレットの使用を検討してください。

注:ビルド中に多くの警告メッセージが生成されます。 あなたはそれらを安全に無視することができます。

ROMの準備が整うと、ビルドが正常に完了したことを示すメッセージが表示されます。 ビルドの正確な期間も確認できます。

Output
... Creating filesystem with parameters: Size: 2147483648 Block size: 4096 Blocks per group: 32768 Inodes per group: 8192 Inode size: 256 Journal blocks: 8192 Label: system Blocks: 524288 Block groups: 16 Reserved block group size: 127 Created filesystem with 2266/131072 inodes and 178244/524288 blocks [100% 63193/63193] Install system fs i... out/target/product/generic/system.img out/target/product/generic/system.img+ maxsize=2192446080 blocksize=2112 total=2147483648 reserve=22146432 #### make completed successfully (01:05:44 (hh:mm:ss)) ####

物事が正しく構築されていることを確認しましょう。

ステップ7—ビルドの確認

ビルドプロセスの出力は、ROMを形成する複数のファイルシステムイメージで構成されます。 それらはout/target/product/generic/ディレクトリにあります。

  1. ls -l out/target/product/generic/*.img
Output
-rw-r--r-- 1 sammy sammy 69206016 Jan 5 18:51 out/target/product/generic/cache.img -rw-rw-r-- 1 sammy sammy 1699731 Jan 5 19:09 out/target/product/generic/ramdisk.img -rw-r--r-- 1 sammy sammy 2147483648 Jan 5 19:10 out/target/product/generic/system.img -rw-r--r-- 1 sammy sammy 576716800 Jan 5 19:09 out/target/product/generic/userdata.img

ROMをテストするには、emulatorコマンドを実行して、ROMを使用してエミュレーターを起動してみます。 GUI以外の環境にいる場合は、必ず-no-windowおよび-noaudioフラグを渡してください。

  1. emulator -no-window -noaudio > /dev/null 2>&1 &

エミュレータが正常に起動したかどうかを確認するには、1分待ってから、Androidデバッグブリッジツールadbを使用して、エミュレータでシェルを開きます。

  1. adb shell

ROMに問題がない場合は、エミュレータで実行されているシェルからのプロンプトが表示されます。

Output
* daemon not running; starting now at tcp:5037 * daemon started successfully generic:/ #

exitと入力してENTERを押すか、CTRL+Dを押して、このシェルを終了します。

注:エミュレーターが起動する前にシェルを開こうとすると、エミュレーターがオフラインであることを通知するエラーメッセージが表示されます。 しばらく待ってから、もう一度やり直してください。

トラブルシューティング

ビルドが失敗した場合、最も可能性の高い原因はメモリ不足です。 これを修正するには、最初に次のコマンドを実行してJackサーバーを強制終了します。

  1. jack-admin kill-server

次に、ビルドを再開しますが、許可される並列ジョブは少なくなります。 たとえば、並列ジョブの数を2つに減らす方法は次のとおりです。

  1. make -j2

ディスク容量が不足しているためにビルドが失敗した場合は、以前のビルドの結果をクリーンアップせずに、複数回ビルドしようとしている可能性があります。 以前のビルドの結果を破棄するには、次のコマンドを実行できます。

  1. make clobber

または、DigitalOceanの Block Storage を使用して、ドロップレットにディスク容量を追加することもできます。

結論

このチュートリアルでは、AndroidOreo用のAOSPベースのROMを正常に構築しました。 今日学んだテクニックは、 LineageOSResurrectionRemix OS など、AOSPのすべてのフォークにも適用できます。 Androidアプリの開発経験がある場合は、AOSPコードベースのごく一部を変更して、ROMに個人的なタッチを与えることに興味があるかもしれません。

AOSPソースコードの作成について詳しくは、GoogleグループのAndroidBuildingフォーラムをご覧ください。