diff --git a/res/drawable/data_usage_bar.xml b/res/drawable/data_usage_bar.xml new file mode 100644 index 00000000000..96f1caedd0e --- /dev/null +++ b/res/drawable/data_usage_bar.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/data_usage_item.xml b/res/layout/data_usage_item.xml index 6451e214f44..d70975390ae 100644 --- a/res/layout/data_usage_item.xml +++ b/res/layout/data_usage_item.xml @@ -14,26 +14,34 @@ limitations under the License. --> - + android:padding="8dip" + android:columnCount="2"> + - + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index b72dbae6e35..f5731819535 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3475,6 +3475,8 @@ found in the list of installed applications. Removed apps + + %1$s received, %2$s sent Emergency call diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index f7bb32f3eca..1f433fb5f4b 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -97,6 +97,7 @@ import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.NumberPicker; +import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.Switch; import android.widget.TabHost; @@ -946,8 +947,11 @@ public class DataUsageSummary extends Fragment { final long now = System.currentTimeMillis(); final NetworkStatsHistory.Entry entry = mDetailHistory.getValues( start, end, now, null); - final long total = entry.rxBytes + entry.txBytes; - mAppSubtitle.setText(Formatter.formatFileSize(context, total)); + + mAppSubtitle.setText( + getString(R.string.data_usage_received_sent, + Formatter.formatFileSize(context, entry.rxBytes), + Formatter.formatFileSize(context, entry.txBytes))); } getLoaderManager().destroyLoader(LOADER_SUMMARY); @@ -1110,6 +1114,7 @@ public class DataUsageSummary extends Fragment { */ public static class DataUsageAdapter extends BaseAdapter { private ArrayList mItems = Lists.newArrayList(); + private long mLargest; /** * Bind the given {@link NetworkStats}, or {@code null} to clear list. @@ -1143,6 +1148,7 @@ public class DataUsageSummary extends Fragment { } Collections.sort(mItems); + mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0; notifyDataSetChanged(); } @@ -1170,12 +1176,17 @@ public class DataUsageSummary extends Fragment { final Context context = parent.getContext(); - final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1); - final TextView text2 = (TextView) convertView.findViewById(android.R.id.text2); + final TextView title = (TextView) convertView.findViewById(android.R.id.title); + final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); + final ProgressBar progress = (ProgressBar) convertView.findViewById( + android.R.id.progress); final AppUsageItem item = mItems.get(position); - text1.setText(resolveLabelForUid(context, item.uid)); - text2.setText(Formatter.formatFileSize(context, item.total)); + title.setText(resolveLabelForUid(context, item.uid)); + summary.setText(Formatter.formatFileSize(context, item.total)); + + final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0; + progress.setProgress(percentTotal); return convertView; } @@ -1187,7 +1198,7 @@ public class DataUsageSummary extends Fragment { * {@link DataUsageSummary}. */ public static class AppDetailsFragment extends Fragment { - public static final String EXTRA_UID = "uid"; + private static final String EXTRA_UID = "uid"; public static void show(DataUsageSummary parent, int uid) { final Bundle args = new Bundle(); @@ -1225,8 +1236,8 @@ public class DataUsageSummary extends Fragment { * {@link NetworkPolicy#limitBytes}. */ public static class ConfirmLimitFragment extends DialogFragment { - public static final String EXTRA_MESSAGE_ID = "messageId"; - public static final String EXTRA_LIMIT_BYTES = "limitBytes"; + private static final String EXTRA_MESSAGE_ID = "messageId"; + private static final String EXTRA_LIMIT_BYTES = "limitBytes"; public static void show(DataUsageSummary parent) { final Bundle args = new Bundle(); @@ -1278,7 +1289,7 @@ public class DataUsageSummary extends Fragment { * Dialog to edit {@link NetworkPolicy#cycleDay}. */ public static class CycleEditorFragment extends DialogFragment { - public static final String EXTRA_CYCLE_DAY = "cycleDay"; + private static final String EXTRA_CYCLE_DAY = "cycleDay"; public static void show(DataUsageSummary parent) { final NetworkPolicy policy = parent.mPolicyEditor.getPolicy(parent.mTemplate); @@ -1331,7 +1342,7 @@ public class DataUsageSummary extends Fragment { * and giving the user an option to bypass. */ public static class PolicyLimitFragment extends DialogFragment { - public static final String EXTRA_TITLE_ID = "titleId"; + private static final String EXTRA_TITLE_ID = "titleId"; public static void show(DataUsageSummary parent) { final Bundle args = new Bundle(); diff --git a/src/com/android/settings/widget/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java index 10d897603a4..51c3c2c34c1 100644 --- a/src/com/android/settings/widget/ChartNetworkSeriesView.java +++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java @@ -16,6 +16,9 @@ package com.android.settings.widget; +import static android.text.format.DateUtils.DAY_IN_MILLIS; +import static android.text.format.DateUtils.WEEK_IN_MILLIS; + import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -46,11 +49,13 @@ public class ChartNetworkSeriesView extends View { private Paint mPaintStroke; private Paint mPaintFill; private Paint mPaintFillSecondary; + private Paint mPaintEstimate; private NetworkStatsHistory mStats; private Path mPathStroke; private Path mPathFill; + private Path mPathEstimate; private long mPrimaryLeft; private long mPrimaryRight; @@ -81,6 +86,7 @@ public class ChartNetworkSeriesView extends View { mPathStroke = new Path(); mPathFill = new Path(); + mPathEstimate = new Path(); } void init(ChartAxis horiz, ChartAxis vert) { @@ -104,6 +110,12 @@ public class ChartNetworkSeriesView extends View { mPaintFillSecondary.setColor(fillSecondary); mPaintFillSecondary.setStyle(Style.FILL); mPaintFillSecondary.setAntiAlias(true); + + mPaintEstimate = new Paint(); + mPaintEstimate.setStrokeWidth(3.0f); + mPaintEstimate.setColor(fillSecondary); + mPaintEstimate.setStyle(Style.STROKE); + mPaintEstimate.setAntiAlias(true); } public void bindNetworkStats(NetworkStatsHistory stats) { @@ -111,6 +123,7 @@ public class ChartNetworkSeriesView extends View { mPathStroke.reset(); mPathFill.reset(); + mPathEstimate.reset(); invalidate(); } @@ -138,6 +151,7 @@ public class ChartNetworkSeriesView extends View { mPathStroke.reset(); mPathFill.reset(); + mPathEstimate.reset(); // bail when not enough stats to render if (mStats == null || mStats.size() < 2) return; @@ -149,6 +163,7 @@ public class ChartNetworkSeriesView extends View { float firstX = 0; float lastX = 0; float lastY = 0; + long lastTime = Long.MIN_VALUE; // TODO: count fractional data from first bucket crossing start; // currently it only accepts first full bucket. @@ -159,6 +174,7 @@ public class ChartNetworkSeriesView extends View { for (int i = 0; i < mStats.size(); i++) { entry = mStats.getValues(i, entry); + lastTime = entry.bucketStart; final float x = mHoriz.convertToPoint(entry.bucketStart); final float y = mVert.convertToPoint(totalData); @@ -193,6 +209,35 @@ public class ChartNetworkSeriesView extends View { // drop to bottom of graph from current location mPathFill.lineTo(lastX, height); mPathFill.lineTo(firstX, height); + + // build estimated data + mPathEstimate.moveTo(lastX, lastY); + + 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 + / entry.bucketDuration; + + totalData += (longWindow * 7 + shortWindow * 3) / 10; + + lastX = mHoriz.convertToPoint(lastTime + futureTime); + final float y = mVert.convertToPoint(totalData); + + mPathEstimate.lineTo(lastX, y); + } } @Override @@ -202,6 +247,11 @@ public class ChartNetworkSeriesView extends View { final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft); final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight); + save = canvas.save(); + canvas.clipRect(0, 0, getWidth(), getHeight()); + canvas.drawPath(mPathEstimate, mPaintEstimate); + canvas.restoreToCount(save); + save = canvas.save(); canvas.clipRect(0, 0, primaryLeftPoint, getHeight()); canvas.drawPath(mPathFill, mPaintFillSecondary);