Metodi di interfaccia Errori

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

Metodi vuoti

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

doThisWith(float param);

… diventa:

void doThisWith(float param);

Metodi a risultato singolo

I metodi che restituiscono un singolo risultato vengono tradotti nei loro equivalenti Java che restituiscono anch'essi un singolo risultato. Ad esempio, quanto segue:

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 a risultati multipli

Per ogni metodo che restituisce più di un risultato, viene generata una classe callback che fornisce tutti i risultati nel relativo metodo onValues . Tale 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() utilizzerebbe in genere una classe interna anonima o lambda 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.
             ...
          }});

O:

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 della morte

Poiché le implementazioni del servizio possono essere eseguite in un processo diverso, in alcuni casi il client può rimanere in vita anche quando il processo che implementa un'interfaccia muore. Le chiamate su un oggetto interfaccia ospitato in un processo morto falliscono con un errore di trasporto (un'eccezione di runtime generata dal metodo chiamato). Il ripristino da un tale errore è possibile richiedendo una nuova istanza del servizio chiamando I<InterfaceName>.getService() . Tuttavia, questo metodo funziona solo se il processo che si è bloccato è stato riavviato e registrato nuovamente i suoi servizi con servicemanager (il che è generalmente vero per le implementazioni HAL).

I client di un'interfaccia possono anche registrare un destinatario di morte per ricevere una notifica quando un servizio muore. Possono comunque verificarsi errori di trasporto se viene effettuata una chiamata proprio mentre il server muore. Per registrarsi per tali notifiche su un'interfaccia IFoo recuperata, un client può effettuare le seguenti operazioni:

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 muore.

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 di morte dopo averlo registrato utilizzando:

foo.unlinkToDeath(recipient);