Musisz używać HIDL do opisywania wszystkich flag kompilacji używanych warunkowo
budowania platformy. Odpowiednie flagi kompilacji muszą być zgrupowane i uwzględnione w
pojedynczy plik .hal
. Używanie HIDL do określania elementów konfiguracji
zapewnia następujące korzyści:
- Uwzględnione w wersji (aby można było dodać nowe elementy konfiguracji, dostawcy/producent OEM muszą wyraźnie rozszerzyć HAL)
- Dobrze udokumentowany
- Kontrola dostępu przy użyciu SELinux
- Kontrola poprawności elementów konfiguracji w Test dostawcy Suite (sprawdzanie zakresu, współdziałanie elementów itp.)
- Automatycznie generowane interfejsy API w C++ i Javie
Określ flagi kompilacji używane przez platformę
Zacznij od wskazania konfiguracji kompilacji używanych do warunkowej skompilowania
platformy, a następnie zrezygnować z nieaktualnych konfiguracji, aby zmniejszyć zbiór. Przykład:
dla surfaceflinger
zidentyfikowano te flagi kompilacji:
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
Tworzenie interfejsu HAL
Dostęp do konfiguracji kompilacji dla podsystemu uzyskuje się przez interfejs HAL, a
interfejsy do przekazywania wartości konfiguracyjnych są zgrupowane w pakiecie HAL
android.hardware.configstore
(obecnie w wersji 1.0).
Aby np. utworzyć plik interfejsu HAL dla języka surfaceflinger
,
hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
package android.hardware.configstore@1.0; interface ISurfaceFlingerConfigs { // TO-BE-FILLED-BELOW };
Po utworzeniu pliku .hal
uruchom
hardware/interfaces/update-makefiles.sh
, aby dodać nowe
.hal
w folderach Android.bp
i
Android.mk
plików.
Dodawanie funkcji do flag kompilacji
Do każdej flagi kompilacji dodaj nową funkcję do interfejsu. Na przykład w polu
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); };
Podczas dodawania funkcji:
- Zachowaj zwięzłość i nazwisko. Unikaj konwertowania zmiennej Makefile
nazwy na nazwy funkcji. Pamiętaj, że
TARGET_
oraz Prefiksy (BOARD_
) nie są już potrzebne. - dodawać komentarze, Pomóż deweloperom zrozumieć, do czego służy funkcja jak zmienia działanie platformy, prawidłowe wartości i inne istotne i informacjami o nich.
Zwracane typy funkcji mogą być
Optional[Bool|String|Int32|UInt32|Int64|UInt64]
Typy są zdefiniowane
w types.hal
w tym samym katalogu i opakuj wartości podstawowe za pomocą tagu
pole wskazujące, czy wartość jest określona przez HAL; Jeśli nie, zostanie zastosowany domyślny
.
struct OptionalString { bool specified; string value; };
W razie potrzeby zdefiniuj wyliczenie, które najlepiej odpowiada typowi wartości
i użyć tego wyliczenia jako zwracanego typu. W przykładzie powyżej
wyliczana NumBuffers
jest zdefiniowana w celu ograniczenia liczby prawidłowych
. Podczas definiowania takich niestandardowych typów danych dodaj pole lub wartość wyliczeniową (w przypadku
np. USE_DEFAULT
) do wskazania, czy wartość jest/nie jest określona
przez HAL.
Nie jest konieczne, aby pojedyncza flaga kompilacji była pojedynczą funkcją w HIDL. Właściciele modułu mogą też agregować ściśle powiązane flagi kompilacji w mają strukturę struct i są wyposażone w funkcję, która zwraca tę strukturę (może to zmniejszyć liczbę wywołań funkcji).
Na przykład opcja agregacji 2 flag kompilacji w jedną strukturę
w: hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
to:
interface ISurfaceFlingerConfigs { // other functions here struct SyncConfigs { OptionalInt64 vsyncEventPhaseoffsetNs; OptionalInt64 presentTimeoffsetFromSyncNs; }; getSyncConfigs() generates (SyncConfigs ret); // other functions here };
Alternatywy dla pojedynczej funkcji HAL
Zamiast używać pojedynczej funkcji HAL na potrzeby wszystkich flag kompilacji, można użyć funkcji HAL
interfejs udostępnia też proste funkcje, takie jak getBoolean(string
key)
i getInteger(string key)
. Rzeczywisty
key=value
pary są przechowywane w osobnych plikach i usłudze HAL
dostarcza wartości przez odczyt/analizę tych plików.
Takie podejście jest łatwe do zdefiniowania, ale nie uwzględnia korzyści udostępniane przez HIDL (wymuszona obsługa wersji, łatwa dokumentacja, kontrola dostępu) i dlatego nie jest zalecana.
Jeden i wiele interfejsów
Interfejs HAL elementów konfiguracji zawiera 2 elementy: opcje:
- Jeden interfejs obejmujący wszystkie elementy konfiguracji
- Wiele interfejsów, z których każdy obejmuje zestaw powiązanych konfiguracji elementy
Jeden interfejs jest prostszy, ale może też stać się problemem z utrzymaniem, elementy konfiguracji zostaną dodane do pojedynczego pliku. Ponadto kontrola dostępu nie jest bardzo szczegółowy, przez co proces z dostępem do interfejsu może odczytać wszystkich elementów konfiguracji (nie można mieć dostępu do częściowego zbioru elementów konfiguracji przyznane). Jeśli nie przyznasz dostępu, elementów konfiguracji nie będzie można przeczytaj.
Z tego powodu Android używa wielu interfejsów z jedną HAL.
dla grupy powiązanych elementów konfiguracji. Przykład:
ISurfaceflingerConfigs
w związku z: surfaceflinger
elementy konfiguracji oraz IBluetoothConfigs
w przypadku funkcji związanych z Bluetoothem
elementów konfiguracji.