Auto grid lines, lower minimum, disable estimates.

Show automatic grid lines with power-of-two spacing, avoiding ANR
when trying to render thousands of gridlines.  Lower minimum chart
height to 50MB to give better view of linear data.  Also disable
estimates rendering.

Bug: 5500204, 6005240
Change-Id: Iacfed11b32c0095c9c2d08bee6a1b5e29637de98
diff --git a/src/com/android/settings/widget/ChartDataUsageView.java b/src/com/android/settings/widget/ChartDataUsageView.java
index 4b4f37d..85ee76a 100644
--- a/src/com/android/settings/widget/ChartDataUsageView.java
+++ b/src/com/android/settings/widget/ChartDataUsageView.java
@@ -237,7 +237,7 @@
         final long maxSweep = Math.max(mSweepWarning.getValue(), mSweepLimit.getValue());
         final long maxSeries = Math.max(mSeries.getMaxVisible(), mDetailSeries.getMaxVisible());
         final long maxVisible = Math.max(maxSeries, maxSweep) * 12 / 10;
-        final long maxDefault = Math.max(maxVisible, 2 * GB_IN_BYTES);
+        final long maxDefault = Math.max(maxVisible, 50 * MB_IN_BYTES);
         newMax = Math.max(maxDefault, newMax);
 
         // only invalidate when vertMax actually changed
@@ -636,15 +636,9 @@
         /** {@inheritDoc} */
         public float[] getTickPoints() {
             final long range = mMax - mMin;
-            final long tickJump;
-            if (range < 6 * GB_IN_BYTES) {
-                tickJump = 256 * MB_IN_BYTES;
-            } else if (range < 12 * GB_IN_BYTES) {
-                tickJump = 512 * MB_IN_BYTES;
-            } else {
-                tickJump = 1 * GB_IN_BYTES;
-            }
 
+            // target about 16 ticks on screen, rounded to nearest power of 2
+            final long tickJump = roundUpToPowerOfTwo(range / 16);
             final int tickCount = (int) (range / tickJump);
             final float[] tickPoints = new float[tickCount];
             long value = mMin;
@@ -681,4 +675,21 @@
         return new int[] { start, end };
     }
 
+    private static long roundUpToPowerOfTwo(long i) {
+        // NOTE: borrowed from Hashtable.roundUpToPowerOfTwo()
+
+        i--; // If input is a power of two, shift its high-order bit right
+
+        // "Smear" the high-order bit all the way to the right
+        i |= i >>>  1;
+        i |= i >>>  2;
+        i |= i >>>  4;
+        i |= i >>>  8;
+        i |= i >>> 16;
+        i |= i >>> 32;
+
+        i++;
+
+        return i > 0 ? i : Long.MAX_VALUE;
+    }
 }
diff --git a/src/com/android/settings/widget/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java
index 7a4617b..5a37bfc 100644
--- a/src/com/android/settings/widget/ChartNetworkSeriesView.java
+++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java
@@ -44,6 +44,8 @@
     private static final String TAG = "ChartNetworkSeriesView";
     private static final boolean LOGD = false;
 
+    private static final boolean ESTIMATE_ENABLED = false;
+
     private ChartAxis mHoriz;
     private ChartAxis mVert;
 
@@ -252,37 +254,39 @@
 
         mMax = totalData;
 
-        // build estimated data
-        mPathEstimate.moveTo(lastX, lastY);
+        if (ESTIMATE_ENABLED) {
+            // build estimated data
+            mPathEstimate.moveTo(lastX, lastY);
 
-        final long now = System.currentTimeMillis();
-        final long bucketDuration = mStats.getBucketDuration();
+            final long now = System.currentTimeMillis();
+            final long bucketDuration = mStats.getBucketDuration();
 
-        // long window is average over two weeks
-        entry = mStats.getValues(lastTime - WEEK_IN_MILLIS * 2, lastTime, now, entry);
-        final long longWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
-                / entry.bucketDuration;
-
-        long futureTime = 0;
-        while (lastX < width) {
-            futureTime += bucketDuration;
-
-            // short window is day average last week
-            final long lastWeekTime = lastTime - WEEK_IN_MILLIS + (futureTime % WEEK_IN_MILLIS);
-            entry = mStats.getValues(lastWeekTime - DAY_IN_MILLIS, lastWeekTime, now, entry);
-            final long shortWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
+            // long window is average over two weeks
+            entry = mStats.getValues(lastTime - WEEK_IN_MILLIS * 2, lastTime, now, entry);
+            final long longWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
                     / entry.bucketDuration;
 
-            totalData += (longWindow * 7 + shortWindow * 3) / 10;
+            long futureTime = 0;
+            while (lastX < width) {
+                futureTime += bucketDuration;
 
-            lastX = mHoriz.convertToPoint(lastTime + futureTime);
-            lastY = mVert.convertToPoint(totalData);
+                // short window is day average last week
+                final long lastWeekTime = lastTime - WEEK_IN_MILLIS + (futureTime % WEEK_IN_MILLIS);
+                entry = mStats.getValues(lastWeekTime - DAY_IN_MILLIS, lastWeekTime, now, entry);
+                final long shortWindow = (entry.rxBytes + entry.txBytes) * bucketDuration
+                        / entry.bucketDuration;
 
-            mPathEstimate.lineTo(lastX, lastY);
+                totalData += (longWindow * 7 + shortWindow * 3) / 10;
+
+                lastX = mHoriz.convertToPoint(lastTime + futureTime);
+                lastY = mVert.convertToPoint(totalData);
+
+                mPathEstimate.lineTo(lastX, lastY);
+            }
+
+            mMaxEstimate = totalData;
         }
 
-        mMaxEstimate = totalData;
-
         invalidate();
     }
 
@@ -291,7 +295,7 @@
     }
 
     public void setEstimateVisible(boolean estimateVisible) {
-        mEstimateVisible = estimateVisible;
+        mEstimateVisible = ESTIMATE_ENABLED ? estimateVisible : false;
         invalidate();
     }