Sie müssen HIDL verwenden, um alle Build-Flags zu beschreiben, die für die bedingte Kompilierung des Frameworks verwendet werden. Relevante Build-Flags müssen gruppiert und in einer einzelnen .hal
-Datei enthalten sein. Die Verwendung von HIDL zum Angeben von Konfigurationselementen bietet folgende Vorteile:
- Versioniert (Anbieter/OEMs müssen den HAL explizit erweitern, um neue Konfigurationselemente hinzuzufügen)
- Gut dokumentiert
- Zugriffssteuerung mit SELinux
- Integritätsprüfung für Konfigurationselemente mit der Anbieter-Test-Suite (Bereichsprüfung, Abhängigkeitsprüfungen zwischen Elementen usw.)
- Automatisch generierte APIs in C++ und Java
Vom Framework verwendete Build-Flags identifizieren
Ermitteln Sie zuerst die Build-Konfigurationen, die zur bedingten Kompilierung des Frameworks verwendet werden, und verwerfen Sie dann veraltete Konfigurationen, um den Satz zu verkleinern. Für surfaceflinger
werden beispielsweise die folgenden Build-Flags identifiziert:
TARGET_USES_HWC2
TARGET_BOARD_PLATFORM
TARGET_DISABLE_TRIPLE_BUFFERING
TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
NUM_FRAMEBUFFER_SURFACE_BUFFERS
TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
VSYNC_EVENT_PHASE_OFFSET_NS
SF_VSYNC_EVENT_PHASE_OFFSET_NS
PRESENT_TIME_OFFSET_FROM_VSYNC_NS
MAX_VIRTUAL_DISPLAY_DIMENSION
HAL-Schnittstelle erstellen
Build-Konfigurationen für ein Subsystem werden über eine HAL-Schnittstelle aufgerufen. Schnittstellen zum Bereitstellen von Konfigurationswerten sind im HAL-Paket android.hardware.configstore
(derzeit in Version 1.0) gruppiert.
So erstellen Sie beispielsweise eine HAL-Schnittstellendatei für surfaceflinger
in hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
package android.hardware.configstore@1.0; interface ISurfaceFlingerConfigs { // TO-BE-FILLED-BELOW };
Nachdem Sie die Datei .hal
erstellt haben, führen Sie hardware/interfaces/update-makefiles.sh
aus, um die neue Datei .hal
den Dateien Android.bp
und Android.mk
hinzuzufügen.
Funktionen für Build-Flags hinzufügen
Fügen Sie der Schnittstelle für jedes Build-Flag eine neue Funktion hinzu. Beispiel in hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
interface ISurfaceFlingerConfigs { disableTripleBuffering() generates(OptionalBool ret); forceHwcForVirtualDisplays() generates(OptionalBool ret); enum NumBuffers: uint8_t { USE_DEFAULT = 0, TWO = 2, THREE = 3, }; numFramebufferSurfaceBuffers() generates(NumBuffers ret); runWithoutSyncFramework() generates(OptionalBool ret); vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret); presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret); maxVirtualDisplayDimension() generates(OptionalInt32 ret); };
Wenn Sie eine Funktion hinzufügen:
- Fassen Sie sich kurz. Vermeiden Sie die Umwandlung von Makefile-Variablennamen in Funktionsnamen und denken Sie daran, dass die Präfixe
TARGET_
undBOARD_
nicht mehr erforderlich sind. - Kommentare hinzufügen Helfen Sie Entwicklern, den Zweck des Konfigurationselements zu verstehen und zu verstehen, wie es das Framework-Verhalten, gültige Werte und andere relevante Informationen ändert.
Funktionsrückgabetypen können Optional[Bool|String|Int32|UInt32|Int64|UInt64]
sein. Typen werden in types.hal
im selben Verzeichnis definiert und umschließen primitive Werte mit einem Feld, das angibt, ob der Wert vom HAL angegeben wird. Andernfalls wird der Standardwert verwendet.
struct OptionalString { bool specified; string value; };
Definieren Sie gegebenenfalls die Aufzählung, die den Typ des Konfigurationselements am besten repräsentiert, und verwenden Sie diese Aufzählung als Rückgabetyp. Im obigen Beispiel ist die Enum NumBuffers
definiert, um die Anzahl der gültigen Werte zu begrenzen. Fügen Sie beim Definieren solcher benutzerdefinierter Datentypen ein Feld oder einen Aufzählungswert (z. B. USE_DEFAULT
) hinzu, um anzugeben, ob der Wert durch den HAL angegeben wird oder nicht.
Ein einzelnes Build-Flag muss in HIDL nicht zu einer einzelnen Funktion werden. Modulinhaber können alternativ eng verwandte Build-Flags in einer Struktur aggregieren und eine Funktion haben, die diese Struktur zurückgibt. Dadurch kann die Anzahl der Funktionsaufrufe reduziert werden.
Eine Option zum Aggregieren von zwei Build-Flags zu einer einzigen Struktur in hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
ist beispielsweise:
interface ISurfaceFlingerConfigs { // other functions here struct SyncConfigs { OptionalInt64 vsyncEventPhaseoffsetNs; OptionalInt64 presentTimeoffsetFromSyncNs; }; getSyncConfigs() generates (SyncConfigs ret); // other functions here };
Alternativen zu einer einzelnen HAL-Funktion
Als Alternative zur Verwendung einer einzigen HAL-Funktion für alle Build-Flags bietet die HAL-Oberfläche auch einfache Funktionen wie getBoolean(string
key)
und getInteger(string key)
. Die tatsächlichen key=value
-Paare werden in separaten Dateien gespeichert und der HAL-Dienst stellt Werte durch Lesen/Parsen dieser Dateien bereit.
Dieser Ansatz ist zwar leicht zu definieren, bietet jedoch nicht die Vorteile von HIDL (erzwungene Versionsverwaltung, einfache Dokumentation, Zugriffssteuerung) und wird daher nicht empfohlen.
Eine und mehrere Benutzeroberflächen
Für das Design der HAL-Schnittstelle für Konfigurationselemente gibt es zwei Auswahlmöglichkeiten:
- Eine Schnittstelle, die alle Konfigurationselemente abdeckt
- Mehrere Schnittstellen, die jeweils eine Reihe verwandter Konfigurationselemente abdecken
Eine einzelne Schnittstelle ist einfacher, kann jedoch unhandlich werden, da der einzelnen Datei weitere Konfigurationselemente hinzugefügt werden. Darüber hinaus ist die Zugriffssteuerung nicht detailliert, sodass ein Prozess, dem Zugriff auf die Schnittstelle gewährt wird, alle Konfigurationselemente lesen kann (Zugriff auf einen Teil der Konfigurationselemente kann nicht gewährt werden). Alternativ können Konfigurationselemente nicht gelesen werden, wenn der Zugriff nicht gewährt wird.
Aufgrund dieser Probleme verwendet Android mehrere Schnittstellen mit einer einzigen HAL-Schnittstelle für eine Gruppe verwandter Konfigurationselemente. Beispiel: ISurfaceflingerConfigs
für surfaceflinger
-bezogene Konfigurationselemente und IBluetoothConfigs
für Bluetooth-bezogene Konfigurationselemente.