Правила сопоставления

Две пары матриц совместимости и манифестов предназначены для согласования, чтобы убедиться, что платформа и реализация поставщика могут работать друг с другом. Эта проверка считается успешной при совпадении между матрицей совместимости платформы и манифестом устройства, а также между манифестом платформы и матрицей совместимости устройства.

Эта проверка выполняется во время сборки, во время создания пакета обновления OTA , во время загрузки и в тестах совместимости VTS.

В следующих разделах подробно описаны правила сопоставления, используемые различными компонентами.

Версия матрицы совместимости платформы совпадает

Чтобы сопоставить манифест устройства с матрицей совместимости платформы, версия FCM доставки, указанная в manifest.target-level , должна быть точно равна версии FCM, указанной в compatibility-matrix.level . В противном случае совпадения нет.

Когда матрица совместимости платформы запрашивается с помощью libvintf , это сопоставление всегда оказывается успешным, поскольку libvintf открывает манифест устройства, извлекает версию FCM доставки и возвращает матрицу совместимости платформы с этой версией FCM доставки (плюс некоторые дополнительные HAL из матриц совместимости с более высоким FCM). Версии).

HAL-матчи

Правило HAL-match определяет версии элементов hal в файле манифеста, которые считаются поддерживаемыми владельцем соответствующей матрицы совместимости.

HIDL и собственные HAL

Правила соответствия для HIDL и собственных HAL следующие.

  • Несколько элементов <hal> оцениваются с помощью одного отношения И.
  • Элементы <hal> могут иметь <hal optional="true"> , чтобы пометить их как необязательные.
  • Несколько элементов <version> в одном <hal> имеют отношение ИЛИ . Если указаны две или более версий, необходимо реализовать только одну из версий. (См. пример DRM ниже.)
  • Несколько элементов <instance> и <regex-instance> в одном <hal> оцениваются с помощью одного отношения AND , когда <hal> требуется. (См. Пример DRM ниже.)

Пример: успешное совпадение HAL для модуля.

Для HAL версии 2.5 правило соответствия следующее:

Матрица Соответствующий манифест
2.5 2,5-2,∞. В матрице совместимости 2.5 — это сокращение от 2.5-5 .
2.5-7 2,5-2,∞. Указывает на следующее:
  • 2.5 — это минимально необходимая версия, что означает, что манифест, обеспечивающий HAL 2.0–2.4, несовместим.
  • 2.7 — это максимальная версия, которую можно запросить. Это означает, что владелец матрицы совместимости (платформы или устройства) не будет запрашивать версии выше 2.7. Владелец соответствующего манифеста по-прежнему может использовать версию 2.10 (в качестве примера), когда запрашивается версия 2.7. Владелец матрицы совместимости знает только то, что запрошенная служба совместима с API версии 2.7.
  • -7 носит исключительно информационный характер и не влияет на процесс OTA-обновления.
Таким образом, устройство с HAL версии 2.10 в файле манифеста остается совместимым с платформой, в матрице совместимости которой указаны значения 2.5-7 .

Пример: успешное совпадение HAL для модуля DRM.

В матрице совместимости платформы указана следующая информация о версии DRM HAL:

<hal>
    <name>android.hardware.drm
    <version>1.0</version>
    <version>3.1-2</version>
    <interface>
        <name>IDrmFactory</name>
        <instance>default</instance>
        <instance>specific</instance>
    </interface>
</hal>
<hal>
    <name>android.hardware.drm
    <version>2.0</version>
    <interface>
        <name>ICryptoFactory</name>
        <instance>default</instance>
        <regex-instance>[a-z]+/[0-9]+</regex-instance>
    </interface>
</hal>

Поставщик должен реализовать ОДИН из следующих экземпляров; или

android.hardware.drm@1.x::IDrmFactory/default          // where x >= 0
android.hardware.drm@1.x::IDrmFactory/specific         // where x >= 0
ИЛИ
android.hardware.drm@3.y::IDrmFactory/default          // where y >= 1
android.hardware.drm@3.y::IDrmFactory/specific         // where y >= 1

И также должен реализовать все эти экземпляры:

android.hardware.drm@2.z::ICryptoFactory/default       // where z >= 0
android.hardware.drm@2.z::ICryptoFactory/${INSTANCE}
            // where z >= 0 and ${INSTANCE} matches [a-z]+/[0-9]+
            // e.g. legacy/0

AIDL HAL

Все версии Android после Android 11 (за исключением Android 11) поддерживают версии для AIDL HAL в VINTF. Правила сопоставления для AIDL HAL аналогичны правилам HIDL и собственных HAL, за исключением того, что не существует основных версий и существует ровно одна версия для каждого экземпляра HAL ( 1 , если версия не указана).

  • Несколько элементов <hal> оцениваются с помощью одного отношения И.
  • Элементы <hal> могут иметь <hal optional="true"> , чтобы пометить их как необязательные.
  • Несколько элементов <instance> и <regex-instance> в одном <hal> оцениваются с помощью одного отношения AND , когда <hal> требуется. (См. пример вибратора ниже.)

Пример: успешное совпадение HAL для модуля.

Для HAL версии 5 правило соответствия следующее:

Матрица Соответствующий манифест
5 5-∞. В матрице совместимости 5 — это сокращение от 5-5 .
5-7 5-∞. Указывает на следующее:
  • 5 — это минимально необходимая версия, что означает, что манифест, обеспечивающий HAL 1–4, несовместим.
  • 7 — это максимальная версия, которую можно запросить. Это означает, что владелец матрицы совместимости (фреймворк или устройство) не будет запрашивать версии выше 7. Владелец соответствующего манифеста все равно может использовать версию 10 (в качестве примера), когда запрашивается версия 7. . Владелец матрицы совместимости знает только то, что запрошенная служба совместима с API версии 7.
  • -7 носит исключительно информационный характер и не влияет на процесс OTA-обновления.
Таким образом, устройство с HAL версии 10 в файле манифеста остается совместимым с платформой, которая указывает 5-7 в матрице совместимости.

Пример: успешное сопоставление HAL для нескольких модулей.

В матрице совместимости платформы указана следующая информация о версии HAL вибратора и камеры:

<hal>
    <name>android.hardware.vibrator
    <version>1-2</version>
    <interface>
        <name>IVibrator</name>
        <instance>default</instance>
        <instance>specific</instance>
    </interface>
</hal>
<hal>
    <name>android.hardware.camera
    <version>5</version>
    <interface>
        <name>ICamera</name>
        <instance>default</instance>
        <regex-instance>[a-z]+/[0-9]+</regex-instance>
    </interface>
</hal>

Поставщик должен реализовать все эти экземпляры:

android.hardware.vibrator.IVibrator/default     // version >= 1
android.hardware.vibrator.IVibrator/specific    // version >= 1
android.hardware.camera.ICamera/default         // version >= 5
android.hardware.camera.ICamera/${INSTANCE}
            // with version >= 5, where ${INSTANCE} matches [a-z]+/[0-9]+
            // e.g. legacy/0

Соответствия ядра

Раздел <kernel> матрицы совместимости платформы описывает требования платформы к ядру Linux на устройстве. Эта информация должна сопоставляться с информацией о ядре, которую сообщает объект VINTF устройства.

Сопоставить ветки ядра

Каждый суффикс ветки ядра (например, 5.4- r ) сопоставлен с уникальной версией FCM ядра (например, 5). Сопоставление такое же, как сопоставление между буквами выпуска (например, R) и версиями FCM (например, 5).

Тесты VTS требуют, чтобы устройство явно указало версию ядра FCM в манифесте устройства /vendor/etc/vintf/manifest.xml , если верно одно из следующих условий:

  • Версия FCM ядра отличается от целевой версии FCM. Например, вышеупомянутое устройство имеет целевую версию FCM 4, а версию FCM ядра — 5 (суффикс ветки ядра r ).
  • Версия FCM ядра больше или равна 5 (суффикс ветки ядра r ).

Тесты VTS гарантируют, что если указана версия FCM ядра, версия FCM ядра больше или равна целевой версии FCM в манифесте устройства.

Пример: определение ветки ядра

Если на устройстве установлена ​​целевая версия FCM 4 (выпущена в Android 10), но работает ядро ​​из ветки 4.19-r , в манифесте устройства должно быть указано следующее:

<manifest version="2.0" type="device" target-level="4">
   <kernel target-level="5" />
</manifest>

Объект VINTF проверяет совместимость ядра на соответствие требованиям ветки ядра 4.19-r , которая указана в FCM версии 5. Эти требования создаются из kernel/configs/r/android-4.19 в дереве исходного кода Android.

Пример: определение ветки ядра для GKI

Если устройство использует универсальный образ ядра (GKI), а строка выпуска ядра из /proc/version имеет следующий вид:

5.4.42-android12-0-00544-ged21d463f856

Затем объект VINTF получает версию Android из версии ядра и использует ее для определения версии ядра FCM. В этом примере android12 означает ядро ​​FCM версии 6 (выпущенное в Android 12).

Подробности о том, как анализируется строка выпуска ядра, см. в разделе Управление версиями GKI .

Соответствие версий ядра

Матрица может включать в себя несколько разделов <kernel> , каждый из которых имеет свой атрибут version в следующем формате:

${ver}.${major_rev}.${kernel_minor_rev}

Объект VINTF учитывает только раздел <kernel> из FCM с соответствующей версией FCM с теми же ${ver} и ${major_rev} что и ядро ​​устройства (т. е. version="${ver}.${major_rev}.${matrix_minor_rev}") ; другие разделы игнорируются. Кроме того, дополнительная версия ядра должна быть значением из матрицы совместимости ( ${kernel_minor_rev} >= ${matrix_minor_rev} ;). Если ни один раздел <kernel> не соответствует этим требованиям, это несоответствие.

Пример: выберите требования для сопоставления

Рассмотрим следующий гипотетический случай, когда FCM в /system/etc/vintf объявляют следующие требования (теги верхнего и нижнего колонтитула опущены):

<!-- compatibility_matrix.3.xml -->
<kernel version="4.4.107" level="3"/>
<!-- See kernel/configs/p/android-4.4/ for 4.4-p requirements -->
<kernel version="4.9.84" level="3"/>
<!-- See kernel/configs/p/android-4.9/ for 4.9-p requirements -->
<kernel version="4.14.42" level="3"/>
<!-- See kernel/configs/p/android-4.14/ for 4.14-p requirements -->

<!-- compatibility_matrix.4.xml -->
<kernel version="4.9.165" level="4"/>
<!-- See kernel/configs/q/android-4.9/ for 4.9-q requirements -->
<kernel version="4.14.105" level="4"/>
<!-- See kernel/configs/q/android-4.14/ for 4.14-q requirements -->
<kernel version="4.19.42" level="4"/>
<!-- See kernel/configs/q/android-4.19/ for 4.19-q requirements -->

<!-- compatibility_matrix.5.xml -->
<kernel version="4.14.180" level="5"/>
<!-- See kernel/configs/r/android-4.14/ for 4.14-r requirements -->
<kernel version="4.19.123" level="5"/>
<!-- See kernel/configs/r/android-4.19/ for 4.19-r requirements -->
<kernel version="5.4.41" level="5"/>
<!-- See kernel/configs/r/android-5.4/ for 5.4-r requirements -->

Целевая версия FCM, версия FCM ядра и версия ядра вместе выбирают требования ядра из FCM:

Целевая версия FCM Версия ядра FCM Версия ядра Совпадает с
3 (П) неопределенные 4.4.106 Нет совпадений (незначительное несоответствие версий)
3 (П) неопределенные 4.4.107 4.4-p
3 (П) неопределенные 4.19.42 4.19-q (см. примечание ниже)
3 (П) неопределенные 5.4.41 5.4-r (см. примечание ниже)
3 (П) 3 (П) 4.4.107 4.4-p
3 (П) 3 (П) 4.19.42 Нет совпадения (нет ветки ядра 4.19-p )
3 (П) 4 (Q) 4.19.42 4.19-q
4 (Q) неопределенные 4.4.107 Нет совпадения (нет ветки ядра 4.4-q )
4 (Q) неопределенные 4.9.165 4.9-q
4 (Q) неопределенные 5.4.41 5.4-r (см. примечание ниже)
4 (Q) 4 (Q) 4.9.165 4.9-q
4 (Q) 4 (Q) 5.4.41 Нет совпадений (нет ветки ядра 5.4-q )
4 (Q) 5 (П) 4.14.105 4.14-r
4 (Q) 5 (П) 5.4.41 5.4-r
5 (П) неопределенные любой Сбой VTS (необходимо указать версию ядра FCM для целевой версии FCM 5)
5 (П) 4 (Q) любой Сбой VTS (версия ядра FCM < целевая версия FCM)
5 (П) 5 (П) 4.14.180 4.14-r

Сопоставить конфигурации ядра

Если раздел <kernel> соответствует, процесс продолжается, пытаясь сопоставить элементы config с /proc/config.gz . Для каждого элемента конфигурации в матрице совместимости он просматривает /proc/config.gz , чтобы узнать, присутствует ли конфигурация. Если для элемента конфигурации установлено значение n в матрице совместимости для соответствующего раздела <kernel> , он должен отсутствовать в /proc/config.gz . Наконец, элемент конфигурации, отсутствующий в матрице совместимости, может присутствовать или отсутствовать в /proc/config.gz .

Пример: сопоставление конфигураций ядра

  • <value type="string">bar</value> соответствует "bar" . Кавычки опущены в матрице совместимости, но присутствуют в /proc/config.gz .
  • <value type="int">4096</value> соответствует 4096 , 0x1000 или 0X1000 .
  • <value type="int">0x1000</value> соответствует 4096 , 0x1000 или 0X1000 .
  • <value type="int">0X1000</value> соответствует 4096 , 0x1000 или 0X1000 .
  • <value type="tristate">y</value> соответствует y .
  • <value type="tristate">m</value> соответствует m .
  • <value type="tristate">n</value> означает, что элемент конфигурации НЕ должен существовать в /proc/config.gz .
  • <value type="range">1-0x3</value> соответствует 1 , 2 или 3 или шестнадцатеричному эквиваленту.

Пример: успешное совпадение ядра

Матрица совместимости платформы с FCM версии 1 содержит следующую информацию о ядре:

<kernel version="4.14.42">
   <config>
      <key>CONFIG_TRI</key>
      <value type="tristate">y</value>
   </config>
   <config>
      <key>CONFIG_NOEXIST</key>
      <value type="tristate">n</value>
   </config>
   <config>
      <key>CONFIG_DEC</key>
      <value type="int">4096</value>
   </config>
   <config>
      <key>CONFIG_HEX</key>
      <value type="int">0XDEAD</value>
   </config>
   <config>
      <key>CONFIG_STR</key>
      <value type="string">str</value>
   </config>
   <config>
      <key>CONFIG_EMPTY</key>
      <value type="string"></value>
   </config>
</kernel>

Ветка ядра сопоставляется первой. Ветка ядра указана в манифесте устройства в manifest.kernel.target-level , который по умолчанию имеет значение manifest.level если первый не указан. Если ветка ядра в манифесте устройства:

  • равно 1, переходит к следующему шагу и проверяет версию ядра.
  • равно 2, нет соответствия матрице. Вместо этого объекты VINTF считывают требования ядра из матрицы FCM версии 2.

Затем сопоставляется версия ядра. Если устройство в uname() сообщает:

  • 4.9.84 (нет соответствия матрице, если нет отдельного раздела ядра с <kernel version="4.9.x"> , где x <= 84 )
  • 4.14.41 (нет соответствия матрице, меньше version )
  • 4.14.42 (соответствие матрице)
  • 4.14.43 (соответствие матрице)
  • 4.1.22 (нет соответствия матрице, если нет отдельного раздела ядра с <kernel version="4.1.x"> где x <= 22 )

После выбора соответствующего раздела <kernel> для каждого элемента <config> со значением, отличным от n , мы ожидаем, что соответствующая запись будет присутствовать в /proc/config.gz ; для каждого элемента <config> со значением n мы ожидаем, что соответствующая запись не будет присутствовать в /proc/config.gz . Мы ожидаем, что содержимое <value> будет точно соответствовать тексту после знака равенства (включая кавычки) вплоть до символа новой строки или # с усеченными начальными и конечными пробелами.

Следующая конфигурация ядра является примером успешного совпадения:

# comments don't matter
CONFIG_TRI=y
# CONFIG_NOEXIST shouldn't exist
CONFIG_DEC = 4096 # trailing comments and whitespaces are fine
CONFIG_HEX=57005  # 0XDEAD == 57005
CONFIG_STR="str"
CONFIG_EMPTY=""   # empty string must have quotes
CONFIG_EXTRA="extra config items are fine too"

Следующая конфигурация ядра является примером неудачного сопоставления:

CONFIG_TRI="y"   # mismatch: quotes
CONFIG_NOEXIST=y # mismatch: CONFIG_NOEXIST exists
CONFIG_HEX=0x0   # mismatch; value doesn't match
CONFIG_DEC=""    # mismatch; type mismatch (expect int)
CONFIG_EMPTY=1   # mismatch; expects ""
# mismatch: CONFIG_STR is missing

Политика SE соответствует

Политика SE требует следующих совпадений:

  • <sepolicy-version> определяет закрытый диапазон второстепенных версий для каждой основной версии. Версия sepolicy, сообщаемая устройством, должна находиться в одном из этих диапазонов, чтобы быть совместимой с платформой. Правила сопоставления аналогичны версиям HAL; это совпадение, если версия sepolicy выше или равна минимальной версии для диапазона. Максимальная версия носит чисто информационный характер.
  • <kernel-sepolicy-version> , т.е. версия policydb. Должно быть меньше значения security_policyvers() , сообщаемого устройством.

Пример: успешное совпадение политики SE

Матрица совместимости платформы содержит следующую информацию о политике безопасности:

<sepolicy>
    <kernel-sepolicy-version>30</kernel-sepolicy-version>
    <sepolicy-version>25.0</sepolicy-version>
    <sepolicy-version>26.0-3</sepolicy-version>
</sepolicy>

На устройстве:

  • Значение, возвращаемое security_policyvers() должно быть больше или равно 30. В противном случае это не совпадение. Например:
    • Если устройство возвращает 29, это не совпадение.
    • Если устройство возвращает 31, это совпадение.
  • Версия политики SE должна быть одной из 25.0-∞ или 26.0-∞. В противном случае это не совпадение. (Значение « -3 » после « 26.0 » носит чисто информационный характер.)

Версия AVB соответствует

Версия AVB содержит версию MAJOR и версию MINOR в формате MAJOR.MINOR (например, 1.0, 2.1). Подробную информацию см. в разделе Управление версиями и совместимость . Версия AVB имеет следующие системные свойства:

  • ro.boot.vbmeta.avb_version — это версия libavb в загрузчике.
  • ro.boot.avb_version — это версия libavb в ОС Android ( init/fs_mgr )

Системное свойство появляется только в том случае, если соответствующая библиотека libavb использовалась для проверки метаданных AVB (и возвращает OK). Он отсутствует, если произошел сбой проверки (или проверка вообще не произошла).

Соответствие совместимости сравнивает следующее:

  • sysprop ro.boot.vbmeta.avb_version с avb.vbmeta-version из матрицы совместимости платформы;
    • ro.boot.vbmeta.avb_version.MAJOR == avb.vbmeta-version.MAJOR
    • ro.boot.vbmeta.avb_version.MINOR >= avb.vbmeta-version.MINOR
  • sysprop ro.boot.avb_version с avb.vbmeta-version из матрицы совместимости платформы.
    • ro.boot.avb_version.MAJOR == avb.vbmeta-version.MAJOR
    • ro.boot.avb_version.MINOR >= avb.vbmeta-version.MINOR

Загрузчик или ОС Android могут содержать две копии библиотек libavb , каждая из которых имеет разную ОСНОВНУЮ версию для устройств обновления и запуска устройств. В этом случае можно использовать один и тот же неподписанный образ системы, но окончательные подписанные образы системы будут разными (с разной avb.vbmeta-version ):

Рисунок 1. Версия AVB соответствует ( /system — P, все остальные разделы — O).


Рисунок 2. Версия AVB совпадает (все разделы P).

Пример: успешное совпадение версий AVB.

В матрице совместимости платформы указана следующая информация AVB:

<avb>
    <vbmeta-version>2.1</vbmeta-version>
</avb>

На устройстве:

ro.boot.avb_version              == 1.0 &&
ro.boot.vbmeta.avb_version       == 2.1  mismatch 
ro.boot.avb_version              == 2.1 &&
ro.boot.vbmeta.avb_version       == 3.0  mismatch 
ro.boot.avb_version              == 2.1 &&
ro.boot.vbmeta.avb_version       == 2.3  match 
ro.boot.avb_version              == 2.3 &&
ro.boot.vbmeta.avb_version       == 2.1  match 

Соответствие версии AVB во время OTA

Для устройств, запущенных с Android 9 или более ранней версии, при обновлении до Android 10 требования к версии AVB в матрице совместимости платформы сопоставляются с текущей версией AVB на устройстве. Если версия AVB имеет основное обновление версии во время OTA (например, с 0,0 до 1,0), проверка VINTF на совместимость в OTA не отражает совместимость после OTA.

Чтобы решить эту проблему, OEM-производитель может поместить поддельную версию AVB в пакет OTA ( compatibility.zip ) для прохождения проверки. Для этого:

  1. Выберите следующие CL для дерева исходного кода Android 9:
  2. Определите BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE для устройства. Его значение должно равняться версии AVB до OTA, то есть версии AVB устройства на момент его запуска.
  3. Пересоберите пакет OTA.

Эти изменения автоматически помещают BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE как compatibility-matrix.avb.vbmeta-version в следующие файлы:

  • /system/compatibility_matrix.xml (который не используется в Android 9) на устройстве
  • system_matrix.xml в compatibility.zip в пакете OTA

Эти изменения не влияют на другие матрицы совместимости платформы, включая /system/etc/vintf/compatibility_matrix.xml . После OTA вместо этого для проверок совместимости используется новое значение в /system/etc/vintf/compatibility_matrix.xml .

Версия VNDK совпадает

Матрица совместимости устройств объявляет необходимую версию VNDK в compatibility-matrix.vendor-ndk.version . Если в матрице совместимости устройств нет тега <vendor-ndk> , никаких требований не налагается, и, следовательно, она всегда считается совпадающей.

Если в матрице совместимости устройств есть тег <vendor-ndk> , запись <vendor-ndk> с соответствующей <version> ищется в наборе снимков поставщика VNDK, предоставленных платформой в манифесте платформы. Если такой записи не существует, совпадения нет.

Если такая запись существует, набор библиотек, перечисленных в матрице совместимости устройств, должен быть подмножеством набора библиотек, указанного в манифесте платформы; в противном случае запись не считается совпадающей.

  • В особом случае, если в матрице совместимости устройств не перечислены библиотеки, запись всегда считается совпадающей, поскольку пустой набор является подмножеством любого набора.

Пример: успешное совпадение версий VNDK.

Если в матрице совместимости устройств указаны следующие требования к ВНДК:

<!-- Example Device Compatibility Matrix -->
<vendor-ndk>
    <version>27</version>
    <library>libjpeg.so</library>
    <library>libbase.so</library>
</vendor-ndk>

В манифесте платформы учитывается только запись с версией 27.

<!-- Framework Manifest Example A -->
<vendor-ndk>
    <version>27</version>
    <library>libjpeg.so</library>
    <library>libbase.so</library>
    <library>libfoo.so</library>
</vendor-ndk>

Пример A соответствует, поскольку VNDK версии 27 находится в манифесте платформы, а {libjpeg.so, libbase.so, libfoo.so} ⊇ {libjpeg.so, libbase.so} .

<!-- Framework Manifest Example B -->
<vendor-ndk>
    <version>26</version>
    <library>libjpeg.so</library>
    <library>libbase.so</library>
</vendor-ndk>
<vendor-ndk>
    <version>27</version>
    <library>libbase.so</library>
</vendor-ndk>

Пример B не соответствует. Несмотря на то, что VNDK версии 27 присутствует в манифесте платформы, libjpeg.so не поддерживается платформой в этом снимке. VNDK версии 26 игнорируется.

Версия системного SDK совпадает

Матрица совместимости устройств объявляет набор требуемых версий System SDK в compatibility-matrix.system-sdk.version . Совпадение существует только в том случае, если набор является подмножеством предоставленных версий System SDK, как указано в манифесте manifest.system-sdk.version в манифесте платформы.

  • В особом случае, если в матрице совместимости устройств не указаны версии System SDK, это всегда считается совпадением, поскольку пустой набор является подмножеством любого набора.

Пример: успешное совпадение версий System SDK.

Если в матрице совместимости устройств указаны следующие требования к системному SDK:

<!-- Example Device Compatibility Matrix -->
<system-sdk>
    <version>26</version>
    <version>27</version>
</system-sdk>

Затем платформа должна предоставить системный SDK версий 26 и 27 для соответствия.

<!-- Framework Manifest Example A -->
<system-sdk>
    <version>26</version>
    <version>27</version>
</system-sdk>

Пример А — совпадение.

<!-- Framework Manifest Example B -->
<system-sdk>
    <version>26</version>
    <version>27</version>
    <version>28</version>
</system-sdk>

Пример Б соответствует.

<!-- Framework Manifest Example C -->
<system-sdk>
    <version>26</version>
</system-sdk>

Пример C не соответствует, так как не предоставлен системный SDK версии 27.