Utilizzo lato client

Puoi eseguire il refactoring del codice compilato in modo condizionale per leggere i valori in modo dinamico dall'interfaccia HAL. Ad esempio:

#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
// some code fragment
#endif

Il codice del 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, definita in ConfigStore HAL come forceHwcForVirtualDisplays() con tipo di ritorno 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 precedente) contatta il servizio configstore per ottenere l'handle del 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, tra cui Optional[Bool|String|Int32|UInt32|Int64|UInt64], come elencato di seguito:

Digitazione 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 richiede due parametri del modello:

  • I è il nome della classe dell'interfaccia.
  • Func è il puntatore alla funzione membro per recuperare l'elemento di configurazione.

Poiché il valore di configurazione è di sola lettura e non cambia, la funzione di utilità memorizza nella cache internamente il valore di configurazione. Le chiamate successive vengono gestite in modo più efficiente utilizzando il valore memorizzato nella cache nella stessa unità di collegamento.

Utilizzare configstore-utils

L'HAL ConfigStore è progettato per essere compatibile con le versioni successive per gli upgrade delle versioni minori, il che significa che quando l'HAL viene rivisto e parte del codice del framework utilizza gli elementi appena introdotti, il servizio ConfigStore con una versione minore precedente in /vendor può essere ancora utilizzato.

Per la compatibilità futura, assicurati che l'implementazione rispetti le seguenti linee guida:

  1. 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);
      }
    
  2. Il client utilizza la prima interfaccia che include l'elemento ConfigStore. Esempio:
    V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED
    
    V1_0::IConfig::getService()->v1_0API(); // OK
    
  3. Il servizio della nuova versione può essere recuperato per l'interfaccia della versione precedente. Nel seguente esempio, se la versione installata è v1_1, il servizio v1_1 deve essere fornito per getService():
    V1_0::IConfig::getService()->v1_0API();
    

Quando le funzioni di accesso nella libreria configstore-utils vengono utilizzate per accedere all'elemento ConfigStore, il punto 1 è garantito dall'implementazione e il punto 2 è garantito da errori del compilatore. Per questi motivi, ti consigliamo vivamente di utilizzare configstore-utils, se possibile.