Google is committed to advancing racial equity for Black communities. See how.
Эта страница переведена с помощью Cloud Translation API.
Switch to English

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

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

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

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

Соответствие версии матрицы совместимости фреймворка

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

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

Матчи HAL

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

HIDL и родные HAL

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

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

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

Для HAL версии 2.5 правило соответствия выглядит следующим образом:

Матрица Соответствующий манифест
2.5 2.5-2.∞. В матрице совместимости 2.5 - это сокращение от 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. Правила соответствия для HAL AIDL аналогичны правилам HIDL и родным HAL, за исключением того, что нет основных версий и существует ровно одна версия на каждый экземпляр HAL ( 1 если версия не указана).

  • Несколько <hal> элементы вычисляются с помощью одного и отношений.
  • Несколько элементов <instance> и <regex-instance> в одном <hal> оцениваются с помощью одного отношения AND . (См. Пример вибратора ниже.)

Пример: успешное совпадение 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 /vendor/etc/vintf/manifest.xml , чтобы устройство явно указывало версию FCM ядра в манифесте устройства, /vendor/etc/vintf/manifest.xml , если /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 в дереве исходных kernel/configs/r/android-4.19 Android.

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

Матрица может включать в себя несколько разделов <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 декларируют следующие требования (теги верхнего и /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 (R) 4.14.105 4.14-r
4 (Q) 5 (R) 5.4.41 5.4-r
5 (R) неопределенные Любые VTS не работает (необходимо указать версию ядра FCM для целевой версии FCM 5)
5 (R) 4 (Q) Любые VTS не работает (версия ядра FCM <целевая версия FCM)
5 (R) 5 (R) 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 существовать в /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 содержит ОСНОВНУЮ версию и МИНИМАЛЬНУЮ версию с форматом ОСНОВНОЙ.МИНОР (например, 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. Выберите Cherry следующие 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 в 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 . manifest.system-sdk.version только в том случае, если набор является подмножеством предоставленных версий системного SDK, как объявлено в manifest.system-sdk.version в манифесте платформы.

  • В качестве особого случая, если в матрице совместимости устройств не указаны версии System 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 не подходит, потому что не предоставляется System SDK версии 27.