Devi utilizzare HIDL per descrivere tutti i flag di compilazione utilizzati per compilare il framework in modo condizionale. I flag di compilazione pertinenti devono essere raggruppati e inclusi in un singolo file .hal
. L'utilizzo di HIDL per specificare gli elementi di configurazione include i seguenti vantaggi:
- Con versione (per aggiungere nuovi elementi di configurazione, i fornitori/OEM devono estendere esplicitamente il HAL)
- Ben documentata
- Controllo dell'accesso mediante SELinux
- Controllo di congruità per gli elementi di configurazione tramite la Vendor Test Suite (controllo dell'intervallo, controllo delle interdipendenze tra gli elementi e così via).
- API generate automaticamente sia in C++ che in Java
Identificare i flag di compilazione utilizzati dal framework
Inizia identificando le configurazioni di build utilizzate per compilare condizionalmente il framework, quindi elimina le configurazioni obsolete per ridurre l'insieme. Ad esempio,
viene identificato il seguente set di flag di build per surfaceflinger
:
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
Crea un'interfaccia HAL
Le configurazioni di build per un sottosistema sono accessibili tramite un'interfaccia HAL, mentre
le interfacce per fornire valori di configurazione sono raggruppate nel pacchetto HAL
android.hardware.configstore
(attualmente alla versione 1.0).
Ad esempio, per creare un file di interfaccia HAL per surfaceflinger
, in
hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
:
package android.hardware.configstore@1.0; interface ISurfaceFlingerConfigs { // TO-BE-FILLED-BELOW };
Dopo aver creato il file .hal
, esegui
hardware/interfaces/update-makefiles.sh
per aggiungere il nuovo
.hal
file ai file Android.bp
e
Android.mk
.
Aggiungere funzioni per i flag di compilazione
Per ogni flag di compilazione, aggiungi una nuova funzione all'interfaccia. Ad esempio, 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); };
Quando aggiungi una funzione:
- Usa nomi concisi. Evita di convertire i nomi delle variabili del file make in nomi di funzione e tieni presente che i prefissi
TARGET_
eBOARD_
non sono più necessari. - Aggiungi commenti. Aiuta gli sviluppatori a comprendere lo scopo dell'elemento di configurazione, in che modo modifica il comportamento del framework, i valori validi e altre informazioni pertinenti.
I tipi restituiti delle funzioni possono essere
Optional[Bool|String|Int32|UInt32|Int64|UInt64]
. I tipi sono definiti in types.hal
nella stessa directory e racchiudono i valori primitivi con un campo che indica se il valore è specificato dall'HAL; in caso contrario, viene utilizzato il valore predefinito.
struct OptionalString { bool specified; string value; };
Se opportuno, definisci l'enum che rappresenta al meglio il tipo di elemento di configurazione e utilizzalo come tipo di ritorno. Nell'esempio riportato sopra,
l'enum NumBuffers
è definito per limitare il numero di valori validi. Quando definisci questi tipi di dati personalizzati, aggiungi un campo o un valore enumerato (ad esempio USE_DEFAULT
) per indicare se il valore è/non è specificato dall'HAL.
Non è obbligatorio che un singolo flag di compilazione diventi una singola funzione in HIDL. In alternativa, i proprietari di moduli possono aggregare flag di compilazione strettamente correlati in una struct e avere una funzione che restituisce questa struct (in questo modo è possibile ridurre il numero di chiamate di funzione).
Ad esempio, un'opzione per aggregare due flag di compilazione in un'unica struct
in hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
è:
interface ISurfaceFlingerConfigs { // other functions here struct SyncConfigs { OptionalInt64 vsyncEventPhaseoffsetNs; OptionalInt64 presentTimeoffsetFromSyncNs; }; getSyncConfigs() generates (SyncConfigs ret); // other functions here };
Alternative a una singola funzione HAL
Come alternativa all'utilizzo di una singola funzione HAL per tutti i flag di compilazione, l'interfaccia HAL fornisce anche funzioni semplici come getBoolean(string
key)
e getInteger(string key)
. Le coppie key=value
effettive sono archiviate in file separati e il servizio HAL fornisce i valori leggendo/analizzando questi file.
Sebbene questo approccio sia facile da definire, non include i vantaggi offerti da HIDL (controllo della versione forzato, facilità di documentazione, controllo dell'accesso) e pertanto non è consigliato.
Interfacce singole e multiple
Il design dell'interfaccia HAL per gli elementi di configurazione offre due opzioni:
- Un'unica interfaccia che copre tutti gli elementi di configurazione
- Più interfacce, ognuna delle quali copre un insieme di elementi di configurazione correlati
Un'interfaccia singola è più semplice, ma può diventare non gestibile man mano che vengono aggiunti più elementi di configurazione al singolo file. Inoltre, il controllo dell'accesso non è granulare, quindi un processo a cui viene concesso l'accesso all'interfaccia può leggere tutti gli elementi di configurazione (non è possibile concedere l'accesso a un insieme parziale di elementi di configurazione). In alternativa, se l'accesso non viene concesso, gli elementi di configurazione non possono essereletti.
A causa di questi problemi, Android utilizza più interfacce con un'unica interfaccia HAL per un gruppo di elementi di configurazione correlati. Ad esempio,ISurfaceflingerConfigs
per gli elementi di configurazione relativi a surfaceflinger
e IBluetoothConfigs
per gli elementi di configurazione relativi al Bluetooth.