return g_hash_table_lookup(hal_table, &key);
}
-static halcc_hal* hashtable_hal_steal(GHashTable *hal_table, const char *name, int major, int minor)
+static halcc_hal* hashtable_hal_steal(GHashTable *hal_table,
+ const char *name, int major, int minor, halcc_hash_compare_type_e type)
{
hash_hal_key key;
halcc_hal *hal = NULL;
return NULL;
}
- key = HASH_HAL_KEY(name, major, minor, HALCC_HASH_COMPARE_TYPE_EXACT_MINOR_VERSION);
+ key = HASH_HAL_KEY(name, major, minor, type);
if (!g_hash_table_steal_extended(hal_table, &key, NULL, (gpointer*) &hal))
return NULL;
raw->name, raw->version.major, raw->version.minor, hal);
}
-int halcc_manifest_steal_hal(halcc_manifest *manifest,
- const char *hal_name, int major, int minor, halcc_hal **hal)
+static int manifest_steal_hal(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal,
+ halcc_hash_compare_type_e type)
{
halcc_hal *h = NULL;
- if (!manifest || !hal_name) {
+ if (!manifest || !hal_name || !hal) {
printf("Invalid parameter\n");
return -EINVAL;
}
- h = hashtable_hal_steal(manifest->hals, hal_name, major, minor);
+ h = hashtable_hal_steal(manifest->hals, hal_name, major, minor, type);
if (!h) {
- printf("Failed to find hal=%s@%d.%d\n", hal_name, major, minor);
+ printf("Failed to find hal=%s@%d.%d, type=%d\n", hal_name, major, minor, type);
return -ENOTSUP;
}
- if (hal)
- *hal = g_steal_pointer(&h);
+ *hal = g_steal_pointer(&h);
return 0;
+
+}
+
+int halcc_manifest_steal_hal(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal)
+{
+ return manifest_steal_hal(manifest,
+ hal_name, major, minor, hal, HALCC_HASH_COMPARE_TYPE_EXACT_MINOR_VERSION);
+}
+
+int halcc_manifest_steal_hal_backward_compatible(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal)
+{
+ return manifest_steal_hal(manifest,
+ hal_name, major, minor, hal, HALCC_HASH_COMPARE_TYPE_BACKWARD_MINOR_VERSION);
+}
+
+int halcc_manifest_steal_hal_forward_compatible(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal)
+{
+ return manifest_steal_hal(manifest,
+ hal_name, major, minor, hal, HALCC_HASH_COMPARE_TYPE_FORWARD_MINOR_VERSION);
}
void halcc_manifest_remove_hal(halcc_manifest *manifest,
halcc_hal *raw, halcc_hal **hal);
int halcc_manifest_steal_hal(halcc_manifest *manifest,
const char *hal_name, int major, int minor, halcc_hal **hal);
+int halcc_manifest_steal_hal_backward_compatible(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal);
+int halcc_manifest_steal_hal_forward_compatible(halcc_manifest *manifest,
+ const char *hal_name, int major, int minor, halcc_hal **hal);
void halcc_manifest_remove_hal(halcc_manifest *manifest,
const char *hal_name, int major, int minor);
void halcc_manifest_foreach_hal(halcc_manifest *manifest,
for (xmlNode *child = node->children; child; child = child->next) {
halcc_hal *h;
+ const char *hal_name;
+ int hal_major;
+ int hal_minor;
+ halcc_hal *hal_backward_compatible = NULL;
if (!xmlStrEqual(child->name, "hal"))
continue;
continue;
}
+ halcc_hal_get_name(h, &hal_name);
+ halcc_hal_get_version(h, &hal_major, &hal_minor, NULL);
+
+ if (halcc_manifest_find_hal(manifest, hal_name, hal_major, hal_minor, NULL) == 0) {
+ halcc_hal_free(h);
+ h = NULL;
+ continue;
+ }
+
+ if (halcc_manifest_find_hal_forward_compatible(manifest,
+ hal_name, hal_major, hal_minor, NULL) == 0) {
+ halcc_hal_free(h);
+ h = NULL;
+ continue;
+ }
+
+ /**
+ * Backward compatible hal can be covered by the current hal.
+ * Therefore, remove it from the manifest.
+ */
+ if (halcc_manifest_steal_hal_backward_compatible(manifest,
+ hal_name, hal_major, hal_minor, &hal_backward_compatible) == 0) {
+ halcc_hal_free(hal_backward_compatible);
+ hal_backward_compatible = NULL;
+ }
+
ret = halcc_manifest_add_hal(manifest, h);
if (ret != 0) {
printf("Failed to halcc_manifest_add_hal(), ret=%d\n", ret);
" </interface>"
" </hal>"
" </manifest>"
+" <manifest version=\"1.0\" type=\"platform\">"
+" <hal>"
+" <name>HAL_MODULE_BAR</name>"
+" <version>2.0</version>"
+" </hal>"
+" </manifest>"
+" <manifest version=\"1.0\" type=\"platform\">"
+" <hal>"
+" <name>HAL_MODULE_BAR</name>"
+" <version>2.2</version>"
+" </hal>"
+" </manifest>"
"</root>";
class HalccObjectTest : public ::testing::Test
ASSERT_EQ(major, 2);
ASSERT_EQ(minor, 34);
}
+
+TEST_F(HalccObjectTest, manifest_find_multiple_hal_success)
+{
+ halcc_hal *hal = NULL;
+ const char *hal_name;
+ int major, minor;
+ int ret;
+
+ ret = halcc_manifest_find_hal(g_manifest, "HAL_MODULE_BAR", 2, 0, &hal);
+ ASSERT_NE(ret, 0); // The 2.0 has been replaced with 2.2
+
+ ret = halcc_manifest_find_hal_forward_compatible(g_manifest, "HAL_MODULE_BAR", 2, 0, &hal);
+ ASSERT_EQ(ret, 0); // 2.0 is covered by 2.2
+
+ ret = halcc_hal_get_name(hal, &hal_name);
+ ASSERT_EQ(ret, 0);
+ ASSERT_STREQ(hal_name, "HAL_MODULE_BAR");
+
+ ret = halcc_hal_get_version(hal, &major, &minor, NULL);
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(major, 2);
+ ASSERT_EQ(minor, 2);
+}