Data usage performance, bugfixes.

Optimize launch times by removing unneeded extra work, including
reloading data and tightening chart invalidation.  Fix invalidation
storm when sweeps overlap.  Move chart history into loader instead of
blocking main thread.

Disable "Split 4G" mode until telephony support is ready, and combine
any existing split policies.

Async loading of application details.  Remove alpha transitions to
speed up on some hardware.  Hide menus in detail mode.  Delay kicking
off force-poll.  Fix inset padding on large devices.

Bug: 5284321, 5273918, 5263056
Change-Id: I746d79c05e2a6ea97bbdbdc5d807e208328d1373
This commit is contained in:
Jeff Sharkey
2011-09-11 17:29:49 -07:00
parent a3fb4572dd
commit b98c55bd09
16 changed files with 663 additions and 262 deletions

View File

@@ -26,9 +26,9 @@ import android.text.SpannableStringBuilder;
public interface ChartAxis {
/** Set range of raw values this axis should cover. */
public void setBounds(long min, long max);
public boolean setBounds(long min, long max);
/** Set range of screen points this axis should cover. */
public void setSize(float size);
public boolean setSize(float size);
/** Convert raw value into screen point. */
public float convertToPoint(long value);

View File

@@ -30,6 +30,7 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.android.internal.util.Objects;
import com.android.settings.R;
import com.android.settings.widget.ChartSweepView.OnSweepListener;
@@ -214,7 +215,8 @@ public class ChartDataUsageView extends ChartView {
// always show known data and policy lines
final long maxSweep = Math.max(mSweepWarning.getValue(), mSweepLimit.getValue());
final long maxVisible = Math.max(mSeries.getMaxVisible(), maxSweep) * 12 / 10;
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);
newMax = Math.max(maxDefault, newMax);
@@ -222,12 +224,14 @@ public class ChartDataUsageView extends ChartView {
if (newMax != mVertMax) {
mVertMax = newMax;
mVert.setBounds(0L, newMax);
final boolean changed = mVert.setBounds(0L, newMax);
mSweepWarning.setValidRange(0L, newMax);
mSweepLimit.setValidRange(0L, newMax);
mSeries.generatePath();
mDetailSeries.generatePath();
if (changed) {
mSeries.invalidatePath();
mDetailSeries.invalidatePath();
}
mGrid.invalidate();
@@ -263,6 +267,10 @@ public class ChartDataUsageView extends ChartView {
interestLine = mSweepLimit.getValue();
}
if (interestLine < 0) {
interestLine = Long.MAX_VALUE;
}
final boolean estimateVisible = (maxEstimate >= interestLine * 7 / 10);
mSeries.setEstimateVisible(estimateVisible);
}
@@ -354,8 +362,10 @@ public class ChartDataUsageView extends ChartView {
* last "week" of available data, without triggering listener events.
*/
public void setVisibleRange(long visibleStart, long visibleEnd) {
mHoriz.setBounds(visibleStart, visibleEnd);
final boolean changed = mHoriz.setBounds(visibleStart, visibleEnd);
mGrid.setBounds(visibleStart, visibleEnd);
mSeries.setBounds(visibleStart, visibleEnd);
mDetailSeries.setBounds(visibleStart, visibleEnd);
final long validStart = Math.max(visibleStart, getStatsStart());
final long validEnd = Math.min(visibleEnd, getStatsEnd());
@@ -378,7 +388,10 @@ public class ChartDataUsageView extends ChartView {
mSweepRight.setValue(sweepMax);
requestLayout();
mSeries.generatePath();
if (changed) {
mSeries.invalidatePath();
mDetailSeries.invalidatePath();
}
updateVertAxisBounds(null);
updateEstimateVisible();
@@ -410,15 +423,30 @@ public class ChartDataUsageView extends ChartView {
setBounds(currentTime - DateUtils.DAY_IN_MILLIS * 30, currentTime);
}
/** {@inheritDoc} */
public void setBounds(long min, long max) {
mMin = min;
mMax = max;
@Override
public int hashCode() {
return Objects.hashCode(mMin, mMax, mSize);
}
/** {@inheritDoc} */
public void setSize(float size) {
this.mSize = size;
public boolean setBounds(long min, long max) {
if (mMin != min || mMax != max) {
mMin = min;
mMax = max;
return true;
} else {
return false;
}
}
/** {@inheritDoc} */
public boolean setSize(float size) {
if (mSize != size) {
mSize = size;
return true;
} else {
return false;
}
}
/** {@inheritDoc} */
@@ -461,15 +489,30 @@ public class ChartDataUsageView extends ChartView {
private long mMax;
private float mSize;
/** {@inheritDoc} */
public void setBounds(long min, long max) {
mMin = min;
mMax = max;
@Override
public int hashCode() {
return Objects.hashCode(mMin, mMax, mSize);
}
/** {@inheritDoc} */
public void setSize(float size) {
mSize = size;
public boolean setBounds(long min, long max) {
if (mMin != min || mMax != max) {
mMin = min;
mMax = max;
return true;
} else {
return false;
}
}
/** {@inheritDoc} */
public boolean setSize(float size) {
if (mSize != size) {
mSize = size;
return true;
} else {
return false;
}
}
/** {@inheritDoc} */

View File

@@ -58,12 +58,16 @@ public class ChartNetworkSeriesView extends View {
private Path mPathFill;
private Path mPathEstimate;
private long mStart;
private long mEnd;
private long mPrimaryLeft;
private long mPrimaryRight;
/** Series will be extended to reach this end time. */
private long mEndTime = Long.MIN_VALUE;
private boolean mPathValid = false;
private boolean mEstimateVisible = false;
private long mMax;
@@ -130,13 +134,15 @@ public class ChartNetworkSeriesView extends View {
public void bindNetworkStats(NetworkStatsHistory stats) {
mStats = stats;
mPathStroke.reset();
mPathFill.reset();
mPathEstimate.reset();
invalidatePath();
invalidate();
}
public void setBounds(long start, long end) {
mStart = start;
mEnd = end;
}
/**
* Set the range to paint with {@link #mPaintFill}, leaving the remaining
* area to be painted with {@link #mPaintFillSecondary}.
@@ -147,26 +153,27 @@ public class ChartNetworkSeriesView extends View {
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
generatePath();
public void invalidatePath() {
mPathValid = false;
mMax = 0;
invalidate();
}
/**
* Erase any existing {@link Path} and generate series outline based on
* currently bound {@link NetworkStatsHistory} data.
*/
public void generatePath() {
private void generatePath() {
if (LOGD) Log.d(TAG, "generatePath()");
mMax = 0;
mPathStroke.reset();
mPathFill.reset();
mPathEstimate.reset();
mPathValid = true;
// bail when not enough stats to render
if (mStats == null || mStats.size() < 2) {
invalidate();
return;
}
@@ -185,7 +192,10 @@ public class ChartNetworkSeriesView extends View {
long totalData = 0;
NetworkStatsHistory.Entry entry = null;
for (int i = 0; i < mStats.size(); i++) {
final int start = mStats.getIndexBefore(mStart);
final int end = mStats.getIndexAfter(mEnd);
for (int i = start; i <= end; i++) {
entry = mStats.getValues(i, entry);
lastTime = entry.bucketStart + entry.bucketDuration;
@@ -206,9 +216,6 @@ public class ChartNetworkSeriesView extends View {
totalData += entry.rxBytes + entry.txBytes;
}
// skip if beyond view
if (x > width) break;
lastX = x;
lastY = y;
}
@@ -284,13 +291,24 @@ public class ChartNetworkSeriesView extends View {
}
public long getMaxVisible() {
return mEstimateVisible ? mMaxEstimate : mMax;
final long maxVisible = mEstimateVisible ? mMaxEstimate : mMax;
if (maxVisible <= 0 && mStats != null) {
// haven't generated path yet; fall back to raw data
final NetworkStatsHistory.Entry entry = mStats.getValues(mStart, mEnd, null);
return entry.rxBytes + entry.txBytes;
} else {
return maxVisible;
}
}
@Override
protected void onDraw(Canvas canvas) {
int save;
if (!mPathValid) {
generatePath();
}
final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);

View File

@@ -76,6 +76,8 @@ public class ChartSweepView extends View {
private ChartSweepView mValidAfterDynamic;
private ChartSweepView mValidBeforeDynamic;
private float mLabelOffset;
private Paint mOutlinePaint = new Paint();
public static final int HORIZONTAL = 0;
@@ -230,12 +232,44 @@ public class ChartSweepView extends View {
private void invalidateLabel() {
if (mLabelTemplate != null && mAxis != null) {
mLabelValue = mAxis.buildLabel(getResources(), mLabelTemplate, mValue);
invalidateLabelOffset();
invalidate();
} else {
mLabelValue = mValue;
}
}
/**
* When overlapping with neighbor, split difference and push label.
*/
public void invalidateLabelOffset() {
float margin;
float labelOffset = 0;
if (mFollowAxis == VERTICAL) {
if (mValidAfterDynamic != null) {
margin = getLabelTop(mValidAfterDynamic) - getLabelBottom(this);
if (margin < 0) {
labelOffset = margin / 2;
}
} else if (mValidBeforeDynamic != null) {
margin = getLabelTop(this) - getLabelBottom(mValidBeforeDynamic);
if (margin < 0) {
labelOffset = -margin / 2;
}
}
} else {
// TODO: implement horizontal labels
}
// when offsetting label, neighbor probably needs to offset too
if (labelOffset != mLabelOffset) {
mLabelOffset = labelOffset;
invalidate();
if (mValidAfterDynamic != null) mValidAfterDynamic.invalidateLabelOffset();
if (mValidBeforeDynamic != null) mValidBeforeDynamic.invalidateLabelOffset();
}
}
@Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
@@ -566,6 +600,12 @@ public class ChartSweepView extends View {
mMargins.offset(-mSweepOffset.x, -mSweepOffset.y);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
invalidateLabelOffset();
}
@Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
@@ -575,36 +615,11 @@ public class ChartSweepView extends View {
canvas.drawRect(0, 0, width, height, mOutlinePaint);
}
// when overlapping with neighbor, split difference and push label
float margin;
float labelOffset = 0;
if (mFollowAxis == VERTICAL) {
if (mValidAfterDynamic != null) {
margin = getLabelTop(mValidAfterDynamic) - getLabelBottom(this);
if (margin < 0) {
labelOffset = margin / 2;
}
} else if (mValidBeforeDynamic != null) {
margin = getLabelTop(this) - getLabelBottom(mValidBeforeDynamic);
if (margin < 0) {
labelOffset = -margin / 2;
}
}
} else {
// TODO: implement horizontal labels
}
// when offsetting label, neighbor probably needs to offset too
if (labelOffset != 0) {
if (mValidAfterDynamic != null) mValidAfterDynamic.invalidate();
if (mValidBeforeDynamic != null) mValidBeforeDynamic.invalidate();
}
final int labelSize;
if (isEnabled() && mLabelLayout != null) {
final int count = canvas.save();
{
canvas.translate(mContentOffset.left, mContentOffset.top + labelOffset);
canvas.translate(mContentOffset.left, mContentOffset.top + mLabelOffset);
mLabelLayout.draw(canvas);
}
canvas.restoreToCount(count);

View File

@@ -31,14 +31,14 @@ public class InvertedChartAxis implements ChartAxis {
}
/** {@inheritDoc} */
public void setBounds(long min, long max) {
mWrapped.setBounds(min, max);
public boolean setBounds(long min, long max) {
return mWrapped.setBounds(min, max);
}
/** {@inheritDoc} */
public void setSize(float size) {
public boolean setSize(float size) {
mSize = size;
mWrapped.setSize(size);
return mWrapped.setSize(size);
}
/** {@inheritDoc} */

View File

@@ -40,7 +40,7 @@ import java.util.ArrayList;
*/
public class PieChartView extends View {
public static final String TAG = "PieChartView";
public static final boolean LOGD = true;
public static final boolean LOGD = false;
private ArrayList<Slice> mSlices = Lists.newArrayList();