Benutzeroberflächenmethoden und -fehler

In diesem Abschnitt werden Methoden und Fehler der Benutzeroberfläche beschrieben.

Methoden zum Aufheben

Methoden, die keine Ergebnisse zurückgeben, werden in Java-Methoden übersetzt, die void zurückgeben. Beispiel: HIDL-Deklaration:

doThisWith(float param);

… wird zu:

void doThisWith(float param);

Methoden mit einem Ergebnis

Methoden, die ein einzelnes Ergebnis zurückgeben, werden in ihre Java-Äquivalente übersetzt, die ebenfalls ein einzelnes Ergebnis zurückgeben. Beispiel:

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

… wird zu:

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

Methoden mit mehreren Ergebnissen

Für jede Methode, die mehr als ein Ergebnis zurückgibt, wird eine Rückrufklasse generiert, die alle Ergebnisse in ihrer onValues-Methode bereitstellt. Dieser Callback dient als zusätzlicher Parameter für die Methode. Zum Beispiel:

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

… wird zu:

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

Ein Aufrufer von oneProducesTwoThings() verwendet in der Regel eine anonyme innere Klasse oder ein Lambda, um den Callback lokal zu implementieren:

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

oder:

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

Sie können auch eine Klasse als Rückruf definieren…

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

… und übergeben Sie eine Instanz von MyCallback als dritten Parameter an oneProducesTwoThings().

Übertragungsfehler und Empfänger von Todesnachrichten

Da Dienstimplementierungen in einem anderen Prozess ausgeführt werden können, bleibt der Client in einigen Fällen aktiv, auch wenn der Prozess, der eine Schnittstelle implementiert, beendet wird. Aufrufe eines in einem toten Prozess gehosteten Interface-Objekts schlagen mit einem Transportfehler fehl (eine Laufzeitausnahme, die von der aufgerufenen Methode ausgelöst wird). Sie können sich von einem solchen Fehler erholen, indem Sie eine neue Instanz des Dienstes anfordern, indem Sie I<InterfaceName>.getService() aufrufen. Diese Methode funktioniert jedoch nur, wenn der abgestürzte Prozess neu gestartet und seine Dienste beim Dienstmanager neu registriert wurden. Dies ist bei HAL-Implementierungen in der Regel der Fall.

Clients einer Benutzeroberfläche können auch einen Empfänger für den Diensttod registrieren, um eine Benachrichtigung zu erhalten, wenn ein Dienst ausfällt. Transportfehler können jedoch auftreten, wenn ein Aufruf genau dann erfolgt, wenn der Server ausfällt. So registriert sich ein Client für solche Benachrichtigungen auf einer abgerufenen IFoo-Benutzeroberfläche:

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

Der Parameter recipient muss eine Implementierung der von HIDL bereitgestellten Schnittstelle HwBinder.DeathRecipient sein. Die Schnittstelle enthält eine einzelne Methode serviceDied(), die aufgerufen wird, wenn der Prozess, der die Schnittstelle hostet, beendet wird.

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

Der Parameter cookie enthält das Cookie, das mit dem Aufruf von linkToDeath() übergeben wurde. Sie können die Registrierung eines Empfängers für den Todesfall auch aufheben, nachdem Sie ihn registriert haben:

foo.unlinkToDeath(recipient);