You can refactor conditionally compiled code to read values dynamically from the HAL interface. For example:
#ifdef TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS // some code fragment #endif
Framework code can then call an appropriate utility function defined in <configstore/Utils.h>
depending on its type.
ConfigStore example
This example shows reading TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
, defined in ConfigStore HAL as forceHwcForVirtualDisplays()
with return type 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);
The utility function (getBool
in the example above) contacts the configstore
service to get the handle for the proxy of the interface function, then retrieves the value by invoking the handle via HIDL/hwbinder.
Utility functions
<configstore/Utils.h>
(configstore/1.0/include/configstore/Utils.h
) provides utility functions for each primitive return type, including Optional[Bool|String|Int32|UInt32|Int64|UInt64]
, as listed below:
Type | Function (template parameters omitted) |
---|---|
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
is a default value returned when the HAL implementation doesn't specify a value for the configuration item. Each function takes two template parameters:
I
is the interface class name.Func
is the member function pointer for getting the configuration item.
Because the configuration value is read-only and doesn't change, the utility function internally caches the configuration value. Subsequent calls are serviced more efficiently using the cached value in the same linking unit.
Use configstore-utils
The ConfigStore HAL is designed to be forward compatible for minor version upgrades, meaning that when the HAL is revised and some framework code uses the newly introduced items, the ConfigStore service with an older minor version in /vendor
can still be used.
For forward compatibility, ensure that your implementation adheres to the following guidelines:
- New items use the default value when only the old version's service is available. Example:
service = V1_1::IConfig::getService(); // null if V1_0 is installed value = DEFAULT_VALUE; if(service) { value = service->v1_1API(DEFAULT_VALUE); }
- The client uses the first interface that included the ConfigStore item. Example:
V1_1::IConfig::getService()->v1_0API(); // NOT ALLOWED V1_0::IConfig::getService()->v1_0API(); // OK
- The new version's service can be retrieved for old version's interface. In the following example, if the installed version is v1_1, the v1_1 service must be returned for
getService()
:V1_0::IConfig::getService()->v1_0API();
When the access functions in the configstore-utils
library are used for accessing the ConfigStore item, #1 is guaranteed by the implementation and #2 is guaranteed by compiler errors. For these reasons, we strongly recommend using configstore-utils
wherever possible.