Check for duplicate uuids when parsing audio_effects.conf

uuids need to be unique, and things don't work properly when they're
not.
Also fix/enhance/extend the dumpEffectDescriptor() method, and
include a list of effects in audioflinger dumpsys.

Change-Id: I3dfbc5ed0f7272c7809e337f2929212ece047ee4
diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h
index b1ed7b0..64a3212 100644
--- a/include/media/EffectsFactoryApi.h
+++ b/include/media/EffectsFactoryApi.h
@@ -171,6 +171,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 int EffectIsNullUuid(const effect_uuid_t *pEffectUuid);
 
+int EffectDumpEffects(int fd);
+
 #if __cplusplus
 }  // extern "C"
 #endif
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 5bfe508..c310fe2 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -28,6 +28,7 @@
 
 static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
 static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+static list_elem_t *gSkippedEffects; // list of effects skipped because of duplicate uuid
 // list of effect_descriptor and list of sub effects : all currently loaded
 // It does not contain effects without sub effects.
 static list_sub_elem_t *gSubEffectList;
@@ -63,10 +64,10 @@
                lib_entry_t **lib,
                effect_descriptor_t **desc);
 // To search a subeffect in the gSubEffectList
-int findSubEffect(const effect_uuid_t *uuid,
+static int findSubEffect(const effect_uuid_t *uuid,
                lib_entry_t **lib,
                effect_descriptor_t **desc);
-static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent);
 static int stringToUuid(const char *str, effect_uuid_t *uuid);
 static int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen);
 
@@ -237,8 +238,8 @@
     }
 
 #if (LOG_NDEBUG == 0)
-    char str[256];
-    dumpEffectDescriptor(pDescriptor, str, 256);
+    char str[512];
+    dumpEffectDescriptor(pDescriptor, str, sizeof(str), 0 /* indent */);
     ALOGV("EffectQueryEffect() desc:%s", str);
 #endif
     pthread_mutex_unlock(&gLibLock);
@@ -611,8 +612,8 @@
         return -EINVAL;
     }
 #if (LOG_NDEBUG==0)
-    char s[256];
-    dumpEffectDescriptor(d, s, 256);
+    char s[512];
+    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
     ALOGV("addSubEffect() read descriptor %p:%s",d, s);
 #endif
     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
@@ -676,6 +677,13 @@
         ALOGW("loadEffect() invalid uuid %s", node->value);
         return -EINVAL;
     }
+    lib_entry_t *tmp;
+    bool skip = false;
+    if (findEffect(NULL, &uuid, &tmp, NULL) == 0) {
+        ALOGW("skipping duplicate uuid %s %s", node->value,
+                node->next ? "and its sub-effects" : "");
+        skip = true;
+    }
 
     d = malloc(sizeof(effect_descriptor_t));
     if (l->desc->get_descriptor(&uuid, d) != 0) {
@@ -686,8 +694,8 @@
         return -EINVAL;
     }
 #if (LOG_NDEBUG==0)
-    char s[256];
-    dumpEffectDescriptor(d, s, 256);
+    char s[512];
+    dumpEffectDescriptor(d, s, sizeof(s), 0 /* indent */);
     ALOGV("loadEffect() read descriptor %p:%s",d, s);
 #endif
     if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
@@ -698,8 +706,14 @@
     }
     e = malloc(sizeof(list_elem_t));
     e->object = d;
-    e->next = l->effects;
-    l->effects = e;
+    if (skip) {
+        e->next = gSkippedEffects;
+        gSkippedEffects = e;
+        return -EINVAL;
+    } else {
+        e->next = l->effects;
+        l->effects = e;
+    }
 
     // After the UUID node in the config_tree, if node->next is valid,
     // that would be sub effect node.
@@ -892,22 +906,30 @@
     return ret;
 }
 
-void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len, int indent) {
     char s[256];
+    char ss[256];
+    char idt[indent + 1];
 
-    snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
-    strncat(str, "- TYPE: ", len);
-    uuidToString(&desc->uuid, s, 256);
-    snprintf(str, len, "- UUID: %s\n", s);
-    uuidToString(&desc->type, s, 256);
-    snprintf(str, len, "- TYPE: %s\n", s);
-    sprintf(s, "- apiVersion: %08X\n- flags: %08X\n",
-            desc->apiVersion, desc->flags);
-    strncat(str, s, len);
-    sprintf(s, "- name: %s\n", desc->name);
-    strncat(str, s, len);
-    sprintf(s, "- implementor: %s\n", desc->implementor);
-    strncat(str, s, len);
+    memset(idt, ' ', indent);
+    idt[indent] = 0;
+
+    str[0] = 0;
+
+    snprintf(s, sizeof(s), "%s%s / %s\n", idt, desc->name, desc->implementor);
+    strlcat(str, s, len);
+
+    uuidToString(&desc->uuid, s, sizeof(s));
+    snprintf(ss, sizeof(ss), "%s  UUID: %s\n", idt, s);
+    strlcat(str, ss, len);
+
+    uuidToString(&desc->type, s, sizeof(s));
+    snprintf(ss, sizeof(ss), "%s  TYPE: %s\n", idt, s);
+    strlcat(str, ss, len);
+
+    sprintf(s, "%s  apiVersion: %08X\n%s  flags: %08X\n", idt,
+            desc->apiVersion, idt, desc->flags);
+    strlcat(str, s, len);
 }
 
 int stringToUuid(const char *str, effect_uuid_t *uuid)
@@ -950,3 +972,40 @@
     return 0;
 }
 
+int EffectDumpEffects(int fd) {
+    char s[512];
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    int found = 0;
+    int ret = 0;
+
+    while (e) {
+        l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        dprintf(fd, "Library %s\n", l->name);
+        if (!efx) {
+            dprintf(fd, "  (no effects)\n");
+        }
+        while (efx) {
+            d = (effect_descriptor_t *)efx->object;
+            dumpEffectDescriptor(d, s, sizeof(s), 2);
+            dprintf(fd, "%s", s);
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+
+    e = gSkippedEffects;
+    if (e) {
+        dprintf(fd, "Skipped effects\n");
+        while(e) {
+            d = (effect_descriptor_t *)e->object;
+            dumpEffectDescriptor(d, s, sizeof(s), 2 /* indent */);
+            dprintf(fd, "%s", s);
+            e = e->next;
+        }
+    }
+    return ret;
+}
+
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e48af20..78aeb4b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -401,6 +401,9 @@
             String8 result(kClientLockedString);
             write(fd, result.string(), result.size());
         }
+
+        EffectDumpEffects(fd);
+
         dumpClients(fd, args);
         if (clientLocked) {
             mClientLock.unlock();