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 la ruta de clase de las 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. Tenga en cuenta, sin embargo, que la mayoría de las bibliotecas no tienen estas características.

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

java_sdk_library implementa API de SDK opcionales para que las usen 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 stubs se generan para incluir stubs , stubs.system y stubs.test . Estas bibliotecas de stubs se crean reconociendo @hide , @SystemApi y @TestApi .
  • java_sdk_library administra archivos de especificación de API (como current.txt ) en un subdirectorio de API. Estos archivos se comparan con el código más reciente para garantizar que sean las versiones más recientes. Si no lo están, 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, use 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 de API, puede hacer una de las siguientes tres cosas:
    • Permita que los cheques continúen. (No hagas nada.)
    • Deshabilite las comprobaciones agregando lo siguiente a java_sdk_library :
      unsafe_ignore_missing_latest_api: true,
    • Proporcione API vacías para los 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

Una java_sdk_library llamada 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á allí solo si otros módulos necesitan acceso explícito a la biblioteca de implementación, como para usar 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. (Al igual que los modificadores de acceso de palabras clave de Java, un ámbito público proporciona una amplia gama de acceso; un ámbito de prueba contiene API que solo se utilizan en las pruebas). Para cada ámbito habilitado, la biblioteca crea lo siguiente:
    • Un módulo fuente de stubs (del tipo de módulo droidstubs ): consume la fuente de implementación y genera un conjunto de fuentes de stub junto con el archivo de especificación API.
    • Una biblioteca de stubs (del tipo de módulo java_library ) - es la versión compilada de los stubs. Las bibliotecas utilizadas para compilar esto no son las mismas que se proporcionan a java_sdk_library , lo que garantiza que los detalles de implementación no se filtren en los apéndices de la API.
    • Si necesita bibliotecas adicionales para compilar los stubs, use las propiedades stub_only_libs y stub_only_static_libs para suministrarlas.

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

  • Verifique que tiene una biblioteca adecuada mirando en la línea de comando e inspeccionando qué stubs 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 ámbito es demasiado limitado: la biblioteca dependiente no tiene acceso a todas las bibliotecas necesarias. Por ejemplo, la biblioteca dependiente necesita usar la API del sistema, pero obtiene la API pública en su lugar. Esto suele dar como resultado un error de compilación porque faltan las API necesarias.
  • Para reparar la biblioteca, realice solo una de las siguientes acciones:
    • 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 usa 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 stubs. La biblioteca de stubs 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 stubs públicos, mientras que un módulo que especifica sdk_version: "system_current" usa los stubs del sistema. Si no se puede encontrar una coincidencia exacta, se utiliza la biblioteca de código auxiliar más cercana. Una java_sdk_library que solo proporciona una API pública proporcionará los stubs públicos para todos.

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

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 ámbitos de API que desean usar. También puede (opcionalmente) migrar instancias existentes de java_sdk_library para habilitar explícitamente los ámbitos 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, use todas las propiedades normales de java_library , 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éndices, use las siguientes propiedades:

  • merge_annotations_dirs y merge_inclusion_annotations_dirs .
  • api_srcs : la lista de archivos de origen opcionales que forman parte de la API pero no de la biblioteca de tiempo de ejecución.
  • stubs_only_libs : la lista de bibliotecas de Java que están en el classpath cuando se construyen stubs.
  • 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 una java_library , pero no es un módulo de droidstubs y, por lo tanto, no es compatible con todas las propiedades de 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,
    }

Mantenimiento de la compatibilidad con versiones anteriores

El sistema de compilación comprueba si las API han mantenido la compatibilidad con versiones anteriores comparando los últimos archivos de API con los archivos de API generados en el momento de la compilación. java_sdk_library realiza la comprobació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 de apéndices 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 de la 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 prebuilds. la version corresponde al nivel de la API y el scope define si el directorio es público, del sistema o de prueba.

  • version / scope contiene bibliotecas de 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