Implémenter la bibliothèque du SDK Java

La plate-forme Android contient un grand nombre de bibliothèques Java partagées qui peuvent être incluses dans le chemin d'accès des applications avec la balise <uses-library> dans le fichier manifeste de l'application. Les applications se lient à ces bibliothèques. Traitez-les donc comme le reste de l'API Android en termes de compatibilité, d'examen de l'API et de prise en charge des outils. Notez toutefois que la plupart des bibliothèques ne disposent pas de ces fonctionnalités.

Le type de module java_sdk_library permet de gérer les bibliothèques de ce type. Les fabricants d'appareils peuvent utiliser ce mécanisme pour leurs propres bibliothèques Java partagées afin de maintenir la rétrocompatibilité de leurs API. Si les fabricants d'appareils utilisent leurs propres bibliothèques Java partagées via la balise <uses-library> au lieu du chemin d'accès de la classe de démarrage, java_sdk_library peut vérifier que ces bibliothèques Java sont stables au niveau de l'API.

java_sdk_library implémente des API de SDK facultatives à utiliser par les applications. Les bibliothèques implémentées via java_sdk_library dans votre fichier de compilation (Android.bp) effectuent les opérations suivantes:

  • Les bibliothèques de bouchons sont générées pour inclure stubs, stubs.system et stubs.test. Ces bibliothèques de bouchons sont créées en reconnaissant les annotations @hide, @SystemApi et @TestApi.
  • java_sdk_library gère les fichiers de spécifications d'API (comme current.txt) dans un sous-répertoire d'API. Ces fichiers sont comparés au dernier code pour s'assurer qu'il s'agit des versions les plus récentes. Si ce n'est pas le cas, un message d'erreur s'affiche et vous explique comment les mettre à jour. Examinez manuellement toutes les modifications apportées à la mise à jour pour vous assurer qu'elles correspondent à vos attentes.

    Pour mettre à jour toutes les API, utilisez m update-api. Pour vérifier qu'une API est à jour, utilisez m checkapi.
  • Les fichiers de spécification de l'API sont comparés aux versions Android les plus récentes pour s'assurer que l'API est rétrocompatible avec les versions antérieures. Les modules java_sdk_library fournis dans le cadre d'AOSP placent leurs versions précédemment publiées dans prebuilts/sdk/<latest number>.
  • En ce qui concerne les vérifications des fichiers de spécification d'API, vous pouvez effectuer l'une des trois opérations suivantes :
    • Autorisez la poursuite des vérifications. (Ne faites rien.)
    • Désactivez les vérifications en ajoutant le code suivant à java_sdk_library:
      unsafe_ignore_missing_latest_api: true,
    • Fournissez des API vides pour les nouveaux modules java_sdk_library en créant des fichiers texte vides nommés module_name.txt dans le répertoire version/scope/api.
  • Si la bibliothèque d'implémentation du runtime est installée, un fichier XML est généré et installé.

Fonctionnement de java_sdk_library

Un java_sdk_library appelé X crée les éléments suivants:

  1. Deux copies de la bibliothèque d'implémentation: une bibliothèque appelée X et une autre appelée X.impl. La bibliothèque X est installée sur l'appareil. La bibliothèque X.impl n'est présente que si d'autres modules ont besoin d'un accès explicite à la bibliothèque d'implémentation, par exemple pour les tests. Notez que l'accès explicite est rarement nécessaire.
  2. Vous pouvez activer et désactiver les champs d'application pour personnaliser l'accès. (Comme les modificateurs d'accès aux mots clés Java, un champ d'application public offre un large éventail d'accès. Un champ d'application de test contient des API utilisées uniquement pour les tests.) Pour chaque champ d'application activé, la bibliothèque crée les éléments suivants:
    • Un module de source de bouchons (de type de module droidstubs) consomme la source d'implémentation et produit un ensemble de sources de bouchons avec le fichier de spécification de l'API.
    • Une bibliothèque de bouchons (de type de module java_library) est la version compilée des bouchons. Les bibliothèques utilisées pour compiler ce code ne sont pas les mêmes que celles fournies à java_sdk_library, ce qui garantit que les détails d'implémentation ne fuient pas dans les bouchons d'API.
    • Si vous avez besoin de bibliothèques supplémentaires pour compiler les bouchons, utilisez les propriétés stub_only_libs et stub_only_static_libs pour les fournir.

Si un java_sdk_library est appelé "X" et est compilé en tant que "X", faites-y toujours référence de cette manière et ne le modifiez pas. Le build sélectionnera une bibliothèque appropriée. Pour vous assurer de disposer de la bibliothèque la plus appropriée, inspectez vos bouchons pour voir si la compilation a introduit des erreurs. Apportez les corrections nécessaires en suivant ces instructions:

  • Vérifiez que vous disposez d'une bibliothèque appropriée en consultant la ligne de commande et en inspectant les bouchons qui y sont listés pour déterminer votre champ d'application:
    • Le champ d'application est trop large: la bibliothèque dépendante nécessite un certain champ d'application d'API. Toutefois, vous voyez des API incluses dans la bibliothèque qui ne relèvent pas de ce champ d'application, telles que les API système incluses avec les API publiques.
    • Le champ d'application est trop restreint: la bibliothèque dépendante n'a pas accès à toutes les bibliothèques requises. Par exemple, la bibliothèque dépendante doit utiliser l'API système, mais elle obtient l'API publique à la place. Cela entraîne généralement une erreur de compilation, car les API requises sont manquantes.
  • Pour corriger la bibliothèque, effectuez une seule des opérations suivantes:
    • Modifiez sdk_version pour sélectionner la version dont vous avez besoin. OU
    • Spécifiez explicitement la bibliothèque appropriée, telle que <X>.stubs ou <X>.stubs.system.

Utilisation de java_sdk_library X

La bibliothèque d'implémentation X est utilisée lorsqu'elle est référencée à partir de apex.java_libs. Toutefois, en raison d'une limitation de Soong, lorsque la bibliothèque X est référencée à partir d'un autre module java_sdk_library dans la même bibliothèque APEX, X.impl doit être utilisé explicitement, et non la bibliothèque X.

Lorsque java_sdk_library est référencé ailleurs, une bibliothèque de bouchons est utilisée. La bibliothèque de bouchons est sélectionnée en fonction du paramètre de propriété sdk_version du module dépendant. Par exemple, un module qui spécifie sdk_version: "current" utilise les bouchons publics, tandis qu'un module qui spécifie sdk_version: "system_current" utilise les bouchons système. Si aucune correspondance exacte n'est trouvée, la bibliothèque de bouchons la plus proche est utilisée. Un java_sdk_library qui ne fournit qu'une API publique fournira les bouchons publics pour tous.

Flux de compilation avec la bibliothèque du SDK Java
Figure 1. Flux de compilation avec la bibliothèque du SDK Java

Exemples et sources

Les propriétés srcs et api_packages doivent être présentes dans java_sdk_library.

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

AOSP recommande (mais n'exige pas) que les nouvelles instances java_sdk_library activent explicitement les champs d'application d'API qu'elles souhaitent utiliser. Vous pouvez également (facultatif) migrer les instances java_sdk_library existantes pour activer explicitement les champs d'application des API qu'elles utiliseront:

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

Pour configurer la bibliothèque impl utilisée pour l'exécution, utilisez toutes les propriétés java_library normales, telles que hostdex, compile_dex et 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,
    }

Pour configurer des bibliothèques de bouchons, utilisez les propriétés suivantes:

  • merge_annotations_dirs et merge_inclusion_annotations_dirs.
  • api_srcs: liste des fichiers sources facultatifs qui font partie de l'API, mais pas de la bibliothèque d'exécution.
  • stubs_only_libs: liste des bibliothèques Java qui se trouvent dans le chemin d'accès aux classes lors de la création de bouchons.
  • hidden_api_packages: liste des noms de packages à masquer de l'API.
  • droiddoc_options: argument supplémentaire pour metalava.
  • droiddoc_option_files: liste les fichiers pouvant être référencés à partir de droiddoc_options à l'aide de $(location <label>), où <file> est une entrée de la liste.
  • annotations_enabled.

java_sdk_library est un java_library, mais pas un module droidstubs. Il n'est donc pas compatible avec toutes les propriétés droidstubs. L'exemple suivant est tiré du fichier de compilation de la bibliothèque 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,
    }

Assurer la rétrocompatibilité

Le système de compilation vérifie si les API ont conservé la rétrocompatibilité en comparant les derniers fichiers d'API avec les fichiers d'API générés au moment de la compilation. java_sdk_library effectue la vérification de la compatibilité à l'aide des informations fournies par prebuilt_apis. Toutes les bibliothèques créées avec java_sdk_library doivent disposer de fichiers d'API dans la dernière version de api_dirs dans prebuilt_apis. Lorsque vous publiez la version, l'API liste les fichiers et les bibliothèques de bouchons pouvant être obtenus avec la compilation dist avec PRODUCT=sdk_phone_armv7-sdk.

La propriété api_dirs est une liste de répertoires de versions d'API dans prebuilt_apis. Les répertoires de versions d'API doivent se trouver au niveau du répertoire Android.bp.

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

Configurez les répertoires avec la structure version/scope/api/ dans le répertoire prebuilts. version correspond au niveau d'API, et scope définit si le répertoire est public, système ou test.

  • version/scope contient des bibliothèques Java.
  • version/scope/api contient les fichiers .txt de l'API. Créez ici des fichiers texte vides nommés module_name.txt et 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