Клиентское использование

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

Чтобы обеспечить совместимость с будущими версиями, следуйте приведенным ниже рекомендациям.

  1. Новые объекты используют значение по умолчанию, когда доступна только старая версия сервиса. Пример:
    service = V1_1::IConfig::getService(); // null if V1_0 is installed
    value = DEFAULT_VALUE;
      if(service) {
        value = service->v1_1API(DEFAULT_VALUE);
      }
    
  2. Клиент использует первый интерфейс, в котором есть элемент ConfigStore. Пример:
    V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED
    
    V1_0::IConfig::getService()->v1_0API(); // OK
    
  3. Сервис новой версии можно получить для интерфейса старой версии. В следующем примере, если установлена версия v1_1, для getService() необходимо вернуть сервис v1_1:
    V1_0::IConfig::getService()->v1_0API();
    

Когда функции доступа в библиотеке configstore-utils используются для доступа к элементу ConfigStore, пункт 1 гарантируется реализацией, а пункт 2 – ошибками компилятора. Поэтому мы настоятельно рекомендуем по возможности использовать свойство configstore-utils.