Вы можете провести рефакторинг кода, который компилируется условно, чтобы считывать значения динамически из интерфейса 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
HAL ConfigStore разработан таким образом, чтобы быть совместимым с будущими версиями при промежуточных обновлениях. Это означает, что когда 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.