* enum #hal_common_transport. An index is paired with the same index in the array
* major_versions and minor_versions. The caller takes ownership of the data so it
* is responsible for caller to free it using free()
+ * @param[out] default_transport Array of default transport by each version. An index is paired
+ * with the same index in the array major_versions and minor_versions. The caller
+ * takes ownership of the data so it is reponsible for caller to free it using free().
* @param[out] num_versions Number of returned major and minor versions
* @return @c 0 on success, otherwise a negative error value
*/
int hal_common_get_supported_interface_versions(enum hal_module module,
unsigned int **major_versions, unsigned int **minor_versions,
- uint32_t **transports, int *num_versions);
+ uint32_t **transports, enum hal_common_transport **default_transport, int *num_versions);
/**
* @brief Get the transport that compatible with the current hal backend
* @details Compare to the hal_common_get_supported_interface_versions(), this function
* is distinctive in that it returns single transport that is compatible with backend,
- * wherase the hal_common_get_supported_interface_versions() returns all the possible
+ * whereas the hal_common_get_supported_interface_versions() returns all the possible
* versions and transports specified on the manifest file.
+ *
+ * The steps how it internally works are:
+ * 1. Gets platform transports of matching version of backend library.
+ * For example on the below table, if installed backend of HAL_MODULE_CODEC is version of 2.0,
+ * then it chooses 'passthrough,ipc' as a transport supported by platform.
+ * 2. Gets backend transport of a module specified by backend manifest.
+ * For example, let the backend transport of module HAL_MODULE_CODEC is 'passthrough'.
+ * 3. Bitwise AND of platform transport and backend transport. In this case, 'passthrough,ipc' & 'passthrough'
+ * 4. The result of AND is what this function returns. If the reulst is 0, then it is error, which means
+ * the backend has specified not supported transport by the platform.
+ * 5. There is one excpetional case, that is, the backend manifest has specified nothing. In this case,
+ * result will be the 'default' of platform manifest. The 'default' here is the first specified transport
+ * of platform manifest.
+ * - "unspecified" -> default: passthrough
+ * - "passthrough" -> default: passthrough
+ * - "ipc" -> default: ipc
+ * - "passthrough,ipc" -> default: passthorugh
+ * - "ipc,passthrough" -> default: ipc
+ * ┌────────────────────────────────────────────────╥───────────────────────╥─────────────────────────────┐
+ * │ platform manifest ║ backend manifest ║ hal_common_get_transport() │
+ * │ (/etc/hal/hal-api-[module]-manifest.xml) ║ (/hal/etc/hal ║ │
+ * ├───────────────────┬─────────┬──────────────────╢ -backend-manifest ║ │
+ * │ module │ version │ transport ║ .xml) ║ │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_AUDIO │ 1.0 │ unspecified ║ unspecified ║ passthrough │
+ * │ │ │ (=passthrough) ║ => select 'default' ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ transport of ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ platform manifest ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ ipc │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_CODEC │ 1.0 │ unspecified ║ passthrough ║ passthrough │
+ * │ │ │ (=passthrough) ║ ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ error (-EMEDIUMTYPE) │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_CAMERA │ 1.0 │ unspecified ║ ipc ║ error (-EMEDIUMTYPE) │
+ * │ │ │ (=passthrough) ║ ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ error (-EMEDIUMTYPE) │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ ipc │
+ * └───────────────────┴─────────┴──────────────────╨───────────────────────╨─────────────────────────────┘
* @param[in] module HAL id among enum hal_module
* @param[out] transport The transport of version that matching to the hal backend installed
* @return @c 0 on success, otherwise a negative error value
* @retval -ELIBBAD Incompatible backend version with platform manifest
+ * @retval -EMEDIUMTYPE Incompatible backend transport with platform manifest
* @retval -ENOENT No backend library installed or no valid data symbol found
* @code
* // If a module manifest has specified transport like below, and the underlying
* // backend is version of 2.0, then it returns HAL_COMMON_TRANSPORT_PASSTHROUGH.
- * // <hal>
+ * // * platform manifest
+ * // <hal-module>
* // <name>HAL_MODULE_FOO</name>
* // <version transport="ipc">1.0</version>
- * // <version transport="passthrough">2.1</version>
- * // </hal>
+ * // <version transport="ipc,passthrough">2.1</version>
+ * // </hal-module>
+ * //
+ * // * backend manifest
+ * // <hal-module>
+ * // <name>HAL_MODULE_FOO</name>
+ * // <transport>passthrough</transport>
+ * // </hal-module>
* int ret = hal_common_get_transport(HAL_MODULE_FOO, &transport); // HAL_COMMON_TRANSPORT_PASSTHROUGH
*
* // If there are multiple transport throughout the platform-version, then
- * // the transport of the latest compatible platform-version will be returned. That is,
+ * // the transport of the latest compatible platform-version will be taken. That is,
* // if a module manifest has specified transport like below, and the underlying
- * // backend is version of 3.0, then it returns HAL_COMMON_TRANSPORT_IPC.
+ * // backend is version of 3.0, then it returns error.
+ * // * platform manifest
* // <manifest platform-version="9.0">
* // <hal>
* // <name>HAL_MODULE_BAR</name>
* // <version transport="ipc">3.1</version>
* // </hal>
* // </manifest>
- * int ret = hal_common_get_transport(HAL_MODULE_BAR, &transport); // HAL_COMMON_TRANSPORT_IPC
+ * //
+ * // * backend manifest
+ * // <hal-module>
+ * // <name>HAL_MODULE_FOO</name>
+ * // <transport>passthrough</transport>
+ * // </hal-module>
+ * int ret = hal_common_get_transport(HAL_MODULE_BAR, &transport); // error. This is because the
+ * // passthrough specified by backend is not supported
+ * // by the platform platform at version 3.1.
* @endcode
*/
int hal_common_get_transport(enum hal_module module, enum hal_common_transport *transport);
EXPORT
int hal_common_get_supported_interface_versions(enum hal_module module,
unsigned int **major_versions, unsigned int **minor_versions,
- uint32_t **transports, int *num_versions)
+ uint32_t **transports, enum hal_common_transport **default_transport, int *num_versions)
{
- if (!major_versions || !minor_versions || !transports || !num_versions)
+ if (!major_versions || !minor_versions || !transports || !default_transport || !num_versions)
return -EINVAL;
if (!HALCC_ENABLED) {
}
return hal_api_cc_get_supported_interface_versions(module,
- major_versions, minor_versions, transports, num_versions);
+ major_versions, minor_versions, transports, default_transport, num_versions);
}
EXPORT
typedef struct halcc_version {
int major;
int minor;
- enum hal_common_transport transport;
+ enum hal_common_transport transport; /* can specify multiple transport */
+ enum hal_common_transport default_transport; /* only one among transport */
} halcc_version;
typedef struct halcc_hal {
char *name;
halcc_version version_list[HALCC_NUM_VERSION_LIST_MAX];
int num_version_list;
+ enum hal_common_transport backend_transport;
} halcc_hal;
typedef struct halcc_manifest {
return 0;
}
-int halcc_hal_add_version(halcc_hal *hal, int major, int minor, enum hal_common_transport transport)
+int halcc_hal_add_version(halcc_hal *hal, int major, int minor, enum hal_common_transport transport,
+ enum hal_common_transport default_transport)
{
int i;
* one only when it has been specified, that is, only when it is other
* than HAL_COMMON_TRANSPORT_UNKNOWN.
*/
- if (transport != HAL_COMMON_TRANSPORT_UNKNOWN)
- hal->version_list[i].transport = transport;
+ hal->version_list[i].transport = transport;
+ hal->version_list[i].default_transport = default_transport;
break;
}
hal->version_list[hal->num_version_list].major = major;
hal->version_list[hal->num_version_list].minor = minor;
hal->version_list[hal->num_version_list].transport = transport;
+ hal->version_list[hal->num_version_list].default_transport = default_transport;
hal->num_version_list += 1;
return 0;
}
-int halcc_hal_get_version_list(halcc_hal *hal, int version_list[][3],
+int halcc_hal_set_backend_transport(halcc_hal *hal, enum hal_common_transport backend_transport)
+{
+ if (!hal)
+ return -EINVAL;
+
+ hal->backend_transport = backend_transport;
+
+ return 0;
+}
+
+int halcc_hal_get_backend_transport(halcc_hal *hal, enum hal_common_transport *backend_transport)
+{
+ if (!hal || !backend_transport)
+ return -EINVAL;
+
+ *backend_transport = hal->backend_transport;
+
+ return 0;
+}
+
+int halcc_hal_get_version_list(halcc_hal *hal, int version_list[][4],
int max_num_version_list, int *num_version_list)
{
if (!hal || !num_version_list)
version_list[i][0] = hal->version_list[i].major;
version_list[i][1] = hal->version_list[i].minor;
version_list[i][2] = hal->version_list[i].transport;
+ version_list[i][3] = hal->version_list[i].default_transport;
}
if (hal->num_version_list > max_num_version_list) {
int halcc_hal_get_transport_by_version(halcc_hal *hal, int major, int minor, enum hal_common_transport *transport)
{
int ret;
- int version_list[64][3] = { 0 , };
+ int version_list[64][4] = { 0 , };
int num_version_list = 0;
if (!hal || !transport)
return -ENOENT;
}
+
+int halcc_hal_get_default_transport_by_version(halcc_hal *hal, int major, int minor, enum hal_common_transport *transport)
+{
+ int ret;
+ int version_list[64][4] = { 0 , };
+ int num_version_list = 0;
+
+ if (!hal || !transport)
+ return -EINVAL;
+
+ ret = halcc_hal_get_version_list(hal, version_list,
+ sizeof(version_list) / sizeof(version_list[0]),
+ &num_version_list);
+ if (ret < 0)
+ return ret;
+
+ for (size_t i = 0; i < num_version_list; ++i) {
+ if (version_list[i][0] != major)
+ continue;
+
+ if (version_list[i][1] < minor)
+ continue;
+
+ *transport = version_list[i][3];
+ return 0;
+ }
+
+ return -ENOENT;
+}
void halcc_hal_free(halcc_hal *hal);
int halcc_hal_set_name(halcc_hal *hal, const char *hal_name);
int halcc_hal_get_name(halcc_hal *hal, const char **hal_name);
-int halcc_hal_add_version(halcc_hal *hal, int major, int minor, enum hal_common_transport transport);
+int halcc_hal_add_version(halcc_hal *hal, int major, int minor, enum hal_common_transport transport,
+ enum hal_common_transport default_transport);
+int halcc_hal_set_backend_transport(halcc_hal *hal, enum hal_common_transport backend_transport);
+int halcc_hal_get_backend_transport(halcc_hal *hal, enum hal_common_transport *backend_transport);
int halcc_hal_get_version_list(halcc_hal *hal,
- int version_list[][3], int max_num_version_list, int *num_version_list);
+ int version_list[][4], int max_num_version_list, int *num_version_list);
bool halcc_hal_is_compatible_with_version(halcc_hal *hal, int major, int minor);
int halcc_hal_get_transport_by_version(halcc_hal *hal, int major, int minor,
enum hal_common_transport *transport);
+int halcc_hal_get_default_transport_by_version(halcc_hal *hal, int major, int minor,
+ enum hal_common_transport *transport);
#ifdef __cplusplus
}
int major, minor;
int scanned;
enum hal_common_transport transports = HAL_COMMON_TRANSPORT_UNKNOWN;
+ enum hal_common_transport default_transport = HAL_COMMON_TRANSPORT_UNKNOWN;
const char *transport = NULL;
__xmlchar__ xmlChar *version = xmlNodeGetContent(child);
__xmlchar__ xmlChar *property = xmlGetProp(child, "transport");
}
if (strncmp(transport, "passthrough", strlen("passtrhough")) == 0) {
+ if (default_transport == HAL_COMMON_TRANSPORT_UNKNOWN)
+ default_transport = HAL_COMMON_TRANSPORT_PASSTHROUGH;
transports |= HAL_COMMON_TRANSPORT_PASSTHROUGH;
transport += strlen("passthrough");
} else if (strncmp(transport, "ipc", strlen("ipc")) == 0) {
+ if (default_transport == HAL_COMMON_TRANSPORT_UNKNOWN)
+ default_transport = HAL_COMMON_TRANSPORT_IPC;
transports |= HAL_COMMON_TRANSPORT_IPC;
transport += strlen("ipc");
} else {
_W("Invalid transport=%s", transport);
transports = HAL_COMMON_TRANSPORT_UNKNOWN;
+ default_transport = HAL_COMMON_TRANSPORT_UNKNOWN;
break;
}
}
- if (transports == HAL_COMMON_TRANSPORT_UNKNOWN)
- transports = HAL_COMMON_TRANSPORT_PASSTHROUGH; // set default
+ // set default transport
+ if (transports == HAL_COMMON_TRANSPORT_UNKNOWN) {
+ transports = HAL_COMMON_TRANSPORT_PASSTHROUGH;
+ default_transport = HAL_COMMON_TRANSPORT_PASSTHROUGH;
+ }
- ret = halcc_hal_add_version(hal, major, minor, transports);
+ ret = halcc_hal_add_version(hal, major, minor, transports, default_transport);
if (ret != 0)
_E("Failed to halcc_hal_add_version(), ret=%d\n", ret);
+ } else if (xmlStrEqual(child->name, "transport")) {
+ __xmlchar__ xmlChar *transport = xmlNodeGetContent(child);
+ enum hal_common_transport backend_transport = HAL_COMMON_TRANSPORT_UNKNOWN;
+
+ if (!transport)
+ continue;
+
+ if (xmlStrEqual(transport, "ipc")) {
+ backend_transport = HAL_COMMON_TRANSPORT_IPC;
+ } else if (xmlStrEqual(transport, "passthrough")) {
+ backend_transport = HAL_COMMON_TRANSPORT_PASSTHROUGH;
+ } else {
+ _E("Invalid transport=%s", transport);
+ continue;
+ }
+
+ ret = halcc_hal_set_backend_transport(hal, backend_transport);
+ if (ret != 0)
+ _W("Failed to halcc_hal_set_backend_transport(), ret=%d", ret);
}
}
// version
prop = xmlGetProp(node, "platform-version");
- if (!prop) {
- _E("Failed to xmlGetProp() \"platform-version\"\n");
- return -EINVAL;
- }
-
- ret = sscanf(prop, "%d.%d", &major, &minor);
- xmlFree(prop);
+ if (prop) {
+ ret = sscanf(prop, "%d.%d", &major, &minor);
+ xmlFree(prop);
- if (ret != 2) {
- _E("Failed to scan platform-version, ret=%d\n", ret);
- return -EINVAL;
- }
+ if (ret != 2) {
+ _E("Failed to scan platform-version, ret=%d\n", ret);
+ return -EINVAL;
+ }
- ret = halcc_manifest_set_platform_version(manifest, major, minor);
- if (ret != 0) {
- _E("Failed to halcc_manifest_set_version(), ret=%d\n", ret);
- return -EINVAL;
+ ret = halcc_manifest_set_platform_version(manifest, major, minor);
+ if (ret != 0) {
+ _E("Failed to halcc_manifest_set_version(), ret=%d\n", ret);
+ return -EINVAL;
+ }
}
for (xmlNode *child = node->children; child; child = child->next)
return -EINVAL;
}
- if (!xmlStrEqual(root->name, "hal-api")) {
+ if (!xmlStrEqual(root->name, "hal-api") && !xmlStrEqual(root->name, "hal-backend")) {
_E("Invalid root node, %s\n", root->name);
return -EINVAL;
}
#define HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH "/opt/etc/hal/.hal-backend-compatibility"
#define HAL_CC_DEFAULT_COMPATIBILITY_LOADED_PATH "/opt/etc/hal/.hal-backend-compatibility-loaded"
+#define HAL_CC_DEFAULT_BACKEND_MANIFEST_PATH "/hal/etc/hal-backend-manifest.xml"
#define COMPAT_INFO_MODULE_NAME_MAX 64
struct compatibility_info {
bool initialized;
char module_name[COMPAT_INFO_MODULE_NAME_MAX];
- int version_list[HALCC_NUM_VERSION_LIST_MAX][3];
+ int version_list[HALCC_NUM_VERSION_LIST_MAX][4];
int num_version_list;
+ enum hal_common_transport compatible_platform_transport;
+ enum hal_common_transport compatible_platform_default_transport;
+ enum hal_common_transport backend_transport;
enum hal_common_backend_compatibility compatibility;
- enum hal_common_transport compatible_transport;
};
static struct compatibility_info g_compatibility_info[HAL_MODULE_END];
static const char *compatibility_result_path = HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH;
static const char *compatibility_loaded_path = HAL_CC_DEFAULT_COMPATIBILITY_LOADED_PATH;
+static const char *backend_manifest_path = HAL_CC_DEFAULT_BACKEND_MANIFEST_PATH;
#ifdef HAL_API_COMMON_UNITTEST
void hal_api_cc_set_compatibility_result_path(const char *path)
{
compatibility_loaded_path = HAL_CC_DEFAULT_COMPATIBILITY_LOADED_PATH;
}
+
+void hal_api_cc_set_backend_manifest_path(const char *path)
+{
+ if (!path)
+ return;
+
+ backend_manifest_path = path;
+}
+
+void hal_api_cc_unset_backend_manifest_path(void)
+{
+ backend_manifest_path = HAL_CC_DEFAULT_BACKEND_MANIFEST_PATH;
+}
#endif /* HAL_API_COMMON_UNITTEST */
static int get_module_by_name(const char *name, enum hal_module *module)
if (ret < 0)
return;
+ info->backend_transport = g_compatibility_info[module].backend_transport;
+
/**
* hal_common_get_backend_version() will acquire lock, but this subroutine
* might have locked already if was triggered from hal_common_get_backend().
info->compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE;
- ret = halcc_hal_get_transport_by_version(hal, major, minor, &info->compatible_transport);
+ ret = halcc_hal_get_transport_by_version(hal, major, minor,
+ &info->compatible_platform_transport);
if (ret < 0)
_W("Failed to get transport, %d", ret);
+ ret = halcc_hal_get_default_transport_by_version(hal, major, minor,
+ &info->compatible_platform_default_transport);
+ if (ret < 0)
+ _W("Failed to get default transport, %d", ret);
+
out:
info->initialized = true;
}
return 0;
}
+static void load_backend_transport_all(void *data_hal, void *data)
+{
+ int ret;
+ halcc_hal *hal = data_hal;
+ const char *hal_name;
+ enum hal_common_transport backend_transport = HAL_COMMON_TRANSPORT_UNKNOWN;
+ enum hal_module module;
+
+ ret = halcc_hal_get_name(hal, &hal_name);
+ if (ret < 0)
+ return;
+
+ ret = get_module_by_name(hal_name, &module);
+ if(ret < 0)
+ return;
+
+ ret = halcc_hal_get_backend_transport(hal, &backend_transport);
+ if (ret < 0) {
+ _E("Failed to get transport");
+ return;
+ }
+
+ g_compatibility_info[module].backend_transport = backend_transport;
+}
+
+static int load_backend_transport(enum hal_module module, struct compatibility_info *info)
+{
+ int ret;
+ halcc_manifest *manifest = NULL;
+
+ assert(info);
+
+ if (g_compatibility_info[module].backend_transport != HAL_COMMON_TRANSPORT_UNKNOWN) {
+ info->backend_transport = g_compatibility_info[module].backend_transport;
+ return 0;
+ }
+
+ ret = halcc_manifest_new(&manifest);
+ if (ret < 0)
+ return ret;
+
+ ret = halcc_parse_path(backend_manifest_path, manifest);
+ if (ret < 0)
+ _W("Failed to parse backend manifest");
+
+ halcc_manifest_foreach_hal(manifest, load_backend_transport_all, NULL);
+
+ halcc_manifest_free(manifest);
+ manifest = NULL;
+
+ info->backend_transport = g_compatibility_info[module].backend_transport;
+
+ return 0;
+}
+
static int load_module_compatibility_info_fallback(enum hal_module module,
struct compatibility_info *info, bool skip_version_check)
{
_hal_api_conf_exit();
+ ret = load_backend_transport(module, info);
+ if (ret < 0)
+ return ret;
+
ret = halcc_manifest_new(&manifest);
if (ret < 0)
return ret;
unsigned int **major_versions,
unsigned int **minor_versions,
uint32_t **transports,
+ enum hal_common_transport **default_transport,
int *num_versions)
{
int ret;
unsigned int *ret_major_versions = NULL;
unsigned int *ret_minor_versions = NULL;
uint32_t *ret_transports = NULL;
+ enum hal_common_transport *ret_default_transport = NULL;
struct compatibility_info info = { 0 , };
if (!major_versions || !minor_versions || !num_versions)
return -ENOMEM;
}
+ ret_default_transport = calloc(ret_num_versions, sizeof(enum hal_common_transport));
+ if (!ret_default_transport) {
+ free(ret_major_versions);
+ free(ret_minor_versions);
+ free(ret_transports);
+ return -ENOMEM;
+ }
+
for (int i = 0; i < ret_num_versions; ++i) {
ret_major_versions[i] = info.version_list[i][0];
ret_minor_versions[i] = info.version_list[i][1];
ret_transports[i] = (uint32_t) info.version_list[i][2];
+ ret_default_transport[i] = info.version_list[i][3];
}
*major_versions = ret_major_versions;
*transports = ret_transports;
ret_transports = NULL;
+ *default_transport = ret_default_transport;
+ ret_default_transport = NULL;
+
*num_versions = ret_num_versions;
ret_num_versions = 0;
{
int ret;
struct compatibility_info info = { 0 , };
+ enum hal_common_transport platform_transport;
+ enum hal_common_transport backend_transport;
+ enum hal_common_transport available_transport;
if (!transport)
return -EINVAL;
else if (info.compatibility == HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE)
return -ELIBBAD;
- *transport = info.compatible_transport;
+ platform_transport = info.compatible_platform_transport;
+ backend_transport = info.backend_transport;
+
+ /**
+ * Special case: If no backend transport has specified
+ * than use default of platform manifest
+ */
+ if (backend_transport == HAL_COMMON_TRANSPORT_UNKNOWN) {
+ *transport = info.compatible_platform_default_transport;
+ return 0;
+ }
+
+ available_transport = (platform_transport & backend_transport);
+ if (!available_transport)
+ return -EMEDIUMTYPE;
+
+ if (available_transport & HAL_COMMON_TRANSPORT_PASSTHROUGH)
+ *transport = HAL_COMMON_TRANSPORT_PASSTHROUGH;
+ else if (available_transport & HAL_COMMON_TRANSPORT_IPC)
+ *transport = HAL_COMMON_TRANSPORT_IPC;
+ else
+ return -EINVAL;
return 0;
}
enum hal_common_backend_compatibility *backend_compatibility);
int hal_api_cc_get_supported_interface_versions(enum hal_module module,
unsigned int **major_versions, unsigned int **minor_versions,
- uint32_t **transports, int *num_versions);
+ uint32_t **transports, enum hal_common_transport **default_transport,
+ int *num_versions);
int hal_api_cc_get_transport(enum hal_module module, enum hal_common_transport *transport);
#ifdef HAL_API_COMMON_UNITTEST /* For test use only */
void hal_api_cc_set_compatibility_loaded_path(const char *path);
void hal_api_cc_unset_compatibility_loaded_path(void);
void hal_api_cc_reset_compatibility_info(void);
+void hal_api_cc_set_backend_manifest_path(const char *path);
+void hal_api_cc_unset_backend_manifest_path(void);
#endif /* HAL_API_COMMON_UNITTEST */
#ifdef __cplusplus
--- /dev/null
+<hal-backend>
+ <manifest>
+ <hal-module>
+ <name>HAL_MODULE_AUDIO</name>
+ <transport><!--empty or unspecified--></transport>
+ </hal-module>
+ <hal-module>
+ <name>HAL_MODULE_CODEC</name>
+ <transport>passthrough</transport>
+ </hal-module>
+ <hal-module>
+ <name>HAL_MODULE_CAMERA</name>
+ <transport>ipc</transport>
+ </hal-module>
+ </manifest>
+</hal-backend>
--- /dev/null
+<hal-api>
+ <manifest platform-version="10.0">
+ <hal-module>
+ <name>HAL_MODULE_AUDIO</name>
+ <version>1.0</version>
+ <version transport="passthrough,ipc">2.0</version>
+ <version transport="ipc,passthrough">3.0</version>
+ <version transport="passthrough">4.0</version>
+ <version transport="ipc">5.0</version>
+ </hal-module>
+ </manifest>
+</hal-api>
+
--- /dev/null
+<hal-api>
+ <manifest platform-version="10.0">
+ <hal-module>
+ <name>HAL_MODULE_CAMERA</name>
+ <version>1.0</version>
+ <version transport="passthrough,ipc">2.0</version>
+ <version transport="ipc,passthrough">3.0</version>
+ <version transport="passthrough">4.0</version>
+ <version transport="ipc">5.0</version>
+ </hal-module>
+ </manifest>
+</hal-api>
+
--- /dev/null
+<hal-api>
+ <manifest platform-version="10.0">
+ <hal-module>
+ <name>HAL_MODULE_CODEC</name>
+ <version>1.0</version>
+ <version transport="passthrough,ipc">2.0</version>
+ <version transport="ipc,passthrough">3.0</version>
+ <version transport="passthrough">4.0</version>
+ <version transport="ipc">5.0</version>
+ </hal-module>
+ </manifest>
+</hal-api>
+
#include <unistd.h>
#include <stdint.h>
+#include <fcntl.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
if (ret == -1)
FAIL();
+ ret = asprintf(&g_backend_config_path, "%s/%s", g_cwd,
+ "test-hal-compatibility-checker-manifest/backend/hal-backend-manifest.xml");
+ if (ret == -1)
+ FAIL();
+
set_module_info_manifest_all(g_manifest_directory);
ret = asprintf(&g_compatibility_result_path, "%s/.hal-backend-compatibility", g_cwd);
hal_api_cc_unset_compatibility_loaded_path();
free(g_compatibility_loaded_path);
free(g_compatibility_result_path);
+ free(g_backend_config_path);
free(g_manifest_directory);
free(g_cwd);
+ g_backend_config_path = NULL;
g_manifest_directory = NULL;
}
static halcc_manifest *g_manifest;
static char *g_manifest_directory;
+ static char *g_backend_config_path;
static char *g_compatibility_result_path;
static char *g_compatibility_loaded_path;
static char *g_cwd;
halcc_manifest* HalccObjectTest::g_manifest = NULL;
char* HalccObjectTest::g_manifest_directory = NULL;
+char* HalccObjectTest::g_backend_config_path = NULL;
char* HalccObjectTest::g_compatibility_result_path = NULL;
char* HalccObjectTest::g_compatibility_loaded_path = NULL;
char* HalccObjectTest::g_cwd = NULL;
+static void reset_result_file(const char *result_path, const char *loaded_path)
+{
+ int fd;
+ int ret;
+
+ fd = open(result_path, O_RDWR, 0);
+ if (fd > 0) {
+ ret = ftruncate(fd, 0);
+ EXPECT_EQ(ret, 0);
+ close(fd);
+ }
+
+ unlink(loaded_path);
+}
+
static bool have_exact_version_within_halcc_hal(halcc_hal *hal, const char *version)
{
- int version_list[HALCC_NUM_VERSION_LIST_MAX][3] = { 0 , };
+ int version_list[HALCC_NUM_VERSION_LIST_MAX][4] = { 0 , };
int num_version_list = 0;
int major, minor;
int ret;
unsigned int *major_versions;
unsigned int *minor_versions;
uint32_t *transports;
+ enum hal_common_transport *default_transport;
int num_versions;
};
ASSERT_EQ(ret, 0);
ret = hal_common_get_supported_interface_versions(HAL_MODULE_DEVICE_DISPLAY,
- &vi.major_versions, &vi.minor_versions, &vi.transports, &vi.num_versions);
+ &vi.major_versions, &vi.minor_versions, &vi.transports, &vi.default_transport,
+ &vi.num_versions);
ASSERT_EQ(ret, 0);
ASSERT_THAT(&vi, HasExactVersionArray("1.2"));
ASSERT_EQ(ret, 0);
ret = hal_common_get_supported_interface_versions(HAL_MODULE_TBM,
- &vi.major_versions, &vi.minor_versions, &vi.transports, &vi.num_versions);
+ &vi.major_versions, &vi.minor_versions, &vi.transports, &vi.default_transport,
+ &vi.num_versions);
ASSERT_EQ(ret, 0);
enum hal_common_transport transport;
hal_api_cc_set_compatibility_result_path(g_compatibility_result_path);
+ hal_api_cc_set_backend_manifest_path(g_backend_config_path);
+
+ /**
+ * ┌────────────────────────────────────────────────╥───────────────────────╥─────────────────────────────┐
+ * │ platform manifest ║ backend manifest ║ hal_common_get_transport() │
+ * │ (/etc/hal/hal-api-[module]-manifest.xml) ║ (/hal/etc/hal ║ │
+ * ├───────────────────┬─────────┬──────────────────╢ -backend-manifest ║ │
+ * │ module │ version │ transport ║ .xml) ║ │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_AUDIO │ 1.0 │ unspecified ║ unspecified ║ passthrough │
+ * │ │ │ (=passthrough) ║ => select 'default' ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ transport of ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ platform manifest ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ ipc │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_CODEC │ 1.0 │ unspecified ║ passthrough ║ passthrough │
+ * │ │ │ (=passthrough) ║ ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ passthrough │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ error (-EMEDIUMTYPE) │
+ * ├───────────────────┼─────────┼──────────────────╫───────────────────────╫─────────────────────────────┤
+ * │ HAL_MODULE_CAMERA │ 1.0 │ unspecified ║ ipc ║ error (-EMEDIUMTYPE) │
+ * │ │ │ (=passthrough) ║ ║ │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 2.0 │ passthrough,ipc ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 3.0 │ ipc,passthrough ║ ║ ipc │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 4.0 │ passthrough ║ ║ error (-EMEDIUMTYPE) │
+ * │ ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╢ ╟╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ * │ │ 5.0 │ ipc ║ ║ ipc │
+ * └───────────────────┴─────────┴──────────────────╨───────────────────────╨─────────────────────────────┘
+ *
+ */
+
+ /* backend version 1.0 */
+ mock_hal_backend_data_set_version(HAL_MODULE_AUDIO, 1, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CODEC, 1, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CAMERA, 1, 0);
+
+ ret = hal_common_get_transport(HAL_MODULE_AUDIO, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
+
+ ret = hal_common_get_transport(HAL_MODULE_CODEC, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
- mock_hal_backend_data_set_version(HAL_MODULE_TBM, 1, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CAMERA, &transport);
+ ASSERT_EQ(ret, -EMEDIUMTYPE);
- ret = hal_common_get_transport(HAL_MODULE_TBM, &transport);
+ /* backend version 2.0 */
+ reset_result_file(g_compatibility_result_path, g_compatibility_loaded_path);
+ hal_api_cc_reset_compatibility_info();
+ mock_hal_backend_data_set_version(HAL_MODULE_AUDIO, 2, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CODEC, 2, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CAMERA, 2, 0);
+
+ ret = hal_common_get_transport(HAL_MODULE_AUDIO, &transport);
ASSERT_EQ(ret, 0);
ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
- /* need to reset cache as the backend version will be changed */
- ret = truncate(g_compatibility_result_path, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CODEC, &transport);
ASSERT_EQ(ret, 0);
- hal_api_cc_reset_compatibility_info();
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
- mock_hal_backend_data_set_version(HAL_MODULE_TBM, 2, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CAMERA, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_IPC);
- ret = hal_common_get_transport(HAL_MODULE_TBM, &transport);
+ /* backend version 3.0 */
+ reset_result_file(g_compatibility_result_path, g_compatibility_loaded_path);
+ hal_api_cc_reset_compatibility_info();
+ mock_hal_backend_data_set_version(HAL_MODULE_AUDIO, 3, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CODEC, 3, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CAMERA, 3, 0);
+
+ ret = hal_common_get_transport(HAL_MODULE_AUDIO, &transport);
ASSERT_EQ(ret, 0);
ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_IPC);
- /* need to remove cache as the backend version will be changed */
- ret = truncate(g_compatibility_result_path, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CODEC, &transport);
ASSERT_EQ(ret, 0);
- hal_api_cc_reset_compatibility_info();
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
- mock_hal_backend_data_set_version(HAL_MODULE_TBM, 3, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CAMERA, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_IPC);
+
+ /* backend version 4.0 */
+ reset_result_file(g_compatibility_result_path, g_compatibility_loaded_path);
+ hal_api_cc_reset_compatibility_info();
+ mock_hal_backend_data_set_version(HAL_MODULE_AUDIO, 4, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CODEC, 4, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CAMERA, 4, 0);
- ret = hal_common_get_transport(HAL_MODULE_TBM, &transport);
+ ret = hal_common_get_transport(HAL_MODULE_AUDIO, &transport);
ASSERT_EQ(ret, 0);
ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
- /* need to remove cache as the backend version will be changed */
- ret = truncate(g_compatibility_result_path, 0);
+ ret = hal_common_get_transport(HAL_MODULE_CODEC, &transport);
ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_PASSTHROUGH);
+
+ ret = hal_common_get_transport(HAL_MODULE_CAMERA, &transport);
+ ASSERT_EQ(ret, -EMEDIUMTYPE);
+
+ /* backend version 5.0 */
+ reset_result_file(g_compatibility_result_path, g_compatibility_loaded_path);
hal_api_cc_reset_compatibility_info();
+ mock_hal_backend_data_set_version(HAL_MODULE_AUDIO, 5, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CODEC, 5, 0);
+ mock_hal_backend_data_set_version(HAL_MODULE_CAMERA, 5, 0);
- /* incompatible version should return error */
- mock_hal_backend_data_set_version(HAL_MODULE_TBM, 8, 0);
+ ret = hal_common_get_transport(HAL_MODULE_AUDIO, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_IPC);
- ret = hal_common_get_transport(HAL_MODULE_TBM, &transport);
- ASSERT_EQ(ret, -ELIBBAD);
+ ret = hal_common_get_transport(HAL_MODULE_CODEC, &transport);
+ ASSERT_EQ(ret, -EMEDIUMTYPE);
- unlink(g_compatibility_result_path);
+ ret = hal_common_get_transport(HAL_MODULE_CAMERA, &transport);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(transport, HAL_COMMON_TRANSPORT_IPC);
+
+ hal_api_cc_unset_backend_manifest_path();
hal_api_cc_unset_compatibility_result_path();
hal_api_cc_reset_compatibility_info();
+ reset_result_file(g_compatibility_result_path, g_compatibility_loaded_path);
}
unsigned int *major_versions = NULL;
unsigned int *minor_versions = NULL;
uint32_t *transports = NULL;
+ enum hal_common_transport *default_transport = NULL;
int num_versions = 0;
strncpy(str, "", BUFF_MAX - 1);
ret = hal_common_get_supported_interface_versions(module,
- &major_versions, &minor_versions, &transports, &num_versions);
+ &major_versions, &minor_versions, &transports, &default_transport,
+ &num_versions);
if (ret < 0) {
printf(" %-25s |", "");
} else {
transport = (transports[i] == HAL_COMMON_TRANSPORT_IPC ? "ipc"
: transports[i] == HAL_COMMON_TRANSPORT_PASSTHROUGH ? "passthrough"
- : transports[i] == (HAL_COMMON_TRANSPORT_IPC | HAL_COMMON_TRANSPORT_PASSTHROUGH) ? "ipc,passthrough"
+ : transports[i] == (HAL_COMMON_TRANSPORT_IPC | HAL_COMMON_TRANSPORT_PASSTHROUGH) ?
+ (default_transport[i] == HAL_COMMON_TRANSPORT_IPC ? "ipc,passthrough" : "passthrough,ipc")
: "Unknown");
pos += snprintf(pos, end - pos, "%u.%u(%s), ",
minor_versions = NULL;
free(transports);
transports = NULL;
+ free(default_transport);
+ default_transport = NULL;
/* Remove trailing ',' and terminate the string */
if (pos < end)