AIDL für HALs

In 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 stabiles 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. Hier sind einige Vorteile von AIDL:

  • 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 es einfacher ist, Code im Laufe der Jahre zu versionieren, und dass die Kosten im Laufe der Jahre 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 stabiles AIDL verwenden möchten, verwenden Sie immer die Systemkopie von libbinder unter system/lib*/libbinder.so und sprechen Sie über /dev/binder. Für Code im vendor-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 Systemlibbinder.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 unter 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.

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

Die Verwendung von backends im folgenden Codebeispiel ist korrekt, da es drei Backends gibt (Java, NDK und CPP). Im Code wird gezeigt, wie ein CPP-Backend deaktiviert wird:

    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 Ordnern mit der Endung aidl:

  • hardware/interfaces ist für Schnittstellen vorgesehen, die in der Regel von Hardware bereitgestellt werden.
  • frameworks/hardware/interfaces ist für Hochschulabsolventen vorgesehen, die für Hardware zuständig sind.
  • system/hardware/interfaces ist für Low-Level-Schnittstellen gedacht, die für die Hardware bereitgestellt werden.

Legen Sie Erweiterungsoberflächen in anderen hardware/interfaces-Unterverzeichnissen in vendor oder hardware ab.

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 mehr mit der AOSP-Android-Laufzeit kompatibel ist. Ändern Sie diese Schnittstellen nicht, 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, sind Zusammenführungskonflikte nicht möglich. Wenn jedoch Downstream-Änderungen an Upstream-AOSP-Komponenten vorgenommen werden, können Zusammenführungskonflikte auftreten. In diesem Fall werden die folgenden Strategien empfohlen:

  • Reichen Sie die Interface-Erweiterungen im nächsten Release an AOSP weiter.
  • Ergänzungen der Upstream-Benutzeroberfläche, die in der nächsten Version mehr Flexibilität (ohne Zusammenführungskonflikte) ermöglichen.

Parcelable-Objekte für Erweiterungen: ParcelableHolder

ParcelableHolder ist eine Instanz der Parcelable-Benutzeroberfläche, die eine weitere Instanz von Parcelable enthalten kann.

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

Mit der ParcelableHolder-Benutzeroberfläche kannst du Parcelable um deine Mehrwertfunktionen erweitern. Die Schnittstelle ParcelableHolder enthält eine Instanz von Parcelable. Wenn Sie versuchen, Parcelable direkt Felder hinzuzufügen, tritt ein Fehler auf:

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 in Konflikt stehen können, wenn Parcelable in den nächsten Android-Releases überarbeitet wird.

Mit ParcelableHolder kann der Inhaber eines Parcelable-Objekts einen Erweiterungspunkt in einer Instanz von Parcelable definieren:

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

Anschließend können die Geräteimplementierer eine eigene Parcelable-Instanz für ihre Erweiterung definieren:

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

Die neue Parcelable-Instanz kann über das 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.:

    <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:

  • Erstellen Sie AIDL-Dateien (.aidl) basierend auf den HAL-Dateien (.hal) für das jeweilige Paket.
  • 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.
  • Erstellen Sie Build-Regeln für Übersetzungsbibliotheken mit den erforderlichen Abhängigkeiten.
  • 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 Release-Branches konvertieren:

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

    Optional kannst du 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 //.
    • Bereinigen und verbessern Sie das Paket.
    • 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 Mit der AIDL-Laufzeit erstellen.
    • 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 entspricht die Sepolicy-Konfiguration der eines anderen AIDL-Dienstes (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

Wenn Sie einen neuen HAL-Typ erstellen, müssen Sie HAL-Attribute hinzufügen. 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, gibt es hal_attribute(foo). Dieses Makro definiert die Attribute hal_foo_client und hal_foo_server. 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).

Für ein bestimmtes HAL-Attribut wird in der Regel auch eine Domain wie hal_foo_default für Referenz- oder Beispiel-HALs erstellt. Einige Geräte verwenden diese Domains jedoch für ihre eigenen Server. Eine Unterscheidung zwischen Domains für mehrere Server ist nur dann wichtig, wenn es mehrere Server gibt, die dieselbe Benutzeroberfläche bereitstellen und in ihren Implementierungen unterschiedliche Berechtigungssätze benötigen. In allen 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 sind hal_foo_service und hal_foo (das Attributpaar aus hal_attribute(foo)) jedoch nicht verknüpft. Ein HAL-Attribut wird mit AIDL HAL-Diensten über das hal_attribute_service-Makro verknüpft (HIDL HALs verwenden das hal_attribute_hwservice-Makro), z. B. 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 Context Manager (servicemanager).

Dienstnamen stimmen möglicherweise nicht immer mit HAL-Attributen überein, z. B. hal_attribute_service(hal_foo, hal_foo2_service). Da dies impliziert, dass die Dienste immer zusammen verwendet werden, können Sie im Allgemeinen hal_foo2_service entfernen und hal_foo_service für alle Dienstkontexte verwenden. Wenn HALs mehrere hal_attribute_service-Instanzen festlegen, liegt das daran, dass der ursprüngliche HAL-Attributname nicht allgemein genug ist und nicht geändert werden kann.

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 direkt beim Dienstmanager registrierte Oberfläche der obersten Ebene oder um eine untergeordnete Oberfläche handelt. Wenn Sie eine Verlängerung erhalten, müssen Sie bestätigen, dass der Typ der Verlängerung wie erwartet ist. Sie können Erweiterungen nur über den Prozess festlegen, der einen Binder bereitstellt.

Verwenden Sie angehängte Erweiterungen, wenn eine Erweiterung die Funktionalität einer vorhandenen HAL ändert. Wenn eine völlig neue Funktion erforderlich ist, ist dieser Mechanismus nicht erforderlich. Sie können eine Erweiterungsoberfläche direkt beim Dienstmanager registrieren. Angehängte Erweiterungsschnittstellen sind am sinnvollsten, wenn sie an untergeordnete Schnittstellen angehängt sind, da diese Hierarchien tief oder mehrstufig sein können. Wenn Sie eine globale Erweiterung verwenden, um die Binder-Schnittstellenhierarchie eines anderen Dienstes zu spiegeln, ist umfangreiches Verwaltungsaufwand erforderlich, um direkt angehängten Erweiterungen vergleichbare Funktionen zur Verfügung zu stellen.

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

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

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

  • NDK-Backend: AIBinder_getExtension
  • Java-Backend: android.os.IBinder.getExtension
  • CPP-Backend: android::IBinder::getExtension
  • 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 Schnittstellendateien Konstante Status-Ints und verwenden Sie EX_SERVICE_SPECIFIC in den CPP- und NDK-Back-Ends und ServiceSpecificException im Java-Back-End. Weitere Informationen finden Sie unter Fehlerbehandlung.
  • AIDL startet keine Threadpools automatisch, wenn Binderobjekte gesendet werden. Sie müssen sie manuell starten (siehe Unterhaltungsverwaltung).
  • AIDL beendet die Übertragung nicht bei nicht geprüften Transportfehlern (HIDL Return beendet die Übertragung bei nicht geprüften Fehlern).
  • In AIDL kann nur ein Typ pro Datei deklariert werden.
  • AIDL-Argumente können zusätzlich zum Ausgabeparameter als in, out oder inout angegeben werden. Es gibt keine synchronen Rückrufe.
  • In AIDL wird fd anstelle von handle 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-Test 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, ob die HALs auf dem Gerät von Android bekannt und erwartet werden

Diese Tests finden Sie unter test/vts-testcase/hal/treble/vintf. Bei diesen Tests wird Folgendes überprüft:

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