Możesz przeprowadzić refaktoryzację kodu skompilowanego warunkowo, aby odczytywać wartości dynamicznie z interfejsu HAL. Przykład:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS // some code fragment #endif
Kod platformy może następnie wywołać odpowiednią funkcję użytkową zdefiniowaną w
<configstore/Utils.h> w zależności od jej typu.
Przykład ConfigStore
Ten przykład pokazuje odczytywanie TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS zdefiniowanego w ConfigStore HAL 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 użytkowa (getBool w powyższym przykładzie) kontaktuje się z usługą configstore, aby uzyskać uchwyt do proxy funkcji interfejsu, a następnie pobiera wartość, wywołując uchwyt za pomocą HIDL/hwbinder.
Funkcje użytkowe
<configstore/Utils.h>
(configstore/1.0/include/configstore/Utils.h) udostępnia funkcje użytkowe dla każdego podstawowego typu zwracanego, w tym
Optional[Bool|String|Int32|UInt32|Int64|UInt64], jak pokazano
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:
Ito nazwa klasy interfejsu.Functo wskaźnik funkcji składowej służący do pobierania elementu konfiguracji.
Ponieważ wartość konfiguracji jest tylko do odczytu i nie zmienia się, funkcja użytkowa wewnętrznie buforuje wartość konfiguracji. Kolejne wywołania są obsługiwane wydajniej dzięki użyciu wartości buforowanej w tej samej jednostce łączenia.
Korzystanie z configstore-utils
HAL ConfigStore jest zaprojektowany tak, aby był zgodny z przyszłymi wersjami w przypadku uaktualnień wersji podrzędnych. Oznacza to, że gdy HAL zostanie zmieniony, a część kodu platformy będzie korzystać z nowo wprowadzonych elementów, nadal będzie można używać usługi ConfigStore ze starszą wersją podrzędną w /vendor.
Aby zapewnić zgodność z przyszłymi wersjami, upewnij się, że Twoja implementacja jest zgodna z tymi wytycznymi:
- Nowe elementy 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); } - 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
- Usługę w nowej wersji można pobrać w przypadku interfejsu w starej wersji. W tym przykładzie, jeśli zainstalowana wersja to v1_1, usługa v1_1 musi zostać zwrócona w przypadku
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, #1 jest gwarantowane przez implementację, a #2 – przez błędy kompilatora. Z tych powodów zdecydowanie zalecamy używanie configstore-utils wszędzie tam, gdzie to możliwe.