В 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могут ссылаться на другие библиотеки, в файлахAndroid.bpкоторых указаноproduct_specific: trueилиproduct_available: true.В файлах
Android.bpбиблиотек VNDK должна быть указанаproduct_available: true, чтобы исполняемые файлы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 AND product_available: true | Н/Д | ядро, продукт, поставщик |
system_ext_specific: true AND 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 , в разделе product приложением или библиотекой Java разрешено использовать только общедоступные и системные 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 | Создайте собственный системный makefile, который определяет пакеты для system раздела, а затем установите проверку требований к пути к артефактам в device.mk (чтобы предотвратить установку несистемных модулей в system раздел). | Н |
| 2 | Упорядочить список разрешенных объектов. | Н |
| 3 | Обеспечить корректное использование нативных интерфейсов и выявлять ошибки компоновки во время выполнения (может выполняться параллельно с обеспечением корректного использования Java). | Я |
| 4 | Обеспечивать соблюдение требований к интерфейсам Java и проверять поведение во время выполнения (может выполняться параллельно с проверкой нативных интерфейсов). | Я |
| 5 | Проверьте поведение во время выполнения. | Я |
| 6 | Обновите файл device.mk , добавив проверку интерфейса продукта. | Я |
Шаг 1: Создайте файл makefile и включите проверку пути к артефакту.
На этом шаге вы определяете system makefile.
Создайте файл 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 , 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 . Этот шаг необязателен, поскольку определение общего образа 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}Пример результата проверки 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