Правила матча

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

Эта проверка выполняется во время сборки, во время генерации пакета обновления 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> оцениваются с помощью единственной связи AND .
  • Элементы <hal> могут иметь <hal optional="true"> чтобы пометить их как необязательные.
  • Несколько элементов <version> в одном элементе <hal> имеют отношение OR . Если указано два или более, необходимо реализовать только одну из версий. (См. Успешное соответствие HAL для модуля DRM .)
  • Несколько элементов <instance> и <regex-instance> в одном элементе <hal> оцениваются с помощью единственной связи AND , когда требуется <hal> . (См. Успешное сопоставление 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 и выше поддерживают версии для AIDL HAL в VINTF. Правила соответствия для AIDL HAL аналогичны правилам HIDL и собственных HAL, за исключением того, что нет основных версий, и есть только одна версия на экземпляр HAL ( 1 , если версия не указана):

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

Если устройство использует образ ядра Generic Kernel Image (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 (В) 4.19.42 4.19-q
4 (В) Не указано 4.4.107 Нет совпадений (нет ветки ядра 4.4-q )
4 (В) Не указано 4.9.165 4.9-q
4 (В) Не указано 5.4.41 5.4-r (см. примечание после таблицы)
4 (В) 4 (В) 4.9.165 4.9-q
4 (В) 4 (В) 5.4.41 Нет совпадений (нет ветки ядра 5.4-q )
4 (В) 5 (П) 4.14.105 4.14-r
4 (В) 5 (П) 5.4.41 5.4-r
5 (П) Не указано любой Сбой VTS (необходимо указать версию ядра FCM для целевой версии FCM 5)
5 (П) 4 (В) любой Сбой 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

SEPolicy соответствует

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

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

Пример: успешное соответствие SEPolicy

Матрица совместимости фреймворка содержит следующую информацию SEPolicy:

<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, это совпадение.
  • Версия SEPolicy должна быть одной из 25.0-∞ или 26.0-∞. В противном случае это не совпадение. ( -3 после 26.0 носит исключительно информационный характер.)

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

Версия AVB содержит ГЛАВНУЮ и ВТОРИЧНУЮ версии в формате ГЛАВНАЯ.ВТОРИЧНУЮ (например, 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 , каждая с разной версией MAJOR для устройств обновления и запуска. В этом случае один и тот же неподписанный образ системы может быть общим, но окончательные подписанные образы системы будут разными (с разной 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

Если в матрице совместимости устройств указано следующее требование к 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 совпадает

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

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

Пример: Успешное совпадение версии системного SDK

Если в матрице совместимости устройств указано следующее требование к System 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>

Пример B — совпадение:

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

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