HIDL-Datendeklarationen generieren C++-Datenstrukturen mit Standardlayout. Diese Strukturen können überall dort platziert werden, wo es sich anfühlt (auf dem Stack, der Datei oder globalen Geltungsbereich oder auf dem Heap) und können auf dieselbe Weise zusammengesetzt werden. Kunde HIDL-Proxy-Code aufruft, übergibt Const-Referenzen und primitive Typen, während der Stub und der Proxy-Code die Details der Serialisierung verbergen.
Hinweis:Zu keinem Zeitpunkt gehört der Entwickler-Programmiercode. die Datenstrukturen explizit serialisieren oder deserialisieren müssen.
In der folgenden Tabelle werden HIDL-Primitive den C++-Datentypen zugeordnet:
HIDL-Typ | C++-Typ | Kopfzeile/Bibliothek |
---|---|---|
enum |
enum class |
|
uint8_t..uint64_t |
uint8_t..uint64_t |
<stdint.h> |
int8_t..int64_t |
int8_t..int64_t |
<stdint.h> |
float |
float |
|
double |
double |
|
vec<T> |
hidl_vec<T> |
libhidlbase |
T[S1][S2]...[SN] |
T[S1][S2]...[SN] |
|
string |
hidl_string |
libhidlbase |
handle |
hidl_handle |
libhidlbase |
safe_union |
(custom) struct |
|
struct |
struct |
|
union |
union |
|
fmq_sync |
MQDescriptorSync |
libhidlbase |
fmq_unsync |
MQDescriptorUnsync |
libhidlbase |
In den folgenden Abschnitten werden die Datentypen ausführlicher beschrieben.
Aufzählung
Aus einer Aufzählung in HIDL wird eine Aufzählung in C++. Hier einige Beispiele:
enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 }; enum SpecialMode : Mode { NONE = 0, COMPARE = 1 << 2 };
... wird zu:
enum class Mode : uint8_t { WRITE = 1, READ = 2 }; enum class SpecialMode : uint8_t { WRITE = 1, READ = 2, NONE = 0, COMPARE = 4 };
Ab Android 10 kann ein Enum iteriert werden.
über ::android::hardware::hidl_enum_range
. Dieser Bereich
enthält jeden Zähler in der Reihenfolge, in der er im HIDL-Quellcode vorkommt:
von der übergeordneten Aufzählung bis zum letzten untergeordneten Element. Dieser Code iteriert beispielsweise
über WRITE
, READ
, NONE
und
COMPARE
in dieser Reihenfolge. Angegebener SpecialMode
oben:
template <typename T> using hidl_enum_range = ::android::hardware::hidl_enum_range<T> for (SpecialMode mode : hidl_enum_range<SpecialMode>) {...}
hidl_enum_range
implementiert auch umgekehrte Iterationen und kann
in constexpr
Kontexten verwendet. Wenn ein Wert in einer Aufzählung enthalten ist
mehrfach vorhanden ist, erscheint der Wert mehrmals im Bereich.
Bitfield<T>
bitfield<T>
(wobei T
eine benutzerdefinierte Aufzählung ist)
wird zum zugrunde liegenden Typ dieser Aufzählung in C++. Im obigen Beispiel
bitfield<Mode>
wird zu uint8_t
.
vec<T>
Die Klassenvorlage hidl_vec<T>
ist Teil von
libhidlbase
und kann verwendet werden, um einen Vektor eines beliebigen HIDL-Typs mit
eine beliebige Größe haben. Der vergleichbare Container mit fester Größe
hidl_array
Ein hidl_vec<T>
kann auch
initialisiert, um auf einen externen Datenpuffer vom Typ T
zu verweisen, wobei
die hidl_vec::setToExternal()
-Funktion.
Zusätzlich zum entsprechenden Ausgabe/Einfügen der Struktur in den generierten
C++-Header enthält, ist die Verwendung von vec<T>
ein wenig praktischer.
Funktionen zur Übersetzung in/aus std::vector
und ohne T
Zeiger zeigen. Wenn vec<T>
als Parameter verwendet wird, gibt die Funktion
ist es überlastet (zwei Prototypen werden generiert), um die
die HIDL-Struktur und einen std::vector<T>
-Typ dafür
.
Array
Konstantenarrays in „hidl“ werden durch die Klasse hidl_array
dargestellt
in libhidlbase
Ein hidl_array<T, S1, S2, …,
SN>
steht für ein n-dimensionales Array mit fester Größe
T[S1][S2]…[SN]
.
string
Die Klasse hidl_string
(Teil von libhidlbase
) kann
wird verwendet, um Zeichenfolgen über HIDL-Schnittstellen zu übergeben.
/system/libhidl/base/include/hidl/HidlSupport.h
Der erste Speicher
Bei der Position in der Klasse handelt es sich um einen Zeiger auf den zugehörigen Zeichenpuffer.
hidl_string
kann die Umwandlung in und aus
std::string and char*
(String im C-Stil) mit
operator=
, implizite Umwandlungen und die Funktion .c_str()
.
HIDL-Stringstrukturen haben die entsprechenden Kopierkonstruktoren und Zuweisung
in:
- Lädt den HIDL-String aus einem
std::string
- oder C-String. - Erstellt eine neue
std::string
aus einem HIDL-String.
HIDL-Strings haben Konvertierungskonstruktoren, sodass C-Strings
(char *
) und C++ Strings (std::string
) können verwendet werden für:
die einen HIDL-String annehmen.
Struktur
Ein struct
in HIDL darf nur Datentypen mit fester Größe enthalten und keine
Funktionen. HIDL-Strukturdefinitionen werden dem Standardlayout direkt zugeordnet
struct
s in C++. Dadurch wird sichergestellt, dass struct
s
ein einheitliches Speicherlayout. Eine Struktur kann HIDL-Typen enthalten, darunter:
handle
, string
und vec<T>
, die
separate Puffer mit variabler Länge.
Alias
WARNUNG:Adressen jeder Art (auch physische) Geräteadressen) dürfen niemals Teil eines nativen Alias sein. Bestanden Informationen zwischen Prozessen sind gefährlich und anfällig für Angriffe. Alle zwischen Prozessen übergebenen Werte müssen validiert werden, bevor sie zum Suchen verwendet werden können den zugewiesenen Speicher eines Prozesses. Andernfalls können schlechte Aliasse zu oder eine Beschädigung des Arbeitsspeichers.
Der Typ handle
wird durch hidl_handle
dargestellt.
in C++. Dabei handelt es sich um einen einfachen Wrapper um einen Zeiger auf eine
const native_handle_t
-Objekt (bereits in Android seit
lange Zeit).
typedef struct native_handle { int version; /* sizeof(native_handle_t) */ int numFds; /* number of file descriptors at &data[0] */ int numInts; /* number of ints at &data[numFds] */ int data[0]; /* numFds + numInts ints */ } native_handle_t;
Standardmäßig übernimmt hidl_handle
keine Inhaberschaft
des native_handle_t
-Zeigers ihn umschließt. Es dient lediglich dazu,
einen Zeiger auf ein native_handle_t
speichern, damit es in
32- und 64-Bit-Prozesse.
Szenarien, in denen hidl_handle
Eigentümer der enthaltenen Datei ist
Zu den Deskriptoren gehören:
- Nach einem Aufruf der Methode
setTo(native_handle_t* handle, bool shouldOwn)
, bei der der ParametershouldOwn
auftrue
- Wenn das
hidl_handle
-Objekt durch die Kopierkonstruktion erstellt wird aus einem anderenhidl_handle
-Objekt - Wenn das
hidl_handle
-Objekt von einem anderen kopierten Element zugewiesen wirdhidl_handle
Objekt
hidl_handle
bietet sowohl implizite als auch explizite Conversions.
von/zu native_handle_t*
Objekten. Der Hauptzweck des
Der Typ handle
in HIDL besteht darin, Dateideskriptoren über HIDL zu übergeben.
Schnittstellen. Ein einzelner Dateideskriptor wird daher durch einen
native_handle_t
ohne int
und eine einzelne
fd
Wenn sich Client und Server in einem anderen Prozess befinden, wird der RPC
-Implementierung übernimmt automatisch den Dateideskriptor, um sicherzustellen,
können beide Prozesse
an derselben Datei arbeiten.
Obwohl ein Dateideskriptor, der in einem hidl_handle
von einem
in diesem Prozess gültig ist, bleibt er nicht über den empfangenden
-Funktion (sie wird geschlossen, wenn die Funktion zurückkehrt). Ein Prozess, bei dem
dauerhaften Zugriff auf den Dateideskriptor beibehalten muss, dup()
oder kopieren Sie das gesamte hidl_handle
-Objekt.
Speicher
Der HIDL-Typ memory
ist der Klasse hidl_memory
zugeordnet
in libhidlbase
, was nicht zugeordnetem freigegebenen Speicher darstellt. Dies ist
Das Objekt, das zwischen Prozessen übergeben werden muss, um Arbeitsspeicher in HIDL gemeinsam zu nutzen. Bis
gemeinsamen Arbeitsspeicher verwenden:
- Instanz von
IAllocator
abrufen (derzeit nur Instanz „Aschmem“ verfügbar) und verwenden Sie sie, um gemeinsamen Arbeitsspeicher zuzuweisen. IAllocator::allocate()
gibthidl_memory
zurück , das über HIDL RPC übergeben und mithilfe von Die FunktionmapMemory
vonlibhidlmemory
.mapMemory
gibt einen Verweis auf einesp<IMemory>
-Objekt, das für den Zugriff auf den Arbeitsspeicher verwendet werden kann. (IMemory
undIAllocator
sind definiert inandroid.hidl.memory@1.0
)
Eine Instanz von IAllocator
kann zum Zuweisen von Arbeitsspeicher verwendet werden:
#include <android/hidl/allocator/1.0/IAllocator.h> #include <android/hidl/memory/1.0/IMemory.h> #include <hidlmemory/mapping.h> using ::android::hidl::allocator::V1_0::IAllocator; using ::android::hidl::memory::V1_0::IMemory; using ::android::hardware::hidl_memory; .... sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) { if (!success) { /* error */ } // now you can use the hidl_memory object 'mem' or pass it around }));
Tatsächliche Änderungen am Arbeitsspeicher müssen über einen IMemory
vorgenommen werden
entweder auf der Seite, auf der mem
erstellt wurde, oder auf der Seite, auf der
empfängt es über HIDL RPC.
// Same includes as above sp<IMemory> memory = mapMemory(mem); void* data = memory->getPointer(); memory->update(); // update memory however you wish after calling update and before calling commit data[0] = 42; memory->commit(); // … memory->update(); // the same memory can be updated multiple times // … memory->commit();
interface
Schnittstellen können als Objekte übergeben werden. Das Wort Interface kann verwendet werden,
als syntaktischer Zucker für den Typ android.hidl.base@1.0::IBase
;
Außerdem werden die aktuelle Schnittstelle und alle importierten Schnittstellen definiert.
als Typ angezeigt.
Variablen, die Schnittstellen enthalten, sollten starke Hinweise sein:
sp<IName>
HIDL-Funktionen, die Schnittstellenparameter verwenden
Rohzeiger in aussagekräftige Hinweise umwandeln, was zu nicht intuitivem Verhalten führt
Der Cursor kann unerwartet gelöscht werden. Zur Vermeidung von Problemen immer HIDL speichern
als sp<>
.