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.