Lockscreen visualiser; add option for animation smoothing

Ported from:
https://github.com/BlissRoms/platform_packages_apps_SmartNav/commit/6d67ac97bfaa330fc1be55d8f1946a226e2f3097

Change-Id: I71067ce0f34ad22e296a8a055f9ecf7304366d24
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 88a3467..5d4c3a7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10806,6 +10806,12 @@
         public static final String LOCKSCREEN_SOLID_UNITS_OPACITY = "lockscreen_solid_units_opacity";
 
         /**
+         * Visualizer smoothing
+         * @hide
+         */
+        public static final String LOCKSCREEN_VISUALIZER_SMOOTHING_ENABLED = "lockscreen_visualizer_smoothing_enabled";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FFTAverage.java b/packages/SystemUI/src/com/android/systemui/statusbar/FFTAverage.java
new file mode 100644
index 0000000..5555152
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FFTAverage.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import java.util.ArrayDeque;
+
+class FFTAverage {
+    private static final int WINDOW_LENGTH = 2;
+    private static final float WINDOW_LENGTH_F = WINDOW_LENGTH;
+    private ArrayDeque<Float> window = new ArrayDeque<>(WINDOW_LENGTH);
+    private float average;
+
+    int average(int dB) {
+        // Waiting until window is full
+        if (window.size() >= WINDOW_LENGTH) {
+            Float first = window.pollFirst();
+            if (first != null)
+                average -= first;
+        }
+        float newValue = dB / WINDOW_LENGTH_F;
+        average += newValue;
+        window.offerLast(newValue);
+
+        return Math.round(average);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java
index 73d6ddd..b065377 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java
@@ -53,6 +53,7 @@
     private Context mContext;
 
     private ValueAnimator[] mValueAnimators;
+    private FFTAverage[] mFFTAverage;
     private float[] mFFTPoints;
 
     private int mStatusBarState;
@@ -72,6 +73,7 @@
     private boolean mAutoColorEnabled;
     private boolean mLavaLampEnabled;
     private int mLavaLampSpeed;
+    private boolean mSmoothingEnabled;
     private boolean shouldAnimate;
     private int mUnits = 32;
     private float mDbFuzzFactor = 16f;
@@ -96,6 +98,9 @@
                 ifk = fft[i * 2 + 3];
                 magnitude = rfk * rfk + ifk * ifk;
                 dbValue = magnitude > 0 ? (int) (10 * Math.log10(magnitude)) : 0;
+                if (mSmoothingEnabled) {
+                    dbValue = mFFTAverage[i].average(dbValue);
+                }
 
                 mValueAnimators[i].setFloatValues(mFFTPoints[i * 4 + 1],
                         mFFTPoints[3] - (dbValue * mDbFuzzFactor));
@@ -309,6 +314,11 @@
                 Settings.Secure.LOCKSCREEN_LAVALAMP_ENABLED , 0, UserHandle.USER_CURRENT) == 1;
     }
 
+    private void setSmoothingAnimation() {
+        mSmoothingEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.LOCKSCREEN_VISUALIZER_SMOOTHING_ENABLED, 0, UserHandle.USER_CURRENT) ==1;
+    }
+
     private void setLavaLampSpeed() {
         mLavaLampSpeed = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.LOCKSCREEN_LAVALAMP_SPEED, 10000, UserHandle.USER_CURRENT);
@@ -333,8 +343,18 @@
                 Settings.Secure.LOCKSCREEN_SOLID_UNITS_COUNT, 32, UserHandle.USER_CURRENT);
         if (mUnits != oldUnits) {
             mFFTPoints = new float[mUnits * 4];
+            if (mSmoothingEnabled) {
+                setupFFTAverage();
+            }
             onSizeChanged(0, 0, 0, 0);
         }
+        if (mSmoothingEnabled) {
+            if (mFFTAverage == null) {
+                setupFFTAverage();
+            }
+        } else {
+            mFFTAverage = null;
+        }
     }
 
     private void setSolidFudgeFactor() {
@@ -415,6 +435,13 @@
         }
     }
 
+    public void setupFFTAverage() {
+        mFFTAverage = new FFTAverage[mUnits];
+        for (int i = 0; i < mUnits; i++) {
+            mFFTAverage[i] = new FFTAverage();
+        }
+    }
+
     @Override
     public void onGenerated(Palette palette) {
         int color = Color.TRANSPARENT;
@@ -543,6 +570,9 @@
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.LOCKSCREEN_SOLID_UNITS_OPACITY),
                     false, this, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.LOCKSCREEN_VISUALIZER_SMOOTHING_ENABLED),
+                    false, this, UserHandle.USER_ALL);
             update();
         }
 
@@ -577,6 +607,9 @@
             } else if (uri.equals(Settings.Secure.getUriFor(
                     Settings.Secure.LOCKSCREEN_SOLID_UNITS_OPACITY))) {
                 setSolidUnitsOpacity();
+            } else if (uri.equals(Settings.Secure.getUriFor(
+                    Settings.Secure.LOCKSCREEN_VISUALIZER_SMOOTHING_ENABLED))) {
+                setSmoothingAnimation();
             }
         }
 
@@ -589,6 +622,7 @@
             setSolidUnitsCount();
             setSolidFudgeFactor();
             setSolidUnitsOpacity();
+            setSmoothingAnimation();
             checkStateChanged();
             updateViewVisibility();
         }