Użycie po stronie klienta

Możesz przekształcić kod kompilowany warunkowo, aby dynamicznie odczytywać wartości z interfejsu HAL. Na przykład:

#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
// some code fragment
#endif

Kod platformy może następnie wywołać odpowiednią funkcję narzędziową zdefiniowaną w <configstore/Utils.h> w zależności od jej typu.

Przykład ConfigStore

Ten przykład pokazuje odczyt TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS zdefiniowany w HAL ConfigStore jako forceHwcForVirtualDisplays() z typem zwracanym 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);

Funkcja narzędziowa (getBool w przykładzie powyżej) kontaktuje się z usługą configstore, aby uzyskać uchwyt do serwera proxy funkcji interfejsu, a następnie pobiera wartość, wywołując uchwyt za pomocą HIDL/hwbinder.

Funkcje narzędziowe

<configstore/Utils.h> (configstore/1.0/include/configstore/Utils.h) udostępnia funkcje narzędziowe dla każdego podstawowego typu zwracanego, w tym Optional[Bool|String|Int32|UInt32|Int64|UInt64], jak podano poniżej:

Typ Funkcja (parametry szablonu pominięte)
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 to wartość domyślna zwracana, gdy implementacja HAL nie określa wartości elementu konfiguracji. Każda funkcja przyjmuje 2 parametry szablonu:

  • I to nazwa klasy interfejsu.
  • Func to wskaźnik funkcji składowej służący do pobierania elementu konfiguracji.

Wartość konfiguracji jest tylko do odczytu i nie zmienia się, dlatego funkcja narzędziowa wewnętrznie buforuje wartość konfiguracji. Kolejne wywołania są obsługiwane wydajniej dzięki użyciu wartości z pamięci podręcznej w tym samym module łączenia.

Używanie narzędzi configstore-utils

Warstwa HAL ConfigStore została zaprojektowana tak, aby była zgodna z przyszłymi wersjami w przypadku aktualizacji do nowszych wersji, co oznacza, że gdy warstwa HAL zostanie zmieniona, a niektóre fragmenty kodu platformy będą korzystać z nowo wprowadzonych elementów, nadal będzie można używać usługi ConfigStore ze starszą wersją w /vendor.

Aby zapewnić zgodność z przyszłymi wersjami, upewnij się, że implementacja jest zgodna z tymi wytycznymi:

  1. Nowe produkty używają wartości domyślnej, gdy dostępna jest tylko usługa w starej wersji. Przykład:
    service = V1_1::IConfig::getService(); // null if V1_0 is installed
    value = DEFAULT_VALUE;
      if(service) {
        value = service->v1_1API(DEFAULT_VALUE);
      }
    
  2. Klient używa pierwszego interfejsu, który zawiera element ConfigStore. Przykład:
    V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED
    
    V1_0::IConfig::getService()->v1_0API(); // OK
    
  3. Usługę nowej wersji można pobrać dla interfejsu starszej wersji. W tym przykładzie, jeśli zainstalowana wersja to v1_1, usługa v1_1 musi zostać zwrócona dla getService():
    V1_0::IConfig::getService()->v1_0API();
    

Gdy do uzyskiwania dostępu do elementu ConfigStore używane są funkcje dostępu w bibliotece configstore-utils, warunek 1 jest gwarantowany przez implementację, a warunek 2 – przez błędy kompilatora. Z tych powodów zdecydowanie zalecamy korzystanie z configstore-utils, gdy tylko jest to możliwe.