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

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

Эта проверка выполняется во время сборки, во время создания пакета обновления 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 HALs

Все версии Android позже Android 11 (кроме Android 11) поддерживают версии для AIDL HAL в VINTF. Правила соответствия для AIDL HAL аналогичны правилам 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 в дереве исходного кода 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 не подходит. Несмотря на то, что версия 27 VNDK находится в манифесте фреймворка, libjpeg.so не поддерживается фреймворком в этом снимке. VNDK версии 26 игнорируется.

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

Матрица совместимости устройств объявляет набор необходимой версии системного SDK в compatibility-matrix.system-sdk.version . manifest.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 не подходит, потому что не предоставляется System SDK версии 27.