Implémentation de la bibliothèque Java SDK

La plate-forme Android contient un grand nombre de bibliothèques Java partagées qui peuvent éventuellement être incluses dans le chemin de classe des applications avec la balise <uses-library> dans le manifeste de l'application. Les applications sont liées à ces bibliothèques, alors traitez-les comme le reste de l'API Android en termes de compatibilité, de révision de l'API et de prise en charge des outils. Notez cependant que la plupart des bibliothèques ne disposent pas de ces fonctionnalités.

Le type de module java_sdk_library permet de gérer des 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 compatibilité ascendante de leurs API. Si les fabricants de périphériques utilisent leurs propres bibliothèques Java partagées via la balise <uses-library> au lieu du chemin de la classe de démarrage, java_sdk_library peut vérifier que ces bibliothèques Java sont stables au niveau API.

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

  • Les bibliothèques de stubs sont générées pour inclure stubs , stubs.system et stubs.test . Ces bibliothèques de stubs sont créées en reconnaissant les annotations @hide , @SystemApi et @TestApi .
  • La java_sdk_library gère les fichiers de spécification d'API (tels que current.txt ) dans un sous-répertoire API. Ces fichiers sont vérifiés par rapport au code le plus récent pour garantir qu'il s'agit des versions les plus récentes. Si ce n'est pas le cas, vous recevez un message d'erreur expliquant 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écifications de l'API sont vérifiés par rapport aux versions Android publiées les plus récemment pour garantir 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 de l'API, vous pouvez effectuer l'une des trois opérations suivantes :
    • Autorisez les vérifications à se poursuivre. (Ne fais rien.)
    • Désactivez les vérifications en ajoutant ce qui suit à 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 pour le runtime est installée, un fichier XML est généré et installé.

Comment fonctionne java_sdk_library

Une java_sdk_library appelée X crée ce qui suit :

  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 là que si un accès explicite à la bibliothèque d'implémentation est requis par d'autres modules, par exemple pour une utilisation dans les tests. Notez qu'un accès explicite est rarement nécessaire.
  2. Les étendues peuvent être activées et désactivées pour personnaliser l’accès. (Semblable aux modificateurs d'accès par mot-clé Java, une portée publique offre une large gamme d'accès ; une portée de test contient des API uniquement utilisées dans les tests.) Pour chaque portée activée, la bibliothèque crée les éléments suivants :
    • Un module source stubs (de type module droidstubs ) - consomme la source d'implémentation et génère un ensemble de sources stubs avec le fichier de spécification de l'API.
    • Une bibliothèque de stubs (de type module java_library ) - est la version compilée des stubs. Les bibliothèques utilisées pour compiler ceci 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 stubs de l'API.
    • Si vous avez besoin de bibliothèques supplémentaires pour compiler les stubs, utilisez les propriétés stub_only_libs et stub_only_static_libs pour les fournir.

Si une java_sdk_library s'appelle « X » et est compilée sous le nom « X », faites-y toujours référence de cette façon et ne la modifiez pas. La construction sélectionnera une bibliothèque appropriée. Pour vous assurer que vous disposez de la bibliothèque la plus appropriée, inspectez vos stubs pour voir si la build a introduit des erreurs. Apportez les corrections nécessaires à l’aide de ces conseils :

  • Vérifiez que vous disposez d'une bibliothèque appropriée en consultant la ligne de commande et en inspectant les stubs qui y sont répertoriés pour déterminer votre portée :
    • La portée est trop large : la bibliothèque dépendante a besoin d'une certaine portée d'API. Mais vous voyez des API incluses dans la bibliothèque qui n'entrent pas dans cette portée, telles que les API système incluses avec les API publiques.
    • La portée est trop étroite : 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 obtient à la place l’API publique. Cela entraîne généralement une erreur de compilation car les API nécessaires sont manquantes.
  • Pour réparer la bibliothèque, effectuez une seule des opérations suivantes :
    • Modifiez le 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 depuis apex.java_libs . Cependant, en raison d'une limitation Soong, lorsque la bibliothèque X est référencée à partir d'un autre module java_sdk_library au sein de la même bibliothèque APEX, X.impl doit explicitement être utilisé, et non la bibliothèque X .

Lorsque la java_sdk_library est référencée ailleurs, une bibliothèque stubs est utilisée. La bibliothèque stubs 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 stubs publics, tandis qu'un module qui spécifie sdk_version: "system_current" utilise les stubs système. Si aucune correspondance exacte ne peut être trouvée, la bibliothèque de stub la plus proche est utilisée. Une java_sdk_library qui fournit uniquement une API publique fournira les stubs publics pour tout le monde.

Créer un flux avec la bibliothèque Java SDK
Figure 1. Créer un flux avec la bibliothèque Java SDK

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 étendues d'API qu'elles souhaitent utiliser. Vous pouvez également (facultatif) migrer les instances java_sdk_library existantes pour activer explicitement les étendues d'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 les bibliothèques de stubs, 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 ne font pas partie de la bibliothèque d'exécution.
  • stubs_only_libs : La liste des bibliothèques Java qui se trouvent dans le chemin de classe lors de la création des stubs.
  • hidden_api_packages : La liste des noms de packages qui doivent être masqués de l'API.
  • droiddoc_options : Argument supplémentaire pour metalava .
  • droiddoc_option_files : Répertorie les fichiers qui peuvent être référencés depuis droiddoc_options en utilisant $(location <label>) , où <file> est une entrée dans la liste.
  • annotations_enabled .

Le java_sdk_library est un java_library , mais ce n'est pas un module droidstubs et ne prend donc pas en charge toutes les propriétés droidstubs . L'exemple suivant est tiré du fichier de construction 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,
    }

Maintenir la compatibilité ascendante

Le système de build vérifie si les API ont maintenu une compatibilité ascendante en comparant les derniers fichiers API avec les fichiers API générés au moment de la construction. La java_sdk_library effectue la vérification de compatibilité en utilisant les informations fournies par prebuilt_apis . Toutes les bibliothèques créées avec java_sdk_library doivent avoir des fichiers API dans la dernière version de api_dirs dans prebuilt_apis . Lorsque vous publiez la version, l'API répertorie les fichiers et les bibliothèques de stubs peuvent être obtenues avec dist build avec PRODUCT=sdk_phone_armv7-sdk .

La propriété api_dirs est la liste des répertoires de versions d'API dans prebuilt_apis . Les répertoires de version API doivent être situés 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/ sous le répertoire prebuilts. version correspond au niveau de l'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 des fichiers API .txt . 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