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
(однако такие процессы могут ссылаться на библиотеки VNDK). Попытки нарушить конфигурацию компоновки времени выполнения приводят к сбою процесса и генерации сообщения об ошибке CANNOT LINK EXECUTABLE
.
Обеспечить соблюдение интерфейсов Java
Чтобы включить принудительное применение интерфейса Java, установите PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
в true
. (Значение автоматически устанавливается в true
, если уровень API доставки для цели больше 29.) При включении принудительное применение разрешает или запрещает следующий доступ:
API | /система | /системное_расширение | /продукт | /продавец | /данные |
---|---|---|---|---|---|
Публичный 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: Создайте makefile и включите проверку пути к артефакту
На этом этапе вы определяете system
make-файл.
Создайте makefile, который определяет пакеты для
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
наследуйте общий makefile для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
, makefiles вне oem_system.mk
не могут включать модули, установленные в root
или system
раздел. Чтобы включить эти модули, необходимо либо определить их в самом файле oem_system.mk
, либо во включенном makefile. Попытки установить модули по запрещенным путям приводят к сбоям сборки. Чтобы исправить сбои, выполните одно из следующих действий:
Вариант 1: Включить системный модуль в makefiles, включенные в
oem_system.mk
. Это позволяет выполнить требование к пути артефакта (поскольку модули теперь существуют во включенном makefile) и, таким образом, позволяет выполнить установку в набор путей в `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 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