Implementazione della libreria Java SDK

La piattaforma Android contiene un gran numero di librerie Java condivise che possono facoltativamente essere incluse nel classpath delle app con il tag <uses-library> nel 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 aiuta a 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 proprie API. Se i produttori di dispositivi utilizzano le proprie librerie Java condivise tramite il tag <uses-library> anziché il percorso bootclass, java_sdk_library può verificare che tali librerie Java siano stabili tramite API.

java_sdk_library implementa API SDK opzionali per l'utilizzo da parte delle app. Le librerie implementate tramite java_sdk_library nel file di build ( Android.bp ) eseguono le seguenti operazioni:

  • Le librerie stub vengono generate per includere stubs , stubs.system e stubs.test . Queste librerie stub vengono create riconoscendo le annotazioni @hide , @SystemApi e @TestApi .
  • java_sdk_library gestisce i file di specifica API (come current.txt ) in una sottodirectory API. Questi file vengono confrontati con il codice più recente per garantire che siano le versioni più recenti. 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, utilizzare m update-api . Per verificare che un'API sia aggiornata, utilizzare m checkapi .
  • I file delle specifiche API vengono confrontati con le versioni Android pubblicate più di recente per garantire che l'API sia compatibile con le versioni precedenti. I moduli java_sdk_library forniti come parte di AOSP inseriscono le versioni rilasciate in precedenza in prebuilts/sdk/<latest number> .
  • Per quanto riguarda i controlli dei file delle specifiche API, puoi eseguire una delle tre cose seguenti:
    • Consentire il proseguimento dei controlli. (Non fare nulla.)
    • Disabilita 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 è installata la libreria di implementazione per il runtime, viene generato e installato un file XML.

Come funziona java_sdk_library

Una java_sdk_library chiamata X crea quanto segue:

  1. Due copie della libreria di implementazione: una libreria chiamata X e un'altra chiamata X.impl . La libreria X è installata sul dispositivo. La libreria X.impl è disponibile solo se altri moduli necessitano dell'accesso esplicito alla libreria di implementazione, ad esempio per l'utilizzo nei test. Tieni presente che l'accesso esplicito è raramente necessario.
  2. Gli ambiti possono essere abilitati e disabilitati per personalizzare l'accesso. (Simile ai modificatori di accesso tramite parole chiave Java, un ambito pubblico fornisce un'ampia gamma di accesso; un ambito di test contiene API utilizzate solo nei test.) Per ogni ambito abilitato la libreria crea quanto segue:
    • Un modulo sorgente stub (del tipo di modulo droidstubs ): utilizza il sorgente di implementazione e restituisce una serie di sorgenti stub insieme al file di specifiche API.
    • Una libreria stub (del tipo di modulo java_library ) - è la versione compilata degli stub. Le librerie utilizzate per compilarlo non sono le stesse fornite a java_sdk_library , il che garantisce che i dettagli di implementazione non penetrino negli stub dell'API.
    • Se sono necessarie librerie aggiuntive per compilare gli stub, utilizzare le proprietà stub_only_libs e stub_only_static_libs per fornirle.

Se una java_sdk_library si chiama " X " e viene compilata come " X ", riferisciti sempre ad essa in questo modo e non modificarla. La build selezionerà una libreria appropriata. Per assicurarti di avere la libreria più appropriata, controlla i tuoi stub per vedere se la build ha introdotto errori. Apportare le correzioni necessarie utilizzando questa guida:

  • Verifica di disporre di una libreria appropriata esaminando la riga di comando e controllando quali stub sono elencati lì per determinare il tuo ambito:
    • L'ambito è troppo ampio: la libreria dipendente richiede un determinato ambito di API. Ma vedi le API incluse nella libreria che non rientrano in tale ambito, come le API di sistema incluse con le API pubbliche.
    • L'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 invece l'API pubblica. Ciò in genere provoca un errore di compilazione perché mancano le API necessarie.
  • Per correggere la libreria, effettuare solo una delle seguenti operazioni:
    • Modifica sdk_version per selezionare la versione che ti serve. O
    • Specificare 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 da apex.java_libs . Tuttavia, a causa di una limitazione di Soong, quando si fa riferimento alla libreria X da un altro modulo java_sdk_library all'interno della stessa libreria APEX, è necessario utilizzare esplicitamente X.impl e non la libreria X .

Quando si fa riferimento a java_sdk_library da altrove, viene utilizzata una libreria stub. La libreria 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ù vicina. Una java_sdk_library che fornisce solo un'API pubblica fornirà gli stub pubblici per tutti.

Crea flusso con la libreria Java SDK
Figura 1. Flusso di creazione con la libreria Java SDK

Esempi e fonti

Le proprietà srcs e api_packages devono essere presenti nella 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 java_sdk_library abilitino esplicitamente gli ambiti API che desiderano utilizzare. Puoi anche (facoltativamente) migrare le istanze java_sdk_library esistenti per abilitare 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, utilizzare tutte le normali proprietà java_library , come 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 stub, utilizzare le seguenti proprietà:

  • merge_annotations_dirs e merge_inclusion_annotations_dirs .
  • api_srcs : l'elenco di 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 classpath durante la creazione di stub.
  • hidden_api_packages : l'elenco dei nomi dei pacchetti che devono essere nascosti dall'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 .

La java_sdk_library è una java_library , ma non è un modulo droidstubs e quindi non supporta tutte le proprietà droidstubs . L'esempio seguente è stato preso dal file di build della libreria 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,
    }

Mantenimento della compatibilità con le versioni precedenti

Il sistema di compilazione verifica se le API hanno mantenuto la compatibilità con le versioni precedenti confrontando i file API più recenti con i file API 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 nell'ultima versione di api_dirs in prebuilt_apis . Quando rilasci la versione, l'API elenca i file e le librerie stub possono essere ottenute con dist build con PRODUCT=sdk_phone_armv7-sdk .

La proprietà api_dirs è l'elenco delle directory della versione API in prebuilt_apis . Le directory della versione API devono trovarsi 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 prebuilts. version corrisponde al livello API e scope definisce se la directory è pubblica, di sistema o di test.

  • version / scope contiene le librerie Java.
  • version / scope /api contiene 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