Mit Android 8 wird das Android-Betriebssystem neu gestaltet, um klare Schnittstellen zwischen den
geräteunabhängige Android-Plattform und geräte- und anbieterspezifischer Code
Android definiert bereits viele solcher Schnittstellen in Form von HAL-Schnittstellen.
als C-Header in hardware/libhardware
definiert. HIDL ersetzt diese
HAL-Schnittstellen mit stabilen, versionierten Schnittstellen, die client- und
serverseitige HIDL-Schnittstellen in C++ (siehe unten) oder
Java
Die Seiten in diesem Abschnitt beschreiben die C++-Implementierungen von HIDL-Schnittstellen,
einschließlich Details zu den Dateien, die automatisch aus dem HIDL .hal
generiert wurden.
Dateien durch den hidl-gen
-Compiler, wie diese Dateien gepackt sind und
wie diese Dateien in den C++-Code integriert werden,
der sie verwendet.
Client- und Serverimplementierungen
HIDL-Schnittstellen haben Client- und Serverimplementierungen:
- Ein Client einer HIDL-Schnittstelle ist der Code, der die Methode durch Aufrufen von Methoden.
- Ein Server ist eine Implementierung einer HIDL-Schnittstelle, empfängt Aufrufe von Clients und gibt Ergebnisse zurück (falls erforderlich).
Beim Wechsel von libhardware
HALs zu HIDL HALs
Implementierung wird zum Server und der Aufruf in den HAL wird zu
Kundschaft. Standardimplementierungen können sowohl Passthrough als auch binderisierte
HALs und können sich im Laufe der Zeit ändern:
Abbildung 1: Entwicklungsfortschritt für Legacy-HALs.
HAL-Client erstellen
Beginnen Sie mit dem Einfügen der HAL-Bibliotheken in das Makefile:
- Marke:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
- Titel:
shared_libs: [ …, android.hardware.nfc@1.0 ]
Fügen Sie als Nächstes die HAL-Headerdateien ein:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
HAL-Server erstellen
Zum Erstellen der HAL-Implementierung benötigen Sie die .hal
-Dateien
die Ihren HAL repräsentieren und bereits Makefiles für Ihren HAL mithilfe von
-Lmakefile
oder -Landroidbp
bei hidl-gen
(./hardware/interfaces/update-makefiles.sh
führt dies für interne
HAL-Dateien und dient als Referenz). Beim Übertragen von HALs von
libhardware
, kannst du viele dieser Aufgaben ganz einfach mit c2hal erledigen.
So erstellen Sie die erforderlichen Dateien zum Implementieren des HAL:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
Damit der HAL im Passthrough-Modus funktioniert, müssen Sie
die Funktion HIDL_FETCH_IModuleName
in
/(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl(OPTIONAL_IDENTIFIER).so
Dabei ist OPTIONAL_IDENTIFIER ein String, der das Passthrough identifiziert.
Implementierung. Die Anforderungen an den Passthrough-Modus werden automatisch vom
der obigen Befehle, durch die auch das android.hardware.nfc@1.0-impl
-Element erstellt wird.
Es kann jedoch jede Erweiterung verwendet werden. Zum Beispiel
android.hardware.nfc@1.0-impl-foo
verwendet -foo
, um
sich von anderen abheben.
Wenn ein HAL eine Nebenversion oder die Erweiterung einer anderen
HAL verwenden, sollte die Basis-HAL verwendet werden, um diese Binärdatei zu benennen. Beispiel:
android.hardware.graphics.mapper@2.1
-Implementierungen sollten
immer noch in einer Binärdatei namens
android.hardware.graphics.mapper@2.0-impl(OPTIONAL_IDENTIFIER)
.
Normalerweise enthält die OPTIONAL_IDENTIFIER hier den tatsächlichen HAL
Version. Wenn Sie die Binärdatei so benennen, können 2.0-Clients sie direkt abrufen,
und 2.1-Kunden können die Implementierung aktualisieren.
Als Nächstes füllen Sie die Stubs mit den entsprechenden Funktionen aus und richten einen Daemon ein. Beispiel Daemon-Code (mit Unterstützung für Passthrough):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
Anruf
dlopen()
für die bereitgestellte -impl
-Bibliothek und stellt sie als
ein gebundener Dienst. Daemon-Beispielcode (für einen reinen binderisierten Dienst):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool never exceeds // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
Dieser Daemon befindet sich normalerweise in $PACKAGE + "-service-suffix"
(für
Beispiel: android.hardware.nfc@1.0-service
), kann aber an einem beliebigen Ort sein.
Die sepolicy für eine bestimmte
Klasse von HALs ist das Attribut hal_<module>
(z. B.
hal_nfc)
. Dieses Attribut muss auf den Daemon angewendet werden, der einen
bestimmte HAL (wenn derselbe Prozess mehrere HALs, mehrere Attribute
angewendet werden kann).