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

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

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

  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