В 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
относятся к варианту продукта, а не к основному варианту.Модули с
product_available: true
в файлахAndroid.bp
доступны для варианта продукта.Библиотеки или двоичные файлы, в которых указано
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
(однако такие процессы могут ссылка на библиотеки ВНДК). Попытки нарушить конфигурацию связи во время выполнения приводят к сбою процесса и появлению сообщения об ошибке CANNOT LINK EXECUTABLE
.
Принудительно использовать интерфейсы Java
Чтобы включить принудительное применение интерфейса Java, установите для PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
значение true
. (Значение автоматически устанавливается равным true
, если уровень API доставки для целевого объекта превышает 29.) Если этот параметр включен, принудительное применение разрешает или запрещает следующий доступ:
API | /система | /system_ext | /продукт | /продавец | /данные |
---|---|---|---|---|---|
Публичный API | |||||
@SystemApi | |||||
@скрыть 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). | Да |
4 | Обеспечьте принудительное применение интерфейсов Java и проверку поведения во время выполнения (может выполняться параллельно с собственным обеспечением). | Да |
5 | Проверьте поведение во время выполнения. | Да |
6 | Обновите файл device.mk , указав принудительное применение интерфейса продукта. | Да |
Шаг 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. Включите системный модуль в 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
файлы make. Этот шаг является необязательным, поскольку определение общего образа 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 smaller 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 , чтобы получить тип использования (связывание или отражение), уровень ограничений и стек вызовов.
Синтаксис Веридекса:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
Пример результата veridex:
#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