diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-08-05 00:14:43 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-08-05 00:14:43 -0700 |
commit | 5c2d982f8e2bc1fc58ea89d747fde2c581095b37 (patch) | |
tree | baff29cae55d7f6ac8af24ea5b40de2f9d119c8c /src/com | |
parent | 48a6de66bbb59041f40b676662b2834a2f842222 (diff) | |
parent | d39c6e4083f1212519d5dc14f64132a10f2b7c7a (diff) | |
download | packages_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')
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()); |