Metodi e errori dell'interfaccia

Questa sezione descrive in dettaglio i metodi e gli errori dell'interfaccia.

Metodi void

I metodi che non restituiscono risultati vengono tradotti in metodi Java che retituan void. Ad esempio, la dichiarazione HIDL:

doThisWith(float param);

… diventa:

void doThisWith(float param);

Metodi con un solo risultato

I metodi che restituiscono un singolo risultato vengono tradotti nei relativi equivalenti Java che restituiscono anche un singolo risultato. Ad esempio:

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

… diventa:

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

Metodi con più risultati

Per ogni metodo che restituisce più di un risultato, viene generata una classe di callback che fornisce tutti i risultati nel relativo metodo onValues. Questo callback funge da parametro aggiuntivo per il metodo. Ad esempio, quanto segue:

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

… diventa:

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

Un chiamante di oneProducesTwoThings() in genere utilizza un classe interna o lambda anonima per implementare il callback localmente:

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

oppure:

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

Puoi anche definire una classe da utilizzare come callback…

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

… e passa un'istanza di MyCallback come terzo parametro a oneProducesTwoThings().

Errori di trasporto e destinatari decessi

Poiché le implementazioni dei servizi possono essere eseguite in un processo diverso, in alcuni casi il client può rimanere attivo anche quando il processo che implementa un'interfaccia termina. Le chiamate a un oggetto interfaccia ospitato in un processo non attivo non vanno a buon fine con un errore di trasporto (un'eccezione di runtime lanciata dal metodo chiamato). È possibile recuperare da questo tipo di errore richiedendo una nuova istanza del servizio chiamando I<InterfaceName>.getService(). Tuttavia, questo metodo funziona solo se il processo che ha avuto un arresto anomalo è stato riavviato e ha registrato di nuovo i suoi servizi con il servicemanager (il che è generalmente vero per le implementazioni HAL).

I client di un'interfaccia possono anche registrare un destinatario per i messaggi di morte per ricevere una notifica quando un servizio non è più disponibile. Gli errori di trasporto possono comunque verificarsi se viene effettuata una chiamata proprio quando il server si arresta in modo anomalo. Per registrarsi a queste notifiche su un'interfaccia IFoo recuperata, un client può:

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

Il parametro recipient deve essere un'implementazione dell'interfaccia HwBinder.DeathRecipient fornita da HIDL. L'interfaccia contiene un singolo metodo serviceDied() che viene chiamato quando il processo che ospita l'interfaccia termina.

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

Il parametro cookie contiene il cookie passato con la chiamata a linkToDeath(). È anche possibile annullare la registrazione di un destinatario in caso di decesso dopo averlo registrato utilizzando:

foo.unlinkToDeath(recipient);