Métodos de interfaz y errores

Esta sección detalla los métodos y errores de la interfaz.

Métodos de anulación

Los métodos que no devuelven resultados se traducen a métodos Java que devuelven void . Por ejemplo, la declaración HIDL:

doThisWith(float param);

… se convierte en:

void doThisWith(float param);

Métodos de resultado único

Los métodos que devuelven un solo resultado se traducen a sus equivalentes de Java y también devuelven un solo resultado. Por ejemplo, lo siguiente:

doQuiteABit(int32_t a, int64_t b,
            float c, double d) generates (double something);

… se convierte en:

double doQuiteABit(int a, long b, float c, double d);

Métodos de resultados múltiples

Para cada método que devuelve más de un resultado, se genera una clase de devolución de llamada que proporciona todos los resultados en su método onValues . Esa devolución de llamada actúa como un parámetro adicional para el método. Por ejemplo, lo siguiente:

oneProducesTwoThings(SomeEnum x) generates (double a, double b);

… se convierte en:

public interface oneProducesTwoThingsCallback {
    public void onValues(double a, double b);
}
void oneProducesTwoThings(byte x, oneProducesTwoThingsCallback cb);

Una persona que llama a oneProducesTwoThings() normalmente usaría una clase interna anónima o lambda para implementar la devolución de llamada localmente:

someInstanceOfFoo.oneProducesTwoThings(
         5 /* x */,
         new IFoo.oneProducesTwoThingsCallback() {
          @Override
          void onValues(double a, double b) {
             // do something interesting with a and b.
             ...
          }});

o:

someInstanceOfFoo.oneProducesTwoThings(5 /* x */,
    (a, b) -> a > 3.0 ? f(a, b) : g(a, b)));

También puede definir una clase para usar como devolución de llamada...

class MyCallback implements oneProducesTwoThingsCallback {
  public void onValues(double a, double b) {
    // do something interesting with a and b.
  }
}

… y pase una instancia de MyCallback como tercer parámetro a oneProducesTwoThings() .

Errores de transporte y destinatarios de muerte

Debido a que las implementaciones de servicios pueden ejecutarse en un proceso diferente, en algunos casos el cliente puede permanecer vivo incluso cuando el proceso que implementa una interfaz muere. Las llamadas a un objeto de interfaz alojado en un proceso muerto fallan con un error de transporte (una excepción de tiempo de ejecución lanzada por el método llamado). La recuperación de una falla de este tipo es posible solicitando una nueva instancia del servicio llamando a I<InterfaceName>.getService() . Sin embargo, este método solo funciona si el proceso que falló se reinició y volvió a registrar sus servicios con el administrador de servicios (lo que generalmente es cierto para las implementaciones de HAL).

Los clientes de una interfaz también pueden registrar un destinatario muerto para recibir una notificación cuando un servicio muere. Todavía pueden ocurrir errores de transporte si se realiza una llamada justo cuando el servidor muere. Para registrarse para tales notificaciones en una interfaz IFoo recuperada, un cliente puede hacer lo siguiente:

foo.linkToDeath(recipient, 1481 /* cookie */);

El parámetro del recipient debe ser una implementación de la interfaz HwBinder.DeathRecipient proporcionada por HIDL. La interfaz contiene un solo método serviceDied() que se llama cuando el proceso que aloja la interfaz muere.

final class DeathRecipient implements HwBinder.DeathRecipient {
    @Override
    public void serviceDied(long cookie) {
        // Deal with service going away
    }
}

El parámetro de cookie contiene la cookie que se pasó con la llamada a linkToDeath() . También es posible cancelar el registro de un destinatario de muerte después de registrarlo usando:

foo.unlinkToDeath(recipient);