È possibile eseguire il refactoring del codice compilato in modo condizionale per leggere i valori in modo dinamico dall'interfaccia HAL. Per esempio:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS //some code fragment #endif
Il codice Framework può quindi chiamare una funzione di utilità appropriata definita in <configstore/Utils.h>
a seconda del tipo.
Esempio di ConfigStore
Questo esempio mostra la lettura di TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
, definito in ConfigStore HAL come forceHwcForVirtualDisplays()
con tipo restituito OptionalBool
:
#include <configstore/Utils.h> using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; static bool vsyncPhaseOffsetNs = getBool<ISurfaceFlingerConfigs, ISurfaceFlingerConfigs::forceHwcForVirtualDisplays>(false);
La funzione di utilità ( getBool
nell'esempio sopra) contatta il servizio configstore
per ottenere l'handle per il proxy della funzione di interfaccia, quindi recupera il valore richiamando l'handle tramite HIDL/hwbinder.
Funzioni di utilità
<configstore/Utils.h>
( configstore/1.0/include/configstore/Utils.h
) fornisce funzioni di utilità per ogni tipo restituito primitivo, incluso Optional[Bool|String|Int32|UInt32|Int64|UInt64]
, come elencato di seguito:
Tipo | Funzione (parametri del modello omessi) |
---|---|
OptionalBool | bool getBool(const bool defValue) |
OptionalInt32 | int32_t getInt32(const int32_t defValue) |
OptionalUInt32 | uint32_t getUInt32(const uint32_t defValue) |
OptionalInt64 | int64_t getInt64(const int64_t defValue) |
OptionalUInt64 | uint64_t getUInt64(const uint64_t defValue) |
OptionalString | std::string getString(const std::string &defValue) |
defValue
è un valore predefinito restituito quando l'implementazione HAL non specifica un valore per l'elemento di configurazione. Ogni funzione accetta due parametri del modello:
-
I
è il nome della classe dell'interfaccia. -
Func
è il puntatore alla funzione membro per ottenere l'elemento di configurazione.
Poiché il valore di configurazione è di sola lettura e non cambia, la funzione di utilità memorizza internamente nella cache il valore di configurazione. Le chiamate successive vengono gestite in modo più efficiente utilizzando il valore memorizzato nella cache nella stessa unità di collegamento.
Utilizzo di configstore-utils
L'HAL di ConfigStore è progettato per essere compatibile con le versioni successive degli aggiornamenti delle versioni secondarie, il che significa che quando l'HAL viene rivisto e alcuni codici del framework utilizzano gli elementi appena introdotti, è ancora possibile utilizzare il servizio ConfigStore con una versione secondaria precedente in /vendor
.
Per la compatibilità futura, assicurati che la tua implementazione rispetti le seguenti linee guida:
- I nuovi elementi utilizzano il valore predefinito quando è disponibile solo il servizio della versione precedente. Esempio:
service = V1_1::IConfig::getService(); // null if V1_0 is installed value = DEFAULT_VALUE; if(service) { value = service->v1_1API(DEFAULT_VALUE); }
- Il client utilizza la prima interfaccia che includeva l'elemento ConfigStore. Esempio:
V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED V1_0::IConfig::getService()->v1_0API(); // OK
- Il servizio della nuova versione può essere recuperato per l'interfaccia della vecchia versione. Nell'esempio seguente, se la versione installata è v1_1, il servizio v1_1 deve essere restituito per
getService()
:V1_0::IConfig::getService()->v1_0API();
Quando le funzioni di accesso nella libreria configstore-utils
vengono utilizzate per accedere all'elemento ConfigStore, #1 è garantito dall'implementazione e #2 è garantito da errori del compilatore. Per questi motivi, consigliamo vivamente di utilizzare configstore-utils
ove possibile.