Fix for audio distortion on speaker

Use the energy sum of all tracks in the volume_listener effect
instead of the max energy.

Bug: 33751694
Test: using piano application and youtube
Change-Id: I5a5a1ff18c72e737ca56102fc1b7e0368d646f6c
(cherry picked from commit 24b4e9cf7ca53f32ad216f84d382304abbe8a642)
(cherry picked from commit 587e9135837a56268ed74a7576a01f23efe7b015)
(cherry picked from commit 243503e50c551d961c96aa6f4197ee3c215b3c7e)
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 4a48a25..1402ae6 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 #include <stdlib.h>
 #include <dlfcn.h>
+#include <math.h>
 
 #include <cutils/list.h>
 #include <cutils/log.h>
@@ -229,7 +230,7 @@
 {
     // iterate through list and make decision to set new gain dep cal level for speaker device
     // 1. find all usecase active on speaker
-    // 2. find average of left and right for each usecase
+    // 2. find energy sum for each usecase
     // 3. find the highest of all the active usecase
     // 4. if new value is different than the current value then load new calibration
 
@@ -243,15 +244,22 @@
 
     ALOGV("%s ==> Start ...", __func__);
 
-    // select the highest volume on speaker device
+    float sum_energy = 0.0;
+    bool sum_energy_used = false;
+    float temp_vol = 0;
+    // compute energy sum for the active speaker device (pick loudest of both channels)
     list_for_each(node, &vol_effect_list) {
         context = node_to_item(node, struct vol_listener_context_s, effect_list_node);
         if ((context->state == VOL_LISTENER_STATE_ACTIVE) &&
-            (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) &&
-            (new_vol < (context->left_vol + context->right_vol) / 2)) {
-            new_vol = (context->left_vol + context->right_vol) / 2;
+            (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER)) {
+            sum_energy_used = true;
+            temp_vol = fmax(context->left_vol, context->right_vol);
+            sum_energy += temp_vol * temp_vol;
         }
     }
+    if (sum_energy_used) {
+        new_vol = fmin(sqrt(sum_energy), 1.0);
+    }
 
     if (new_vol != current_vol) {
         ALOGV("%s:: Change in decision :: current volume is %f new volume is %f",