Implementación de la biblioteca SDK de Java

La plataforma Android contiene una gran cantidad de bibliotecas Java compartidas que, opcionalmente, se pueden incluir en el classpath de aplicaciones con la etiqueta <uses-library> en el manifiesto de la aplicación. Las aplicaciones se vinculan con estas bibliotecas, así que trátelas como el resto de la API de Android en términos de compatibilidad, revisión de API y soporte de herramientas. Sin embargo, tenga en cuenta que la mayoría de las bibliotecas no tienen estas funciones.

El tipo de módulo java_sdk_library ayuda a gestionar bibliotecas de este tipo. Los fabricantes de dispositivos pueden utilizar este mecanismo para sus propias bibliotecas Java compartidas, para mantener la compatibilidad con versiones anteriores de sus API. Si los fabricantes de dispositivos utilizan sus propias bibliotecas Java compartidas a través de la etiqueta <uses-library> en lugar de la ruta de clase de arranque, java_sdk_library puede verificar que esas bibliotecas Java sean estables en API.

java_sdk_library implementa API de SDK opcionales para que las utilicen las aplicaciones. Las bibliotecas implementadas a través de java_sdk_library en su archivo de compilación ( Android.bp ) realizan las siguientes operaciones:

  • Las bibliotecas de códigos auxiliares se generan para incluir stubs , stubs.system y stubs.test . Estas bibliotecas auxiliares se crean reconociendo las anotaciones @hide , @SystemApi y @TestApi .
  • java_sdk_library administra archivos de especificación API (como current.txt ) en un subdirectorio API. Estos archivos se comparan con el código más reciente para garantizar que sean las versiones más recientes. Si no es así, recibirá un mensaje de error que explica cómo actualizarlos. Revise manualmente todos los cambios de actualización para asegurarse de que coincidan con sus expectativas.

    Para actualizar todas las API, utilice m update-api . Para verificar que una API esté actualizada, use m checkapi .
  • Los archivos de especificación de API se comparan con las versiones de Android publicadas más recientemente para garantizar que la API sea compatible con versiones anteriores. Los módulos java_sdk_library proporcionados como parte de AOSP colocan sus versiones publicadas anteriormente en prebuilts/sdk/<latest number> .
  • Con respecto a las comprobaciones de los archivos de especificación API, puede hacer una de las tres cosas siguientes:
    • Permita que continúen las comprobaciones. (No hagas nada.)
    • Deshabilite las comprobaciones agregando lo siguiente a java_sdk_library :
      unsafe_ignore_missing_latest_api: true,
    • Proporcione API vacías para nuevos módulos java_sdk_library creando archivos de texto vacíos denominados module_name.txt en el directorio version/scope/api .
  • Si la biblioteca de implementación para el tiempo de ejecución está instalada, se genera e instala un archivo XML.

Cómo funciona java_sdk_library

Un java_sdk_library llamado X crea lo siguiente:

  1. Dos copias de la biblioteca de implementación: una biblioteca llamada X y otra llamada X.impl . La biblioteca X está instalada en el dispositivo. La biblioteca X.impl está ahí solo si otros módulos necesitan acceso explícito a la biblioteca de implementación, como por ejemplo para su uso en pruebas. Tenga en cuenta que rara vez se necesita acceso explícito.
  2. Los ámbitos se pueden habilitar y deshabilitar para personalizar el acceso. (De manera similar a los modificadores de acceso a palabras clave de Java, un alcance público proporciona una amplia gama de acceso; un alcance de prueba contiene API que solo se usan en pruebas). Para cada alcance habilitado, la biblioteca crea lo siguiente:
    • Un módulo de código auxiliar (del tipo de módulo droidstubs ): consume el código fuente de implementación y genera un conjunto de fuentes de código auxiliar junto con el archivo de especificación API.
    • Una biblioteca de apéndices (del tipo de módulo java_library ): es la versión compilada de los apéndices. Las bibliotecas utilizadas para compilar esto no son las mismas que las proporcionadas a java_sdk_library , lo que garantiza que los detalles de implementación no se filtren en los códigos auxiliares de API.
    • Si necesita bibliotecas adicionales para compilar los códigos auxiliares, utilice las propiedades stub_only_libs y stub_only_static_libs para proporcionarlos.

Si java_sdk_library se llama " X " y se está compilando como " X ", consúltelo siempre de esa manera y no lo modifique. La compilación seleccionará una biblioteca apropiada. Para asegurarse de tener la biblioteca más adecuada, inspeccione sus resguardos para ver si la compilación introdujo errores. Realice las correcciones necesarias siguiendo esta guía:

  • Verifique que tenga una biblioteca adecuada buscando en la línea de comando e inspeccionando qué apéndices se enumeran allí para determinar su alcance:
    • El alcance es demasiado amplio: la biblioteca dependiente necesita un cierto alcance de API. Pero ve API incluidas en la biblioteca que quedan fuera de ese alcance, como las API del sistema incluidas con las API públicas.
    • El alcance es demasiado limitado: la biblioteca dependiente no tiene acceso a todas las bibliotecas necesarias. Por ejemplo, la biblioteca dependiente necesita utilizar la API del sistema, pero en su lugar obtiene la API pública. Esto normalmente resulta en un error de compilación porque faltan las API necesarias.
  • Para arreglar la biblioteca, haga solo uno de los siguientes:
    • Cambie sdk_version para seleccionar la versión que necesita. O
    • Especifique explícitamente la biblioteca adecuada, como <X>.stubs o <X>.stubs.system .

uso de java_sdk_library X

La biblioteca de implementación X se utiliza cuando se hace referencia a ella desde apex.java_libs . Sin embargo, debido a una limitación de Soong, cuando se hace referencia a la biblioteca X desde otro módulo java_sdk_library dentro de la misma biblioteca APEX, se debe usar explícitamente X.impl , no la biblioteca X

Cuando se hace referencia a java_sdk_library desde otro lugar, se utiliza una biblioteca de códigos auxiliares. La biblioteca de códigos auxiliares se selecciona de acuerdo con la configuración de la propiedad sdk_version del módulo dependiente. Por ejemplo, un módulo que especifica sdk_version: "current" usa los códigos auxiliares públicos, mientras que un módulo que especifica sdk_version: "system_current" usa los códigos auxiliares del sistema. Si no se puede encontrar una coincidencia exacta, se utiliza la biblioteca de resguardos más cercana. Una java_sdk_library que solo proporciona una API pública proporcionará los códigos auxiliares públicos para todos.

Flujo de compilación con la biblioteca Java SDK
Figura 1. Flujo de compilación con la biblioteca Java SDK

Ejemplos y fuentes

Las propiedades srcs y api_packages deben estar presentes en java_sdk_library .

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

AOSP recomienda (pero no exige) que las nuevas instancias java_sdk_library habiliten explícitamente los alcances de API que desean usar. También puedes (opcionalmente) migrar instancias java_sdk_library existentes para habilitar explícitamente los alcances de API que usarán:

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

Para configurar la biblioteca impl utilizada para el tiempo de ejecución, utilice todas las propiedades java_library normales, como hostdex , compile_dex y 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,
    }

Para configurar bibliotecas de apéndice, utilice las siguientes propiedades:

  • merge_annotations_dirs y merge_inclusion_annotations_dirs .
  • api_srcs : la lista de archivos fuente opcionales que forman parte de la API pero no de la biblioteca de tiempo de ejecución.
  • stubs_only_libs : la lista de bibliotecas Java que se encuentran en el classpath al crear apéndices.
  • hidden_api_packages : la lista de nombres de paquetes que deben ocultarse de la API.
  • droiddoc_options : Argumento adicional para metalava .
  • droiddoc_option_files : enumera los archivos a los que se puede hacer referencia desde droiddoc_options usando $(location <label>) , donde <file> es una entrada en la lista.
  • annotations_enabled .

java_sdk_library es java_library , pero no es un módulo droidstubs y, por lo tanto, no admite todas las propiedades droidstubs . El siguiente ejemplo se tomó del archivo de compilación de la biblioteca 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,
    }

Mantener la compatibilidad con versiones anteriores

El sistema de compilación verifica si las API han mantenido la compatibilidad con versiones anteriores comparando los archivos API más recientes con los archivos API generados en el momento de la compilación. java_sdk_library realiza la verificación de compatibilidad utilizando la información proporcionada por prebuilt_apis . Todas las bibliotecas creadas con java_sdk_library deben tener archivos API en la última versión de api_dirs en prebuilt_apis . Cuando lanza la versión, la API enumera los archivos y las bibliotecas auxiliares que se pueden obtener con dist build con PRODUCT=sdk_phone_armv7-sdk .

La propiedad api_dirs es una lista de directorios de versiones de API en prebuilt_apis . Los directorios de la versión API deben estar ubicados en el nivel del directorio Android.bp .

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

Configure los directorios con la estructura version / scope /api/ en el directorio precompilado. version corresponde al nivel de API y scope define si el directorio es público, de sistema o de prueba.

  • version / scope contiene bibliotecas Java.
  • version / scope /api contiene archivos API .txt . Cree archivos de texto vacíos llamados module_name .txt y module_name -removed.txt aquí.
     ├── 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