summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2014-07-22 23:40:05 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-07-22 20:40:07 +0000
commite65bb4927faf8e353c73b58648e51a8081615dcf (patch)
tree0d0a2f20cc881e9f4f1fb1df8ee8213c5947df2e /src/com/android
parent0da1f8515a6af368a923cc99e5435795a031692a (diff)
parentb654846300f79e9e4c605ce62d09f9a05d232fee (diff)
downloadpackages_apps_Settings-e65bb4927faf8e353c73b58648e51a8081615dcf.zip
packages_apps_Settings-e65bb4927faf8e353c73b58648e51a8081615dcf.tar.gz
packages_apps_Settings-e65bb4927faf8e353c73b58648e51a8081615dcf.tar.bz2
Merge "Data Usage, materialized!" into lmp-dev
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/DataUsageSummary.java441
-rw-r--r--src/com/android/settings/net/DataUsageMeteredSettings.java6
-rw-r--r--src/com/android/settings/widget/ChartDataUsageView.java93
-rw-r--r--src/com/android/settings/widget/ChartGridView.java94
-rw-r--r--src/com/android/settings/widget/ChartNetworkSeriesView.java42
-rw-r--r--src/com/android/settings/widget/ChartSweepView.java9
-rw-r--r--src/com/android/settings/widget/ChartView.java9
-rw-r--r--src/com/android/settings/widget/PieChartView.java244
8 files changed, 339 insertions, 599 deletions
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index bdae072..f8f285f 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -55,6 +55,7 @@ import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
@@ -63,6 +64,7 @@ import android.content.Loader;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -107,9 +109,6 @@ import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
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;
@@ -138,7 +137,6 @@ import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.widget.ChartDataUsageView;
import com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
-import com.android.settings.widget.PieChartView;
import com.google.android.collect.Lists;
import libcore.util.Objects;
@@ -170,7 +168,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private static final String TAB_ETHERNET = "ethernet";
private static final String TAG_CONFIRM_DATA_DISABLE = "confirmDataDisable";
- private static final String TAG_CONFIRM_DATA_ROAMING = "confirmDataRoaming";
private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
private static final String TAG_CYCLE_EDITOR = "cycleEditor";
private static final String TAG_WARNING_EDITOR = "warningEditor";
@@ -189,15 +186,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private static final int LOADER_CHART_DATA = 2;
private static final int LOADER_SUMMARY = 3;
- private static final int FOREGROUND_BYTES_COLOR = 0xff009688;
- private static final int DEFAULT_BYTES_COLOR = 0xffced7db;
-
private INetworkManagementService mNetworkService;
private INetworkStatsService mStatsService;
private NetworkPolicyManager mPolicyManager;
private TelephonyManager mTelephonyManager;
-
private INetworkStatsSession mStatsSession;
private static final String PREF_FILE = "data_usage";
@@ -219,29 +212,33 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private ViewGroup mNetworkSwitchesContainer;
private LinearLayout mNetworkSwitches;
+ private boolean mDataEnabledSupported;
private Switch mDataEnabled;
private View mDataEnabledView;
- private CheckBox mDisableAtLimit;
+ private boolean mDisableAtLimitSupported;
+ private Switch mDisableAtLimit;
private View mDisableAtLimitView;
private View mCycleView;
private Spinner mCycleSpinner;
private CycleAdapter mCycleAdapter;
+ private TextView mCycleSummary;
private ChartDataUsageView mChart;
- private TextView mUsageSummary;
+ private View mDisclaimer;
private TextView mEmpty;
+ private View mStupidPadding;
private View mAppDetail;
private ImageView mAppIcon;
private ViewGroup mAppTitles;
- private PieChartView mAppPieChart;
+ private TextView mAppTotal;
private TextView mAppForeground;
private TextView mAppBackground;
private Button mAppSettings;
private LinearLayout mAppSwitches;
- private CheckBox mAppRestrict;
+ private Switch mAppRestrict;
private View mAppRestrictView;
private boolean mShowWifi = false;
@@ -259,9 +256,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private String mCurrentTab = null;
private String mIntentTab = null;
- private MenuItem mMenuDataRoaming;
private MenuItem mMenuRestrictBackground;
- private MenuItem mMenuAutoSync;
+ private MenuItem mMenuShowWifi;
+ private MenuItem mMenuShowEthernet;
+ private MenuItem mMenuSimCards;
+ private MenuItem mMenuCellularNetworks;
/** Flag used to ignore listeners during binding. */
private boolean mBinding;
@@ -359,13 +358,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mNetworkSwitches = (LinearLayout) mHeader.findViewById(R.id.network_switches);
mDataEnabled = new Switch(inflater.getContext());
+ mDataEnabled.setClickable(false);
+ mDataEnabled.setFocusable(false);
mDataEnabledView = inflatePreference(inflater, mNetworkSwitches, mDataEnabled);
mDataEnabledView.setTag(R.id.preference_highlight_key,
DATA_USAGE_ENABLE_MOBILE_KEY);
- mDataEnabled.setOnCheckedChangeListener(mDataEnabledListener);
+ mDataEnabledView.setClickable(true);
+ mDataEnabledView.setFocusable(true);
+ mDataEnabledView.setOnClickListener(mDataEnabledListener);
mNetworkSwitches.addView(mDataEnabledView);
- mDisableAtLimit = new CheckBox(inflater.getContext());
+ mDisableAtLimit = new Switch(inflater.getContext());
mDisableAtLimit.setClickable(false);
mDisableAtLimit.setFocusable(false);
mDisableAtLimitView = inflatePreference(inflater, mNetworkSwitches, mDisableAtLimit);
@@ -375,15 +378,16 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mDisableAtLimitView.setFocusable(true);
mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
mNetworkSwitches.addView(mDisableAtLimitView);
- }
- // bind cycle dropdown
- mCycleView = mHeader.findViewById(R.id.cycles);
- mCycleView.setTag(R.id.preference_highlight_key, DATA_USAGE_CYCLE_KEY);
- mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
- mCycleAdapter = new CycleAdapter(context);
- mCycleSpinner.setAdapter(mCycleAdapter);
- mCycleSpinner.setOnItemSelectedListener(mCycleListener);
+ mCycleView = inflater.inflate(R.layout.data_usage_cycles, mNetworkSwitches, false);
+ mCycleView.setTag(R.id.preference_highlight_key, DATA_USAGE_CYCLE_KEY);
+ mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
+ mCycleAdapter = new CycleAdapter(context);
+ mCycleSpinner.setAdapter(mCycleAdapter);
+ mCycleSpinner.setOnItemSelectedListener(mCycleListener);
+ mCycleSummary = (TextView) mCycleView.findViewById(R.id.cycle_summary);
+ mNetworkSwitches.addView(mCycleView);
+ }
mChart = (ChartDataUsageView) mHeader.findViewById(R.id.chart);
mChart.setListener(mChartListener);
@@ -394,7 +398,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mAppDetail = mHeader.findViewById(R.id.app_detail);
mAppIcon = (ImageView) mAppDetail.findViewById(R.id.app_icon);
mAppTitles = (ViewGroup) mAppDetail.findViewById(R.id.app_titles);
- mAppPieChart = (PieChartView) mAppDetail.findViewById(R.id.app_pie_chart);
mAppForeground = (TextView) mAppDetail.findViewById(R.id.app_foreground);
mAppBackground = (TextView) mAppDetail.findViewById(R.id.app_background);
mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
@@ -402,7 +405,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
mAppSettings.setOnClickListener(mAppSettingsListener);
- mAppRestrict = new CheckBox(inflater.getContext());
+ mAppRestrict = new Switch(inflater.getContext());
mAppRestrict.setClickable(false);
mAppRestrict.setFocusable(false);
mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict);
@@ -412,8 +415,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mAppSwitches.addView(mAppRestrictView);
}
- mUsageSummary = (TextView) mHeader.findViewById(R.id.usage_summary);
+ mDisclaimer = mHeader.findViewById(R.id.disclaimer);
mEmpty = (TextView) mHeader.findViewById(android.R.id.empty);
+ mStupidPadding = mHeader.findViewById(R.id.stupid_padding);
mAdapter = new DataUsageAdapter(mUidDetailProvider, mInsetSide);
mListView.setOnItemClickListener(mListListener);
@@ -480,40 +484,25 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final boolean appDetailMode = isAppDetailMode();
final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
- mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming);
- mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
- mMenuDataRoaming.setChecked(getDataRoaming());
-
- mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
- mMenuRestrictBackground.setVisible(
- hasReadyMobileRadio(context) && isOwner && !appDetailMode);
- mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground());
-
+ mMenuShowWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
// TODO: Define behavior of this sync button. See: http://b/16076571
- mMenuAutoSync = menu.findItem(R.id.data_usage_menu_auto_sync);
- mMenuAutoSync.setChecked(ContentResolver.getMasterSyncAutomatically());
- mMenuAutoSync.setVisible(!appDetailMode);
-
- final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g);
- split4g.setVisible(hasReadyMobile4gRadio(context) && isOwner && !appDetailMode);
- split4g.setChecked(isMobilePolicySplit());
-
- final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
if (hasWifiRadio(context) && hasReadyMobileRadio(context)) {
- showWifi.setVisible(!appDetailMode);
- showWifi.setChecked(mShowWifi);
+ mMenuShowWifi.setVisible(!appDetailMode);
} else {
- showWifi.setVisible(false);
+ mMenuShowWifi.setVisible(false);
}
- final MenuItem showEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet);
+ mMenuShowEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet);
if (hasEthernet(context) && hasReadyMobileRadio(context)) {
- showEthernet.setVisible(!appDetailMode);
- showEthernet.setChecked(mShowEthernet);
+ mMenuShowEthernet.setVisible(!appDetailMode);
} else {
- showEthernet.setVisible(false);
+ mMenuShowEthernet.setVisible(false);
}
+ mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
+ mMenuRestrictBackground.setVisible(
+ hasReadyMobileRadio(context) && isOwner && !appDetailMode);
+
final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
metered.setVisible(!appDetailMode);
@@ -521,6 +510,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
metered.setVisible(false);
}
+ // TODO: show when multiple sims available
+ mMenuSimCards = menu.findItem(R.id.data_usage_menu_sim_cards);
+ mMenuSimCards.setVisible(false);
+
+ mMenuCellularNetworks = menu.findItem(R.id.data_usage_menu_cellular_networks);
+ if (hasReadyMobileRadio(context)) {
+ mMenuCellularNetworks.setVisible(!appDetailMode);
+ } else {
+ mMenuCellularNetworks.setVisible(false);
+ }
+
final MenuItem help = menu.findItem(R.id.data_usage_menu_help);
String helpUrl;
if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_data_usage))) {
@@ -528,23 +528,35 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
} else {
help.setVisible(false);
}
+
+ updateMenuTitles();
+ }
+
+ private void updateMenuTitles() {
+ if (mPolicyManager.getRestrictBackground()) {
+ mMenuRestrictBackground.setTitle(R.string.data_usage_menu_allow_background);
+ } else {
+ mMenuRestrictBackground.setTitle(R.string.data_usage_menu_restrict_background);
+ }
+
+ if (mShowWifi) {
+ mMenuShowWifi.setTitle(R.string.data_usage_menu_hide_wifi);
+ } else {
+ mMenuShowWifi.setTitle(R.string.data_usage_menu_show_wifi);
+ }
+
+ if (mShowEthernet) {
+ mMenuShowEthernet.setTitle(R.string.data_usage_menu_hide_ethernet);
+ } else {
+ mMenuShowEthernet.setTitle(R.string.data_usage_menu_show_ethernet);
+ }
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.data_usage_menu_roaming: {
- final boolean dataRoaming = !item.isChecked();
- if (dataRoaming) {
- ConfirmDataRoamingFragment.show(this);
- } else {
- // no confirmation to disable roaming
- setDataRoaming(false);
- }
- return true;
- }
case R.id.data_usage_menu_restrict_background: {
- final boolean restrictBackground = !item.isChecked();
+ final boolean restrictBackground = !mPolicyManager.getRestrictBackground();
if (restrictBackground) {
ConfirmRestrictFragment.show(this);
} else {
@@ -553,41 +565,37 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
return true;
}
- case R.id.data_usage_menu_split_4g: {
- final boolean mobileSplit = !item.isChecked();
- setMobilePolicySplit(mobileSplit);
- item.setChecked(isMobilePolicySplit());
- updateTabs();
- return true;
- }
case R.id.data_usage_menu_show_wifi: {
- mShowWifi = !item.isChecked();
+ mShowWifi = !mShowWifi;
mPrefs.edit().putBoolean(PREF_SHOW_WIFI, mShowWifi).apply();
- item.setChecked(mShowWifi);
+ updateMenuTitles();
updateTabs();
return true;
}
case R.id.data_usage_menu_show_ethernet: {
- mShowEthernet = !item.isChecked();
+ mShowEthernet = !mShowEthernet;
mPrefs.edit().putBoolean(PREF_SHOW_ETHERNET, mShowEthernet).apply();
- item.setChecked(mShowEthernet);
+ updateMenuTitles();
updateTabs();
return true;
}
+ case R.id.data_usage_menu_sim_cards: {
+ // TODO: hook up to sim cards
+ return true;
+ }
+ case R.id.data_usage_menu_cellular_networks: {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(new ComponentName("com.android.phone",
+ "com.android.phone.MobileNetworkSettings"));
+ startActivity(intent);
+ return true;
+ }
case R.id.data_usage_menu_metered: {
final SettingsActivity sa = (SettingsActivity) getActivity();
sa.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
R.string.data_usage_metered_title, null, this, 0);
return true;
}
- case R.id.data_usage_menu_auto_sync: {
- if (ActivityManager.isUserAMonkey()) {
- Log.d("SyncState", "ignoring monkey's attempt to flip global sync state");
- } else {
- ConfirmAutoSyncChangeFragment.show(this, !item.isChecked());
- }
- return true;
- }
}
return false;
}
@@ -725,7 +733,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
- mDataEnabledView.setVisibility(isOwner ? View.VISIBLE : View.GONE);
+ mDataEnabledSupported = isOwner;
+ mDisableAtLimitSupported = true;
// TODO: remove mobile tabs when SIM isn't ready
@@ -748,14 +757,14 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
} else if (TAB_WIFI.equals(currentTab)) {
// wifi doesn't have any controls
- mDataEnabledView.setVisibility(View.GONE);
- mDisableAtLimitView.setVisibility(View.GONE);
+ mDataEnabledSupported = false;
+ mDisableAtLimitSupported = false;
mTemplate = buildTemplateWifiWildcard();
} else if (TAB_ETHERNET.equals(currentTab)) {
// ethernet doesn't have any controls
- mDataEnabledView.setVisibility(View.GONE);
- mDisableAtLimitView.setVisibility(View.GONE);
+ mDataEnabledSupported = false;
+ mDisableAtLimitSupported = false;
mTemplate = buildTemplateEthernet();
} else {
@@ -808,12 +817,25 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mAppIcon.setImageDrawable(detail.icon);
mAppTitles.removeAllViews();
+
+ View title = null;
if (detail.detailLabels != null) {
for (CharSequence label : detail.detailLabels) {
- mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, label));
+ title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
+ ((TextView) title.findViewById(R.id.app_title)).setText(label);
+ mAppTitles.addView(title);
}
} else {
- mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, detail.label));
+ title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
+ ((TextView) title.findViewById(R.id.app_title)).setText(detail.label);
+ mAppTitles.addView(title);
+ }
+
+ // Remember last slot for summary
+ if (title != null) {
+ mAppTotal = (TextView) title.findViewById(R.id.app_summary);
+ } else {
+ mAppTotal = null;
}
// enable settings button when package provides it
@@ -904,24 +926,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
}
- private boolean getDataRoaming() {
- final ContentResolver resolver = getActivity().getContentResolver();
- return android.provider.Settings.Global.getInt(resolver,
- android.provider.Settings.Global.DATA_ROAMING, 0) != 0;
- }
-
- private void setDataRoaming(boolean enabled) {
- // TODO: teach telephony DataConnectionTracker to watch and apply
- // updates when changed.
- final ContentResolver resolver = getActivity().getContentResolver();
- android.provider.Settings.Global.putInt(resolver,
- android.provider.Settings.Global.DATA_ROAMING, enabled ? 1 : 0);
- mMenuDataRoaming.setChecked(enabled);
- }
-
public void setRestrictBackground(boolean restrictBackground) {
mPolicyManager.setRestrictBackground(restrictBackground);
- mMenuRestrictBackground.setChecked(restrictBackground);
+ updateMenuTitles();
}
private boolean getAppRestrictBackground() {
@@ -943,10 +950,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
* current {@link #mTemplate}.
*/
private void updatePolicy(boolean refreshCycle) {
+ boolean dataEnabledVisible = mDataEnabledSupported;
+ boolean disableAtLimitVisible = mDisableAtLimitSupported;
+
if (isAppDetailMode()) {
- mNetworkSwitches.setVisibility(View.GONE);
- } else {
- mNetworkSwitches.setVisibility(View.VISIBLE);
+ dataEnabledVisible = false;
+ disableAtLimitVisible = false;
}
// TODO: move enabled state directly into policy
@@ -958,7 +967,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
if (isNetworkPolicyModifiable(policy)) {
- mDisableAtLimitView.setVisibility(View.VISIBLE);
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
if (!isAppDetailMode()) {
mChart.bindNetworkPolicy(policy);
@@ -966,10 +974,13 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
} else {
// controls are disabled; don't bind warning/limit sweeps
- mDisableAtLimitView.setVisibility(View.GONE);
+ disableAtLimitVisible = false;
mChart.bindNetworkPolicy(null);
}
+ mDataEnabledView.setVisibility(dataEnabledVisible ? View.VISIBLE : View.GONE);
+ mDisableAtLimitView.setVisibility(disableAtLimitVisible ? View.VISIBLE : View.GONE);
+
if (refreshCycle) {
// generate cycle list based on policy and available history
updateCycleList(policy);
@@ -1049,12 +1060,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
}
- private OnCheckedChangeListener mDataEnabledListener = new OnCheckedChangeListener() {
+ private View.OnClickListener mDataEnabledListener = new View.OnClickListener() {
@Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ public void onClick(View v) {
if (mBinding) return;
- final boolean dataEnabled = isChecked;
+ final boolean dataEnabled = !mDataEnabled.isChecked();
final String currentTab = mCurrentTab;
if (TAB_MOBILE.equals(currentTab)) {
if (dataEnabled) {
@@ -1178,15 +1189,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final long defaultBytes = entry.rxBytes + entry.txBytes;
entry = mChartData.detailForeground.getValues(start, end, now, entry);
final long foregroundBytes = entry.rxBytes + entry.txBytes;
+ final long totalBytes = defaultBytes + foregroundBytes;
- mAppPieChart.setOriginAngle(175);
-
- mAppPieChart.removeAllSlices();
- mAppPieChart.addSlice(foregroundBytes, FOREGROUND_BYTES_COLOR);
- mAppPieChart.addSlice(defaultBytes, DEFAULT_BYTES_COLOR);
-
- mAppPieChart.generatePath();
-
+ if (mAppTotal != null) {
+ mAppTotal.setText(Formatter.formatFileSize(context, totalBytes));
+ }
mAppBackground.setText(Formatter.formatFileSize(context, defaultBytes));
mAppForeground.setText(Formatter.formatFileSize(context, foregroundBytes));
@@ -1195,11 +1202,15 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
getLoaderManager().destroyLoader(LOADER_SUMMARY);
+ mCycleSummary.setVisibility(View.GONE);
+
} else {
if (mChartData != null) {
entry = mChartData.network.getValues(start, end, now, null);
}
+ mCycleSummary.setVisibility(View.VISIBLE);
+
// kick off loader for detailed stats
getLoaderManager().restartLoader(LOADER_SUMMARY,
SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryCallbacks);
@@ -1207,18 +1218,19 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
- final String rangePhrase = formatDateRange(context, start, end);
+ mCycleSummary.setText(totalPhrase);
- final int summaryRes;
if (TAB_MOBILE.equals(mCurrentTab) || TAB_3G.equals(mCurrentTab)
|| TAB_4G.equals(mCurrentTab)) {
- summaryRes = R.string.data_usage_total_during_range_mobile;
+ if (isAppDetailMode()) {
+ mDisclaimer.setVisibility(View.GONE);
+ } else {
+ mDisclaimer.setVisibility(View.VISIBLE);
+ }
} else {
- summaryRes = R.string.data_usage_total_during_range;
+ mDisclaimer.setVisibility(View.GONE);
}
- mUsageSummary.setText(getString(summaryRes, totalPhrase, rangePhrase));
-
// initial layout is finished above, ensure we have transitions
ensureLayoutTransitions();
}
@@ -1278,6 +1290,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private void updateEmptyVisible() {
final boolean isEmpty = mAdapter.isEmpty() && !isAppDetailMode();
mEmpty.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
+ mStupidPadding.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
}
};
@@ -1309,12 +1322,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private DataUsageChartListener mChartListener = new DataUsageChartListener() {
@Override
- public void onInspectRangeChanged() {
- if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
- updateDetailData();
- }
-
- @Override
public void onWarningChanged() {
setPolicyWarningBytes(mChart.getWarningBytes());
}
@@ -1404,8 +1411,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private final CycleChangeItem mChangeItem;
public CycleAdapter(Context context) {
- super(context, android.R.layout.simple_spinner_item);
- setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ super(context, R.layout.data_usage_cycle_item);
+ setDropDownViewResource(R.layout.data_usage_cycle_item_dropdown);
mChangeItem = new CycleChangeItem(context);
}
@@ -1447,11 +1454,21 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
public static class AppItem implements Comparable<AppItem>, Parcelable {
+ public static final int CATEGORY_USER = 0;
+ public static final int CATEGORY_APP_TITLE = 1;
+ public static final int CATEGORY_APP = 2;
+
public final int key;
public boolean restricted;
+ public int category;
+
public SparseBooleanArray uids = new SparseBooleanArray();
public long total;
+ public AppItem() {
+ this.key = 0;
+ }
+
public AppItem(int key) {
this.key = key;
}
@@ -1480,7 +1497,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
@Override
public int compareTo(AppItem another) {
- return Long.compare(another.total, total);
+ int comparison = Integer.compare(another.category, category);
+ if (comparison == 0) {
+ comparison = Long.compare(another.total, total);
+ }
+ return comparison;
}
public static final Creator<AppItem> CREATOR = new Creator<AppItem>() {
@@ -1516,9 +1537,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
*/
public void bindStats(NetworkStats stats, int[] restrictedUids) {
mItems.clear();
+ mLargest = 0;
final int currentUserId = ActivityManager.getCurrentUser();
final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
+ boolean hasApps = false;
NetworkStats.Entry entry = null;
final int size = stats != null ? stats.size() : 0;
@@ -1548,6 +1571,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
item.addUid(uid);
item.total += entry.rxBytes + entry.txBytes;
+ if (item.total > mLargest) {
+ mLargest = item.total;
+ }
}
for (int uid : restrictedUids) {
@@ -1564,8 +1590,14 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
item.restricted = true;
}
+ hasApps = !mItems.isEmpty();
+ if (hasApps) {
+ final AppItem title = new AppItem();
+ title.category = AppItem.CATEGORY_APP_TITLE;
+ mItems.add(title);
+ }
+
Collections.sort(mItems);
- mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0;
notifyDataSetChanged();
}
@@ -1585,36 +1617,72 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(parent.getContext()).inflate(
- R.layout.data_usage_item, parent, false);
+ public int getViewTypeCount() {
+ return 2;
+ }
- if (mInsetSide > 0) {
- convertView.setPaddingRelative(mInsetSide, 0, mInsetSide, 0);
- }
+ @Override
+ public int getItemViewType(int position) {
+ final AppItem item = mItems.get(position);
+ if (item.category == AppItem.CATEGORY_APP_TITLE) {
+ return 1;
+ } else {
+ return 0;
}
+ }
- final Context context = parent.getContext();
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false;
+ }
- final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
- final ProgressBar progress = (ProgressBar) convertView.findViewById(
- android.R.id.progress);
+ @Override
+ public boolean isEnabled(int position) {
+ return getItemViewType(position) == 0;
+ }
- // kick off async load of app details
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
final AppItem item = mItems.get(position);
- UidDetailTask.bindView(mProvider, item, convertView);
+ if (getItemViewType(position) == 1) {
+ if (convertView == null) {
+ convertView = inflateCategoryHeader(LayoutInflater.from(parent.getContext()),
+ parent);
+ }
+
+ final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+ title.setText(R.string.data_usage_app);
- if (item.restricted && item.total <= 0) {
- text1.setText(R.string.data_usage_app_restricted);
- progress.setVisibility(View.GONE);
} else {
- text1.setText(Formatter.formatFileSize(context, item.total));
- progress.setVisibility(View.VISIBLE);
- }
+ if (convertView == null) {
+ convertView = LayoutInflater.from(parent.getContext()).inflate(
+ R.layout.data_usage_item, parent, false);
- final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
- progress.setProgress(percentTotal);
+ if (mInsetSide > 0) {
+ convertView.setPaddingRelative(mInsetSide, 0, mInsetSide, 0);
+ }
+ }
+
+ final Context context = parent.getContext();
+
+ final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
+ final ProgressBar progress = (ProgressBar) convertView.findViewById(
+ android.R.id.progress);
+
+ // kick off async load of app details
+ UidDetailTask.bindView(mProvider, item, convertView);
+
+ if (item.restricted && item.total <= 0) {
+ text1.setText(R.string.data_usage_app_restricted);
+ progress.setVisibility(View.GONE);
+ } else {
+ text1.setText(Formatter.formatFileSize(context, item.total));
+ progress.setVisibility(View.VISIBLE);
+ }
+
+ final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
+ progress.setProgress(percentTotal);
+ }
return convertView;
}
@@ -1639,7 +1707,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
ft.add(fragment, TAG_APP_DETAILS);
ft.addToBackStack(TAG_APP_DETAILS);
- ft.setBreadCrumbTitle(label);
+ ft.setBreadCrumbTitle(
+ parent.getResources().getString(R.string.data_usage_app_summary_title));
ft.commitAllowingStateLoss();
}
@@ -1948,46 +2017,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
/**
* Dialog to request user confirmation before setting
- * {@link android.provider.Settings.Global#DATA_ROAMING}.
- */
- public static class ConfirmDataRoamingFragment extends DialogFragment {
- public static void show(DataUsageSummary parent) {
- if (!parent.isAdded()) return;
-
- final ConfirmDataRoamingFragment dialog = new ConfirmDataRoamingFragment();
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_ROAMING);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.roaming_reenable_title);
- if (Utils.hasMultipleUsers(context)) {
- builder.setMessage(R.string.roaming_warning_multiuser);
- } else {
- builder.setMessage(R.string.roaming_warning);
- }
-
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
- if (target != null) {
- target.setDataRoaming(true);
- }
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- /**
- * Dialog to request user confirmation before setting
* {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
*/
public static class ConfirmRestrictFragment extends DialogFragment {
@@ -2308,12 +2337,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
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;
+ private static View inflateCategoryHeader(LayoutInflater inflater, ViewGroup root) {
+ final TypedArray a = inflater.getContext().obtainStyledAttributes(null,
+ com.android.internal.R.styleable.Preference,
+ com.android.internal.R.attr.preferenceCategoryStyle, 0);
+ final int resId = a.getResourceId(com.android.internal.R.styleable.Preference_layout, 0);
+ return inflater.inflate(resId, root, false);
}
/**
diff --git a/src/com/android/settings/net/DataUsageMeteredSettings.java b/src/com/android/settings/net/DataUsageMeteredSettings.java
index 87358f6..d567c7e 100644
--- a/src/com/android/settings/net/DataUsageMeteredSettings.java
+++ b/src/com/android/settings/net/DataUsageMeteredSettings.java
@@ -29,10 +29,9 @@ import android.net.NetworkTemplate;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
-import android.provider.SearchIndexableResource;
+import android.preference.SwitchPreference;
import android.telephony.TelephonyManager;
import com.android.settings.R;
@@ -42,7 +41,6 @@ import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
@@ -117,7 +115,7 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
return pref;
}
- private class MeteredPreference extends CheckBoxPreference {
+ private class MeteredPreference extends SwitchPreference {
private final NetworkTemplate mTemplate;
private boolean mBinding;
diff --git a/src/com/android/settings/widget/ChartDataUsageView.java b/src/com/android/settings/widget/ChartDataUsageView.java
index 4e16bfc..c20a8db 100644
--- a/src/com/android/settings/widget/ChartDataUsageView.java
+++ b/src/com/android/settings/widget/ChartDataUsageView.java
@@ -50,26 +50,24 @@ public class ChartDataUsageView extends ChartView {
private static final int MSG_UPDATE_AXIS = 100;
private static final long DELAY_MILLIS = 250;
- private static final boolean LIMIT_SWEEPS_TO_VALID_DATA = false;
-
private ChartGridView mGrid;
private ChartNetworkSeriesView mSeries;
private ChartNetworkSeriesView mDetailSeries;
private NetworkStatsHistory mHistory;
- private ChartSweepView mSweepLeft;
- private ChartSweepView mSweepRight;
private ChartSweepView mSweepWarning;
private ChartSweepView mSweepLimit;
+ private long mInspectStart;
+ private long mInspectEnd;
+
private Handler mHandler;
/** Current maximum value of {@link #mVert}. */
private long mVertMax;
public interface DataUsageChartListener {
- public void onInspectRangeChanged();
public void onWarningChanged();
public void onLimitChanged();
public void requestWarningEdit();
@@ -112,43 +110,27 @@ public class ChartDataUsageView extends ChartView {
mDetailSeries = (ChartNetworkSeriesView) findViewById(R.id.detail_series);
mDetailSeries.setVisibility(View.GONE);
- mSweepLeft = (ChartSweepView) findViewById(R.id.sweep_left);
- mSweepRight = (ChartSweepView) findViewById(R.id.sweep_right);
mSweepLimit = (ChartSweepView) findViewById(R.id.sweep_limit);
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
// prevent sweeps from crossing each other
- mSweepLeft.setValidRangeDynamic(null, mSweepRight);
- mSweepRight.setValidRangeDynamic(mSweepLeft, null);
mSweepWarning.setValidRangeDynamic(null, mSweepLimit);
mSweepLimit.setValidRangeDynamic(mSweepWarning, null);
// mark neighbors for checking touch events against
- mSweepLeft.setNeighbors(mSweepRight);
- mSweepRight.setNeighbors(mSweepLeft);
- mSweepLimit.setNeighbors(mSweepWarning, mSweepLeft, mSweepRight);
- mSweepWarning.setNeighbors(mSweepLimit, mSweepLeft, mSweepRight);
+ mSweepLimit.setNeighbors(mSweepWarning);
+ mSweepWarning.setNeighbors(mSweepLimit);
- mSweepLeft.addOnSweepListener(mHorizListener);
- mSweepRight.addOnSweepListener(mHorizListener);
mSweepWarning.addOnSweepListener(mVertListener);
mSweepLimit.addOnSweepListener(mVertListener);
mSweepWarning.setDragInterval(5 * MB_IN_BYTES);
mSweepLimit.setDragInterval(5 * MB_IN_BYTES);
- // TODO: make time sweeps adjustable through dpad
- mSweepLeft.setClickable(false);
- mSweepLeft.setFocusable(false);
- mSweepRight.setClickable(false);
- mSweepRight.setFocusable(false);
-
// tell everyone about our axis
mGrid.init(mHoriz, mVert);
mSeries.init(mHoriz, mVert);
mDetailSeries.init(mHoriz, mVert);
- mSweepLeft.init(mHoriz);
- mSweepRight.init(mHoriz);
mSweepWarning.init(mVert);
mSweepLimit.init(mVert);
@@ -194,7 +176,7 @@ public class ChartDataUsageView extends ChartView {
mSweepLimit.setEnabled(true);
mSweepLimit.setValue(policy.limitBytes);
} else {
- mSweepLimit.setVisibility(View.VISIBLE);
+ mSweepLimit.setVisibility(View.INVISIBLE);
mSweepLimit.setEnabled(false);
mSweepLimit.setValue(-1);
}
@@ -295,23 +277,6 @@ public class ChartDataUsageView extends ChartView {
mSeries.setEstimateVisible(estimateVisible);
}
- private OnSweepListener mHorizListener = new OnSweepListener() {
- @Override
- public void onSweep(ChartSweepView sweep, boolean sweepDone) {
- updatePrimaryRange();
-
- // update detail list only when done sweeping
- if (sweepDone && mListener != null) {
- mListener.onInspectRangeChanged();
- }
- }
-
- @Override
- public void requestEdit(ChartSweepView sweep) {
- // ignored
- }
- };
-
private void sendUpdateAxisDelayed(ChartSweepView sweep, boolean force) {
if (force || !mHandler.hasMessages(MSG_UPDATE_AXIS, sweep)) {
mHandler.sendMessageDelayed(
@@ -369,11 +334,11 @@ public class ChartDataUsageView extends ChartView {
}
public long getInspectStart() {
- return mSweepLeft.getValue();
+ return mInspectStart;
}
public long getInspectEnd() {
- return mSweepRight.getValue();
+ return mInspectEnd;
}
public long getWarningBytes() {
@@ -384,14 +349,6 @@ public class ChartDataUsageView extends ChartView {
return mSweepLimit.getLabelValue();
}
- private long getHistoryStart() {
- return mHistory != null ? mHistory.getStart() : Long.MAX_VALUE;
- }
-
- private long getHistoryEnd() {
- return mHistory != null ? mHistory.getEnd() : Long.MIN_VALUE;
- }
-
/**
* Set the exact time range that should be displayed, updating how
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
@@ -403,30 +360,8 @@ public class ChartDataUsageView extends ChartView {
mSeries.setBounds(visibleStart, visibleEnd);
mDetailSeries.setBounds(visibleStart, visibleEnd);
- final long historyStart = getHistoryStart();
- final long historyEnd = getHistoryEnd();
-
- final long validStart = historyStart == Long.MAX_VALUE ? visibleStart
- : Math.max(visibleStart, historyStart);
- final long validEnd = historyEnd == Long.MIN_VALUE ? visibleEnd
- : Math.min(visibleEnd, historyEnd);
-
- if (LIMIT_SWEEPS_TO_VALID_DATA) {
- // prevent time sweeps from leaving valid data
- mSweepLeft.setValidRange(validStart, validEnd);
- mSweepRight.setValidRange(validStart, validEnd);
- } else {
- mSweepLeft.setValidRange(visibleStart, visibleEnd);
- mSweepRight.setValidRange(visibleStart, visibleEnd);
- }
-
- // default sweeps to last week of data
- final long halfRange = (visibleEnd + visibleStart) / 2;
- final long sweepMax = validEnd;
- final long sweepMin = Math.max(visibleStart, (sweepMax - DateUtils.WEEK_IN_MILLIS));
-
- mSweepLeft.setValue(sweepMin);
- mSweepRight.setValue(sweepMax);
+ mInspectStart = visibleStart;
+ mInspectEnd = visibleEnd;
requestLayout();
if (changed) {
@@ -440,15 +375,11 @@ public class ChartDataUsageView extends ChartView {
}
private void updatePrimaryRange() {
- final long left = mSweepLeft.getValue();
- final long right = mSweepRight.getValue();
-
// prefer showing primary range on detail series, when available
if (mDetailSeries.getVisibility() == View.VISIBLE) {
- mDetailSeries.setPrimaryRange(left, right);
- mSeries.setPrimaryRange(0, 0);
+ mSeries.setSecondary(true);
} else {
- mSeries.setPrimaryRange(left, right);
+ mSeries.setSecondary(false);
}
}
diff --git a/src/com/android/settings/widget/ChartGridView.java b/src/com/android/settings/widget/ChartGridView.java
index ec5882c..4cd6f5f 100644
--- a/src/com/android/settings/widget/ChartGridView.java
+++ b/src/com/android/settings/widget/ChartGridView.java
@@ -19,22 +19,25 @@ package com.android.settings.widget;
import static com.android.settings.DataUsageSummary.formatDateRange;
import android.content.Context;
+import android.content.res.ColorStateList;
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.Log;
import android.util.TypedValue;
import android.view.View;
import com.android.internal.util.Preconditions;
import com.android.settings.R;
+import java.util.Locale;
+
/**
* Background of {@link ChartView} that renders grid lines as requested by
* {@link ChartAxis#getTickPoints()}.
@@ -47,10 +50,13 @@ public class ChartGridView extends View {
private Drawable mPrimary;
private Drawable mSecondary;
private Drawable mBorder;
+
+ private int mLabelSize;
private int mLabelColor;
- private Layout mLayoutStart;
- private Layout mLayoutEnd;
+ private Layout mLabelStart;
+ private Layout mLabelMid;
+ private Layout mLabelEnd;
public ChartGridView(Context context) {
this(context, null, 0);
@@ -71,7 +77,17 @@ 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);
- mLabelColor = a.getColor(R.styleable.ChartGridView_labelColor, Color.RED);
+
+ final int taId = a.getResourceId(R.styleable.ChartGridView_android_textAppearance, -1);
+ final TypedArray ta = context.obtainStyledAttributes(taId,
+ com.android.internal.R.styleable.TextAppearance);
+ mLabelSize = ta.getDimensionPixelSize(
+ com.android.internal.R.styleable.TextAppearance_textSize, 0);
+ ta.recycle();
+
+ final ColorStateList labelColor = a.getColorStateList(
+ R.styleable.ChartGridView_android_textColor);
+ mLabelColor = labelColor.getDefaultColor();
a.recycle();
}
@@ -83,71 +99,83 @@ public class ChartGridView extends View {
void setBounds(long start, long end) {
final Context context = getContext();
- mLayoutStart = makeLayout(formatDateRange(context, start, start));
- mLayoutEnd = makeLayout(formatDateRange(context, end, end));
+ final long mid = (start + end) / 2;
+ mLabelStart = makeLabel(formatDateRange(context, start, start));
+ mLabelMid = makeLabel(formatDateRange(context, mid, mid));
+ mLabelEnd = makeLabel(formatDateRange(context, end, end));
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
- final int height = getHeight();
+ final int height = getHeight() - getPaddingBottom();
final Drawable secondary = mSecondary;
- final int secondaryHeight = mSecondary.getIntrinsicHeight();
-
- final float[] vertTicks = mVert.getTickPoints();
- for (float y : vertTicks) {
- final int bottom = (int) Math.min(y + secondaryHeight, height);
- secondary.setBounds(0, (int) y, width, bottom);
- secondary.draw(canvas);
+ if (secondary != null) {
+ final int secondaryHeight = secondary.getIntrinsicHeight();
+
+ final float[] vertTicks = mVert.getTickPoints();
+ for (float y : vertTicks) {
+ final int bottom = (int) Math.min(y + secondaryHeight, height);
+ secondary.setBounds(0, (int) y, width, bottom);
+ secondary.draw(canvas);
+ }
}
final Drawable primary = mPrimary;
- final int primaryWidth = mPrimary.getIntrinsicWidth();
- final int primaryHeight = mPrimary.getIntrinsicHeight();
-
- final float[] horizTicks = mHoriz.getTickPoints();
- for (float x : horizTicks) {
- final int right = (int) Math.min(x + primaryWidth, width);
- primary.setBounds((int) x, 0, right, height);
- primary.draw(canvas);
+ if (primary != null) {
+ final int primaryWidth = primary.getIntrinsicWidth();
+ final int primaryHeight = primary.getIntrinsicHeight();
+
+ final float[] horizTicks = mHoriz.getTickPoints();
+ for (float x : horizTicks) {
+ final int right = (int) Math.min(x + primaryWidth, width);
+ primary.setBounds((int) x, 0, right, height);
+ primary.draw(canvas);
+ }
}
mBorder.setBounds(0, 0, width, height);
mBorder.draw(canvas);
- final int padding = mLayoutStart != null ? mLayoutStart.getHeight() / 8 : 0;
+ final int padding = mLabelStart != null ? mLabelStart.getHeight() / 8 : 0;
- final Layout start = mLayoutStart;
+ final Layout start = mLabelStart;
if (start != null) {
- canvas.save();
+ final int saveCount = canvas.save();
canvas.translate(0, height + padding);
start.draw(canvas);
- canvas.restore();
+ canvas.restoreToCount(saveCount);
+ }
+
+ final Layout mid = mLabelMid;
+ if (mid != null) {
+ final int saveCount = canvas.save();
+ canvas.translate((width - mid.getWidth()) / 2, height + padding);
+ mid.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
- final Layout end = mLayoutEnd;
+ final Layout end = mLabelEnd;
if (end != null) {
- canvas.save();
+ final int saveCount = canvas.save();
canvas.translate(width - end.getWidth(), height + padding);
end.draw(canvas);
- canvas.restore();
+ canvas.restoreToCount(saveCount);
}
}
- private Layout makeLayout(CharSequence text) {
+ private Layout makeLabel(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()));
+ paint.setTextSize(mLabelSize);
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/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java
index 6250a25..7aaba66 100644
--- a/src/com/android/settings/widget/ChartNetworkSeriesView.java
+++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java
@@ -60,17 +60,17 @@ public class ChartNetworkSeriesView extends View {
private Path mPathFill;
private Path mPathEstimate;
+ private int mSafeRegion;
+
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 boolean mSecondary = false;
private long mMax;
private long mMaxEstimate;
@@ -93,8 +93,11 @@ public class ChartNetworkSeriesView extends View {
final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
final int fillSecondary = a.getColor(
R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
+ final int safeRegion = a.getDimensionPixelSize(
+ R.styleable.ChartNetworkSeriesView_safeRegion, 0);
setChartColor(stroke, fill, fillSecondary);
+ setSafeRegion(safeRegion);
setWillNotDraw(false);
a.recycle();
@@ -134,6 +137,10 @@ public class ChartNetworkSeriesView extends View {
mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
}
+ public void setSafeRegion(int safeRegion) {
+ mSafeRegion = safeRegion;
+ }
+
public void bindNetworkStats(NetworkStatsHistory stats) {
mStats = stats;
invalidatePath();
@@ -145,14 +152,8 @@ public class ChartNetworkSeriesView extends View {
mEnd = end;
}
- /**
- * Set the range to paint with {@link #mPaintFill}, leaving the remaining
- * area to be painted with {@link #mPaintFillSecondary}.
- */
- public void setPrimaryRange(long left, long right) {
- mPrimaryLeft = left;
- mPrimaryRight = right;
- invalidate();
+ public void setSecondary(boolean secondary) {
+ mSecondary = secondary;
}
public void invalidatePath() {
@@ -322,9 +323,6 @@ public class ChartNetworkSeriesView extends View {
generatePath();
}
- final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
- final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);
-
if (mEstimateVisible) {
save = canvas.save();
canvas.clipRect(0, 0, getWidth(), getHeight());
@@ -332,21 +330,11 @@ public class ChartNetworkSeriesView extends View {
canvas.restoreToCount(save);
}
- save = canvas.save();
- canvas.clipRect(0, 0, primaryLeftPoint, getHeight());
- canvas.drawPath(mPathFill, mPaintFillSecondary);
- canvas.restoreToCount(save);
+ final Paint paintFill = mSecondary ? mPaintFillSecondary : mPaintFill;
save = canvas.save();
- canvas.clipRect(primaryRightPoint, 0, getWidth(), getHeight());
- canvas.drawPath(mPathFill, mPaintFillSecondary);
+ canvas.clipRect(mSafeRegion, 0, getWidth(), getHeight() - mSafeRegion);
+ canvas.drawPath(mPathFill, paintFill);
canvas.restoreToCount(save);
-
- save = canvas.save();
- canvas.clipRect(primaryLeftPoint, 0, primaryRightPoint, getHeight());
- canvas.drawPath(mPathFill, mPaintFill);
- canvas.drawPath(mPathStroke, mPaintStroke);
- canvas.restoreToCount(save);
-
}
}
diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java
index 774e5d8..04fc862 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -58,6 +58,7 @@ public class ChartSweepView extends View {
private Rect mMargins = new Rect();
private float mNeighborMargin;
+ private int mSafeRegion;
private int mFollowAxis;
@@ -125,6 +126,7 @@ public class ChartSweepView extends View {
setSweepDrawable(a.getDrawable(R.styleable.ChartSweepView_sweepDrawable));
setFollowAxis(a.getInt(R.styleable.ChartSweepView_followAxis, -1));
setNeighborMargin(a.getDimensionPixelSize(R.styleable.ChartSweepView_neighborMargin, 0));
+ setSafeRegion(a.getDimensionPixelSize(R.styleable.ChartSweepView_safeRegion, 0));
setLabelMinSize(a.getDimensionPixelSize(R.styleable.ChartSweepView_labelSize, 0));
setLabelTemplate(a.getResourceId(R.styleable.ChartSweepView_labelTemplate, 0));
@@ -259,7 +261,6 @@ public class ChartSweepView extends View {
paint.density = getResources().getDisplayMetrics().density;
paint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
paint.setColor(mLabelColor);
- paint.setShadowLayer(4 * paint.density, 0, 0, Color.BLACK);
mLabelTemplate = new SpannableStringBuilder(template);
mLabelLayout = new DynamicLayout(
@@ -383,6 +384,10 @@ public class ChartSweepView extends View {
mNeighborMargin = neighborMargin;
}
+ public void setSafeRegion(int safeRegion) {
+ mSafeRegion = safeRegion;
+ }
+
/**
* Set valid range this sweep can move within, defined by the given
* {@link ChartSweepView}. The most restrictive combination of all valid
@@ -709,7 +714,7 @@ public class ChartSweepView extends View {
mLabelLayout.draw(canvas);
}
canvas.restoreToCount(count);
- labelSize = (int) mLabelSize;
+ labelSize = (int) mLabelSize + mSafeRegion;
} else {
labelSize = 0;
}
diff --git a/src/com/android/settings/widget/ChartView.java b/src/com/android/settings/widget/ChartView.java
index 69e6e94..30284bc 100644
--- a/src/com/android/settings/widget/ChartView.java
+++ b/src/com/android/settings/widget/ChartView.java
@@ -112,12 +112,18 @@ public class ChartView extends FrameLayout {
parentRect.set(mContent);
- if (child instanceof ChartNetworkSeriesView || child instanceof ChartGridView) {
+ if (child instanceof ChartNetworkSeriesView) {
// series are always laid out to fill entire graph area
// TODO: handle scrolling for series larger than content area
Gravity.apply(params.gravity, width, height, parentRect, childRect);
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
+ } else if (child instanceof ChartGridView) {
+ // Grid uses some extra room for labels
+ Gravity.apply(params.gravity, width, height, parentRect, childRect);
+ child.layout(childRect.left, childRect.top, childRect.right,
+ childRect.bottom + child.getPaddingBottom());
+
} else if (child instanceof ChartSweepView) {
layoutSweep((ChartSweepView) child, parentRect, childRect);
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
@@ -154,5 +160,4 @@ public class ChartView extends FrameLayout {
parentRect, childRect);
}
}
-
}
diff --git a/src/com/android/settings/widget/PieChartView.java b/src/com/android/settings/widget/PieChartView.java
deleted file mode 100644
index 6070190..0000000
--- a/src/com/android/settings/widget/PieChartView.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.Path.Direction;
-import android.graphics.RadialGradient;
-import android.graphics.RectF;
-import android.graphics.Shader.TileMode;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
-
-/**
- * Pie chart with multiple items.
- */
-public class PieChartView extends View {
- public static final String TAG = "PieChartView";
- public static final boolean LOGD = false;
-
- private static final boolean FILL_GRADIENT = false;
-
- private ArrayList<Slice> mSlices = Lists.newArrayList();
-
- private int mOriginAngle;
- private Matrix mMatrix = new Matrix();
-
- private Paint mPaintOutline = new Paint();
-
- private Path mPathSide = new Path();
- private Path mPathSideOutline = new Path();
-
- private Path mPathOutline = new Path();
-
- private int mSideWidth;
-
- public class Slice {
- public long value;
-
- public Path path = new Path();
- public Path pathSide = new Path();
- public Path pathOutline = new Path();
-
- public Paint paint;
-
- public Slice(long value, int color) {
- this.value = value;
- this.paint = buildFillPaint(color, getResources());
- }
- }
-
- public PieChartView(Context context) {
- this(context, null);
- }
-
- public PieChartView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PieChartView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mPaintOutline.setColor(Color.BLACK);
- mPaintOutline.setStyle(Style.STROKE);
- mPaintOutline.setStrokeWidth(3f * getResources().getDisplayMetrics().density);
- mPaintOutline.setAntiAlias(true);
-
- mSideWidth = (int) (20 * getResources().getDisplayMetrics().density);
-
- setWillNotDraw(false);
- }
-
- private static Paint buildFillPaint(int color, Resources res) {
- final Paint paint = new Paint();
-
- paint.setColor(color);
- paint.setStyle(Style.FILL_AND_STROKE);
- paint.setAntiAlias(true);
-
- if (FILL_GRADIENT) {
- final int width = (int) (280 * res.getDisplayMetrics().density);
- paint.setShader(new RadialGradient(0, 0, width, color, darken(color), TileMode.MIRROR));
- }
-
- return paint;
- }
-
- public void setOriginAngle(int originAngle) {
- mOriginAngle = originAngle;
- }
-
- public void addSlice(long value, int color) {
- mSlices.add(new Slice(value, color));
- }
-
- public void removeAllSlices() {
- mSlices.clear();
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- final float centerX = getWidth() / 2;
- final float centerY = getHeight() / 2;
-
- mMatrix.reset();
- mMatrix.postScale(0.665f, 0.95f, centerX, centerY);
- mMatrix.postRotate(-40, centerX, centerY);
-
- generatePath();
- }
-
- public void generatePath() {
- if (LOGD) Log.d(TAG, "generatePath()");
-
- long total = 0;
- for (Slice slice : mSlices) {
- slice.path.reset();
- slice.pathSide.reset();
- slice.pathOutline.reset();
- total += slice.value;
- }
-
- mPathSide.reset();
- mPathSideOutline.reset();
- mPathOutline.reset();
-
- // bail when not enough stats to render
- if (total == 0) {
- invalidate();
- return;
- }
-
- final int width = getWidth();
- final int height = getHeight();
-
- final RectF rect = new RectF(0, 0, width, height);
- final RectF rectSide = new RectF();
- rectSide.set(rect);
- rectSide.offset(-mSideWidth, 0);
-
- mPathSide.addOval(rectSide, Direction.CW);
- mPathSideOutline.addOval(rectSide, Direction.CW);
- mPathOutline.addOval(rect, Direction.CW);
-
- int startAngle = mOriginAngle;
- for (Slice slice : mSlices) {
- final int sweepAngle = (int) (slice.value * 360 / total);
- final int endAngle = startAngle + sweepAngle;
-
- final float startAngleMod = startAngle % 360;
- final float endAngleMod = endAngle % 360;
- final boolean startSideVisible = startAngleMod > 90 && startAngleMod < 270;
- final boolean endSideVisible = endAngleMod > 90 && endAngleMod < 270;
-
- // draw slice
- slice.path.moveTo(rect.centerX(), rect.centerY());
- slice.path.arcTo(rect, startAngle, sweepAngle);
- slice.path.lineTo(rect.centerX(), rect.centerY());
-
- if (startSideVisible || endSideVisible) {
-
- // when start is beyond horizon, push until visible
- final float startAngleSide = startSideVisible ? startAngle : 450;
- final float endAngleSide = endSideVisible ? endAngle : 270;
- final float sweepAngleSide = endAngleSide - startAngleSide;
-
- // draw slice side
- slice.pathSide.moveTo(rect.centerX(), rect.centerY());
- slice.pathSide.arcTo(rect, startAngleSide, 0);
- slice.pathSide.rLineTo(-mSideWidth, 0);
- slice.pathSide.arcTo(rectSide, startAngleSide, sweepAngleSide);
- slice.pathSide.rLineTo(mSideWidth, 0);
- slice.pathSide.arcTo(rect, endAngleSide, -sweepAngleSide);
- }
-
- // draw slice outline
- slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
- slice.pathOutline.arcTo(rect, startAngle, 0);
- if (startSideVisible) {
- slice.pathOutline.rLineTo(-mSideWidth, 0);
- }
- slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
- slice.pathOutline.arcTo(rect, startAngle + sweepAngle, 0);
- if (endSideVisible) {
- slice.pathOutline.rLineTo(-mSideWidth, 0);
- }
-
- startAngle += sweepAngle;
- }
-
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
-
- canvas.concat(mMatrix);
-
- for (Slice slice : mSlices) {
- canvas.drawPath(slice.pathSide, slice.paint);
- }
- canvas.drawPath(mPathSideOutline, mPaintOutline);
-
- for (Slice slice : mSlices) {
- canvas.drawPath(slice.path, slice.paint);
- canvas.drawPath(slice.pathOutline, mPaintOutline);
- }
- canvas.drawPath(mPathOutline, mPaintOutline);
- }
-
- public static int darken(int color) {
- float[] hsv = new float[3];
- Color.colorToHSV(color, hsv);
- hsv[2] /= 2;
- hsv[1] /= 2;
- return Color.HSVToColor(hsv);
- }
-
-}