Uso del cliente

Puedes refactorizar el código compilado de forma condicional para leer valores de forma dinámica desde la interfaz de HAL. Por ejemplo:

#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
// some code fragment
#endif

Luego, el código del framework puede llamar a una función de utilidad adecuada definida en <configstore/Utils.h> según su tipo.

Ejemplo de ConfigStore

En este ejemplo, se muestra la lectura de TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS, definida en el HAL de ConfigStore como forceHwcForVirtualDisplays() con el tipo de devolución 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);

La función de utilidad (getBool en el ejemplo anterior) se comunica con el servicio configstore para obtener el identificador del proxy de la función de interfaz y, luego, recupera el valor invocando el identificador a través de HIDL/hwbinder.

Funciones de utilidad

<configstore/Utils.h> (configstore/1.0/include/configstore/Utils.h) proporciona funciones de utilidad para cada tipo de datos primitivo que se devuelve, incluido Optional[Bool|String|Int32|UInt32|Int64|UInt64], como se indica a continuación:

Tipo Función (se omiten los parámetros de plantilla)
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 es un valor predeterminado que se devuelve cuando la implementación de HAL no especifica un valor para el elemento de configuración. Cada función toma dos parámetros de plantilla:

  • I es el nombre de la clase de la interfaz.
  • Func es el puntero de la función miembro para obtener el elemento de configuración.

Dado que el valor de configuración es de solo lectura y no cambia, la función de utilidad almacena en caché de forma interna el valor de configuración. Las llamadas posteriores se atienden de manera más eficiente con el valor almacenado en caché en la misma unidad de vinculación.

Usa configstore-utils

La HAL de ConfigStore está diseñada para ser compatible con versiones posteriores en las actualizaciones de versiones secundarias, lo que significa que, cuando se revisa la HAL y parte del código del framework usa los elementos recién introducidos, aún se puede usar el servicio de ConfigStore con una versión secundaria anterior en /vendor.

Para garantizar la compatibilidad con versiones futuras, asegúrate de que tu implementación cumpla con los siguientes lineamientos:

  1. Los elementos nuevos usan el valor predeterminado cuando solo está disponible el servicio de la versión anterior. Ejemplo:
    service = V1_1::IConfig::getService(); // null if V1_0 is installed
    value = DEFAULT_VALUE;
      if(service) {
        value = service->v1_1API(DEFAULT_VALUE);
      }
    
  2. El cliente usa la primera interfaz que incluyó el elemento ConfigStore. Ejemplo:
    V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED
    
    V1_0::IConfig::getService()->v1_0API(); // OK
    
  3. Se puede recuperar el servicio de la versión nueva para la interfaz de la versión anterior. En el siguiente ejemplo, si la versión instalada es v1_1, se debe devolver el servicio v1_1 para getService():
    V1_0::IConfig::getService()->v1_0API();
    

Cuando se usan las funciones de acceso en la biblioteca configstore-utils para acceder al elemento ConfigStore, la implementación garantiza el punto 1 y los errores del compilador garantizan el punto 2. Por estos motivos, te recomendamos que uses configstore-utils siempre que sea posible.