Można dokonać refaktoryzacji skompilowanego warunkowo kodu, aby dynamicznie odczytywać wartości z interfejsu HAL. Na przykład:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS // some code fragment #endif
Kod frameworka 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 ConfigStore HAL jako forceHwcForVirtualDisplays()
z typem powrotu 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 powyższym przykładzie) kontaktuje się z usługą configstore
, aby uzyskać uchwyt dla serwera proxy funkcji interfejsu, a następnie pobiera wartość, wywołując uchwyt za pośrednictwem HIDL/hwbinder.
Funkcje użytkowe
<configstore/Utils.h>
( configstore/1.0/include/configstore/Utils.h
) udostępnia funkcje narzędziowe dla każdego pierwotnego typu zwracanego, w tym Optional[Bool|String|Int32|UInt32|Int64|UInt64]
, jak wymieniono poniżej:
Typ | Funkcja (pominięte parametry szablonu) |
---|---|
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 dwa parametry szablonu:
-
I
to nazwa klasy interfejsu. -
Func
jest wskaźnikiem funkcji członkowskiej służącym do pobierania elementu konfiguracji.
Ponieważ wartość konfiguracyjna jest tylko do odczytu i nie zmienia się, funkcja narzędzia wewnętrznie buforuje wartość konfiguracyjną. Kolejne wywołania są obsługiwane wydajniej przy użyciu wartości buforowanej w tej samej jednostce łączącej.
Korzystanie z configstore-utils
ConfigStore HAL zaprojektowano tak, aby był kompatybilny z nowszymi aktualizacjami wersji mniejszych, co oznacza, że gdy warstwa HAL zostanie poprawiona i jakiś kod frameworku będzie korzystał z nowo wprowadzonych elementów, nadal będzie można używać usługi ConfigStore ze starszą wersją pomocniczą w /vendor
.
Aby zapewnić zgodność z przyszłymi wersjami, upewnij się, że implementacja jest zgodna z następującymi wytycznymi:
- Nowe elementy używają wartości domyślnej, gdy dostępna jest tylko usługa 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 korzysta z pierwszego interfejsu zawierającego element ConfigStore. Przykład:
V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED V1_0::IConfig::getService()->v1_0API(); // OK
- Usługę nowej wersji można pobrać dla interfejsu starej wersji. W poniższym przykładzie, jeśli zainstalowana wersja to v1_1, dla funkcji
getService()
należy zwrócić usługę v1_1:V1_0::IConfig::getService()->v1_0API();
Gdy funkcje dostępu w bibliotece configstore-utils
są używane do uzyskiwania dostępu do elementu ConfigStore, numer 1 jest gwarantowany przez implementację, a numer 2 jest gwarantowany przez błędy kompilatora. Z tych powodów zdecydowanie zalecamy używanie configstore-utils
gdy tylko jest to możliwe.