Обеспечьте соблюдение интерфейсов разделов продуктов

В 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-файл.

  1. Создайте 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),)
    
  2. В файле 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 , а затем ищете ошибки сборки и выполнения и устраняете их. Чтобы проверить загрузку устройства и журналы, а также найти и исправить ошибки компоновки во время выполнения:

  1. Установить PRODUCT_PRODUCT_VNDK_VERSION := current .

  2. Соберите устройство и проверьте на наличие ошибок сборки. Скорее всего, вы увидите несколько ошибок сборки, связанных с отсутствием некоторых вариантов продукта или основных вариантов. Распространенные ошибки включают:

    • Любой модуль hidl_interface с product_specific: true не будет доступен для системных модулей. Чтобы исправить это, замените product_specific: true на system_ext_specific: true .
    • В модулях может отсутствовать вариант продукта, необходимый для модулей продукта. Чтобы исправить это, сделайте этот модуль доступным для раздела product , установив параметр product_available: true , или переместите модуль в раздел product , установив параметр product_specific: true .
  3. Устраните ошибки сборки и обеспечьте успешную сборку устройства.

  4. Перепрошейте образ и проверьте наличие ошибок выполнения при загрузке устройства и в журналах.

    • Если тег linker из журнала тестового случая показывает сообщение CANNOT LINK EXECUTABLE , в make-файле отсутствует зависимость (и она не была зафиксирована во время сборки).
    • Чтобы проверить ее из системы сборки, добавьте требуемую библиотеку в поле shared_libs: или required:
  5. Устраните недостающие зависимости, следуя приведенным выше рекомендациям.

Шаг 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