Verificación de compatibilidad con versiones anteriores del marco HIDL

Las HAL de HIDL garantizan que el sistema central de Android (también conocido como system.img o el marco) es compatible con versiones anteriores. Si bien las pruebas de Vendor Test Suite (VTS) garantizan que las HAL funcionen como se espera (por ejemplo, las pruebas de HAL 1.1 se ejecutan en todas las implementaciones 1.2), se necesitan pruebas de marco para garantizar que cuando se proporciona una HAL compatible (1.0, 1.1 o 1.2), la framework funciona correctamente con ese HAL.

Para obtener detalles sobre el lenguaje de definición de interfaz HAL (HIDL), consulte HIDL , control de versiones de HIDL y HIDL HAL Obsoleto .

Acerca de las actualizaciones de HAL

Hay dos tipos de actualizaciones de HAL: mayor y menor . La mayoría de los sistemas incluyen solo una implementación de HAL, pero se admiten múltiples implementaciones. Por ejemplo:

android.hardware.teleport@1.0 # initial interface
android.hardware.teleport@1.1 # minor version upgrade
android.hardware.teleport@1.2 # another minor version upgrade
...
android.hardware.teleport@2.0 # major version upgrade
...

La partición del sistema generalmente incluye un demonio de marco (como teleportd ) que administra la comunicación con un grupo específico de implementaciones HAL. Alternativamente, los sistemas pueden incluir una biblioteca del sistema (como android.hardware.configstore-utils ) que implementa un comportamiento conveniente del cliente. En el ejemplo anterior, teleportd debe funcionar sin importar qué versión de HAL esté instalada en el dispositivo.

Versiones mantenidas por Google

Si existen actualizaciones de versiones principales (1.0, 2.0, 3.0, etc.), al menos un dispositivo mantenido por Google debe mantener una implementación de cada versión principal hasta que esa versión quede obsoleta. Si ningún dispositivo mantenido por Google se envía con una versión principal específica, Google continúa manteniendo una implementación anterior de esa versión principal.

Dicho mantenimiento agrega una sobrecarga adicional menor porque la implementación anterior (p. ej., 1.2) puede conservarse y no usarse de forma predeterminada cuando se crea una nueva implementación (p. ej., 2.0).

Prueba de actualizaciones de versiones secundarias

Probar la compatibilidad con versiones anteriores de versiones secundarias en el marco requiere una forma de generar automáticamente implementaciones de versiones secundarias. Dadas las restricciones en torno a las versiones mantenidas por Google, hidl-gen solo generará (y solo puede) adaptadores que tomen una implementación 1.(x+n) y proporcionen una implementación 1.x; no puede generar una implementación 1.0 a partir de una implementación 2.0 (por definición de una versión principal).

Por ejemplo, para ejecutar pruebas 1.1 en una implementación 1.2, debe poder simular tener una implementación 1.1. Las interfaces 1.2 se pueden usar automáticamente como implementación 1.1 con algunas ligeras diferencias en el comportamiento (como que el marco verifique manualmente qué versión es algo o llame a castFrom en él).

La idea básica es esta:

  1. Instale una interfaz x.(y+n) en un dispositivo móvil Android.
  2. Instale y active un adaptador de destino xy.
  3. Pruebe el dispositivo para verificar que funciona como se esperaba cuando ejecuta una versión menor anterior.

Estos adaptadores ocultan por completo el hecho de que la implementación en realidad está respaldada por una interfaz 1.2 y solo proporciona la interfaz 1.1 (el adaptador toma una interfaz 1.2 y hace que parezca una interfaz 1.1).

Flujo de trabajo de ejemplo

En este ejemplo, el dispositivo Android ejecuta android.hardware.foo@1.1::IFoo/default . Para garantizar que un cliente funcione correctamente con android.hardware.foo@1.0::IFoo/default :

  1. En una terminal, ejecuta lo siguiente:
    $ PACKAGE=android.hidl.allocator@1.0-adapter
    $ INTERFACE=IAllocator
    $ INSTANCE=ashmem
    $ THREAD_COUNT=1 # can see current thread use on `lshal -i -e`
    $ m -j $PACKAGE
    $ /data/nativetest64/$PACKAGE/$PACKAGE $INTERFACE $INSTANCE $THREAD_COUNT
    Trying to adapt down android.hidl.allocator@1.0-adapter/default
    Press any key to disassociate adapter.
  2. Reinicie el cliente usando adb shell stop (o start ) o simplemente elimine el proceso.
  3. Una vez finalizada la prueba, desasocie el adaptador.
  4. Restaure el estado del sistema reiniciando el dispositivo O reiniciando el cliente.

Objetivos adicionales

hidl-gen agrega automáticamente objetivos de compilación adicionales para los adaptadores para cada interfaz especificada con hidl_interface en el sistema de compilación. Para el paquete abc@xy , hay un objetivo adicional de C++ abc@xy-adapter .

Un adaptador para abc@xy toma como entrada alguna implementación, abc@x.(y+n)::ISomething/instance-name , y debe registrar abc@xy::ISomething/instance-name que también debe anular el registro de y+n .

Dada la siguiente interfaz de ejemplo:

// IFoo.hal
package a.b.c@1.0;
interface IFoo {
    doFoo(int32_t a) generates (int64_t b);
    doSubInterface() generates (IFoo a);
};

El código proporcionado por abc@1.0-adapter es similar al siguiente ejemplo:

// autogenerated code
// in namespace a::b::c::V1_0::IFoo
struct MockFoo {
    // takes some subclass of V1_0. May be V1_1, V1_2, etc...
    MockFoo(V1_0::IFoo impl) mImpl(impl) {}

    Return<int64_t> doFoo(int32_t a) {
        return this->mImpl->doFoo(a);
    }

    Return<V1_0::ICallback> doSubInterface() {
        // getMockForBinder returns MockCallback instance
        // that corresponds to a particular binder object
        // It can't return a new object every time or
        // clients using interfacesSame will have
        // divergent behavior when using the mock.
        auto _hidl_out = this->mImpl->doSubInterface();
        return getMockForBinder(_hidl_out);
    }
};

Los valores de datos se reenvían exactamente dentro y fuera de la clase simulada generada automáticamente, a excepción de las subinterfaces, que se devuelven. Estas interfaces deben incluirse en el objeto de devolución de llamada más reciente correspondiente.