summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-08-05 00:14:43 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-08-05 00:14:43 -0700
commit5c2d982f8e2bc1fc58ea89d747fde2c581095b37 (patch)
treebaff29cae55d7f6ac8af24ea5b40de2f9d119c8c /src/com
parent48a6de66bbb59041f40b676662b2834a2f842222 (diff)
parentd39c6e4083f1212519d5dc14f64132a10f2b7c7a (diff)
downloadpackages_apps_settings-5c2d982f8e2bc1fc58ea89d747fde2c581095b37.zip
packages_apps_settings-5c2d982f8e2bc1fc58ea89d747fde2c581095b37.tar.gz
packages_apps_settings-5c2d982f8e2bc1fc58ea89d747fde2c581095b37.tar.bz2
Merge "Data usage app icons and details, chart labels."
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/settings/DataUsageSummary.java120
-rw-r--r--src/com/android/settings/widget/ChartGridView.java56
-rw-r--r--src/com/android/settings/widget/ChartSweepView.java1
-rw-r--r--src/com/android/settings/widget/DataUsageChartView.java1
4 files changed, 134 insertions, 44 deletions
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index 45793b1..bccc5a5 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -37,6 +37,9 @@ import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
import static android.net.NetworkTemplate.buildTemplateMobile4g;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
+import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
+import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
+import static android.text.format.Time.TIMEZONE_UTC;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.animation.LayoutTransition;
@@ -57,6 +60,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
@@ -78,7 +82,6 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Formatter;
-import android.text.format.Time;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -97,6 +100,7 @@ import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.NumberPicker;
@@ -190,8 +194,8 @@ public class DataUsageSummary extends Fragment {
private TextView mEmpty;
private View mAppDetail;
- private TextView mAppTitle;
- private TextView mAppSubtitle;
+ private ImageView mAppIcon;
+ private ViewGroup mAppTitles;
private Button mAppSettings;
private LinearLayout mAppSwitches;
@@ -295,8 +299,8 @@ public class DataUsageSummary extends Fragment {
{
// bind app detail controls
mAppDetail = mHeader.findViewById(R.id.app_detail);
- mAppTitle = (TextView) mAppDetail.findViewById(R.id.app_title);
- mAppSubtitle = (TextView) mAppDetail.findViewById(R.id.app_subtitle);
+ mAppIcon = (ImageView) mAppDetail.findViewById(R.id.app_icon);
+ mAppTitles = (ViewGroup) mAppDetail.findViewById(R.id.app_titles);
mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
@@ -643,6 +647,10 @@ public class DataUsageSummary extends Fragment {
* depending on {@link #isAppDetailMode()}.
*/
private void updateAppDetail() {
+ final Context context = getActivity();
+ final PackageManager pm = context.getPackageManager();
+ final LayoutInflater inflater = getActivity().getLayoutInflater();
+
if (isAppDetailMode()) {
mAppDetail.setVisibility(View.VISIBLE);
mCycleAdapter.setChangeVisible(false);
@@ -658,8 +666,18 @@ public class DataUsageSummary extends Fragment {
// remove warning/limit sweeps while in detail mode
mChart.bindNetworkPolicy(null);
- final PackageManager pm = getActivity().getPackageManager();
- mAppTitle.setText(pm.getNameForUid(mUid));
+ // show icon and all labels appearing under this app
+ final UidDetail detail = resolveDetailForUid(context, mUid);
+ mAppIcon.setImageDrawable(detail.icon);
+
+ mAppTitles.removeAllViews();
+ if (detail.detailLabels != null) {
+ for (CharSequence label : detail.detailLabels) {
+ mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, label));
+ }
+ } else {
+ mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, detail.label));
+ }
// enable settings button when package provides it
// TODO: target torwards entire UID instead of just first package
@@ -693,7 +711,6 @@ public class DataUsageSummary extends Fragment {
updateDetailData();
- final Context context = getActivity();
if (NetworkPolicyManager.isUidValidForPolicy(context, mUid) && !getRestrictBackground()
&& isBandwidthControlEnabled()) {
mAppRestrictView.setVisibility(View.VISIBLE);
@@ -814,7 +831,9 @@ public class DataUsageSummary extends Fragment {
if (isNetworkPolicyModifiable()) {
mDisableAtLimitView.setVisibility(View.VISIBLE);
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
- mChart.bindNetworkPolicy(policy);
+ if (!isAppDetailMode()) {
+ mChart.bindNetworkPolicy(policy);
+ }
} else {
// controls are disabled; don't bind warning/limit sweeps
@@ -998,11 +1017,6 @@ public class DataUsageSummary extends Fragment {
if (isAppDetailMode()) {
if (mDetailHistory != null) {
entry = mDetailHistory.getValues(start, end, now, null);
-
- mAppSubtitle.setText(
- getString(R.string.data_usage_received_sent,
- Formatter.formatFileSize(context, entry.rxBytes),
- Formatter.formatFileSize(context, entry.txBytes)));
} else {
entry = null;
}
@@ -1015,12 +1029,11 @@ public class DataUsageSummary extends Fragment {
// kick off loader for detailed stats
getLoaderManager().restartLoader(LOADER_SUMMARY,
SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryForAllUid);
-
}
final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
- final String rangePhrase = formatDateRange(context, start, end, null);
+ final String rangePhrase = formatDateRange(context, start, end, false);
mUsageSummary.setText(
getString(R.string.data_usage_total_during_range, totalPhrase, rangePhrase));
@@ -1104,7 +1117,7 @@ public class DataUsageSummary extends Fragment {
}
public CycleItem(Context context, long start, long end) {
- this.label = formatDateRange(context, start, end, Time.TIMEZONE_UTC);
+ this.label = formatDateRange(context, start, end, true);
this.start = start;
this.end = end;
}
@@ -1119,14 +1132,11 @@ public class DataUsageSummary extends Fragment {
private static final java.util.Formatter sFormatter = new java.util.Formatter(
sBuilder, Locale.getDefault());
- private static String formatDateRange(Context context, long start, long end, String timezone) {
- synchronized (sBuilder) {
- int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH;
- if (Time.getJulianDay(start, 0) == Time.getJulianDay(end, 0)) {
- // when times are on same day, include time detail
- flags |= DateUtils.FORMAT_SHOW_TIME;
- }
+ public static String formatDateRange(Context context, long start, long end, boolean utcTime) {
+ final int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
+ final String timezone = utcTime ? TIMEZONE_UTC : null;
+ synchronized (sBuilder) {
sBuilder.setLength(0);
return DateUtils
.formatDateRange(context, sFormatter, start, end, flags, timezone).toString();
@@ -1250,13 +1260,17 @@ public class DataUsageSummary extends Fragment {
final Context context = parent.getContext();
+ final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
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);
- title.setText(resolveLabelForUid(context, item.uid));
+ final UidDetail detail = resolveDetailForUid(context, item.uid);
+
+ icon.setImageDrawable(detail.icon);
+ title.setText(detail.label);
summary.setText(Formatter.formatFileSize(context, item.total));
final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
@@ -1536,48 +1550,66 @@ public class DataUsageSummary extends Fragment {
}
}
+ public static class UidDetail {
+ public CharSequence label;
+ public CharSequence[] detailLabels;
+ public Drawable icon;
+ }
+
/**
* Resolve best descriptive label for the given UID.
*/
- public static CharSequence resolveLabelForUid(Context context, int uid) {
+ public static UidDetail resolveDetailForUid(Context context, int uid) {
final Resources res = context.getResources();
final PackageManager pm = context.getPackageManager();
+ final UidDetail detail = new UidDetail();
+ detail.label = pm.getNameForUid(uid);
+ detail.icon = pm.getDefaultActivityIcon();
+
// handle special case labels
switch (uid) {
case android.os.Process.SYSTEM_UID:
- return res.getText(R.string.process_kernel_label);
+ detail.label = res.getString(R.string.process_kernel_label);
+ detail.icon = pm.getDefaultActivityIcon();
+ return detail;
case TrafficStats.UID_REMOVED:
- return res.getText(R.string.data_usage_uninstalled_apps);
+ detail.label = res.getString(R.string.data_usage_uninstalled_apps);
+ detail.icon = pm.getDefaultActivityIcon();
+ return detail;
}
// otherwise fall back to using packagemanager labels
final String[] packageNames = pm.getPackagesForUid(uid);
final int length = packageNames != null ? packageNames.length : 0;
- CharSequence label = pm.getNameForUid(uid);
try {
if (length == 1) {
final ApplicationInfo info = pm.getApplicationInfo(packageNames[0], 0);
- label = info.loadLabel(pm);
+ detail.label = info.loadLabel(pm).toString();
+ detail.icon = info.loadIcon(pm);
} else if (length > 1) {
- for (String packageName : packageNames) {
- final PackageInfo info = pm.getPackageInfo(packageName, 0);
- if (info.sharedUserLabel != 0) {
- label = pm.getText(packageName, info.sharedUserLabel, info.applicationInfo);
- if (!TextUtils.isEmpty(label)) {
- break;
- }
+ detail.detailLabels = new CharSequence[length];
+ for (int i = 0; i < length; i++) {
+ final String packageName = packageNames[i];
+ final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+ final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
+
+ detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
+ if (packageInfo.sharedUserLabel != 0) {
+ detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
+ packageInfo.applicationInfo).toString();
+ detail.icon = appInfo.loadIcon(pm);
}
}
}
} catch (NameNotFoundException e) {
}
- if (TextUtils.isEmpty(label)) {
- label = Integer.toString(uid);
+ if (TextUtils.isEmpty(detail.label)) {
+ detail.label = Integer.toString(uid);
}
- return label;
+ return detail;
}
/**
@@ -1652,6 +1684,14 @@ public class DataUsageSummary extends Fragment {
return view;
}
+ private static View inflateAppTitle(
+ LayoutInflater inflater, ViewGroup root, CharSequence label) {
+ final TextView view = (TextView) inflater.inflate(
+ R.layout.data_usage_app_title, root, false);
+ view.setText(label);
+ return view;
+ }
+
/**
* Set {@link android.R.id#title} for a preference view inflated with
* {@link #inflatePreference(LayoutInflater, ViewGroup, View)}.
diff --git a/src/com/android/settings/widget/ChartGridView.java b/src/com/android/settings/widget/ChartGridView.java
index 7a83fbf..c2702e4 100644
--- a/src/com/android/settings/widget/ChartGridView.java
+++ b/src/com/android/settings/widget/ChartGridView.java
@@ -17,12 +17,20 @@
package com.android.settings.widget;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.drawable.Drawable;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.View;
+import com.android.settings.DataUsageSummary;
import com.android.settings.R;
import com.google.common.base.Preconditions;
@@ -32,14 +40,16 @@ import com.google.common.base.Preconditions;
*/
public class ChartGridView extends View {
- // TODO: eventually teach about drawing chart labels
-
private ChartAxis mHoriz;
private ChartAxis mVert;
private Drawable mPrimary;
private Drawable mSecondary;
private Drawable mBorder;
+ private int mLabelColor;
+
+ private Layout mLayoutStart;
+ private Layout mLayoutEnd;
public ChartGridView(Context context) {
this(context, null, 0);
@@ -60,7 +70,7 @@ public class ChartGridView extends View {
mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
- // TODO: eventually read labelColor
+ mLabelColor = a.getColor(R.styleable.ChartGridView_labelColor, Color.RED);
a.recycle();
}
@@ -70,6 +80,13 @@ public class ChartGridView extends View {
mVert = Preconditions.checkNotNull(vert, "missing vert");
}
+ void setBounds(long start, long end) {
+ final Context context = getContext();
+ mLayoutStart = makeLayout(DataUsageSummary.formatDateRange(context, start, start, true));
+ mLayoutEnd = makeLayout(DataUsageSummary.formatDateRange(context, end, end, true));
+ invalidate();
+ }
+
@Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
@@ -98,5 +115,38 @@ public class ChartGridView extends View {
mBorder.setBounds(0, 0, width, height);
mBorder.draw(canvas);
+
+ final int padding = mLayoutStart.getHeight() / 8;
+
+ final Layout start = mLayoutStart;
+ if (start != null) {
+ canvas.save();
+ canvas.translate(0, height + padding);
+ start.draw(canvas);
+ canvas.restore();
+ }
+
+ final Layout end = mLayoutEnd;
+ if (end != null) {
+ canvas.save();
+ canvas.translate(width - end.getWidth(), height + padding);
+ end.draw(canvas);
+ canvas.restore();
+ }
}
+
+ private Layout makeLayout(CharSequence text) {
+ final Resources res = getResources();
+ final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+ paint.density = res.getDisplayMetrics().density;
+ paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
+ paint.setColor(mLabelColor);
+ paint.setTextSize(
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, res.getDisplayMetrics()));
+
+ return new StaticLayout(text, paint,
+ (int) Math.ceil(Layout.getDesiredWidth(text, paint)),
+ Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
+ }
+
}
diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java
index b5e044f..d5e8de8 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -29,7 +29,6 @@ import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
diff --git a/src/com/android/settings/widget/DataUsageChartView.java b/src/com/android/settings/widget/DataUsageChartView.java
index b2ad844..a1c92e1 100644
--- a/src/com/android/settings/widget/DataUsageChartView.java
+++ b/src/com/android/settings/widget/DataUsageChartView.java
@@ -343,6 +343,7 @@ public class DataUsageChartView extends ChartView {
*/
public void setVisibleRange(long visibleStart, long visibleEnd) {
mHoriz.setBounds(visibleStart, visibleEnd);
+ mGrid.setBounds(visibleStart, visibleEnd);
final long validStart = Math.max(visibleStart, getStatsStart());
final long validEnd = Math.min(visibleEnd, getStatsEnd());