Implementando a biblioteca Java SDK

A plataforma Android contém um grande número de bibliotecas Java compartilhadas que podem ser opcionalmente incluídas no caminho de classe de aplicativos com a tag <uses-library> no manifesto do aplicativo. Os aplicativos são vinculados a essas bibliotecas, portanto, trate-os como o restante da API do Android em termos de compatibilidade, revisão de API e suporte a ferramentas. Observe, no entanto, que a maioria das bibliotecas não possui esses recursos.

O tipo de módulo java_sdk_library ajuda a gerenciar bibliotecas desse tipo. Os fabricantes de dispositivos podem usar esse mecanismo para suas próprias bibliotecas Java compartilhadas, para manter a compatibilidade com versões anteriores de suas APIs. Se os fabricantes de dispositivos usarem suas próprias bibliotecas Java compartilhadas por meio da tag <uses-library> em vez do caminho bootclass, java_sdk_library poderá verificar se essas bibliotecas Java são estáveis ​​em relação à API.

A java_sdk_library implementa APIs SDK opcionais para uso por aplicativos. As bibliotecas implementadas por meio de java_sdk_library em seu arquivo de compilação ( Android.bp ) realizam as seguintes operações:

  • As bibliotecas de stubs são geradas para incluir stubs , stubs.system e stubs.test . Essas bibliotecas de stubs são criadas reconhecendo @hide , @SystemApi e @TestApi .
  • A java_sdk_library gerencia arquivos de especificação de API (como current.txt ) em um subdiretório de API. Esses arquivos são verificados em relação ao código mais recente para garantir que sejam as versões mais atuais. Se não estiverem, você receberá uma mensagem de erro que explica como atualizá-los. Revise manualmente todas as alterações de atualização para garantir que elas correspondam às suas expectativas.

    Para atualizar todas as APIs, use m update-api . Para verificar se uma API está atualizada, use m checkapi .
  • Os arquivos de especificação da API são verificados em relação às versões do Android publicadas mais recentemente para garantir que a API seja compatível com versões anteriores. Os módulos java_sdk_library fornecidos como parte do AOSP colocam suas versões lançadas anteriormente em prebuilts/sdk/<latest number> .
  • Com relação às verificações dos arquivos de especificação da API, você pode fazer uma das três coisas a seguir:
    • Permita que as verificações prossigam. (Não faça nada.)
    • Desative as verificações adicionando o seguinte a java_sdk_library :
      unsafe_ignore_missing_latest_api: true,
    • Forneça APIs vazias para novos módulos java_sdk_library criando arquivos de texto vazios denominados module_name.txt no diretório version/scope/api .
  • Se a biblioteca de implementação para o tempo de execução estiver instalada, um arquivo XML será gerado e instalado.

Como java_sdk_library funciona

Uma java_sdk_library chamada X cria o seguinte:

  1. Duas cópias da biblioteca de implementação: uma biblioteca chamada X e outra chamada X.impl . A Biblioteca X está instalada no dispositivo. A biblioteca X.impl existe apenas se o acesso explícito à biblioteca de implementação for necessário por outros módulos, como para uso em testes. Observe que o acesso explícito raramente é necessário.
  2. Os escopos podem ser ativados e desativados para personalizar o acesso. (Semelhante aos modificadores de acesso por palavra-chave Java, um escopo público fornece uma ampla variedade de acesso; um escopo de teste contém APIs usadas apenas em testes.) Para cada escopo habilitado, a biblioteca cria o seguinte:
    • Um módulo de origem de stubs (do tipo de módulo droidstubs ) - consome a fonte de implementação e gera um conjunto de fontes de stub junto com o arquivo de especificação da API.
    • Uma biblioteca de stubs (do tipo de módulo java_library ) - é a versão compilada dos stubs. As bibliotecas usadas para compilar isso não são as mesmas fornecidas ao java_sdk_library , o que garante que os detalhes da implementação não vazem nos stubs da API.
    • Se você precisar de bibliotecas adicionais para compilar os stubs, use as propriedades stub_only_libs e stub_only_static_libs para fornecê-los.

Se uma java_sdk_library é chamada de “ X ” e está sendo compilada como “ X ”, sempre se refira a ela dessa forma e não a modifique. A compilação selecionará uma biblioteca apropriada. Para garantir que você tenha a biblioteca mais apropriada, inspecione seus stubs para ver se a compilação introduziu erros. Faça as correções necessárias usando esta orientação:

  • Verifique se você tem uma biblioteca apropriada olhando na linha de comando e inspecionando quais stubs estão listados lá para determinar seu escopo:
    • O escopo é muito amplo: a biblioteca dependente precisa de um determinado escopo de APIs. Mas você vê APIs incluídas na biblioteca que estão fora desse escopo, como APIs do sistema incluídas nas APIs públicas.
    • O escopo é muito restrito: a biblioteca dependente não tem acesso a todas as bibliotecas necessárias. Por exemplo, a biblioteca dependente precisa usar a API do sistema, mas obtém a API pública. Isso geralmente resulta em um erro de compilação porque as APIs necessárias estão ausentes.
  • Para corrigir a biblioteca, siga um destes procedimentos:
    • Altere o sdk_version para selecionar a versão que você precisa. OU
    • Especifique explicitamente a biblioteca apropriada, como <X>.stubs ou <X>.stubs.system .

Uso de java_sdk_library X

A biblioteca de implementação X é usada quando é referenciada de apex.java_libs . No entanto, devido a uma limitação Soong, quando a biblioteca X é referenciada de outro módulo java_sdk_library dentro da mesma biblioteca APEX, X.impl deve ser usado explicitamente , não a biblioteca X .

Quando o java_sdk_library é referenciado de outro lugar, uma biblioteca de stubs é usada. A biblioteca de stubs é selecionada de acordo com a configuração da propriedade sdk_version do módulo dependente. Por exemplo, um módulo que especifica sdk_version: "current" usa os stubs públicos, enquanto um módulo que especifica sdk_version: "system_current" usa os stubs do sistema. Se uma correspondência exata não puder ser encontrada, a biblioteca de stub mais próxima será usada. Um java_sdk_library que fornece apenas uma API pública fornecerá os stubs públicos para todos.

Fluxo de compilação com a biblioteca Java SDK
Figura 1. Fluxo de compilação com a biblioteca Java SDK

Exemplos e fontes

As propriedades srcs e api_packages devem estar presentes no java_sdk_library .

java_sdk_library {
        name: "com.android.future.usb.accessory",
        srcs: ["src/**/*.java"],
        api_packages: ["com.android.future.usb"],
    }

O AOSP recomenda (mas não exige) que novas instâncias java_sdk_library habilitem explicitamente os escopos de API que desejam usar. Você também pode (opcionalmente) migrar instâncias java_sdk_library existentes para habilitar explicitamente os escopos de API que eles usarão:

java_sdk_library {
         name: "lib",
         public: {
           enabled: true,
         },
         system: {
           enabled: true,
         },
         …
    }

Para configurar a biblioteca impl usada para tempo de execução, use todas as propriedades java_library normais, como hostdex , compile_dex e errorprone .

java_sdk_library {
        name: "android.test.base",

        srcs: ["src/**/*.java"],

        errorprone: {
          javacflags: ["-Xep:DepAnn:ERROR"],
        },

        hostdex: true,

        api_packages: [
            "android.test",
            "android.test.suitebuilder.annotation",
            "com.android.internal.util",
            "junit.framework",
        ],

        compile_dex: true,
    }

Para configurar bibliotecas de stubs, use as seguintes propriedades:

  • merge_annotations_dirs e merge_inclusion_annotations_dirs .
  • api_srcs : a lista de arquivos de origem opcionais que fazem parte da API, mas não fazem parte da biblioteca de tempo de execução.
  • stubs_only_libs : A lista de bibliotecas Java que estão no caminho de classe ao construir stubs.
  • hidden_api_packages : A lista de nomes de pacotes que devem ser ocultados da API.
  • droiddoc_options : Argumento adicional para metalava .
  • droiddoc_option_files : Lista os arquivos que podem ser referenciados de dentro de droiddoc_options usando $(location <label>) , onde <file> é uma entrada na lista.
  • annotations_enabled .

O java_sdk_library é um java_library , mas não é um módulo droidstubs e, portanto, não suporta todas as propriedades droidstubs . O exemplo a seguir foi retirado do arquivo de compilação da biblioteca android.test.mock .

java_sdk_library {
        name: "android.test.mock",

        srcs: [":android-test-mock-sources"],
        api_srcs: [
            // Note: The following aren’t APIs of this library. Only APIs under the
            // android.test.mock package are taken. These do provide private APIs
            // to which android.test.mock APIs reference. These classes are present
            // in source code form to access necessary comments that disappear when
            // the classes are compiled into a Jar library.
            ":framework-core-sources-for-test-mock",
            ":framework_native_aidl",
        ],

        libs: [
            "framework",
            "framework-annotations-lib",
            "app-compat-annotations",
            "Unsupportedappusage",
        ],

        api_packages: [
            "android.test.mock",
        ],
        permitted_packages: [
            "android.test.mock",
        ],
        compile_dex: true,
        default_to_stubs: true,
    }

Mantendo a compatibilidade com versões anteriores

O sistema de compilação verifica se as APIs mantiveram a compatibilidade com versões anteriores comparando os arquivos de API mais recentes com os arquivos de API gerados no momento da compilação. A java_sdk_library executa a verificação de compatibilidade usando as informações fornecidas por prebuilt_apis . Todas as bibliotecas criadas com java_sdk_library devem ter arquivos de API na versão mais recente de api_dirs em prebuilt_apis . Quando você libera a versão, a API lista os arquivos e as bibliotecas de stubs que podem ser obtidas com dist build com PRODUCT=sdk_phone_armv7-sdk .

A propriedade api_dirs é uma lista de diretórios de versão da API em prebuilt_apis . Os diretórios de versão da API devem estar localizados no nível do diretório Android.bp .

prebuilt_apis {
       name: "foo",
       api_dirs: [
           "1",
           "2",
             ....
           "30",
           "current",
       ],
    }

Configure os diretórios com a estrutura version / scope /api/ no diretório pré-construído. version corresponde ao nível da API e o scope define se o diretório é público, sistema ou teste.

  • version / scope contém bibliotecas Java.
  • version / scope /api contém arquivos .txt da API. Crie arquivos de texto vazios denominados module_name .txt e module_name -removed.txt aqui.
     ├── 30
          │   ├── public
          │   │   ├── api
          │   │   │   ├── android.test.mock-removed.txt
          │   │   │   └── android.test.mock.txt
          │   │   └── android.test.mock.jar
          │   ├── system
          │   │   ├── api
          │   │   │   ├── android.test.mock-removed.txt
          │   │   │   └── android.test.mock.txt
          │   │   └── android.test.mock.jar
          │   └── test
          │       ├── api
          │       │   ├── android.test.mock-removed.txt
          │       │   └── android.test.mock.txt
          │       └── android.test.mock.jar
          └── Android.bp