Общее системное изображение

На этой странице описаны различные механизмы, которые производители устройств Android могут использовать для создания общего образа системы (SSI) для разных товарных линеек. Также в нем предлагается процедура создания SSI на основе общего образа системы (GSI), созданного в AOSP.

Фон

Фреймворк Android Open Source Project (AOSP) соответствует архитектуре Mainline, чтобы поддерживать обратную совместимость с более старыми реализациями поставщиков. Например, образ Generic System Image (GSI), созданный на основе исходного кода Android 10 AOSP, можно запустить на любом устройстве с поддержкой Treble и ОС Android 8 или более поздней версии.

Mainline разделяет Android на две части: реализацию поставщика оборудования и общую платформу ОС Android. Каждый компонент устанавливается в отдельный раздел: раздел поставщика для ПО, предназначенного для конкретного оборудования, и системный раздел для общей ОС. Между ними действует интерфейс с версиями, который называется интерфейсом поставщика (VINTF). Такая система разделов позволяет OEM-производителям изменять системный раздел, не затрагивая раздел поставщика, и наоборот.

Раньше поставщики однокристальных систем и производители оригинального оборудования сильно изменяли фреймворк Android, который поставлялся на потребительские устройства. Подробнее об этом рассказывается в статье Жизненный цикл выпуска Android. Поскольку эти расширения фреймворка редко разрабатывались с учетом обратной совместимости, модификации, относящиеся к определенным устройствам, значительно увеличивали сложность и финансовые затраты на последующие обновления ОС. В Android 10 (уровень API 29) и более ранних версиях не было четкой стандартизированной архитектуры, которая позволяла бы партнерам создавать модульные расширения для фреймворка Android.

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

Подробные инструкции по реализации вы найдете в разделе Рекомендуемые шаги для входа с помощью аккаунта Google. Шаги являются модульными. В зависимости от архитектуры вы можете реализовать определенные этапы (например, Шаг 1. Наследуйте generic_system.mk для системного образа OEM (OEM GSI)), а не все.

Обзор SSI

При использовании SSI компоненты ПО, относящиеся к определенному продукту, и расширения OEM размещаются в новом разделе /product. Компоненты в разделе /product используют четко определенный стабильный интерфейс для взаимодействия с компонентами в разделе /system. Производители могут создать один SSI или несколько SSI для использования в разных SKU устройств. Когда выходит новая версия ОС Android, производители оборудования тратят средства только на одно обновление своих SSI до последней версии Android. Они могут повторно использовать SSI для обновления нескольких устройств без обновления раздела /product.

Производители оборудования и поставщики систем на кристалле могут создавать SSI с собственными функциями и изменениями. Механизмы и рекомендации, приведенные на этой странице, предназначены для того, чтобы помочь OEM-производителям достичь следующих целей:

  • Повторно использовать SSI для разных SKU устройств.
  • Обновление системы Android с помощью модульных расширений, чтобы упростить обновление ОС.

Основная идея разделения компонентов, относящихся к определенному продукту, на раздел продукта аналогична разделению компонентов, относящихся к определенной системе на кристалле, на раздел поставщика в Mainline. Интерфейс продукта (похожий на VINTF) позволяет SSI взаимодействовать с разделом продукта. В отношении SSI термин компоненты описывает все ресурсы, двоичные файлы, тексты и библиотеки, которые устанавливаются в образы, становящиеся разделами.

Разделы вокруг SSI

На рисунке 1 показаны разделы вокруг SSI, а также интерфейсы с версиями в разных разделах и правила для этих интерфейсов. В этом разделе подробно описаны все разделы и интерфейсы.

Разделы и интерфейсы вокруг блок-схемы SSI

Рисунок 1. Разделы и интерфейсы, связанные с SSI.

Образы и разделы

В этом разделе объясняется разница между терминами образ и раздел.

  • Образ – это концептуальная часть программного обеспечения, которую можно обновлять независимо от других частей.
  • Раздел – это физическое место хранения, которое можно обновлять независимо от других разделов.

Разделы на рисунке 1 определены следующим образом:

  • SSI – изображение, которое используется на нескольких устройствах одного производителя оригинального оборудования. В нем нет компонентов, относящихся к определенному оборудованию или продукту. Все, что есть в определенном SSI, по определению доступно всем устройствам, использующим этот SSI. SSI состоит из одного изображения /system или из изображения /system и разделов /system_ext.

  • Образ продукта. Набор компонентов, относящихся к определенному продукту или устройству, которые представляют собой настройки и расширения ОС Android, выполненные производителем. Поместите компоненты, относящиеся к однокристальной системе, в раздел /vendor. Поставщики SoC также могут использовать раздел /product для подходящих компонентов, например независимых от SoC. Например, если поставщик SoC предоставляет своим клиентам из числа OEM-производителей независимый от SoC компонент, который можно не включать в продукт, поставщик SoC может разместить этот компонент на изображении продукта. Расположение компонента определяется его назначением, а не принадлежностью.

  • Образ поставщика. Набор компонентов, предназначенных для определенной однокристальной системы.

  • Образ ODM. Набор компонентов, предназначенных для конкретной платы и не предоставляемых SoC. Как правило, образ поставщика принадлежит поставщику SoC, а образ ODM – производителю устройства. Если отдельного раздела /odmнет, изображения поставщика SoC и ODM объединяются в разделе /vendor.

Раздел /system_ext

Раздел /system_ext указывать необязательно. Используйте этот раздел для любых специальных функций и расширений, тесно связанных с компонентами на основе AOSP. Предполагается, что этот раздел является расширением раздела /system, относящимся к производителю оригинального оборудования, без интерфейса, определенного для обоих разделов. Компоненты в разделе /system_ext могут выполнять частные вызовы API в раздел /system, а компоненты в разделе /system могут выполнять частные вызовы API в раздел /system_ext.

Поскольку эти два раздела тесно связаны, они обновляются вместе при выпуске новой версии Android. Раздел /system_ext, созданный для предыдущей версии Android, не обязательно должен быть совместим с разделом /system в следующей версии Android.

Чтобы установить модуль в раздел /system_ext, добавьте system_ext_specific: true в файл Android.bp. На устройствах, где нет раздела /system_ext, устанавливайте такие модули в подкаталог ./system_ext в разделе /system.

История. Изначально раздел /system_ext был предназначен для размещения всех компонентов, относящихся к производителю оригинального оборудования, независимо от того, являются ли они общими, в разделе /product. Однако перенести их все сразу было невозможно, особенно учитывая, что некоторые компоненты были тесно связаны с разделом /system. Чтобы переместить тесно связанный компонент в раздел /product, необходимо расширить интерфейс продукта. Часто для этого требовалось значительно переработать сам компонент, что отнимало много времени и сил. Раздел /system_ext изначально был создан для временного хранения компонентов, которые ещё не готовы к переносу в раздел /product. Цель SSI – в конечном итоге удалить раздел /system_ext.

Однако раздел /system_ext полезен для того, чтобы раздел /system был как можно ближе к AOSP. При обновлении SSI большая часть усилий приходится на компоненты в разделах /system и /system_ext. Если образ системы создан на основе источников, максимально похожих на AOSP, то при обновлении можно сосредоточиться на образе system_ext.

Интерфейсы между изображениями

В SSI есть два основных интерфейса для изображений поставщиков и товаров:

  • Интерфейс поставщика (VINTF). VINTF – это интерфейс для компонентов, которые находятся в образах поставщика и ODM. Компоненты в образах продукта и системы могут взаимодействовать с образами поставщика и ODM только через этот интерфейс. Например, изображение поставщика не может зависеть от закрытой части системного образа, и наоборот. Это определено в архитектуре Treble (теперь она является частью более широкой архитектуры Mainline), которая разделяет образы на системный и поставщика. Интерфейс описан с помощью следующих механизмов:

    • HIDL (Passthrough HAL доступен только для модулей system и system_ext)
    • Stable AIDL
    • Конфигурации
      • API системных свойств
      • API схемы файла конфигурации
    • VNDK
    • API Android SDK
    • Библиотека Java SDK
  • Интерфейсы продукта. Интерфейс продукта – это интерфейс между SSI и изображением продукта. Определение стабильного интерфейса позволяет отделить компоненты продукта от системных компонентов в SSI.

Включить SSI

В этом разделе объясняется, как поддерживать SSI в Android 11 и более поздних версиях.

Как отменить объединение компонентов

Чтобы отделить раздел /product от системных компонентов, для /product него нужно задать те же правила принудительного применения, что и для раздела /vendor, который уже был отделен с помощью Mainline.

  • Встроенные интерфейсы. Встроенные модули в разделе /product должны быть отделены от других разделов. Единственные допустимые зависимости модулей продукта – это некоторые библиотеки VNDK (включая LLNDK) из раздела /system. Библиотеки JNI, от которых зависят приложения продукта, должны быть библиотеками NDK.
  • Интерфейсы Java. Модули Java (приложения) в разделе /product не могут использовать скрытые API, поскольку они нестабильны. Эти модули должны использовать только общедоступные и системные API из раздела /system, а также библиотеки Java SDK из разделов /system или /system_ext. Вы можете определить библиотеки Java SDK для пользовательских API.

Принудительное применение интерфейсов продуктов

Чтобы убедиться, что раздел /product не связан с другими разделами, производители устройств могут настроить принудительное использование интерфейсов продукта, задав значение PRODUCT_PRODUCT_VNDK_VERSION:= current для встроенных модулей и PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true для модулей Java. Эти переменные устанавливаются автоматически, если значение PRODUCT_SHIPPING_API_LEVEL устройства больше или равно 30. Подробнее об интерфейсах для разделения товаров…

Рекомендуемые действия для SSI на основе GSI

Предлагаемые разделы для SSI на основе GSI

Рисунок 2. Предлагаемые разделы для SSI на основе GSI.

Общий образ системы (GSI) – это образ системы, созданный непосредственно на основе AOSP. Он используется для тестирования на соответствие требованиям (например, CTS-on-GSI) и в качестве эталонной платформы, которую разработчики приложений могут использовать для тестирования совместимости своих приложений, когда у них нет реального устройства с требуемой версией Android.

Производители оригинального оборудования также могут использовать GSI для создания SSI. Как описано в разделе Образы и разделы, SSI состоит из системного образа для компонентов, определенных AOSP, и образа system_ext для компонентов, определенных OEM. Если в качестве образа system используется GSI, производитель устройства может сосредоточиться на образе system_ext при обновлении.

В этом разделе приведены инструкции для производителей устройств, которые хотят разделить свои настройки на разделы /system_ext и /product, используя образ системы AOSP или почти AOSP. Если производитель устройства создает образ системы на основе исходного кода AOSP, он может заменить созданный им образ на GSI, предоставленный AOSP. Однако производителям оригинального оборудования не обязательно сразу переходить к последнему шагу (использованию GSI в исходном виде).

Шаг 1. Наследуйте generic_system.mk для образа системы OEM (OEM GSI)

Благодаря наследованию generic_system.mk (в Android 11 этот файл назывался mainline_system.mk, а в AOSP был переименован в generic_system.mk) образ системы (OEM GSI) включает все файлы, которые есть в AOSP GSI. Эти файлы могут быть изменены производителями оборудования, чтобы OEM GSI содержал собственные файлы OEM в дополнение к файлам AOSP GSI.

Наследование generic_system.mk для образа системы OEM

Рисунок 3. Наследуйте generic_system.mk для образа системы OEM.

Шаг 2. Убедитесь, что список файлов в образе GSI от OEM-производителя совпадает со списком файлов в образе GSI от AOSP

На этом этапе в GSI от OEM-производителя не должно быть дополнительных файлов, поэтому переместите проприетарные файлы в раздел system_ext или product.

Перемещение добавленных файлов из GSI OEM

Рисунок 4. Переместите добавленные файлы из OEM GSI.

Шаг 3. Создайте белый список, чтобы ограничить количество измененных файлов в GSI от OEM-производителя

Чтобы проверить измененные файлы, OEM-производители могут использовать инструмент compare_images и сравнить GSI AOSP с GSI OEM. Получите образ системы AOSP GSI из целевого объекта generic_system_* AOSP lunch.

Периодически запуская инструмент compare_images с параметром allowlist, вы можете отслеживать различия, не входящие в разрешенный список. Это предотвращает дальнейшие изменения в GSI от OEM.

Как создать белый список, чтобы сократить список измененных файлов в образе GSI от OEM-производителя

Рисунок 5. Определите белый список, чтобы сократить список измененных файлов в образе GSI от OEM-производителя.

Шаг 4. Убедитесь, что в образе GSI от OEM используются те же исполняемые файлы, что и в образе GSI от AOSP

Очистка белого списка позволяет OEM-производителям использовать AOSP GSI в качестве образа системы для своих продуктов. Чтобы очистить белый список, производители устройств могут либо отказаться от изменений в GSI для OEM, либо передать их в AOSP, чтобы они были включены в GSI для AOSP.

Как сделать так, чтобы в образе GSI от OEM-производителя были те же двоичные файлы, что и в образе GSI от AOSP

Рисунок 6. Убедитесь, что в GSI от OEM и AOSP используются одни и те же двоичные файлы.

Что такое SSI

Чтобы определить SSI, производители оригинального оборудования могут воспользоваться следующими рекомендациями.

Защита раздела /system во время сборки

Чтобы избежать изменений в разделе /system, связанных с определенным продуктом, и определить OEM GSI, производители оборудования могут использовать макрос makefile под названием require-artifacts-in-path. Он запрещает объявление системных модулей после вызова макроса. Пример приведен в разделе Шаг 1. Создайте make-файл и включите проверку пути к артефакту.

OEM-производители могут определить список, чтобы разрешить временную установку модулей для конкретных продуктов в раздел /system. Однако, чтобы сделать образ GSI общим для всех продуктов OEM, список должен быть пустым. Этот процесс предназначен для определения GSI OEM и может не зависеть от шагов для GSI AOSP.

Как сделать раздел /system_ext общим

Раздел /system_ext может различаться на разных устройствах, поскольку в нем могут быть системные модули, предназначенные для конкретных устройств. Поскольку SSI состоит из разделов /system и /system_ext, различия в разделе /system_ext мешают OEM-производителям определить SSI. OEM-производители могут иметь собственный SSI и использовать его на нескольких устройствах, удалив все различия и сделав раздел /system_ext общим.

В этом разделе приведены рекомендации по созданию общего раздела /system_ext.

Предоставление доступа к скрытым API в системном разделе

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

Рекомендуемый способ удалить скрытые API из приложений – найти альтернативные общедоступные или системные API и заменить ими скрытые. Если нет API, которые могли бы заменить скрытые API, производители оригинального оборудования могут внести свой вклад в AOSP, чтобы определить новые системные API для своих устройств.

Кроме того, производители оригинального оборудования могут создавать собственные API, добавляя библиотеку Java SDK в раздел /system_ext. Эта библиотека может использовать скрытые API в системном разделе и предоставлять API приложениям в разделе продукта или поставщика. Производители оборудования должны заморозить API, ориентированные на продукт, для обеспечения обратной совместимости.

Замена отключения приложений на уровне SKU

В Android 16 устаревший механизм выборочного отключения APK-файлов на основе SKU оборудования с помощью оверлеев ресурсов фреймворка (config_disableApksUnlessMatchedSku_apk_list и config_disableApkUnlessMatchedSku_skus_list) был удален. Подробнее об этом рассказывается в изменении 3444399.

Вместо этого рекомендуется использовать системную конфигурацию install-in-user-type в каталогах, относящихся к определенным SKU. Этот подход позволяет предотвратить установку пакета для любого пользователя с определенным SKU, а не просто отключить его после установки.

  1. Включите в образ все APK (суперсет всех потенциальных приложений для всех SKU в образе системы), обычно в раздел /product.

  2. Убедитесь, что SKU устройства правильно задан в системном свойстве ro.boot.hardware.sku (используется системой для определения SKU устройства во время загрузки).

  3. Создайте вложенные каталоги sysconfig для каждого SKU в каталоге /product/etc/sysconfig/ с помощью соглашения об именовании sku_<SKU_NAME>. Система автоматически загружает конфигурации из каталога, соответствующего свойству ro.boot.hardware.sku. Пример пути: /product/etc/sysconfig/sku_basic_model/.

  4. Настройте запрет на установку приложений. В каталоге, относящемся к SKU, создайте XML-файл конфигурации (например, disabled_apps.xml) и используйте тег <do-not-install-in>, чтобы исключить определенные пакеты.

Пример XML-кода (/product/etc/sysconfig/sku_basic_model/disabled_apps.xml):

<?xml version="1.0" encoding="utf-8"?>
<config>
    <!-- Prevents this package from being installed for ANY user on this SKU -->
    <install-in-user-type package="com.example.premium.feature.app" >
        <do-not-install-in user-type="FULL" />
        <do-not-install-in user-type="SYSTEM" />
    </install-in-user-type>
</config>

Ниже приведено сравнение этих двух методов.

Функция Android 15 и более ранние версии Android 16 и более поздних версий
Способ настройки Переопределения ресурсов фреймворка XML-файлы SystemConfig
Логическое местоположение config.xml (наложение ресурсов) /product/etc/sysconfig/sku_<name>/
Результат Отключает приложение с помощью PackageManager. Запрещает пользователю устанавливать приложения.
Надежность Может быть включено системными службами Пакет не устанавливается для пользователя.

Если вам нужен более детальный контроль (например, отключение приложения, которое обычно устанавливается по умолчанию во всех версиях), Android также поддерживает теги disabled-in-sku и enabled-in-sku-override в файле sysconfig:

  • <disabled-in-sku package="com.example.app" /> отключает приложение для всех пользователей.

  • <enabled-in-sku-override package="com.example.app" /> снова включает приложение для определенного SKU, если поместить его в соответствующий каталог sku_<name>.

Определите RRO вместо использования статического наложения ресурсов

Статический оверлей ресурсов управляет пакетами, на которые он накладывается. Однако это может помешать определению SSI, поэтому убедитесь, что свойства для RRO включены и настроены правильно. Задав следующие свойства, производители устройств могут сделать все автоматически созданные оверлеи RRO.

PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty

Если требуется подробная конфигурация, определите RRO вручную, а не полагайтесь на созданный автоматически. Подробную информацию можно найти в статье Как изменить значение ресурсов приложения во время выполнения. Производители устройств также могут определять условные RRO, которые зависят от системных свойств, с помощью атрибутов android:requiredSystemPropertyName и android:requiredSystemPropertyValue.

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

Ниже приведены ответы на часто задаваемые вопросы об SSI.

Можно ли определить несколько источников структурированных данных?

Это зависит от общих характеристик устройств (или группы устройств). Производители устройств могут сделать раздел system_ext общим, как описано в разделе Как сделать раздел system_ext общим. Если в группе устройств много различий, лучше определить несколько SSI.

Можно ли удалить из файла generic_system.mk модули, которые конфликтуют с моей реализацией?

Нет. В GSI есть минимальный набор загружаемых и тестируемых модулей. Если вы считаете, что модуль не нужен, сообщите об ошибке, чтобы обновить файл generic_system.mk.