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

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