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 <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 n'ont pas ces fonctionnalités.

Le type de module java_sdk_library aide à 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 de périphériques utilisent leurs propres bibliothèques Java partagées via la <uses-library> au lieu du chemin bootclass, java_sdk_library peut vérifier que ces bibliothèques Java sont stables pour l'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 construction ( 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 @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 d'API. Ces fichiers sont vérifiés par rapport au dernier code pour s'assurer 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 de 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 vérifiés par rapport aux versions Android les plus récemment publiées 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 actions suivantes :
    • Laissez les vérifications se poursuivre. (Ne faites 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 du 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. (Similaire aux modificateurs d'accès par mot-clé Java, une étendue publique fournit un large éventail d'accès ; une étendue de test contient des API uniquement utilisées dans les tests.) Pour chaque étendue activée, la bibliothèque crée ce qui suit :
    • Un module source de stubs (de type module droidstubs ) - consomme la source d'implémentation et génère un ensemble de sources de 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 d'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 en tant que « 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 construction 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 regardant sur 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 ne relèvent pas de 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 l'API publique à la place. Cela entraîne généralement une erreur de compilation car les API nécessaires sont manquantes.
  • Pour réparer la bibliothèque, effectuez l'une des actions suivantes :
    • Modifiez le sdk_version pour sélectionner la version dont vous avez besoin. OU ALORS
    • 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 de 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 être utilisé explicitement , et non la bibliothèque X .

Lorsque la java_sdk_library est référencée ailleurs, une bibliothèque de stubs est utilisée. La bibliothèque de 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 ne fournit qu'une API publique fournira les stubs publics pour tout le monde.

Créer un flux avec la bibliothèque Java SDK
Figure 1. Flux de génération avec la bibliothèque Java SDK

Exemples et sources

Les propriétés srcs et api_packages doivent être présentes dans la 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 explicitement les étendues d'API qu'elles souhaitent utiliser. Vous pouvez également (facultatif) migrer des instances java_sdk_library existantes pour activer explicitement les portées 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 : La liste des fichiers source facultatifs qui font partie de l'API mais pas de la bibliothèque d'exécution.
  • stubs_only_libs : La liste des bibliothèques Java qui se trouvent dans le classpath lors de la construction des stubs.
  • hidden_api_packages : La liste des noms de packages qui doivent être cachés à l'API.
  • droiddoc_options : Argument supplémentaire pour metalava .
  • droiddoc_option_files : Répertorie les fichiers qui peuvent être référencés à partir de droiddoc_options en utilisant $(location <label>) , où <file> est une entrée dans la liste.
  • annotations_enabled .

La java_sdk_library est une 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 a été 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,
    }

Maintien de la rétrocompatibilité

Le système de génération vérifie si les API ont maintenu la compatibilité descendante en comparant les derniers fichiers d'API avec les fichiers d'API générés au moment de la génération. La java_sdk_library effectue la vérification de compatibilité en utilisant les informations fournies par prebuilt_apis . Toutes les bibliothèques construites 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 version d'API dans prebuilt_apis . Les répertoires de la 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. la version correspond au niveau de l'API et la 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