Вы можете рефакторить условно скомпилированный код для динамического чтения значений из интерфейса HAL. Например:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS // some code fragment #endif
 Затем код фреймворка может вызвать соответствующую служебную функцию, определенную в <configstore/Utils.h> в зависимости от ее типа.
Пример ConfigStore
 В этом примере показано чтение TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS , определенного в ConfigStore HAL как forceHwcForVirtualDisplays() с возвращаемым типом 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);
 Вспомогательная функция ( getBool в примере выше) обращается к службе configstore , чтобы получить дескриптор прокси-сервера интерфейсной функции, а затем извлекает значение, вызывая дескриптор через HIDL/hwbinder.
Функции полезности
 <configstore/Utils.h> ( configstore/1.0/include/configstore/Utils.h ) предоставляет служебные функции для каждого примитивного типа возвращаемого значения, включая Optional[Bool|String|Int32|UInt32|Int64|UInt64] , как указано ниже:
| Тип | Функция (параметры шаблона опущены) | 
|---|---|
 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 — это значение по умолчанию, возвращаемое, если реализация HAL не указывает значение для элемента конфигурации. Каждая функция принимает два параметра шаблона:
-  
I— имя класса интерфейса. -  
Func— указатель функции-члена для получения элемента конфигурации. 
Поскольку значение конфигурации доступно только для чтения и не изменяется, служебная функция кэширует его внутри себя. Последующие вызовы обслуживаются более эффективно, используя кэшированное значение в том же модуле компоновки.
Использовать configstore-utils
 ConfigStore HAL разработан с учетом обеспечения прямой совместимости для обновлений младших версий. Это означает, что при обновлении HAL и использовании некоторых кодов фреймворка недавно введенных элементов служба ConfigStore со старой младшей версией в /vendor по-прежнему может использоваться.
Для обеспечения прямой совместимости убедитесь, что ваша реализация соответствует следующим рекомендациям:
-  Новые элементы используют значение по умолчанию, когда доступна только старая версия сервиса. Пример: 
service = V1_1::IConfig::getService(); // null if V1_0 is installed value = DEFAULT_VALUE; if(service) { value = service->v1_1API(DEFAULT_VALUE); } - Клиент использует первый интерфейс, содержащий элемент ConfigStore. Пример: 
V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED V1_0::IConfig::getService()->v1_0API(); // OK
 - Сервис новой версии можно получить из интерфейса старой версии. В следующем примере, если установлена версия v1_1, для 
getService()необходимо вернуть сервис v1_1:V1_0::IConfig::getService()->v1_0API();
 
 При использовании функций доступа из библиотеки configstore-utils для доступа к элементу ConfigStore, #1 гарантируется реализацией, а #2 — ошибками компиляции. По этим причинам мы настоятельно рекомендуем использовать configstore-utils везде, где это возможно.