Вы можете выполнить рефакторинг условно скомпилированного кода для динамического чтения значений из интерфейса HAL. Например:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS // some code fragment #endif
Затем код платформы может вызвать соответствующую служебную функцию, определенную в <configstore/Utils.h>
в зависимости от ее типа.
Пример хранилища конфигураций
В этом примере показано чтение 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, служба v1_1 должна быть возвращена для
getService()
:V1_0::IConfig::getService()->v1_0API();
Когда функции доступа в библиотеке configstore-utils
используются для доступа к элементу ConfigStore, #1 гарантируется реализацией, а #2 — ошибками компилятора. По этим причинам мы настоятельно рекомендуем везде, где это возможно, использовать configstore-utils
.