Сборка ROM-ов для Android в Ubuntu 16.04

Android – самая популярная операционная система в мире на сегодняшний день. Сотни оригинальных производителей оборудования (OEM) устанавливают ее на свои устройства, потому что она является свободной и открытой и имеет большую экосистему приложений и сервисов. К сожалению, многие OEM-производители регулярно не выгружают обновления для Android. Некоторые OEM-производители предоставляют обновления только в течение ограниченного периода времени после запуска устройства. Кроме того, они обычно кастомизируют систему Android, чтобы обеспечить уникальность своих устройств. Новые настройки системы включают альтернативные модули запуска, пользовательские интерфейсы с уникальными темами и предустановленные приложения.

Если вы хотите удалить все эти кастомные настройки или запустить последнюю чистую версию Android на своем устройстве, вы можете самостоятельно создать для нее прошивку. В сообществе разработчиков модов Android такую прошивку обычно называют ROM (сокращенно от Read Only Memory).

Данный мануал поможет вам создать Oreo ROM для Android на основе Android Open Source Project (AOSP). Чтобы мануал не зависел от устройства, мы будем использовать эмулятор AOSP, а вы можете применять те же методы на реальных устройствах.

Требования

  • Сервер Ubuntu 16.04 x64, настроенный по этому мануалу.
  • 16 Гб RAM, 4 ЦП, 120 Гб дискового пространства. Для процесса компиляции требуется много оперативной памяти. Чем больше будет процессоров, тем быстрее будет выполнена компиляция. Кроме того, файлы, которые вы будете собирать, достаточно велики.
  • Система Git, установленная по руководству Установка Git в Ubuntu 16.04.

1: Запуск сессии Screen

Некоторые команды данного мануала могут работать в течение нескольких часов. Если соединение SSH между вашим ПК и сервером прервется во время выполнения команд, они прекратят работу. Чтобы избежать такой ситуации, используйте утилиту screen, которая позволяет запускать несколько сеансов консоли в одном терминале. С помощью screen вы можете отсоединиться от текущей сессии и снова подключиться к ней позже.

Читайте также: Установка и использование Screen на облачном сервере Ubuntu

Запустите сессию screen:

screen

При первом запуске screen будет предоставлено лицензионное соглашение. Нажмите Enter, чтобы принять лицензию.

Если после этого ваше SSH-соединение будет прервано, ваши длительные операции будут продолжать работу в фоновом режиме. После того, как вы восстановите соединение SSH, вы сможете возобновить сессию, запустив screen -r.

2: Установка зависимостей

Исходный код AOSP распределен между несколькими репозиториями Git. Чтобы пользователям было проще загружать все эти репозитории, сообщество AOSP создало инструмент командной строки repo.

ЗАгрузите последнюю версию инструмента с помощью wget и сохраните его в каталоге ~/bin. Сначала создайте каталог ~/bin:

mkdir -p ~/bin

Затем загрузите сценарий repo:

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

Примечание: Если вас беспокоит безопасность компьютера, проверьте содержимое сценария, загруженного с другого сайта:

less ~/bin/repo

Убедившись, что сценарий не причинит вреда системе, продолжайте работу.

Используйте chmod, чтобы предоставить вашему текущему пользователю права на запуск repo.

chmod +x ~/bin/repo

Инструмент repo использует Git и требует, чтобы вы создали конфигурацию Git и указали имя пользователя и адрес электронной почты. Выполните эти команды:

git config --global user.name "your name"
git config --global user.email "your_email@your_domain.com"

Исходный код Android в основном состоит из файлов Java, C++ и XML. Чтобы скомпилировать исходный код, вам необходимо установить компиляторы OpenJDK 8, GNU C и C++, библиотеки анализа XML, ImageMagick и несколько других связанных пакетов. К счастью, вы можете установить все эти пакеты с помощью apt. Прежде чем это сделать, обновите индекс пакетов:

sudo apt-get update

Установите зависимости:

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: Загрузка исходного кода

Сценарий репо может выполнить несколько задач, чтобы подготовить рабочее пространство сервера. Создайте новый каталог для хранения загружаемого кода Android:

mkdir -p ~/aosp/oreo

Оставайтесь в этом каталоге на протяжении всего этого мануала, перейдите в него сейчас:

cd ~/aosp/oreo

Каталог должен быть инициализирован репозиторием манифеста AOSP (специальным репозиторием Git, содержащим XML-файл default.xml – он определяет пути остальных репозиториев Git, которые вместе образуют кодовую базу AOSP).

Работать со всем деревом кода AOSP довольно сложно. Поэтому вы должны дополнительно указать имя конкретной версии или интересующей вас ветки. В этом мануале создается Oreo ROM, потому мы будем использовать ветку android-8.0.0_r33 (идентификатор OPD1.170816.025). Вы можете получить список всех доступных идентификаторов на этой странице AOSP.

Кроме того, в этом мануале вам не понадобится вся история коммитов дерева кода. Вы можете сэкономить время и пространство, обрезав историю до уровня 1.

Используйте команду repo init для инициализации каталога и укажите следующие параметры:

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

Когда будет предложено включить отображение цвета, нажмите Y, а затем Enter.

Затем загрузите файлы AOSP из разных репозиториев, запустив команду:

repo sync

Вышеуказанная команда загрузит более 30 Гб данных, а это займет время. После загрузки нужно настроить кэш, чтобы ускорить компиляцию.

4: Подготовка кэша компилятора

Чтобы ускорить сборку, вы можете использовать кэш компилятора. Как следует из названия, кеш компилятора помогает избежать повторной компиляции фрагментов ROM, которые были скомпилированы ранее.

Чтобы включить поддержку кэша компилятора, установите переменную среды USE_CCACHE.

export USE_CCACHE=1

Если у вас нет свободного места на диске, вы можете ограничить размер кэша. Если вы создаете ROM для одного устройства, вы можете ограничить его до 15 Гб. Для этого используйте команду ccache.

prebuilts/misc/linux-x86/ccache/ccache -M 15G
Set cache size limit to 15.0 Gbytes

5: Настройка сервера Jack

Сервер Jack, который отвечает за сборку большинства частей ROM на основе Java, требует много памяти. Чтобы избежать ошибок, связанных с распределением памяти, вы можете использовать переменную среды ANDROID_JACK_VM_ARGS и указать, сколько памяти может использовать Jack. Обычно достаточно выделить около 50% оперативной памяти сервера. Эта переменная среды также указывает другие параметры компиляции.

Выполните следующую команду, чтобы выделить 8 Гб памяти серверу Jack и сохранить параметры компиляции по умолчанию:

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

6: Начало сборки

Дерево кода AOSP содержит сценарий envsetup.sh, который имеет несколько вспомогательных функций, связанных со сборкой. Многие вспомогательные функции (mm, mma и mmm) являются ярлыками команды make; другие, такие как lunch, используют важные переменные среды, которые, среди прочего, определяют архитектуру процессора ROM, а также тип сборки.

Выполните следующую команду. Чтобы получить доступ к вспомогательным функциям:

source build/envsetup.sh
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 и укажите кодовое имя вашего устройства и суффикс типа сборки (это может быть eng, userdebug или user). Типы сборки eng и userdebug подходят для создания ROM-ов для тестирования, а тип user рекомендуется использовать в производстве.

Чтобы создать тестовый ROM, который может запускаться на эмуляторе AOSP ARM, передайте aosp_arm-eng команде lunch:

lunch aosp_arm-eng
============================================
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, чтобы определить количество параллельных заданий (оно должно быть равно количеству доступных на сервере процессоров).

Используйте команду nproc, чтобы узнать, сколько у вас процессоров:

nproc
8

Затем используйте этот результат в команде make:

make -j8

Даже с 8 процессорами для завершения сборки вам потребуется более часа (при условии, что на вашем сервере не будет активных процессов с интенсивным потреблением ресурсов). Продолжительность сборки прямо пропорциональна объему RAM и количеству доступных процессоров.

Примечание: Во время сборки вы увидите много предупреждений. Можете смело игнорировать их.

Как только ROM будет готов, вы увидите сообщение о том, что сборка выполнена успешно. Вы также сможете увидеть точную продолжительность сборки.

...
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/.

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

Чтобы протестировать ROM, вы можете попытаться загрузить его с помощью команды emulator. Если вы находитесь в среде, которая не является GUI, передаете флаги -no-window и -noaudio.

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

Чтобы проверить, удалось ли эмулятору успешно загрузиться, подождите минуту и используйте утилиту отладки Android, adb, чтобы открыть оболочку на эмуляторе.

adb shell

Если в ROM нет ошибок, вы увидите командную строку оболочки, запущенной на эмуляторе.

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

Выйдите из этой оболочки, набрав exit и нажав Enter, или нажав Ctrl + D.

Примечание: Если вы попытаетесь открыть оболочку перед запуском эмулятора, вы увидите сообщение об ошибке (потому что эмулятор отключен). Подождите немного и повторите попытку.

Устранение неполадок

Если ваша сборка не удалась, наиболее вероятной причиной является недостаточное количество памяти. Чтобы исправить это, сначала запустите сервер Jack, выполнив следующую команду:

jack-admin kill-server

Затем запустите сборку, но установите меньшее количество параллельных задач. Например, вот так вы можете уменьшить количество параллельных задач до 2:

make -j2

Если сборка завершилась неудачно из-за нехватки дискового пространства, вы, вероятно, запустили повторную сборку, не очистив перед этим результаты предыдущих сборок. Чтобы удалить результаты предыдущих сборок, вы можете запустить следующую команду:

make clobber

Также вы можете попробовать добавить дисковое пространство с помощью блочных хранилищ.

Заключение

В этом уроке вы научились создавать AOSP ROM для Android Oreo. Методы, которые вы узнали сегодня, применимы ко всем форкам AOSP (в том числе к Lineage OS и Resurrection Remix OS). Если у вас есть опыт разработки приложений для Android, вы можете попробовать изменить небольшие части кодовой базы AOSP, чтобы кастомизировать ROM.

Чтобы узнать больше о создании исходного кода AOSP, посетите форум Android Building в Google Groups.

Tags: , ,