Android AOSP Overlay: принципы работы и практическое применение

Ошибка сборки вида duplicate resource или ситуация, когда изменённый в overlay файл не попадает в итоговый образ прошивки — типичный признак того, что механизм overlay в AOSP настроен неправильно или разработчик не учёл порядок приоритетов. Проверить это можно быстро: если значение из вашего оверлея не применилось, первым делом стоит убедиться, что путь к каталогу overlay действительно передан через переменную DEVICE_PACKAGE_OVERLAYS или PRODUCT_PACKAGE_OVERLAYS в конфигурации устройства.

Механизм overlay (оверлей, наложение ресурсов) — один из ключевых инструментов кастомизации Android Open Source Project. Он позволяет изменять ресурсы и конфигурацию системы, не редактируя исходный код фреймворка напрямую. Именно так производители устройств адаптируют AOSP под свои модели: меняют строки, размеры, массивы настроек и значения по умолчанию, сохраняя при этом возможность обновлять основной код без конфликтов слияния.

В этой статье разберём, как устроен механизм overlay в AOSP, какие бывают виды оверлеев, где они применяются на практике и какие ошибки встречаются чаще всего при работе с ними.

Что такое overlay в AOSP и зачем он нужен

Под overlay в контексте AOSP понимается каталог с ресурсами, которые «накладываются» поверх ресурсов основного пакета при сборке или во время выполнения. Система при обращении к ресурсу сначала проверяет наличие переопределённого значения в оверлее и только потом берёт значение по умолчанию из исходного пакета.

Главная практическая ценность подхода — отделение кастомизации от ядра. Вам не нужно править файлы в frameworks/base или packages/apps/Settings: достаточно создать зеркальную структуру каталогов в дереве устройства и положить туда только те ресурсы, которые требуется изменить. При обновлении исходников AOSP ваши изменения не конфликтуют с обновлённым кодом.

Типичные задачи, которые решаются через overlay:

  • 🔧 Изменение конфигурации фреймворка: параметры энергосбережения, списки системных разрешений, значения config.xml
  • 🎨 Замена строк, иконок и цветов в системных приложениях под бренд производителя
  • 📱 Настройка параметров под конкретное железо: размеры экрана, наличие датчиков, профили яркости
  • 🌐 Переопределение сетевых настроек оператора через CarrierConfig

Виды оверлеев: статические и runtime

В экосистеме Android существует два принципиально разных механизма наложения ресурсов, и их часто путают. Первый — статический overlay на этапе сборки: ресурсы подменяются ещё при компиляции пакета, и в итоговый APK попадают уже изменённые значения. Второй — Runtime Resource Overlay (RRO): отдельный пакет-оверлей, который накладывается на целевое приложение во время работы системы и может включаться и отключаться без пересборки прошивки.

Статические оверлеи задаются через переменные сборки, например DEVICE_PACKAGE_OVERLAYS в файле конфигурации устройства:

DEVICE_PACKAGE_OVERLAYS += device/vendor/model/overlay

RRO-пакеты, напротив, собираются как отдельные APK с манифестом, где указан целевой пакет:

<overlay android:targetPackage="com.android.settings"

android:targetName="Settings" />

Выбор между подходами зависит от задачи. Статический overlay проще и надёжнее, но требует пересборки образа при любом изменении. RRO гибче — его можно обновлять как обычное приложение, — однако накладывает ограничения: не все типы ресурсов доступны для переопределения во время выполнения.

КритерийСтатический overlayRRO (Runtime Resource Overlay)
Момент примененияВо время сборки образаВо время выполнения системы
Изменение без пересборкиНет, требуется пересборкаДа, оверлей можно обновлять
Форма поставкиКаталог ресурсов в дереве устройстваОтдельный APK-пакет
Типичное применениеКонфигурация устройства у производителяТемы, операторские настройки, варианты продукта
📊 Какой тип overlay вы используете чаще всего?
Статический overlay при сборке
Runtime Resource Overlay (RRO)
Оба подхода в одном проекте
Только изучаю тему

Структура каталогов и приоритеты

Каталог overlay повторяет структуру ресурсов целевого пакета. Например, чтобы переопределить значение из frameworks/base/core/res/res/values/config.xml, нужно создать файл по пути overlay/frameworks/base/core/res/res/values/config.xml и указать в нём только изменяемые ресурсы. Система сборки объединит их с исходными значениями.

Важный момент — приоритеты. Если один и тот же ресурс переопределён в нескольких overlay-каталогах, итоговое значение зависит от порядка их подключения в конфигурации сборки. Как правило, более специфичные оверлеи (уровня продукта) должны идти после более общих (уровня вендора или платформы), но точное поведение стоит проверять в документации к используемой системе сборки и версии Android, поскольку семантика переменных менялась между версиями.

⚠️ Внимание: порядок объявления overlay-каталогов в DEVICE_PACKAGE_OVERLAYS напрямую влияет на итоговые значения ресурсов. Если результат в прошивке не совпадает с ожиданием, проверьте, не переопределяется ли ваш ресурс другим overlay, подключённым позже в цепочке.

Для RRO приоритеты заданы иначе — через атрибуты манифеста и системные настройки, а конфликты между несколькими оверлеями на один пакет разрешаются системой по своим правилам. Перед проектированием сложной схемы с несколькими RRO стоит изучить раздел о runtime resource overlays в официальной документации AOSP для вашей версии Android.

Практика: настройка статического overlay для устройства

Ниже — общий порядок действий, который не зависит от конкретной модели устройства. Детали именования каталогов могут отличаться в зависимости от структуры вашего дерева исходников, поэтому сверяйтесь с примерами конфигураций устройств в ветке AOSP, на которую вы опираетесь.

Шаг первый — создать каталог overlay в дереве устройства и зарегистрировать его в конфигурации продукта. Затем внутри него воспроизвести путь к переопределяемому ресурсу и положить файл с нужными значениями. После этого выполняется полная или инкрементальная сборка, и результат проверяется на устройстве или эмуляторе.

☑️ Проверка статического overlay перед сборкой

Выполнено: 0 / 5

После прошивки результата полезно убедиться, что значение действительно применилось. Для ресурсов фреймворка это можно сделать, проверив соответствующее поведение системы или изучив содержимое собранного пакета. Если значение не изменилось, наиболее вероятные причины — неверный путь внутри overlay, опечатка в имени ресурса или перекрытие значения другим оверлеем с более высоким приоритетом.

Runtime Resource Overlay: особенности и ограничения

RRO работает иначе: это полноценный APK, который не содержит кода, а только ресурсы и манифест с указанием целевого пакета. Система сопоставляет ресурсы оверлея с ресурсами цели по именам и подменяет их при обращении. В современных версиях Android механизм развит в Runtime Resource Overlay с поддержкой целевых наборов ресурсов и политик наложения.

Существуют ограничения, о которых нужно знать до начала работы:

  • 🚫 RRO не может добавлять новые ресурсы в целевой пакет — только переопределять существующие
  • 🔒 Для системных пакетов оверлей обычно должен быть подписан соответствующим ключом или размещён в системном разделе
  • 📦 Не все типы ресурсов одинаково хорошо поддаются переопределению в рантайме; поведение зависит от версии Android

Управление состоянием RRO (включение, отключение) выполняется системными средствами. Разработчики прошивок могут использовать команды через adb shell, например cmd overlay, чтобы посмотреть список оверлеев и переключать их состояние на отладочной сборке. Доступность отдельных подкоманд зависит от версии системы.

adb shell cmd overlay list

adb shell cmd overlay enable имя.пакета.оверлея

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

Чем RRO отличается от тем Substratum и подобных решений

Пользовательские движки тем исторически использовали механизм RRO (а ранее — его предшественники) для подмены ресурсов системных приложений. Однако в стоковом Android применение неподписанных оверлеев ограничено: система проверяет подпись и размещение оверлей-пакетов. Поэтому полноценная работа сторонних тем обычно требует либо кастомной прошивки, либо специальных привилегий.

Типичные ошибки и их диагностика

Большинство проблем с overlay сводится к нескольким повторяющимся сценариям. Первая группа — ошибки сборки: конфликты ресурсов, когда один и тот же ресурс определён несколько раз с несовместимыми значениями, или ссылки на несуществующие идентификаторы. Система сборки в таких случаях выдаёт сообщение с указанием файла и имени ресурса — начинать разбор стоит именно с этого сообщения, а не с пересборки «с нуля».

Вторая группа — «тихие» неудачи: сборка проходит, но значение в прошивке не меняется. Здесь диагностика идёт по цепочке: проверяется регистрация каталога overlay в конфигурации, затем точность пути и имени ресурса, затем приоритеты конкурирующих оверлеев. Для RRO добавляется проверка состояния оверлея в системе и соответствия подписи.

Третья группа — проблемы после обновления исходников AOSP. Ресурс, который вы переопределяли, мог быть переименован или удалён в новой версии платформы, и тогда overlay либо перестаёт действовать, либо ломает сборку. Поэтому при миграции на новую версию Android разумно пересматривать содержимое overlay-каталогов и сверять его с актуальным деревом ресурсов.

Где применяются оверлеи в реальных проектах

В дереве AOSP примеры overlay-конфигураций можно найти в каталогах эталонных устройств и в конфигурациях Cuttlefish — виртуального устройства Google. Изучение этих примеров — хороший способ понять принятые соглашения об именовании и структуре, прежде чем проектировать собственную схему.

Производители устройств используют overlay для всего спектра кастомизации: от значений config.xml фреймворка (поведение кнопок, параметры дисплея, функции питания) до настроек операторов связи через механизм CarrierConfig. Разработчики кастомных прошивок применяют тот же подход, добавляя собственные значения по умолчанию поверх чистого AOSP.

Если вы только начинаете работу с AOSP, имеет смысл сначала собрать неизменённый образ для эмулятора или поддерживаемого устройства, убедиться в работоспособности сборочного окружения и лишь затем добавлять overlay-модификации небольшими порциями, проверяя результат после каждого изменения.

Часто задаваемые вопросы

Можно ли изменить код приложения через overlay?

Нет. Механизм overlay работает только с ресурсами: строками, размерами, массивами, цветами, разметкой и подобными сущностями. Изменить логику Java- или Kotlin-кода через overlay нельзя — для этого требуется правка исходников и пересборка пакета.

Чем overlay отличается от прямой правки исходников AOSP?

При прямой правке вы меняете файлы платформы, что создаёт конфликты при каждом обновлении исходников. Overlay хранит изменения отдельно, в дереве устройства, поэтому обновление AOSP проходит значительно проще, а кастомизация остаётся прозрачной и переносимой.

Работает ли RRO на обычном смартфоне без кастомной прошивки?

В стоковых прошивках применение произвольных RRO ограничено: система контролирует подпись и размещение оверлей-пакетов. Полноценная работа с собственными RRO обычно доступна при сборке собственного образа либо в отладочном окружении. Конкретные ограничения зависят от версии Android и политики производителя устройства.

Как узнать, какие оверлеи активны в системе?

На отладочной сборке можно использовать команду adb shell cmd overlay list, которая показывает известные системе оверлей-пакеты и их состояние. Набор доступных подкоманд зависит от версии Android.

Почему мой overlay применяется к одному приложению, но не к другому?

Возможные причины: ресурс в целевом пакете имеет другое имя или квалификатор конфигурации (например, значения для конкретной локали или плотности экрана), либо пакет получает значение не из ресурсов, а из другого источника — базы настроек или кода. Проверьте, откуда целевое приложение реально читает нужное значение.