AIDL für HALs

Mit Android 11 können Sie AIDL für HALs in Android verwenden. So können Teile von Android ohne HIDL implementiert werden. HALs nach Möglichkeit ausschließlich auf AIDL umstellen (wenn vorgelagerte HALs HIDL verwenden, muss HIDL verwendet werden).

HALs, die AIDL zur Kommunikation zwischen Framework-Komponenten wie denen in system.img und Hardwarekomponenten wie denen in vendor.img verwenden, müssen Stable AIDL verwenden. Für die Kommunikation innerhalb einer Partition, z. B. von einem HAL zu einem anderen, gibt es jedoch keine Einschränkungen für den zu verwendenden IPC-Mechanismus.

Ziel

AIDL gibt es schon länger als HIDL und wird an vielen anderen Stellen verwendet, z. B. zwischen Android-Framework-Komponenten oder in Apps. Da AIDL jetzt Stabilität unterstützt, ist es möglich, einen gesamten Stack mit einer einzigen IPC-Laufzeit zu implementieren. AIDL hat außerdem ein besseres Versionsverwaltungssystem als HIDL.

  • Wenn Sie nur eine IPC-Sprache verwenden, müssen Sie nur eine Sprache lernen, debuggen, optimieren und sichern.
  • AIDL unterstützt die In-Place-Versionierung für die Eigentümer einer Schnittstelle:
    • Inhaber können am Ende von Schnittstellen Methoden oder Felder zu Parcelable-Objekten hinzufügen. Das bedeutet, dass der Code im Laufe der Jahre einfacher versioniert werden kann und die Kosten im Jahresverlauf geringer sind (Typen können vor Ort geändert werden und es sind keine zusätzlichen Bibliotheken für jede Benutzeroberflächenversion erforderlich).
    • Erweiterungsschnittstellen können zur Laufzeit und nicht im Typsystem angehängt werden. Daher müssen Downstream-Erweiterungen nicht auf neuere Versionen von Schnittstellen umgestellt werden.
  • Eine vorhandene AIDL-Schnittstelle kann direkt verwendet werden, wenn der Eigentümer sie stabilisiert. Bisher musste eine vollständige Kopie der Schnittstelle in HIDL erstellt werden.

Mit der AIDL-Laufzeit erstellen

AIDL hat drei verschiedene Backends: Java, NDK und CPP. Wenn Sie Stable AIDL verwenden möchten, müssen Sie immer die Systemkopie von libbinder unter system/lib*/libbinder.so verwenden und /dev/binder verwenden. Für Code im Anbieter-Image bedeutet das, dass libbinder (aus dem VNDK) nicht verwendet werden kann: Diese Bibliothek hat eine instabile C++ API und instabile interne Funktionen. Stattdessen muss nativer Anbietercode das NDK-Backend von AIDL verwenden, mit libbinder_ndk (das vom System libbinder.so unterstützt wird) verknüpft werden und mit den NDK-Bibliotheken verknüpft werden, die durch aidl_interface-Einträge erstellt wurden. Die genauen Modulnamen finden Sie in den Regeln für die Benennung von Modulen.

AIDL HAL-Schnittstelle schreiben

Damit eine AIDL-Schnittstelle zwischen System und Anbieter verwendet werden kann, sind zwei Änderungen erforderlich:

  • Jede Typdefinition muss mit @VintfStability annotiert sein.
  • Die aidl_interface-Erklärung muss stability: "vintf", enthalten.

Nur der Inhaber einer Benutzeroberfläche kann diese Änderungen vornehmen.

Wenn Sie diese Änderungen vornehmen, muss sich die Benutzeroberfläche im VINTF-Manifest befinden, damit sie funktioniert. Testen Sie dies (und zugehörige Anforderungen, z. B. die Überprüfung, ob freigegebene Schnittstellen eingefroren sind) mit dem VTS-Test vts_treble_vintf_vendor_test. Sie können eine @VintfStability-Schnittstelle ohne diese Anforderungen verwenden, indem Sie entweder AIBinder_forceDowngradeToLocalStability im NDK-Backend, android::Stability::forceDowngradeToLocalStability im C++-Backend oder android.os.Binder#forceDowngradeToSystemStability im Java-Backend auf ein Binder-Objekt aufrufen, bevor es an einen anderen Prozess gesendet wird. Das Downgrade eines Dienstes auf die Stabilität des Anbieters wird in Java nicht unterstützt, da alle Apps in einem Systemkontext ausgeführt werden.

Deaktivieren Sie außerdem das CPP-Backend, um die Code-Übertragbarkeit zu maximieren und potenzielle Probleme wie unnötige zusätzliche Bibliotheken zu vermeiden.

Beachten Sie, dass die Verwendung von backends im folgenden Codebeispiel korrekt ist, da es drei Backends gibt (Java, NDK und CPP). Im folgenden Code wird beschrieben, wie Sie das CPP-Backend speziell auswählen, um es zu deaktivieren.

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

AIDL HAL-Schnittstellen finden

Stabile AOSP-AIDL-Schnittstellen für HALs befinden sich in denselben Basisverzeichnissen wie HIDL-Schnittstellen, in aidl-Ordnern.

  • hardware/interfaces: für Schnittstellen, die in der Regel von der Hardware bereitgestellt werden
  • frameworks/hardware/interfaces: für Hochebenen-Schnittstellen für Hardware
  • system/hardware/interfaces: für Low-Level-Schnittstellen für die Hardware

Sie sollten Erweiterungsschnittstellen in andere hardware/interfaces-Unterverzeichnisse in vendor oder hardware einfügen.

Erweiterungsschnittstellen

Android hat mit jeder Version eine Reihe offizieller AOSP-Schnittstellen. Wenn Android-Partner diesen Schnittstellen Funktionen hinzufügen möchten, sollten sie diese nicht direkt ändern, da ihre Android-Laufzeit dann nicht mit der AOSP-Android-Laufzeit kompatibel wäre. Bei GMS-Geräten ist es außerdem wichtig, diese Schnittstellen nicht zu ändern, damit das GSI-Image weiterhin funktioniert.

Erweiterungen können auf zwei verschiedene Arten registriert werden:

Wenn eine Erweiterung registriert ist und die Schnittstelle von anbieterspezifischen Komponenten (d. h. nicht Teil des Upstream-AOSP) verwendet wird, kann es zu keinen Zusammenführungskonflikten kommen. Wenn jedoch Downstream-Änderungen an Upstream-AOSP-Komponenten vorgenommen werden, können Zusammenführungskonflikte auftreten. Daher werden die folgenden Strategien empfohlen:

  • Die Interface-Erweiterungen können im nächsten Release an AOSP gesendet werden.
  • Interface-Erweiterungen, die für mehr Flexibilität sorgen, ohne dass es zu Konflikt beim Zusammenführen kommt, können in der nächsten Version übernommen werden.

Parcelable-Objekte für Erweiterungen: ParcelableHolder

ParcelableHolder ist ein Parcelable, das ein weiteres Parcelable enthalten kann. Der Hauptanwendungsfall von ParcelableHolder besteht darin, eine Parcelable erweiterbar zu machen. Angenommen, Geräteimplementierer erwarten, dass sie eine von AOSP definierte Parcelable, AospDefinedParcelable, um ihre Mehrwertfunktionen erweitern können.

Bisher konnten Geräteimplementierer ohne ParcelableHolder eine von AOSP definierte stabile AIDL-Schnittstelle nicht ändern, da das Hinzufügen weiterer Felder einen Fehler darstellt:

parcelable AospDefinedParcelable {
  int a;
  String b;
  String x; // ERROR: added by a device implementer
  int[] y; // added by a device implementer
}

Wie im vorherigen Code zu sehen, ist diese Vorgehensweise nicht zulässig, da die vom Geräteimplementierer hinzugefügten Felder zu einem Konflikt führen können, wenn die Parcelable-Klasse in den nächsten Android-Releases überarbeitet wird.

Mit ParcelableHolder kann der Eigentümer eines Parzellierungsgrundstücks einen Erweiterungspunkt in einem Parcelable definieren.

parcelable AospDefinedParcelable {
  int a;
  String b;
  ParcelableHolder extension;
}

Die Geräteimplementierer können dann ihre eigene Parcelable für ihre Erweiterung definieren.

parcelable OemDefinedParcelable {
  String x;
  int[] y;
}

Schließlich kann die neue Parcelable mit dem Feld ParcelableHolder an die ursprüngliche Parcelable angehängt werden.


// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;

ap.extension.setParcelable(op);

...

OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);

// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();

ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);

...

std::shared_ptr<OemDefinedParcelable> op_ptr;

ap.extension.getParcelable(&op_ptr);

// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);

...

std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);

// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });

ap.extension.set_parcelable(Rc::clone(&op));

...

let op = ap.extension.get_parcelable::<OemDefinedParcelable>();

Namen der AIDL HAL-Serverinstanz

AIDL HAL-Dienste haben üblicherweise einen Instanznamen im Format $package.$type/$instance. Beispielsweise wird eine Instanz der HAL für den Vibrator als android.hardware.vibrator.IVibrator/default registriert.

AIDL HAL-Server schreiben

@VintfStability AIDL-Server müssen im VINTF-Manifest deklariert werden, z. B. so:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>

Andernfalls sollte er einen AIDL-Dienst wie gewohnt registrieren. Bei der Ausführung von VTS-Tests sollten alle deklarierten AIDL HALs verfügbar sein.

AIDL-Client schreiben

AIDL-Clients müssen sich in der Kompatibilitätsmatrix deklarieren, z. B. so:

    <hal format="aidl" optional="true">
        <name>android.hardware.vibrator</name>
        <version>1-2</version>
        <interface>
            <name>IVibrator</name>
            <instance>default</instance>
        </interface>
    </hal>

Vorhandene HAL von HIDL in AIDL konvertieren

Verwenden Sie das hidl2aidl-Tool, um eine HIDL-Schnittstelle in AIDL zu konvertieren.

hidl2aidl-Funktionen:

  • .aidl-Dateien basierend auf den .hal-Dateien für das angegebene Paket erstellen
  • Erstellen Sie Build-Regeln für das neu erstellte AIDL-Paket mit allen aktivierten Back-Ends.
  • Erstellen Sie Übersetzungsmethoden in den Java-, CPP- und NDK-Back-Ends, um von den HIDL-Typen zu den AIDL-Typen zu übersetzen.
  • Build-Regeln für Übersetzungsbibliotheken mit erforderlichen Abhängigkeiten erstellen
  • Erstellen Sie statische Assertions, um sicherzustellen, dass HIDL- und AIDL-Enumeratoren in den CPP- und NDK-Backends dieselben Werte haben.

So konvertieren Sie ein Paket mit HAL-Dateien in .aidl-Dateien:

  1. Erstellen Sie das Tool unter system/tools/hidl/hidl2aidl.

    Wenn Sie dieses Tool aus der neuesten Quelle erstellen, erhalten Sie die beste Leistung. Mit der neuesten Version können Sie Benutzeroberflächen in älteren Branches aus früheren Releases konvertieren.

    m hidl2aidl
  2. Führen Sie das Tool mit einem Ausgabeverzeichnis gefolgt vom zu konvertierenden Paket aus.

    Optional können Sie mit dem Argument -l den Inhalt einer neuen Lizenzdatei an den Anfang aller generierten Dateien einfügen. Achten Sie darauf, die richtige Lizenz und das richtige Datum zu verwenden.

    hidl2aidl -o <output directory> -l <file with license> <package>

    Beispiel:

    hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
  3. Sehen Sie sich die generierten Dateien an und beheben Sie alle Probleme mit der Umwandlung.

    • conversion.log enthält alle nicht behobenen Probleme, die zuerst behoben werden müssen.
    • Die generierten .aidl-Dateien enthalten möglicherweise Warnungen und Vorschläge, die Sie beachten sollten. Diese Kommentare beginnen mit //.
    • Nutzen Sie die Gelegenheit, das Paket zu bereinigen und zu verbessern.
    • Prüfe die Anmerkung @JavaDerive auf Funktionen, die möglicherweise erforderlich sind, z. B. toString oder equals.
  4. Erstellen Sie nur die Ziele, die Sie benötigen.

    • Deaktivieren Sie Backends, die nicht verwendet werden. Verwenden Sie das NDK-Back-End anstelle des CPP-Back-Ends. Weitere Informationen finden Sie unter Laufzeit auswählen.
    • Entfernen Sie Übersetzungsbibliotheken oder den generierten Code, der nicht verwendet wird.
  5. Weitere Informationen finden Sie unter Wichtige Unterschiede zwischen AIDL und HIDL.

    • Die Verwendung der integrierten Status- und Ausnahmetypen von AIDL verbessert in der Regel die Benutzeroberfläche und macht einen weiteren schnittstellenspezifischen Statustyp überflüssig.
    • AIDL-Schnittstellenargumente in Methoden sind standardmäßig nicht @nullable, wie es in HIDL der Fall war.

SEPolicy für AIDL HALs

Ein AIDL-Diensttyp, der für Anbietercode sichtbar ist, muss das Attribut hal_service_type haben. Ansonsten ist die Sepolicy-Konfiguration mit der eines anderen AIDL-Dienstes identisch (es gibt jedoch spezielle Attribute für HALs). Hier ist eine Beispieldefinition für einen HAL-Dienstkontext:

    type hal_foo_service, service_manager_type, hal_service_type;

Für die meisten von der Plattform definierten Dienste ist bereits ein Dienstkontext mit dem richtigen Typ hinzugefügt. android.hardware.foo.IFoo/default ist beispielsweise bereits als hal_foo_service gekennzeichnet. Wenn ein Framework-Client jedoch mehrere Instanznamen unterstützt, müssen in gerätespezifischen service_contexts-Dateien zusätzliche Instanznamen hinzugefügt werden.

    android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0

HAL-Attribute müssen hinzugefügt werden, wenn wir einen neuen HAL-Typ erstellen. Ein bestimmtes HAL-Attribut kann mehreren Diensttypen zugeordnet sein, von denen jeder, wie bereits erwähnt, mehrere Instanzen haben kann. Für eine HAL, foo, haben wir hal_attribute(foo). In diesem Makro werden die Attribute hal_foo_client und hal_foo_server definiert. Mit den Makros hal_client_domain und hal_server_domain wird einer Domain ein bestimmtes HAL-Attribut zugewiesen. Wenn der Systemserver beispielsweise ein Client dieser HAL ist, entspricht das der Richtlinie hal_client_domain(system_server, hal_foo). Ein HAL-Server enthält ebenfalls hal_server_domain(my_hal_domain, hal_foo). Normalerweise erstellen wir für ein bestimmtes HAL-Attribut auch eine Domain wie hal_foo_default als Referenz oder Beispiel-HALs. Einige Geräte verwenden diese Domains jedoch für ihre eigenen Server. Die Unterscheidung zwischen Domains für mehrere Server ist nur dann wichtig, wenn wir mehrere Server haben, die dieselbe Benutzeroberfläche bereitstellen und in ihren Implementierungen unterschiedliche Berechtigungen benötigen. In all diesen Makros ist hal_foo kein Sepolicy-Objekt. Stattdessen wird dieses Token von diesen Makros verwendet, um auf die Gruppe von Attributen zu verweisen, die mit einem Client-Server-Paar verknüpft sind.

Bisher haben wir hal_foo_service und hal_foo (das Attributpaar aus hal_attribute(foo)) jedoch noch nicht verknüpft. Ein HAL-Attribut wird mit AIDL HAL-Diensten über das Makro hal_attribute_service verknüpft (HIDL HALs verwenden das Makro hal_attribute_hwservice). Beispiel: hal_attribute_service(hal_foo, hal_foo_service). Das bedeutet, dass hal_foo_client-Prozesse auf die HAL zugreifen und hal_foo_server-Prozesse die HAL registrieren können. Die Durchsetzung dieser Registrierungsregeln erfolgt durch den Kontextmanager (servicemanager). Dienstnamen stimmen möglicherweise nicht immer mit HAL-Attributen überein. Beispiel: hal_attribute_service(hal_foo, hal_foo2_service) Da dies jedoch impliziert, dass die Dienste immer zusammen verwendet werden, könnten wir hal_foo2_service entfernen und hal_foo_service für alle unsere Dienstkontexte verwenden. Bei den meisten HALs, in denen mehrere hal_attribute_service festgelegt werden, ist der ursprüngliche HAL-Attributname nicht allgemein genug und kann nicht geändert werden.

Zusammengenommen sieht eine Beispiel-HAL so aus:

    public/attributes:
    // define hal_foo, hal_foo_client, hal_foo_server
    hal_attribute(foo)

    public/service.te
    // define hal_foo_service
    type hal_foo_service, hal_service_type, protected_service, service_manager_type

    public/hal_foo.te:
    // allow binder connection from client to server
    binder_call(hal_foo_client, hal_foo_server)
    // allow client to find the service, allow server to register the service
    hal_attribute_service(hal_foo, hal_foo_service)
    // allow binder communication from server to service_manager
    binder_use(hal_foo_server)

    private/service_contexts:
    // bind an AIDL service name to the selinux type
    android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0

    private/<some_domain>.te:
    // let this domain use the hal service
    binder_use(some_domain)
    hal_client_domain(some_domain, hal_foo)

    vendor/<some_hal_server_domain>.te
    // let this domain serve the hal service
    hal_server_domain(some_hal_server_domain, hal_foo)

Angehängte Erweiterungsschnittstellen

Eine Erweiterung kann an jede Binder-Oberfläche angehängt werden, unabhängig davon, ob es sich um eine oberste Ebene handelt, die direkt beim Dienstmanager registriert ist, oder um eine untergeordnete Ebene. Wenn Sie eine Verlängerung erhalten, müssen Sie bestätigen, dass der Typ der Verlängerung wie erwartet ist. Erweiterungen können nur über den Prozess festgelegt werden, der einen Binder bereitstellt.

Angehängte Erweiterungen sollten verwendet werden, wenn eine Erweiterung die Funktionalität einer vorhandenen HAL ändert. Wenn eine völlig neue Funktion erforderlich ist, muss dieser Mechanismus nicht verwendet werden. Eine Erweiterungsoberfläche kann direkt beim Dienstmanager registriert werden. Angehängte Erweiterungsschnittstellen sind am sinnvollsten, wenn sie an untergeordnete Schnittstellen angehängt sind, da diese Hierarchien tief oder mehrmals vorhanden sein können. Wenn Sie eine globale Erweiterung verwenden, um die Binder-Benutzeroberflächenhierarchie eines anderen Dienstes zu spiegeln, ist ein umfangreiches Buchhaltungssystem erforderlich, um eine entsprechende Funktionalität für direkt angehängte Erweiterungen bereitzustellen.

Verwenden Sie die folgenden APIs, um eine Erweiterung für den Binder festzulegen:

  • Im NDK-Backend: AIBinder_setExtension
  • Im Java-Backend: android.os.Binder.setExtension
  • Im CPP-Backend: android::Binder::setExtension
  • Im Rust-Backend: binder::Binder::set_extension

Verwenden Sie die folgenden APIs, um eine Verlängerung für einen Auslieferschein zu erhalten:

  • Im NDK-Backend: AIBinder_getExtension
  • Im Java-Backend: android.os.IBinder.getExtension
  • Im CPP-Backend: android::IBinder::getExtension
  • Im Rust-Backend: binder::Binder::get_extension

Weitere Informationen zu diesen APIs finden Sie in der Dokumentation der getExtension-Funktion im entsprechenden Backend. Ein Beispiel für die Verwendung von Erweiterungen finden Sie unter hardware/interfaces/tests/extension/vibrator.

Wichtige Unterschiede zwischen AIDL und HIDL

Wenn Sie AIDL HALs oder AIDL HAL-Schnittstellen verwenden, beachten Sie die Unterschiede zum Schreiben von HIDL HALs.

  • Die Syntax der AIDL-Sprache ähnelt eher Java. Die HIDL-Syntax ähnelt C++.
  • Alle AIDL-Schnittstellen haben integrierte Fehlerstatus. Anstatt benutzerdefinierte Statustypen zu erstellen, erstellen Sie in den Interfacedateien konstante Status-Ints und verwenden Sie EX_SERVICE_SPECIFIC in den CPP/NDK-Back-Ends und ServiceSpecificException im Java-Back-End. Weitere Informationen finden Sie unter Umgang mit Fehlern.
  • AIDL startet keine Threadpools automatisch, wenn Binder-Objekte gesendet werden. Sie müssen manuell gestartet werden (siehe Threadverwaltung).
  • AIDL wird bei nicht überprüften Transportfehlern nicht abgebrochen (HIDL Return wird bei nicht überprüften Fehlern abgebrochen).
  • In AIDL kann nur ein Typ pro Datei deklariert werden.
  • AIDL-Argumente können zusätzlich zum Ausgabeparameter als in/out/inout angegeben werden (es gibt keine „synchronen Rückrufe“).
  • In AIDL wird anstelle von „handle“ ein fd als primitiver Typ verwendet.
  • HIDL verwendet Hauptversionen für inkompatible Änderungen und Nebenversionen für kompatible Änderungen. In AIDL werden abwärtskompatible Änderungen direkt vorgenommen. AIDL hat kein explizites Konzept für Hauptversionen. Stattdessen wird dies in Paketnamen einbezogen. AIDL kann beispielsweise den Paketnamen bluetooth2 verwenden.
  • AIDL erbt standardmäßig keine Echtzeitpriorität. Die Funktion setInheritRt muss pro Binder verwendet werden, um die Echtzeitprioritätsübernahme zu aktivieren.

Vendor Test Suite (VTS)-Tests für HALs

Android nutzt die Vendor Test Suite (VTS), um die erwarteten HAL-Implementierungen zu überprüfen. VTS trägt dazu bei, dass Android abwärtskompatibel mit alten Anbieterimplementierungen ist. Bei Implementierungen, die den VTS nicht bestehen, sind bekannte Kompatibilitätsprobleme bekannt, die die Funktion mit zukünftigen Versionen des Betriebssystems beeinträchtigen können.

VTS für HALs besteht aus zwei Hauptteilen.

1. Prüfen Sie, ob die HALs auf dem Gerät von Android bekannt und erwartet werden.

Diese Tests finden Sie unter test/vts-testcase/hal/treble/vintf. Sie sind für Folgendes verantwortlich:

  • Jede @VintfStability-Schnittstelle, die in einem VINTF-Manifest deklariert ist, wird auf einer bekannten veröffentlichten Version eingefroren. So wird sichergestellt, dass sich beide Seiten der Schnittstelle über die genaue Definition dieser Version der Schnittstelle einigen. Dies ist für die grundlegende Funktion erforderlich.
  • Alle HALs, die in einem VINTF-Manifest deklariert sind, sind auf diesem Gerät verfügbar. Jeder Client mit ausreichenden Berechtigungen zur Verwendung eines deklarierten HAL-Dienstes muss diese Dienste jederzeit abrufen und verwenden können.
  • Alle HALs, die in einem VINTF-Manifest deklariert sind, dienen der Version der Benutzeroberfläche, die im Manifest deklariert ist.
  • Auf einem Gerät werden keine veralteten HALs bereitgestellt. Android unterstützt keine niedrigeren Versionen von HAL-Schnittstellen mehr, wie im FCM-Lebenszyklus beschrieben.
  • Auf dem Gerät sind die erforderlichen HALs vorhanden. Einige HALs sind erforderlich, damit Android ordnungsgemäß funktioniert.

2. Erwartetes Verhalten der einzelnen HALs prüfen

Für jede HAL-Schnittstelle gibt es eigene VTS-Tests, um das erwartete Verhalten der Clients zu überprüfen. Die Testfälle werden auf jeder Instanz einer deklarierten HAL-Schnittstelle ausgeführt und erzwingen ein bestimmtes Verhalten basierend auf der implementierten Version der Schnittstelle.

Bei diesen Tests wird versucht, jeden Aspekt der HAL-Implementierung abzudecken, auf den das Android-Framework angewiesen ist oder in Zukunft angewiesen sein könnte.

Dazu gehören die Überprüfung der Unterstützung von Funktionen, der Fehlerbehandlung und aller anderen Verhaltensweisen, die ein Kunde vom Dienst erwarten kann.

VTS-Meilensteine für die HAL-Entwicklung

VTS-Tests müssen aktualisiert werden, wenn die HAL-Schnittstellen von Android erstellt oder geändert werden.

VTS-Tests müssen abgeschlossen sein und die Anbieterimplementierungen müssen bereit sein, um überprüft zu werden, bevor sie für Android-Anbieter API-Releases eingefroren werden. Sie müssen fertig sein, bevor die Schnittstellen eingefroren werden, damit die Entwickler ihre Implementierungen erstellen, überprüfen und Feedback an die Entwickler der HAL-Schnittstelle geben können.

VTS auf Cuttlefish

Wenn keine Hardware verfügbar ist, verwendet Android Cuttlefish als Entwicklungstool für HAL-Schnittstellen. Dies ermöglicht skalierbare VTS- und Integrationstests von Android. Mit hal_implementation_test wird geprüft, ob Cuttlefish Implementierungen der neuesten HAL-Schnittstellenversionen hat, damit Android die neuen Schnittstellen verarbeiten kann. Außerdem werden die VTS-Tests so vorbereitet, dass sie die neuen Implementierungen der Anbieter testen können, sobald neue Hardware und Geräte verfügbar sind.