Применение интерфейсов разделов продукта

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 , /system_ext и /product )

основной

(включает /system и /system_ext но не /product )

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

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

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

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

    • Любой модуль hidl_interface со значением product_specific: true не будет доступен для системных модулей. Чтобы исправить это, замените product_specific: true на system_ext_specfic: true .
    • В модулях может отсутствовать вариант продукта, необходимый для модулей продукта. Чтобы исправить это, сделайте этот модуль доступным для раздела product , установив vendor_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