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
находятся в варианте продукта, а не в основном варианте.Модули с
vendor_available: true
в своих файлахAndroid.bp
доступны для варианта продукта и варианта поставщика.Библиотеки или двоичные файлы, в которых указано
product_specific: true
, могут ссылаться на другие библиотеки, в которых указаноproduct_specific: true
илиvendor_available: true
в своих файлахAndroid.bp
.Библиотеки VNDK должны иметь
vendor_available: true
в своих файлахAndroid.bp
, чтобы двоичные файлыproduct
могли ссылаться на библиотеки VNDK.
В следующей таблице приведены свойства Android.bp
, используемые для создания вариантов изображения.
Свойства в Android.bp | Созданные варианты | |
---|---|---|
До исполнения | После исполнения | |
по умолчанию (нет) | основной (включает | основной (включает |
system_ext_specific: true | основной | основной |
product_specific: true | основной | товар |
vendor: true | продавец | продавец |
vendor_available: true | ядро, поставщик | ядро, продукт, поставщик |
system_ext_specific: true И vendor_available: true | ядро, поставщик | ядро, продукт, поставщик |
product_specific: true AND 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 | |||||
@скрыть 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_specfic: true
. - В модулях может отсутствовать вариант продукта, необходимый для модулей продукта. Чтобы исправить это, сделайте этот модуль доступным для раздела
product
, установивvendor_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 , чтобы узнать тип использования (связывание или отражение), уровень ограничений и стек вызовов.
Синтаксис 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