В Android 11 раздел product
разделяется, делая его независимым от system
и раздела vendor
. В рамках этих изменений теперь можно контролировать доступ раздела product
к нативным и Java-интерфейсам (аналогично тому, как работает принудительное применение интерфейсов для разделов vendor
).
Обеспечить использование собственных интерфейсов
Чтобы включить принудительное применение собственного интерфейса, установите для PRODUCT_PRODUCT_VNDK_VERSION
значение current
. (Версия автоматически устанавливается current
, если уровень API доставки для цели превышает 29.) Принудительное применение позволяет:
- Нативные модули в разделе
product
для ссылки:- Статически или динамически к другим модулям в разделе
product
, которые включают статические, общие или заголовочные библиотеки. - Динамически в библиотеки VNDK в
system
разделе.
- Статически или динамически к другим модулям в разделе
- Библиотеки JNI в нераспакованных APK в разделе
product
для связи с библиотеками в/product/lib
или/product/lib64
(это в дополнение к библиотекам NDK).
Принудительное исполнение не допускает иных ссылок на разделы, кроме раздела product
.
Контроль времени сборки (Android.bp)
В Android 11 системные модули могут создавать варианты изображений продукта в дополнение к вариантам основного изображения и изображения поставщика. При включенном принудительном использовании нативного интерфейса ( PRODUCT_PRODUCT_VNDK_VERSION
имеет значение current
):
Собственные модули в разделе
product
находятся в варианте продукта, а не в варианте ядра.Модули, в файлах
Android.bp
которых указаноproduct_available: true
доступны для варианта продукта.Библиотеки или двоичные файлы, которые указывают
product_specific: true
могут ссылаться на другие библиотеки, которые указываютproduct_specific: true
илиproduct_available: true
в своих файлахAndroid.bp
.Библиотеки VNDK должны иметь
product_available: true
в своих файлахAndroid.bp
, чтобы двоичные файлыproduct
могли ссылаться на библиотеки VNDK.
В следующей таблице приведены свойства Android.bp
, используемые для создания вариантов изображений.
Свойства в Android.bp | Созданные варианты | |
---|---|---|
До вступления в силу | После исполнения | |
по умолчанию (нет) | основной (включая /system , /system_ext и /product ) | основной (включая /system и /system_ext , но не /product ) |
system_ext_specific: true | основной | основной |
product_specific: true | основной | продукт |
vendor: true | продавец | продавец |
vendor_available: true | ядро, поставщик | ядро, поставщик |
product_available: true | Н/Д | ядро, продукт |
vendor_available: true И product_available: true | Н/Д | ядро, продукт, поставщик |
system_ext_specific: true И vendor_available: true | ядро, поставщик | ядро, поставщик |
product_specific: true И vendor_available: true | ядро, поставщик | продукт, поставщик |
Контроль времени сборки (Android.mk)
При включении принудительного использования нативного интерфейса нативные модули, установленные в разделе product
, имеют тип ссылки native:product
, который может ссылаться только на другие модули native:product
или native:vndk
. Попытка ссылаться на любые другие модули приводит к ошибке проверки типа ссылки системой сборки.
Обеспечение выполнения
При включении принудительного использования собственного интерфейса конфигурация компоновщика для бионического компоновщика не позволяет системным процессам использовать библиотеки product
, создавая раздел product
для процессов product
, которые не могут ссылаться на библиотеки вне раздела product
(однако такие процессы могут ссылаться на библиотеки VNDK). Попытки нарушить конфигурацию компоновки среды выполнения приводят к сбою процесса и появлению сообщения об ошибке CANNOT LINK EXECUTABLE
.
Обеспечить соблюдение интерфейсов Java
Чтобы включить принудительное использование интерфейса Java, установите для PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
значение true
. (Значение автоматически устанавливается равным true
, если уровень API доставки для целевого объекта превышает 29.) При включении принудительное использование разрешает или запрещает следующий доступ:
API | /система | /system_ext | /продукт | /продавец | /данные |
---|---|---|---|---|---|
Публичный API | |||||
@SystemApi | |||||
@hide API |
Как и в разделе vendor
, приложению или библиотеке Java в разделе product
разрешено использовать только публичные и системные API; ссылка на библиотеку, использующую скрытые API, запрещена. Это ограничение включает в себя ссылку на этапе сборки и рефлексию во время выполнения.
Соблюдение сроков сборки
Во время сборки Make и Soong проверяют, что модули Java в разделе product
не используют скрытые API, проверяя поля platform_apis
и sdk_version
. В полях sdk_version
приложений в разделе product
должна быть указана current
, system_current
или числовая версия API, а поле platform_apis
должно быть пустым.
Обеспечение выполнения
Среда выполнения Android проверяет, что приложения в разделе product
не используют скрытые API, включая рефлексию. Подробнее см. в разделе «Ограничения на интерфейсы, не входящие в SDK» .
Включить принудительное применение интерфейса продукта
Используйте шаги, описанные в этом разделе, чтобы включить принудительное применение интерфейса продукта.
Шаг | Задача | Необходимый |
---|---|---|
1 | Определите свой собственный системный make-файл, который определяет пакеты для system раздела, затем установите проверку требований к пути к артефактам в device.mk (чтобы предотвратить установку несистемных модулей в system раздел). | Н |
2 | Очистите список разрешенных. | Н |
3 | Обеспечить применение собственных интерфейсов и выявить сбои в работе ссылок (может работать параллельно с применением Java). | Y |
4 | Обеспечить соблюдение интерфейсов Java и проверить поведение среды выполнения (может работать параллельно с собственным обеспечением). | Y |
5 | Проверьте поведение во время выполнения. | Y |
6 | Обновите device.mk с учетом поддержки интерфейса продукта. | Y |
Шаг 1: Создайте make-файл и включите проверку пути к артефакту
На этом этапе вы определяете system
make-файл.
Создайте make-файл, определяющий пакеты для
system
раздела. Например, создайте файлoem_system.mk
со следующим содержимым:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)
В файле
device.mk
унаследуйте общий make-файл дляsystem
раздела и включите проверку требований к пути к артефакту. Например:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
О требованиях к пути артефакта
Если PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
имеет значение true
или strict
, система сборки запрещает установку пакетов, определенных в других make-файлах, по путям, указанным в require-artifacts-in-path
и запрещает пакетам, определенным в текущем make-файле, устанавливать артефакты за пределами путей, определенных в require-artifacts-in-path
.
В примере выше, когда PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
установлен в strict
, make-файлы вне oem_system.mk
не могут включать модули, установленные в root
или system
разделе. Чтобы включить эти модули, необходимо либо определить их в самом файле oem_system.mk
, либо во включаемом make-файле. Попытки установить модули по запрещённым путям приводят к сбоям сборки. Чтобы исправить сбои, выполните одно из следующих действий:
Вариант 1: включить модуль system в make-файлы, входящие в состав
oem_system.mk
. Это обеспечит выполнение требования к пути к артефакту (поскольку модули теперь находятся во включённом make-файле) и, таким образом, позволит выполнить установку по набору путей, указанных в `require-artifacts-in-path.Вариант 2: Установить модули в раздел
system_ext
илиproduct
(и не устанавливать модули вsystem
раздел).Вариант 3: Добавьте модули в список
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
. Здесь перечислены модули, разрешённые к установке.
Шаг 2: Очистите список разрешенных
На этом этапе список PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
становится пустым, чтобы все устройства, использующие файл oem_system.mk
, также могли использовать один и тот же образ system
. Чтобы очистить список разрешённых модулей, переместите все модули из списка в раздел system_ext
или product
либо добавьте их в файлы сборки system
. Этот шаг необязателен, поскольку определение общего образа system
не требуется для включения принудительного использования интерфейса продукта. Однако очистка списка разрешённых модулей полезна для определения границ system
с помощью system_ext
.
Шаг 3: Внедрение собственных интерфейсов
На этом этапе вы устанавливаете PRODUCT_PRODUCT_VNDK_VERSION := current
, а затем ищете ошибки сборки и выполнения и устраняете их. Чтобы проверить загрузку устройства и журналы, а также найти и исправить ошибки компоновки во время выполнения:
Установить
PRODUCT_PRODUCT_VNDK_VERSION := current
.Соберите устройство и проверьте на наличие ошибок сборки. Скорее всего, вы увидите несколько ошибок сборки, связанных с отсутствием некоторых вариантов продукта или основных вариантов. Распространенные ошибки включают:
- Любой модуль
hidl_interface
сproduct_specific: true
не будет доступен для системных модулей. Чтобы исправить это, заменитеproduct_specific: true
наsystem_ext_specific: true
. - В модулях может отсутствовать вариант продукта, необходимый для модулей продукта. Чтобы исправить это, сделайте этот модуль доступным для раздела
product
, установив параметрproduct_available: true
, или переместите модуль в разделproduct
, установив параметрproduct_specific: true
.
- Любой модуль
Устраните ошибки сборки и обеспечьте успешную сборку устройства.
Перепрошейте образ и проверьте наличие ошибок выполнения при загрузке устройства и в журналах.
- Если тег
linker
из журнала тестового случая показывает сообщениеCANNOT LINK EXECUTABLE
, в make-файле отсутствует зависимость (и она не была зафиксирована во время сборки). - Чтобы проверить ее из системы сборки, добавьте требуемую библиотеку в поле
shared_libs:
илиrequired:
- Если тег
Устраните недостающие зависимости, следуя приведенным выше рекомендациям.
Шаг 4: Внедрение интерфейсов Java
На этом этапе вы устанавливаете PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
, а затем находите и исправляете возникающие ошибки сборки. Обратите внимание на два конкретных типа ошибок:
Ошибки типа ссылки. Эта ошибка указывает на то, что приложение ссылается на модули Java с более широким значением
sdk_version
. Чтобы исправить это, можно расширитьsdk_version
приложения или ограничить значениеsdk_version
библиотеки. Пример ошибки:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or sma
ller API set than the source.Ошибки символов. Эта ошибка означает, что символ не может быть найден, поскольку он находится в скрытом API. Чтобы исправить это, используйте видимый (не скрытый) API или найдите альтернативу. Пример ошибки:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
Шаг 5: Проверка поведения во время выполнения
На этом этапе вы проверяете, соответствует ли поведение среды выполнения ожидаемому. Для отлаживаемых приложений вы можете отслеживать использование скрытого API, используя журнал с помощью StrictMode.detectNonSdkApiUsage
(который генерирует журнал, когда приложение использует скрытый API). Кроме того, вы можете использовать инструмент статического анализа Veridex для получения информации о типе использования (связывание или отражение), уровне ограничений и стеке вызовов.
Синтаксис Veridex:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Пример результата проверки:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
Подробную информацию об использовании Veridex см. в разделе Тестирование с использованием инструмента Veridex .
Шаг 6: Обновите device.mk
После исправления всех ошибок сборки и выполнения, а также проверки того, что поведение выполнения соответствует ожидаемому, установите в device.mk
следующее:
-
PRODUCT_PRODUCT_VNDK_VERSION := current
-
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true