audio_route: fix crash with unsupported control types

Check if control type is supported before accessing xxx_value
fields in mixer_state structure.

Also remove unused parameter warning.

Bug: 12871072.
Change-Id: I64c7d5e16728e3502f1fcd0a40658b72ec7acbe7
diff --git a/audio_route/audio_route.c b/audio_route/audio_route.c
index 4a44907..d8e4151 100644
--- a/audio_route/audio_route.c
+++ b/audio_route/audio_route.c
@@ -77,6 +77,18 @@
 
 /* path functions */
 
+bool is_supported_ctl_type(enum mixer_ctl_type type)
+{
+    switch (type) {
+    case MIXER_CTL_TYPE_BOOL:
+    case MIXER_CTL_TYPE_INT:
+    case MIXER_CTL_TYPE_ENUM:
+        return true;
+    default:
+        return false;
+    }
+}
+
 static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar,
                                              unsigned int ctl_index)
 {
@@ -289,9 +301,15 @@
 {
     unsigned int i;
     unsigned int ctl_index;
+    struct mixer_ctl *ctl;
+    enum mixer_ctl_type type;
 
     for (i = 0; i < path->length; i++) {
         ctl_index = path->setting[i].ctl_index;
+        ctl = index_to_ctl(ar, ctl_index);
+        type = mixer_ctl_get_type(ctl);
+        if (!is_supported_ctl_type(type))
+            continue;
 
         /* apply the new value(s) */
         memcpy(ar->mixer_state[ctl_index].new_value, path->setting[i].value,
@@ -306,9 +324,15 @@
     unsigned int i;
     unsigned int j;
     unsigned int ctl_index;
+    struct mixer_ctl *ctl;
+    enum mixer_ctl_type type;
 
     for (i = 0; i < path->length; i++) {
         ctl_index = path->setting[i].ctl_index;
+        ctl = index_to_ctl(ar, ctl_index);
+        type = mixer_ctl_get_type(ctl);
+        if (!is_supported_ctl_type(type))
+            continue;
 
         /* reset the value(s) */
         memcpy(ar->mixer_state[ctl_index].new_value,
@@ -347,6 +371,7 @@
     int value;
     unsigned int id;
     struct mixer_value mixer_value;
+    enum mixer_ctl_type type;
 
     /* Get name, id and value attributes (these may be empty) */
     for (i = 0; attr[i]; i += 2) {
@@ -404,19 +429,22 @@
         if (state->level == 1) {
             /* top level ctl (initial setting) */
 
-            /* apply the new value */
-            if (attr_id) {
-                /* set only one value */
-                id = atoi((char *)attr_id);
-                if (id < ar->mixer_state[ctl_index].num_values)
-                    ar->mixer_state[ctl_index].new_value[id] = value;
-                else
-                    ALOGE("value id out of range for mixer ctl '%s'",
-                          mixer_ctl_get_name(ctl));
-            } else {
-                /* set all values the same */
-                for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
-                    ar->mixer_state[ctl_index].new_value[i] = value;
+            type = mixer_ctl_get_type(ctl);
+            if (is_supported_ctl_type(type)) {
+                /* apply the new value */
+                if (attr_id) {
+                    /* set only one value */
+                    id = atoi((char *)attr_id);
+                    if (id < ar->mixer_state[ctl_index].num_values)
+                        ar->mixer_state[ctl_index].new_value[id] = value;
+                    else
+                        ALOGE("value id out of range for mixer ctl '%s'",
+                              mixer_ctl_get_name(ctl));
+                } else {
+                    /* set all values the same */
+                    for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
+                        ar->mixer_state[ctl_index].new_value[i] = value;
+                }
             }
         } else {
             /* nested ctl (within a path) */
@@ -437,6 +465,7 @@
 static void end_tag(void *data, const XML_Char *tag_name)
 {
     struct config_parse_state *state = data;
+    (void)tag_name;
 
     state->level--;
 }
@@ -463,8 +492,8 @@
 
         /* Skip unsupported types that are not supported yet in XML */
         type = mixer_ctl_get_type(ctl);
-        if ((type != MIXER_CTL_TYPE_BOOL) && (type != MIXER_CTL_TYPE_INT) &&
-            (type != MIXER_CTL_TYPE_ENUM))
+
+        if (!is_supported_ctl_type(type))
             continue;
 
         ar->mixer_state[i].old_value = malloc(num_values * sizeof(int));
@@ -485,8 +514,13 @@
 static void free_mixer_state(struct audio_route *ar)
 {
     unsigned int i;
+    enum mixer_ctl_type type;
 
     for (i = 0; i < ar->num_mixer_ctls; i++) {
+        type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
+        if (!is_supported_ctl_type(type))
+            continue;
+
         free(ar->mixer_state[i].old_value);
         free(ar->mixer_state[i].new_value);
         free(ar->mixer_state[i].reset_value);
@@ -511,8 +545,7 @@
 
         /* Skip unsupported types */
         type = mixer_ctl_get_type(ctl);
-        if ((type != MIXER_CTL_TYPE_BOOL) && (type != MIXER_CTL_TYPE_INT) &&
-            (type != MIXER_CTL_TYPE_ENUM))
+        if (!is_supported_ctl_type(type))
             continue;
 
         /* if the value has changed, update the mixer */
@@ -540,8 +573,13 @@
 static void save_mixer_state(struct audio_route *ar)
 {
     unsigned int i;
+    enum mixer_ctl_type type;
 
     for (i = 0; i < ar->num_mixer_ctls; i++) {
+        type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
+        if (!is_supported_ctl_type(type))
+            continue;
+
         memcpy(ar->mixer_state[i].reset_value, ar->mixer_state[i].new_value,
                ar->mixer_state[i].num_values * sizeof(int));
     }
@@ -551,9 +589,14 @@
 void audio_route_reset(struct audio_route *ar)
 {
     unsigned int i;
+    enum mixer_ctl_type type;
 
     /* load all of the saved values */
     for (i = 0; i < ar->num_mixer_ctls; i++) {
+        type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
+        if (!is_supported_ctl_type(type))
+            continue;
+
         memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].reset_value,
                ar->mixer_state[i].num_values * sizeof(int));
     }