Implementa la libreria SDK Java

La piattaforma Android contiene un numero elevato di librerie Java condivise che, facoltativamente, possono essere incluse nel percorso di classe delle app con il tag <uses-library> nel file manifest dell'app. Le app si collegano a queste librerie, quindi trattale come il resto dell'API Android in termini di compatibilità, revisione dell'API e supporto degli strumenti. Tieni presente, tuttavia, che la maggior parte delle librerie non dispone di queste funzionalità.

Il tipo di modulo java_sdk_library consente di gestire librerie di questo tipo. I produttori di dispositivi possono utilizzare questo meccanismo per le proprie librerie Java condivise, per mantenere la compatibilità con le versioni precedenti delle loro API. Se i produttori di dispositivi utilizzano le proprie librerie Java condivise tramite il tag <uses-library> anziché il percorso della classe di avvio, java_sdk_library può verificare che queste librerie Java siano API-stable.

java_sdk_library implementa API SDK facoltative da utilizzare dalle app. Le librerie implementate tramite java_sdk_library nel file di compilazione (Android.bp) eseguono le seguenti operazioni:

  • Le librerie di stub vengono generate in modo da includere stubs, stubs.system e stubs.test. Queste librerie di stub vengono create riconoscendo le annotazioni @hide, @SystemApi e @TestApi.
  • java_sdk_library gestisce i file di specifiche dell'API (ad esempio current.txt) in una sottodirectory dell'API. Questi file vengono controllati in base al codice più recente per assicurarsi che siano le versioni più aggiornate. In caso contrario, riceverai un messaggio di errore che spiega come aggiornarli. Esamina manualmente tutte le modifiche dell'aggiornamento per assicurarti che corrispondano alle tue aspettative.

    Per aggiornare tutte le API, utilizza m update-api. Per verificare che un'API sia aggiornata, utilizza m checkapi.
  • I file delle specifiche dell'API vengono controllati in base alle versioni Android pubblicate più di recente per garantire la compatibilità con le release precedenti. I moduli java_sdk_library forniti nell'ambito di AOSP posizionano le versioni rilasciate in precedenza in prebuilts/sdk/<latest number>.
  • In merito ai controlli dei file delle specifiche dell'API, puoi eseguire una delle seguenti tre operazioni:
    • Consenti l'esecuzione dei controlli. (Non fare nulla.)
    • Disattiva i controlli aggiungendo quanto segue a java_sdk_library:
      unsafe_ignore_missing_latest_api: true,
    • Fornisci API vuote per i nuovi moduli java_sdk_library creando file di testo vuoti denominati module_name.txt nella directory version/scope/api.
  • Se la libreria di implementazione per il runtime è installata, viene generato e installato un file XML.

Come funziona java_sdk_library

Un java_sdk_library denominato X crea quanto segue:

  1. Due copie della libreria di implementazione: una chiamata X e l'altra X.impl. La raccolta X è installata sul dispositivo. La libreria X.impl è presente solo se altri moduli richiedono l'accesso esplicito alla libreria di implementazione, ad esempio per l'utilizzo nei test. Tieni presente che l'accesso esplicito è necessario raramente.
  2. Gli ambiti possono essere attivati e disattivati per personalizzare l'accesso. Analogamente ai modificatori di accesso alle parole chiave di Java, un ambito pubblico fornisce un'ampia gamma di accessi; un ambito di test contiene API utilizzate solo per i test. Per ogni ambito abilitato, la libreria crea quanto segue:
    • Un modulo di origine stub (di tipo di modulo droidstubs) che utilizza l'origine dell'implementazione e genera un insieme di origini stub insieme al file di specifica dell'API.
    • Una libreria di stub (di tipo di modulo java_library) è la versione compilata degli stub. Le librerie utilizzate per la compilazione non sono le stesse di quelle fornite a java_sdk_library, il che garantisce che i dettagli di implementazione non vengano divulgati negli stub dell'API.
    • Se hai bisogno di librerie aggiuntive per compilare gli stub, utilizza le proprietà stub_only_libs e stub_only_static_libs per fornirle.

Se un java_sdk_library si chiama "X" e viene compilato come "X", fai sempre riferimento a questo nome e non modificarlo. La compilazione selezionerà una libreria appropriata. Per assicurarti di avere la biblioteca più appropriata, controlla gli stub per vedere se la compilazione ha introdotto errori. Apporta le correzioni necessarie seguendo queste indicazioni:

  • Verifica di disporre di una libreria appropriata controllando la riga di comando e esaminando gli stub elencati per determinare l'ambito:
    • Ambito troppo ampio: la libreria dipendente ha bisogno di un determinato ambito di API. Tuttavia, vedi API incluse nella libreria che non rientrano in questo ambito, come le API di sistema incluse nelle API pubbliche.
    • Ambito troppo ristretto: la libreria dipendente non ha accesso a tutte le librerie richieste. Ad esempio, la libreria dipendente deve utilizzare l'API di sistema, ma ottiene l'API pubblica. In genere si verifica un errore di compilazione perché mancano le API necessarie.
  • Per correggere la libreria, esegui solo una delle seguenti operazioni:
    • Modifica il sdk_version per selezionare la versione di cui hai bisogno. O
    • Specifica esplicitamente la libreria appropriata, ad esempio <X>.stubs o <X>.stubs.system.

Utilizzo di java_sdk_library X

La libreria di implementazione X viene utilizzata quando viene fatto riferimento a apex.java_libs. Tuttavia, a causa di una limitazione di Soong, quando viene fatto riferimento alla libreria X da un altro modulo java_sdk_library all'interno della stessa libreria APEX, deve essere utilizzata X.impl esplicitamente, non la libreria X.

Quando a java_sdk_library viene fatto riferimento da un'altra posizione, viene utilizzata una libreria di stub. La raccolta di stub viene selezionata in base all'impostazione della proprietà sdk_version del modulo dipendente. Ad esempio, un modulo che specifica sdk_version: "current" utilizza gli stub pubblici, mentre un modulo che specifica sdk_version: "system_current" utilizza gli stub di sistema. Se non è possibile trovare una corrispondenza esatta, viene utilizzata la libreria stub più simile. Un java_sdk_library che fornisce solo un'API pubblica fornirà gli stub pubblici a tutti.

Creare un flusso con la libreria SDK Java
Figura 1. Flusso di compilazione con la libreria SDK Java

Esempi e fonti

Le proprietà srcs e api_packages devono essere presenti in java_sdk_library.

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

AOSP consiglia (ma non richiede) che le nuove istanze di java_sdk_library abilitino esplicitamente gli ambiti API che vogliono utilizzare. Puoi anche (facoltativo) eseguire la migrazione delle istanze java_sdk_library esistenti per attivare esplicitamente gli ambiti API che utilizzeranno:

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

Per configurare la libreria impl utilizzata per il runtime, utilizza tutte le proprietà java_library normali, ad esempio 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,
    }

Per configurare le librerie di stub, utilizza le seguenti proprietà:

  • merge_annotations_dirs e merge_inclusion_annotations_dirs.
  • api_srcs: l'elenco dei file di origine facoltativi che fanno parte dell'API, ma non della libreria di runtime.
  • stubs_only_libs: l'elenco delle librerie Java presenti nel percorso di ricerca durante la creazione di stub.
  • hidden_api_packages: l'elenco dei nomi dei pacchetti che devono essere nascosti all'API.
  • droiddoc_options: argomento aggiuntivo per metalava.
  • droiddoc_option_files: elenca i file a cui è possibile fare riferimento da droiddoc_options utilizzando $(location <label>), dove <file> è una voce nell'elenco.
  • annotations_enabled.

java_sdk_library è un java_library, ma non è un modulo droidstubs e quindi non supporta tutte le proprietà droidstubs. Il seguente esempio è stato tratto dal file android.test.mock library build.

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

Mantenere la compatibilità con le versioni precedenti

Il sistema di compilazione controlla se le API hanno mantenuto la compatibilità con le versioni precedenti confrontando i file API più recenti con quelli generati in fase di compilazione. java_sdk_library esegue il controllo di compatibilità utilizzando le informazioni fornite da prebuilt_apis. Tutte le librerie create con java_sdk_library devono avere file API nella versione più recente di api_dirs in prebuilt_apis. Quando rilasci la versione, l'API elenca i file e le librerie di stub che possono essere ottenuti con la compilazione dist con PRODUCT=sdk_phone_armv7-sdk.

La proprietà api_dirs è l'elenco delle directory delle versioni dell'API in prebuilt_apis. Le directory delle versioni dell'API devono essere situate a livello di directory Android.bp.

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

Configura le directory con la struttura version/scope/api/ nella directory prebuilt. version corrisponde al livello API e scope definisce se la directory è pubblica, di sistema o di test.

  • version/scope contiene librerie Java.
  • version/scope/api contiene i file API .txt. Crea qui file di testo vuoti denominati module_name.txt e module_name-removed.txt.
     ├── 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