【AOSP】ビルドしたAndroidOSを実機に入れる

この記事は[FUN Advent Calendar 2019](https://adventar.org/calendars/4058)の19日目の記事です。
未来大生なら誰もが触っているAndrooidOSについてです。

AndroidOSをビルドして、実機で動かす方法について説明します。
エミュレータで動かす方法については[@natmarkさんの記事](https://qiita.com/natmark/items/09802c7f16733cd77f8e)が一番わかりやすいです。

※こちらの方法で端末が文鎮化しても一切責任は取りません
文鎮化した場合はこちらの記事を参考に直してみてください
- [【AOSP】Androidが文鎮化しそうな時に工場出荷時状態に戻す方法](https://qiita.com/yamakentoc/items/044275de35570bf6669d)

#環境
ビルドするためには、64ビットで250GBの空き容量が必要です。
自分はこんな感じの環境でやりました。

- OS: Ubuntu18.04
- RAM: 8GB
- CPU: Corei3(2コア/4スレッド)
- ROM: HDD 500GB
- 実機: Pixel 3a

#ビルドの準備

###必要なパッケージをインストール
```
$ sudo apt update
$ sudo apt -y install curl make zip unzip \
git python default-jre openjdk-8-jdk \
bison g++-multilib gcc-multilib libxml2-utils 
```
###repoのインストール
ソースコードのDLに必要[repo](https://qiita.com/fuuuuumin65/items/12310745a0d3c2319fe1)が必要になります

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

###プロジェクト用のフォルダの作成
```
$ mkdir AOSP
$ cd AOSP
```

###リポジトリのクローン
```
$ repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r1
$ repo sync -j4
```
- `-b android-10.0.0_r1`でタグを選択しています
    - [タグ一覧](https://source.android.com/setup/start/build-numbers.html#source-code-tags-and-builds)
    - ここで選択するタグはなんでもいいわけではなく、`Supported devices`に、AndroidOSを入れようとしている実機の名前が無いといけません。
    - 本記事ではPixel 3aを使用するので、Pixel 3aをサポートしている`android-10.0.0_r1`を選択しています
- `repo sync`でリポジトリのクローンをします
    - 環境にもよりますが、1時間以上かかります

###デバイスドライバの入手
- リポジトリをクローンをした時のタグのビルドバージョンを確認します
    - https://source.android.com/setup/start/build-numbers.html#source-code-tags-and-builds
<img width="877" alt="スクリーンショット_2019-12-12_16_22_56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/87cb6642-55b2-64f5-61f6-b7834af3f603.png">
- `android10.0.0-r1`のビルドバージョンは`QP1A.190711.019`
- [こちらのページ](https://developers.google.com/android/drivers)で、端末名とビルドバージョンにあったものを探します
<img width="891" alt="スクリーンショット_2019-12-12_16_40_57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/97c39caa-4108-603b-cccc-18c6d03c80df.png">

`Vendor image`のDownload Linkのリンクのアドレスをコピーして、AOSPフォルダ内でcurlして解凍します

```
$ curl -o hoge コピーしたリンクのアドレス
$ tar -xzvf hoge
```
解凍すると`x extract-google_devices-sargo.sh`のようにシェルが生成されるので実行します

```
$./extract-google_devices-sargo.sh
```
- 利用規約が流れるのでずーっとみていって、最後に「I ACCEPT」と入力してくださいと表示されるので「I ACCEPT」を入力してEnterを押します
- すると、AOSPフォルダ内に`vendor`が生成されます
<img width="645" alt="スクリーンショット_2019-12-12_17_07_32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/a2e0c4b1-f9e0-3b2f-7ae6-288136dcb052.png">
- ここでビルドバージョンを間違えると、ビルドと実機に入れることが成功しても、タッチが効かないなどバグるので気をつけてください

#ビルド
###前準備
AOSPフォルダ内で以下のコマンド入力します

```
$ export LC_ALL=C
$ source build/envsetup.sh #環境設定
$ lunch ターゲット端末のコードネーム
```
- ローケル環境変数を英語にしないとビルドがこけるため `LC_ALL=C`とします
- `source build/envsetup.sh`で`lunch`コマンドなどが使えるようになります
- `lunch`コマンドでは、どの端末を対象とするのか、コードネームを指定する必要があり、[このページ](https://source.android.com/setup/build/running)から各端末のコードネームを確認することができます
- Pixel 3aのコードネームは`sargo`なので、`lunch aosp_sargo-userdebug`と叩きます
<img width="880" alt="スクリーンショット_2019-12-12_21_21_54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/2f5c8d15-feec-c853-0515-0030c9211ce7.png">
- 引数なしで`lunch`のみを叩くと全てのターゲットの選択肢が表示されるので、それで指定することもできます

```
$ lunch

You're building on Linux

Lunch menu... pick a combo:
     1. aosp_arm-eng
     2. aosp_arm64-eng
     3. aosp_blueline-userdebug
     4. aosp_bonito-userdebug
     5. aosp_car_arm-userdebug
     6. aosp_car_arm64-userdebug
     7. aosp_car_x86-userdebug
     8. aosp_car_x86_64-userdebug
     9. aosp_cf_arm64_phone-userdebug
     10. aosp_cf_x86_64_phone-userdebug
     11. aosp_cf_x86_auto-userdebug
     12. aosp_cf_x86_phone-userdebug
     13. aosp_cf_x86_tv-userdebug
     14. aosp_crosshatch-userdebug
     15. aosp_marlin-userdebug
     16. aosp_sailfish-userdebug
     17. aosp_sargo-userdebug
     18. aosp_taimen-userdebug
     19. aosp_walleye-userdebug
     20. aosp_walleye_test-userdebug
     21. aosp_x86-eng
     22. aosp_x86_64-eng
     23. beagle_x15-userdebug
     24. fuchsia_arm64-eng
     25. fuchsia_x86_64-eng
     26. hikey-userdebug
     27. hikey64_only-userdebug
     28. hikey960-userdebug
     29. hikey960_tv-userdebug
     30. hikey_tv-userdebug
     31. m_e_arm-userdebug
     32. mini_emulator_arm64-userdebug
     33. mini_emulator_x86-userdebug
     34. mini_emulator_x86_64-userdebug
     35. poplar-eng
     36. poplar-user
     37. poplar-userdebug
     38. qemu_trusty_arm64-userdebug
     39. uml-userdebug

Which would you like? [aosp_arm-eng] 17
```

###ビルド
```
$ make -j4
```
- -jオプションでスレッド数を指定すると、ビルド時間を短縮できます
- 自分の環境では***8時間***かかりました

###ビルドの完了
```
#### build completed successfully (49:27 (mm:ss)) ####
```
最後にこれが表示されていればビルド成功です！

###キャッシュ
- キャッシュを有効にすると次回以降のビルド時間を早めることができます

```
$ export USE_CCACHE=1 #ccacheを有効にする
$ export CCACHE_DIR=/home/$USER/.ccache #キャッシュディレクトリの指定
$ ccache -M 100G #ccacheでキャッシュするサイズ上限
```

###ビルドが失敗した場合

- 前のビルドで生成されたファイルを削除します
- 基本的にビルドに失敗した場合に使います
 
```
$ make clobber
```

#実機にビルドしたAndroidOSを入れる
###adb, fastbootの導入
adbとfastbootを導入します

```
$ sudo apt-get install android-tools-adb
$ sudo apt-get install android-tools-fastboot
```
- adbとfastbootは最新バージョンでなければ実機に入れる時にエラーを吐きます
- 上記コマンドで最新バージョンを入手できたとは限らないため、[このページ](https://developer.android.com/studio/releases/platform-tools)から入手します
- SDK Platform-Tools for Linuxをダウンロードして解凍すると、platform-toolsが生成され、その中に最新バージョンのadbとfastbootが入っています

現状入っているadbを最新バージョンのadbと置き換えるため、`adb --version`を使ってadbの場所を確認します

```
$ adb --version
Android Debug Bridge version 1.0.41
Version 29.0.5-5949299
Installed as /usr/lib/android-sdk/platform-tools/adb
```
- `/usr/lib/android-sdk/platform-tools/adb`に入っていることを確認したので、`/usr/lib/android-sdk/platform-tools`をダウンロードしたplatform-toolsと置き換えます
- これで最新のadbとfastbootを導入することができました

###実機の設定をする
- 設定アプリを開き、デバイス情報を開き、一番下にある「ビルド番号」を10回ほど連続でタップします
    - これで開発者向けオプションが有効になります
- システムを開き、開発者向けオプションを開きます

    - 「OEMロック解除」をONにします
    - 「USBデバッグ」をONにします

###fastbootモードに入る
- 実機をPCに接続します
- fastbootモードに入るために次のコマンドを打ちます

```
$ adb reboot bootloader
```
するとこのような画面になります
<img width="500" alt="locked.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/21617eda-e50c-a3cb-f348-bf48e4becdd5.jpeg">
次にブートローダーをアンロックします

```
$ fastboot flashing unlock
```
<img width="500" alt="select_lock.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/5f93e4b2-69e3-ca39-3b1e-e9a707db2719.jpeg">
音量ボタン押して`Do not unlock the bootloader`を`Unlock the bootloader`に変更し、電源ボタンを押します
これでブートローダーがアンロックされました
<img width="500" alt="unlock.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/f32efdde-e554-bbb3-adae-c48b8832f925.jpeg">

最後にこのコマンドを打ち込んでしばらく待つと...

```
$ fastboot flashall -w
```
<img width="500" alt="FASTBOOTD.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/ea2812c5-bb11-13a4-767c-d5a2aeddbcb8.jpeg">
↓
<img width="500" alt="1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/e2b83f5c-87d1-d3ac-d1a1-922d7f22513d.jpeg">
↓
<img width="500" alt="2.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/659f5767-fecc-c182-2d85-314d89516730.jpeg">
↓
<img width="500" alt="3.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237700/4e9bef4b-3334-3679-3d37-ed0e3e200385.jpeg">

無事、ビルドしたAndroidOSを実機に入れることができました！！！

###ANDROID_PRODUCT_OUT not setが表示された場合
boot.imgなどが入った、端末のコードネームのフォルダのpathを指定する必要があります
`.bashrc`を開き、pathを書きます

```
$ vim .bashrc
```
```
#.bashrcにこれを追加します
export ANDROID_PRODUCT_OUT=/home/ユーザー名/AOSP/out/target/product/端末のコードネーム
```
自分の環境(Pixel 3a)の場合、`export ANDROID_PRODUCT_OUT=/home/yamakentoc/AOSP/out/target/product/sargo`となります
最後に`.bashrc`を読み込んで...

```
$ source .bashrc
```
もう一度`fastboot flashall -w`を叩くとできるはずです


#終わりに
ビルドしたAndroidOSを実機へ導入する方法を解説しているサイトは少なく、どうしても英語や中国語のサイトを見なければいけなく大変でした。。。(それでもサイトの内容が古かったり)
[AlaskaLinuxUser AKLU](https://www.youtube.com/channel/UCnGqG_jyyXmTzdamBpKfeHA)というYoutubeチャンネルがAOSP関連のこと(ビルドの方法含め)で動画を随時投稿しているっぽいのでおすすめです
なんだかんだ10日間かかって実機で動かすことができたのでよかったです。
間違いなどありましたらコメントでご教授くださるとありがたいです。

`fastboot flashall -w`でエラーが起きたり、エラーが起きなくても、起動ができないことがよくあります。
そういう場合は使用している`android-10.0.0_r1`などのタグ(ブランチ)が悪さしていることもあるので、どうしても上手くいかない場合はタグを切り替えてみた方がいいです
確認できているタグだと、`android9.0.0_r47`は`fastboot flahall -w`の実行中に、本来fastbootdモードに勝手に切り替わるところが切り替わらないなど、バグがあります。
エラーが起きた場合は最後にまとめたよく使うadb, fastbootコマンドが役に立つと思います。

#よく使うadb, fastbootコマンド
- 接続されている端末の確認

```
$ adb devices
 #or
$ fastboot devices
```

- fastbootモードで再起動

```
$ adb reboot bootloader
```
- リカバリーモードで再起動

```
$ adb reboot recovery
```
- fastbootモード内でfastbootモードを再起動

```
$ fastboot reboot-bootloader
```
- システムの通常起動

```
$ fastboot reboot
```
- fastbootdモードで再起動

```
$ adb reboot fastboot
```



#参考サイト
- [AOSP環境構築 [備忘録]](https://qiita.com/natmark/items/09802c7f16733cd77f8e)
- [Android Open Source Project](https://source.android.com/)
- [Building A Connected Android-Based Bus Stop Display](https://www.intellectsoft.net/blog/build-and-run-android-from-aosp-source-code-to-a-nexus-7/)
- [Build your own custom Android ROM using Android Open Source Project(AOSP)](https://www.talentica.com/blogs/build-custom-android-rom-using-android-open-source-projectaosp/)
- [build-aosp-on-ubuntu](https://tabacowang.me/2019/04/18/build-aosp-on-ubuntu/)
- [building AOSP, fastbooting on a device](https://medium.com/@sohambhattacharya/building-aosp-fastbooting-on-device-eae05938cef8)
- [Flash Nexus Device with Compiled AOSP](https://zeqiii.github.io/2016/07/10/flash-nexus-device-with-compiled-aosp/)
- [Compile AOSP 10: Setting up the build environment and repo sync](https://www.youtube.com/watch?v=FdLNDdgehGY)