Corresponder às regras

Os dois pares de matrizes de compatibilidade e manifestos precisam ser reconciliados para verificar se a implementação do framework e do fornecedor podem funcionar entre si. Essa verificação é bem-sucedida após uma correspondência entre a matriz de compatibilidade do framework e o manifesto do dispositivo, bem como entre o manifesto do framework e a matriz de compatibilidade do dispositivo.

Essa verificação é feita no momento da criação, no momento da geração do pacote de atualização OTA, no momento da inicialização e nos testes de compatibilidade do VTS.

As seções a seguir detalham as regras de correspondência usadas por vários componentes.

Correspondências de versão da matriz de compatibilidade do framework

Para corresponder um manifesto de dispositivo com uma matriz de compatibilidade de framework, a versão de envio do FCM especificada por manifest.target-level precisa ser exatamente igual à versão do FCM especificada por compatibility-matrix.level. Caso contrário, não há correspondência.

Quando a matriz de compatibilidade do framework é solicitada com libvintf, essa correspondência sempre é bem-sucedida, porque libvintf abre o manifesto do dispositivo, recupera a versão de envio do FCM e retorna a matriz de compatibilidade do framework nessa versão do FCM (além de algumas HALs opcionais de matrizes de compatibilidade em versões mais recentes do FCM).

Correspondências de HAL

A regra HAL-match identifica as versões de elementos hal em um arquivo de manifesto que são consideradas compatíveis com o proprietário da matriz de compatibilidade correspondente.

HIDL e HALs nativos

As regras de correspondência para HIDL e HALs nativos são as seguintes.

  • Vários elementos <hal> são avaliados com uma única relação AND.
  • Os elementos <hal> podem ter <hal optional="true"> para marcá-los como não obrigatórios.
  • Vários elementos <version> no mesmo <hal> têm a relação OR. Se duas ou mais versões forem especificadas, apenas uma delas precisa ser implementada. Consulte o exemplo de DRM abaixo.
  • Vários elementos <instance> e <regex-instance> no mesmo <hal> são avaliados com uma única relação AND quando o <hal> é necessário. Veja o <ahref="#drm">exemplo de DRM abaixo.</ahref="#drm">

Exemplo: correspondência bem-sucedida do HAL para um módulo

Para uma HAL na versão 2.5, a regra de correspondência é a seguinte:

Matriz Manifesto correspondente
2.5 2.5-2.∞. Na matriz de compatibilidade, 2.5 é a abreviação de 2.5-5.
2.5-7 2,5-2,∞. Indica o seguinte:
  • A versão 2.5 é a mínima necessária. Isso significa que um manifesto que fornece a HAL 2.0-2.4 não é compatível.
  • 2.7 é a versão máxima que pode ser solicitada. Isso significa que o proprietário da matriz de compatibilidade (framework ou dispositivo) não vai solicitar versões além da 2.7. O proprietário do manifesto correspondente ainda pode veicular a versão 2.10 (como exemplo) quando a 2.7 for solicitada. O proprietário da matriz de compatibilidade sabe apenas que o serviço solicitado é compatível com a versão 2.7 da API.
  • O -7 é apenas informativo e não afeta o processo de atualização OTA.
Assim, um dispositivo com uma HAL na versão 2.10 no arquivo de manifesto permanece compatível com um framework que declara 2.5-7 na matriz de compatibilidade.

Exemplo: correspondência bem-sucedida do HAL para o módulo DRM

A matriz de compatibilidade do framework informa as seguintes informações de versão para o HAL do DRM:

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

Um fornecedor precisa implementar UMA das seguintes instâncias:

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

E também precisa implementar todas estas instâncias:

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

HALs AIDL

Todas as versões do Android mais recentes que o Android 11 (exceto o Android 11) oferecem suporte a versões para HALs AIDL no VINTF. As regras de correspondência para HALs da AIDL são semelhantes às de HALs nativas e da HIDL, exceto que não há versões principais e há exatamente uma versão por instância de HAL (1 se a versão não estiver especificada).

  • Vários elementos <hal> são avaliados com uma única relação AND.
  • Os elementos <hal> podem ter <hal optional="true"> para marcá-los como não obrigatórios.
  • Vários elementos <instance> e <regex-instance> no mesmo <hal> são avaliados com uma única relação AND quando o <hal> é necessário. Consulte o <ahref="#vibrator">exemplo de vibrador abaixo.</ahref="#vibrator">

Exemplo: correspondência bem-sucedida do HAL para um módulo

Para um HAL na versão 5, a regra de correspondência é a seguinte:

Matriz Manifesto correspondente
5 5 a ∞. Na matriz de compatibilidade, 5 é a abreviação de 5-5.
5-7 5-∞. Indica o seguinte:
  • 5 é a versão mínima necessária, o que significa que um manifesto que fornece HAL 1-4 não é compatível.
  • 7 é a versão máxima que pode ser solicitada, ou seja, o proprietário da matriz de compatibilidade (framework ou dispositivo) não vai solicitar versões além da 7. O proprietário do manifesto correspondente ainda poderá disponibilizar a versão 10 (por exemplo) quando a versão 7 for solicitada. O proprietário da matriz de compatibilidade sabe apenas que o serviço solicitado é compatível com a versão 7 da API.
  • O -7 é apenas informativo e não afeta o processo de atualização OTA.
Assim, um dispositivo com uma HAL na versão 10 no arquivo de manifesto permanece compatível com um framework que declara 5-7 na matriz de compatibilidade.

Exemplo: correspondência bem-sucedida da HAL para vários módulos

A matriz de compatibilidade do framework informa as seguintes informações de versão para HALs de vibrador e câmera:

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

Um fornecedor precisa implementar todas essas instâncias:

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

Kernels correspondentes

A seção <kernel> da matriz de compatibilidade do framework descreve os requisitos do framework do kernel do Linux no dispositivo. Essas informações devem ser comparadas com as informações sobre o kernel que são relatadas pelo objeto VINTF do dispositivo.

Corresponde a ramos do kernel

Cada sufixo de ramificação do kernel (por exemplo, 5.4-r) é mapeado para uma versão exclusiva do FCM do kernel (por exemplo, 5). O mapeamento é o mesmo que o mapeamento entre as letras de lançamento (por exemplo, R) e as versões do FCM (por exemplo, 5).

Os testes VTS exigem que o dispositivo especifique explicitamente a versão do FCM do kernel no manifesto do dispositivo, /vendor/etc/vintf/manifest.xml, se uma das seguintes condições for verdadeira:

  • A versão do FCM do kernel é diferente da versão do FCM de destino. Por exemplo, o dispositivo mencionado tem uma versão do FCM de destino 4, e a versão do FCM do kernel é 5 (sufixo de ramificação do kernel r).
  • A versão do FCM do kernel é maior ou igual a 5 (sufixo da ramificação do kernel r).

Os testes do VTS garantem que, se a versão do FCM do kernel for especificada, ela será maior ou igual à versão do FCM de destino no manifesto do dispositivo.

Exemplo: determinar a ramificação do kernel

Se o dispositivo tiver a versão 4 do FCM de destino (lançada no Android 10), mas executar o kernel do ramo 4.19-r, o manifesto do dispositivo precisará especificar o seguinte:

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

O objeto VINTF verifica a compatibilidade do kernel com os requisitos na ramificação do kernel 4.19-r, especificada na versão 5 do FCM. Esses requisitos são criados com base em kernel/configs/r/android-4.19 na árvore de origem do Android.

Exemplo: determinar a ramificação do kernel para GKI

Se o dispositivo usa a imagem genérica do kernel (GKI) e a string de versão do kernel de /proc/version é a seguinte:

5.4.42-android12-0-00544-ged21d463f856

Em seguida, o objeto VINTF recebe a versão do Android da versão do kernel e a usa para determinar a versão do FCM do kernel. Neste exemplo, android12 significa a versão 6 do FCM do kernel (lançada no Android 12).

Para saber como a string de versão do kernel é analisada, consulte Controle de versões do GKI.

Corresponder às versões do kernel

Uma matriz pode incluir várias seções <kernel>, cada uma com um atributo version diferente usando o formato:

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

O objeto VINTF considera apenas a seção <kernel> do FCM com a versão correspondente do FCM que tem os mesmos ${ver} e ${major_rev} que o kernel do dispositivo (ou seja, version="${ver}.${major_rev}.${matrix_minor_rev}"). As outras seções são ignoradas. Além disso, a revisão secundária do kernel precisa ser um valor da matriz de compatibilidade (${kernel_minor_rev} >= ${matrix_minor_rev};). Se nenhuma seção <kernel> atender a esses requisitos, ela não corresponde.

Exemplo: selecionar requisitos para correspondência

Considere o seguinte caso hipotético em que as FCMs em /system/etc/vintf declaram os requisitos abaixo (as tags de cabeçalho e rodapé são omitidas):

<!-- 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 -->

A versão de destino do FCM, a versão do FCM do kernel e a versão do kernel selecionam os requisitos do kernel a partir dos FCMs:

Versão de destino do FCMVersão do FCM do kernelVersão do kernelCorresponder a
3 (P)não especificado4.4.106 Nenhuma correspondência (incompatibilidade de versão secundária)
3 (p)não especificado4.4.107 4.4-p
3 (P)não especificado4.19.42 4.19-q (consulte a observação abaixo)
3 (P)não especificado5.4.41 5.4-r (confira a observação abaixo)
3 (P)3 (P) 4.4.107 4.4-p
3 (P)3 (P) 4.19.42 Nenhuma correspondência (nenhuma ramificação do kernel 4.19-p)
3 (P)4 (T) 4.19.42 4.19-q
4 (T)não especificado4.4.107 Nenhuma correspondência (nenhuma ramificação do kernel 4.4-q)
4 (Q)não especificado4.9.165 4.9-q
4 (Q)não especificado5.4.41 5.4-r (confira a observação abaixo)
4 (Q)4 (T) 4.9.165 4.9-q
4 (Q)4 (T) 5.4.41 Nenhuma correspondência (nenhuma ramificação do kernel 5.4-q)
4 (T)5 (D) 4.14.1054.14-r
4 (Q)5 (D) 5.4.41 5.4-r
5 (D)não especificadoqualquer A VTS falha. É necessário especificar a versão do kernel do FCM para a versão 5 de destino do FCM.
5 (D)4 (T) qualquer VTS falha (versão do FCM do kernel < versão do FCM de destino)
5 (R)5 (R) 4.14.1804.14-r

Corresponder às configurações do kernel

Se a seção <kernel> corresponder, o processo continuará tentando corresponder elementos config com /proc/config.gz. Para cada elemento de configuração na matriz de compatibilidade, ele procura /proc/config.gz para saber se a configuração está presente. Quando um item de configuração é definido como n na matriz de compatibilidade para a seção <kernel> correspondente, ele precisa estar ausente de /proc/config.gz. Por fim, um item de configuração que não está na matriz de compatibilidade pode ou não estar presente em /proc/config.gz.

Exemplo: corresponder a configurações do kernel

  • <value type="string">bar</value> corresponde "bar". As aspas são omitidas na matriz de compatibilidade, mas estão presentes em /proc/config.gz.
  • <value type="int">4096</value> corresponde a 4096 ou 0x1000 ou 0X1000.
  • <value type="int">0x1000</value> corresponde a 4096 ou 0x1000 ou 0X1000.
  • <value type="int">0X1000</value> corresponde a 4096 ou 0x1000 ou 0X1000.
  • <value type="tristate">y</value> corresponde y.
  • <value type="tristate">m</value> corresponde m.
  • <value type="tristate">n</value> significa que o item de configuração NÃO pode existir em /proc/config.gz.
  • <value type="range">1-0x3</value> corresponde a 1, 2 ou 3, ou equivalente hexadecimal.

Exemplo: correspondência bem-sucedida do kernel

Uma matriz de compatibilidade do framework com a versão 1 do FCM tem as seguintes informações do kernel:

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

A correspondência da ramificação do kernel é feita primeiro. O branch do kernel é especificado no manifesto do dispositivo em manifest.kernel.target-level, que tem manifest.level como padrão se o primeiro não for especificado. Se a ramificação do kernel no manifesto do dispositivo:

  • é 1, prossegue para a próxima etapa e verifica a versão do kernel.
  • é 2, sem correspondência com a matriz. Os objetos VINTF leem os requisitos do kernel da matriz na versão 2 do FCM.

Em seguida, a versão do kernel é correspondida. Se um dispositivo em uname() informar:

  • 4.9.84 (não há correspondência com a matriz, a menos que haja uma seção de kernel separada com <kernel version="4.9.x">, onde x <= 84)
  • 4.14.41 (sem correspondência para a matriz, menor que version)
  • 4.14.42 (correspondência à matriz)
  • 4.14.43 (corresponde à matriz)
  • 4.1.22 (não há correspondência com a matriz, a menos que haja uma seção de kernel separada com <kernel version="4.1.x"> em que x <= 22)

Depois que a seção <kernel> adequada é selecionada, para cada item <config> com valor diferente de n, esperamos que a entrada correspondente esteja presente em /proc/config.gz. Para cada item <config> com valor n, esperamos que a entrada correspondente não esteja presente em /proc/config.gz. Esperamos que o conteúdo de <value> corresponda exatamente ao texto após o sinal de igual (incluindo aspas), até o caractere de nova linha ou #, com espaços em branco à esquerda e à direita.

A seguinte configuração de kernel é um exemplo de uma correspondência bem-sucedida:

# 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"

A seguinte configuração de kernel é um exemplo de correspondência malsucedida:

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

Correspondências de políticas do SE

A política de SE exige as seguintes correspondências:

  • <sepolicy-version> define um intervalo fechado de versões secundárias para cada versão principal. A versão do sepolicy informada pelo dispositivo precisa estar dentro de um desses intervalos para ser compatível com o framework. As regras de correspondência são semelhantes às versões do HAL. Elas são correspondentes se a versão da sepolicy for maior ou igual à versão mínima do intervalo. A versão máxima é apenas informativa.
  • <kernel-sepolicy-version>, ou seja, a versão da policydb. Precisa ser menor que o security_policyvers() informado pelo dispositivo.

Exemplo: correspondência da política de SE bem-sucedida

A matriz de compatibilidade do framework apresenta as seguintes informações sepolicy:

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

No dispositivo:

  • O valor retornado por security_policyvers() precisa ser maior ou igual a 30. Caso contrário, não é uma correspondência. Por exemplo:
    • Se um dispositivo retornar 29, ele não será correspondente.
    • Se o dispositivo retornar 31, é uma correspondência.
  • A versão da política de SE deve ser 25,0-✕ ou 26,0- inclusive. Caso contrário, não é correspondente. O "-3" depois de "26.0" é meramente informativo.

Correspondências da versão do AVB

A versão AVB contém uma versão PRINCIPAL e uma MINOR, com o formato como PRINCIPAL.MINOR (por exemplo, 1.0, 2.1). Para ver detalhes, consulte Controle de versões e compatibilidade. A versão AVB tem as seguintes propriedades do sistema:

  • ro.boot.vbmeta.avb_version é a versão libavb no carregador de inicialização
  • ro.boot.avb_version é a versão libavb no SO Android (init/fs_mgr).

A propriedade do sistema aparece somente quando o libavb correspondente é usado para verificar os metadados AVB (e retorna OK). Ele está ausente se ocorreu uma falha de verificação ou se nenhuma verificação ocorreu.

Uma correspondência de compatibilidade compara o seguinte:

  • sysprop ro.boot.vbmeta.avb_version com avb.vbmeta-version da matriz de compatibilidade do framework;
    • ro.boot.vbmeta.avb_version.MAJOR == avb.vbmeta-version.MAJOR
    • ro.boot.vbmeta.avb_version.MINOR >= avb.vbmeta-version.MINOR
  • ro.boot.avb_version do sysprop com avb.vbmeta-version da matriz de compatibilidade do framework.
    • ro.boot.avb_version.MAJOR == avb.vbmeta-version.MAJOR
    • ro.boot.avb_version.MINOR >= avb.vbmeta-version.MINOR

O carregador de inicialização ou o SO Android pode conter duas cópias de bibliotecas libavb, cada uma com uma versão MAJOR diferente para dispositivos de upgrade e de lançamento. Nesse caso, a mesma imagem de sistema não assinada pode ser compartilhada, mas as imagens de sistema assinhadas são diferentes (com avb.vbmeta-version diferentes):

Figura 1. A versão do AVB corresponde (/system é P, todas as outras partições são O).



Figura 2. A versão do AVB corresponde (todas as partições são P).

Exemplo: correspondência da versão AVB concluída

A matriz de compatibilidade do framework apresenta as seguintes informações do AVB:

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

No dispositivo:

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 

Corresponder a versão do AVB durante o OTA

Para dispositivos lançados com o Android 9 ou versões anteriores, ao atualizar para o Android 10, os requisitos da versão do AVB na matriz de compatibilidade do framework são comparados com a versão atual do AVB no dispositivo. Se a versão do AVB tiver um upgrade de versão principal durante uma OTA (por exemplo, de 0.0 para 1.0), a verificação de compatibilidade do VINTF na OTA não vai refletir a compatibilidade após a OTA.

Para atenuar o problema, um OEM pode colocar uma versão falsa do AVB no pacote OTA (compatibility.zip) para passar na verificação. Para fazer isso, siga estas etapas:

  1. Selecione os CLs abaixo para a árvore de origem do Android 9:
  2. Defina BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE para o dispositivo. O valor precisa ser igual à versão do AVB antes da OTA, ou seja, a versão do AVB do dispositivo quando ele foi lançado.
  3. Crie o pacote OTA novamente.

Essas mudanças colocam automaticamente BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE como compatibility-matrix.avb.vbmeta-version nos seguintes arquivos:

  • /system/compatibility_matrix.xml (que não é usado no Android 9) no dispositivo
  • system_matrix.xml em compatibility.zip no pacote OTA

Essas mudanças não afetam outras matrizes de compatibilidade do framework, incluindo /system/etc/vintf/compatibility_matrix.xml. Após o OTA, o novo valor em /system/etc/vintf/compatibility_matrix.xml é usado para verificações de compatibilidade.

Correspondências de versão do VNDK

A matriz de compatibilidade do dispositivo declara a versão necessária do VNDK em compatibility-matrix.vendor-ndk.version. Se a matriz de compatibilidade do dispositivo não tiver uma tag <vendor-ndk>, nenhum requisito será imposto e, portanto, ele sempre será considerado uma correspondência.

Se a matriz de compatibilidade do dispositivo tiver uma tag <vendor-ndk>, uma entrada <vendor-ndk> com uma <version> correspondente será pesquisada no conjunto de snapshots do fornecedor de VNDK fornecido pelo framework no manifesto do framework. Se essa entrada não existir, não haverá correspondência.

Se essa entrada existir, o conjunto de bibliotecas enumerado na matriz de compatibilidade do dispositivo precisará ser um subconjunto do conjunto de bibliotecas indicado no manifesto do framework. Caso contrário, a entrada não será considerada uma correspondência.

  • Como caso especial, se nenhuma biblioteca for enumerada na matriz de compatibilidade do dispositivo, a entrada será sempre considerada uma correspondência, porque o conjunto vazio é um subconjunto de qualquer conjunto.

Exemplo: correspondência bem-sucedida da versão do VNDK

Se a matriz de compatibilidade do dispositivo indicar o seguinte requisito no VNDK:

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

No manifesto do framework, apenas a entrada com a versão 27 é considerada.

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

O exemplo A é uma correspondência, porque a versão 27 do VNDK está no manifesto do framework e em {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>

O exemplo B não é uma correspondência. Embora a versão 27 do VNDK esteja no manifesto do framework, o framework não oferece suporte a libjpeg.so nesse snapshot. A versão 26 do VNDK é ignorada.

Versão do SDK do sistema correspondente

A matriz de compatibilidade do dispositivo declara um conjunto de versões do SDK do sistema necessárias em compatibility-matrix.system-sdk.version. Há uma correspondência somente se o conjunto for um subconjunto das versões do SDK do sistema fornecidas, conforme declarado em manifest.system-sdk.version no manifesto do framework.

  • Como caso especial, se nenhuma versão do SDK do sistema for enumerada na matriz de compatibilidade do dispositivo, ela sempre será considerada uma correspondência, porque o conjunto vazio é um subconjunto de qualquer conjunto.

Exemplo: correspondência de versão do SDK do sistema concluída

Se a matriz de compatibilidade do dispositivo declarar o seguinte requisito no SDK do sistema:

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

Em seguida, o framework precisa fornecer as versões 26 e 27 do SDK do sistema para fazer a correspondência.

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

O exemplo A é uma correspondência.

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

O exemplo B é uma correspondência.

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

O exemplo C não é uma correspondência porque a versão 27 do SDK do sistema não foi fornecida.