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

В 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 (однако такие процессы могут ссылка на библиотеки ВНДК). Попытки нарушить конфигурацию связи во время выполнения приводят к сбою процесса и появлению сообщения об ошибке 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_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 , чтобы получить тип использования (связывание или отражение), уровень ограничений и стек вызовов.

  • Синтаксис Веридекса:

    ./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