Merge "Data usage fit and finish."
This commit is contained in:
@@ -50,20 +50,6 @@
|
|||||||
settings:fillColor="#c0ba7f3e"
|
settings:fillColor="#c0ba7f3e"
|
||||||
settings:fillColorSecondary="#0000" />
|
settings:fillColorSecondary="#0000" />
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
|
||||||
android:id="@+id/sweep_left"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
settings:sweepDrawable="@drawable/data_sweep_left"
|
|
||||||
settings:followAxis="horizontal" />
|
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
|
||||||
android:id="@+id/sweep_right"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
settings:sweepDrawable="@drawable/data_sweep_right"
|
|
||||||
settings:followAxis="horizontal" />
|
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
<com.android.settings.widget.ChartSweepView
|
||||||
android:id="@+id/sweep_warning"
|
android:id="@+id/sweep_warning"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -84,4 +70,18 @@
|
|||||||
settings:labelTemplate="@string/data_usage_sweep_limit"
|
settings:labelTemplate="@string/data_usage_sweep_limit"
|
||||||
settings:labelColor="#c01a2c" />
|
settings:labelColor="#c01a2c" />
|
||||||
|
|
||||||
|
<com.android.settings.widget.ChartSweepView
|
||||||
|
android:id="@+id/sweep_left"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
settings:sweepDrawable="@drawable/data_sweep_left"
|
||||||
|
settings:followAxis="horizontal" />
|
||||||
|
|
||||||
|
<com.android.settings.widget.ChartSweepView
|
||||||
|
android:id="@+id/sweep_right"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
settings:sweepDrawable="@drawable/data_sweep_right"
|
||||||
|
settings:followAxis="horizontal" />
|
||||||
|
|
||||||
</com.android.settings.widget.DataUsageChartView>
|
</com.android.settings.widget.DataUsageChartView>
|
||||||
|
|||||||
37
res/layout/data_usage_cycles.xml
Normal file
37
res/layout/data_usage_cycles.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/cycles"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="16dip"
|
||||||
|
android:paddingRight="16dip">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:text="@string/data_usage_cycle" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/cycles_spinner"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -32,28 +32,19 @@
|
|||||||
android:divider="?android:attr/listDivider" />
|
android:divider="?android:attr/listDivider" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<include layout="@layout/data_usage_cycles" />
|
||||||
|
<include layout="@layout/data_usage_chart" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/usage_summary"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingLeft="16dip"
|
android:paddingLeft="16dip"
|
||||||
android:paddingRight="16dip">
|
android:paddingRight="16dip"
|
||||||
|
android:paddingTop="8dip"
|
||||||
|
android:paddingBottom="8dip"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:text="@string/data_usage_cycle" />
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/cycles"
|
|
||||||
android:layout_width="0dip"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<include layout="@layout/data_usage_chart" />
|
|
||||||
<include layout="@layout/data_usage_detail" />
|
<include layout="@layout/data_usage_detail" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -17,20 +17,22 @@
|
|||||||
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dip"
|
android:paddingLeft="16dip"
|
||||||
|
android:paddingRight="16dip"
|
||||||
|
android:paddingTop="8dip"
|
||||||
|
android:paddingBottom="8dip"
|
||||||
android:columnCount="2">
|
android:columnCount="2">
|
||||||
|
|
||||||
<!-- TODO: consider using canShrink -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/title"
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_gravity="fill_horizontal"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:layout_columnFlexibility="canStretch"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/summary"
|
android:id="@android:id/summary"
|
||||||
android:layout_gravity="right"
|
|
||||||
android:layout_marginLeft="8dip"
|
android:layout_marginLeft="8dip"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
|
|||||||
@@ -3468,6 +3468,8 @@ found in the list of installed applications.</string>
|
|||||||
<string name="data_usage_uninstalled_apps">Removed apps</string>
|
<string name="data_usage_uninstalled_apps">Removed apps</string>
|
||||||
<!-- Combination of total network bytes sent and received by an application. [CHAR LIMIT=NONE] -->
|
<!-- Combination of total network bytes sent and received by an application. [CHAR LIMIT=NONE] -->
|
||||||
<string name="data_usage_received_sent"><xliff:g id="received" example="128KB">%1$s</xliff:g> received, <xliff:g id="sent" example="1.3GB">%2$s</xliff:g> sent</string>
|
<string name="data_usage_received_sent"><xliff:g id="received" example="128KB">%1$s</xliff:g> received, <xliff:g id="sent" example="1.3GB">%2$s</xliff:g> sent</string>
|
||||||
|
<!-- Label displaying total network data transferred during a specific time period. [CHAR LIMIT=64] -->
|
||||||
|
<string name="data_usage_total_during_range">Data usage: <xliff:g id="total" example="128KB">%1$s</xliff:g> between <xliff:g id="range" example="Jul 1 - Jul 31">%2$s</xliff:g></string>
|
||||||
|
|
||||||
<!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
|
<!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
|
||||||
<string name="cryptkeeper_emergency_call">Emergency call</string>
|
<string name="cryptkeeper_emergency_call">Emergency call</string>
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
private static final boolean LOGD = true;
|
private static final boolean LOGD = true;
|
||||||
|
|
||||||
// TODO: remove this testing code
|
// TODO: remove this testing code
|
||||||
|
private static final boolean TEST_ANIM = false;
|
||||||
private static final boolean TEST_RADIOS = false;
|
private static final boolean TEST_RADIOS = false;
|
||||||
private static final String TEST_RADIOS_PROP = "test.radios";
|
private static final String TEST_RADIOS_PROP = "test.radios";
|
||||||
|
|
||||||
@@ -175,10 +176,12 @@ public class DataUsageSummary extends Fragment {
|
|||||||
private CheckBox mDisableAtLimit;
|
private CheckBox mDisableAtLimit;
|
||||||
private View mDisableAtLimitView;
|
private View mDisableAtLimitView;
|
||||||
|
|
||||||
|
private View mCycleView;
|
||||||
private Spinner mCycleSpinner;
|
private Spinner mCycleSpinner;
|
||||||
private CycleAdapter mCycleAdapter;
|
private CycleAdapter mCycleAdapter;
|
||||||
|
|
||||||
private DataUsageChartView mChart;
|
private DataUsageChartView mChart;
|
||||||
|
private TextView mUsageSummary;
|
||||||
|
|
||||||
private View mAppDetail;
|
private View mAppDetail;
|
||||||
private TextView mAppTitle;
|
private TextView mAppTitle;
|
||||||
@@ -272,7 +275,8 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bind cycle dropdown
|
// bind cycle dropdown
|
||||||
mCycleSpinner = (Spinner) mHeader.findViewById(R.id.cycles);
|
mCycleView = mHeader.findViewById(R.id.cycles);
|
||||||
|
mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
|
||||||
mCycleAdapter = new CycleAdapter(context);
|
mCycleAdapter = new CycleAdapter(context);
|
||||||
mCycleSpinner.setAdapter(mCycleAdapter);
|
mCycleSpinner.setAdapter(mCycleAdapter);
|
||||||
mCycleSpinner.setOnItemSelectedListener(mCycleListener);
|
mCycleSpinner.setOnItemSelectedListener(mCycleListener);
|
||||||
@@ -282,12 +286,12 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// bind app detail controls
|
// bind app detail controls
|
||||||
mAppDetail = view.findViewById(R.id.app_detail);
|
mAppDetail = mHeader.findViewById(R.id.app_detail);
|
||||||
mAppTitle = (TextView) view.findViewById(R.id.app_title);
|
mAppTitle = (TextView) mAppDetail.findViewById(R.id.app_title);
|
||||||
mAppSubtitle = (TextView) view.findViewById(R.id.app_subtitle);
|
mAppSubtitle = (TextView) mAppDetail.findViewById(R.id.app_subtitle);
|
||||||
mAppSwitches = (LinearLayout) view.findViewById(R.id.app_switches);
|
mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
|
||||||
|
|
||||||
mAppSettings = (Button) view.findViewById(R.id.app_settings);
|
mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
|
||||||
mAppSettings.setOnClickListener(mAppSettingsListener);
|
mAppSettings.setOnClickListener(mAppSettingsListener);
|
||||||
|
|
||||||
mAppRestrict = new CheckBox(inflater.getContext());
|
mAppRestrict = new CheckBox(inflater.getContext());
|
||||||
@@ -300,8 +304,10 @@ public class DataUsageSummary extends Fragment {
|
|||||||
mAppSwitches.addView(mAppRestrictView);
|
mAppSwitches.addView(mAppRestrictView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mUsageSummary = (TextView) mHeader.findViewById(R.id.usage_summary);
|
||||||
|
|
||||||
// only assign layout transitions once first layout is finished
|
// only assign layout transitions once first layout is finished
|
||||||
mHeader.getViewTreeObserver().addOnGlobalLayoutListener(mFirstLayoutListener);
|
mListView.getViewTreeObserver().addOnGlobalLayoutListener(mFirstLayoutListener);
|
||||||
|
|
||||||
mAdapter = new DataUsageAdapter();
|
mAdapter = new DataUsageAdapter();
|
||||||
mListView.setOnItemClickListener(mListListener);
|
mListView.setOnItemClickListener(mListListener);
|
||||||
@@ -443,19 +449,28 @@ public class DataUsageSummary extends Fragment {
|
|||||||
private OnGlobalLayoutListener mFirstLayoutListener = new OnGlobalLayoutListener() {
|
private OnGlobalLayoutListener mFirstLayoutListener = new OnGlobalLayoutListener() {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void onGlobalLayout() {
|
public void onGlobalLayout() {
|
||||||
mHeader.getViewTreeObserver().removeGlobalOnLayoutListener(mFirstLayoutListener);
|
mListView.getViewTreeObserver().removeGlobalOnLayoutListener(mFirstLayoutListener);
|
||||||
|
|
||||||
mTabsContainer.setLayoutTransition(new LayoutTransition());
|
mTabsContainer.setLayoutTransition(buildLayoutTransition());
|
||||||
mHeader.setLayoutTransition(new LayoutTransition());
|
mHeader.setLayoutTransition(buildLayoutTransition());
|
||||||
mNetworkSwitchesContainer.setLayoutTransition(new LayoutTransition());
|
mNetworkSwitchesContainer.setLayoutTransition(buildLayoutTransition());
|
||||||
|
|
||||||
final LayoutTransition chartTransition = new LayoutTransition();
|
final LayoutTransition chartTransition = buildLayoutTransition();
|
||||||
chartTransition.setStartDelay(LayoutTransition.APPEARING, 0);
|
chartTransition.setStartDelay(LayoutTransition.APPEARING, 0);
|
||||||
chartTransition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
|
chartTransition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
|
||||||
mChart.setLayoutTransition(chartTransition);
|
mChart.setLayoutTransition(chartTransition);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static LayoutTransition buildLayoutTransition() {
|
||||||
|
final LayoutTransition transition = new LayoutTransition();
|
||||||
|
if (TEST_ANIM) {
|
||||||
|
transition.setDuration(1500);
|
||||||
|
}
|
||||||
|
transition.setAnimateParentHierarchy(false);
|
||||||
|
return transition;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuild all tabs based on {@link NetworkPolicyEditor} and
|
* Rebuild all tabs based on {@link NetworkPolicyEditor} and
|
||||||
* {@link #mShowWifi}, hiding the tabs entirely when applicable. Selects
|
* {@link #mShowWifi}, hiding the tabs entirely when applicable. Selects
|
||||||
@@ -668,7 +683,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
updateDetailData();
|
updateDetailData();
|
||||||
|
|
||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
if (NetworkPolicyManager.isUidValidForPolicy(context, mUid)) {
|
if (NetworkPolicyManager.isUidValidForPolicy(context, mUid) && !getRestrictBackground()) {
|
||||||
mAppRestrictView.setVisibility(View.VISIBLE);
|
mAppRestrictView.setVisibility(View.VISIBLE);
|
||||||
mAppRestrict.setChecked(getAppRestrictBackground());
|
mAppRestrict.setChecked(getAppRestrictBackground());
|
||||||
|
|
||||||
@@ -710,13 +725,22 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getRestrictBackground() {
|
private boolean getRestrictBackground() {
|
||||||
return !mConnService.getBackgroundDataSetting();
|
try {
|
||||||
|
return mPolicyService.getRestrictBackground();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "problem talking with policy service: " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRestrictBackground(boolean restrictBackground) {
|
private void setRestrictBackground(boolean restrictBackground) {
|
||||||
if (LOGD) Log.d(TAG, "setRestrictBackground()");
|
if (LOGD) Log.d(TAG, "setRestrictBackground()");
|
||||||
mConnService.setBackgroundDataSetting(!restrictBackground);
|
try {
|
||||||
mMenuRestrictBackground.setChecked(restrictBackground);
|
mPolicyService.setRestrictBackground(restrictBackground);
|
||||||
|
mMenuRestrictBackground.setChecked(restrictBackground);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "problem talking with policy service: " + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getAppRestrictBackground() {
|
private boolean getAppRestrictBackground() {
|
||||||
@@ -732,7 +756,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setAppRestrictBackground(boolean restrictBackground) {
|
private void setAppRestrictBackground(boolean restrictBackground) {
|
||||||
if (LOGD) Log.d(TAG, "setRestrictBackground()");
|
if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
|
||||||
try {
|
try {
|
||||||
mPolicyService.setUidPolicy(
|
mPolicyService.setUidPolicy(
|
||||||
mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
||||||
@@ -909,7 +933,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
// update chart to show selected cycle, and update detail data
|
// update chart to show selected cycle, and update detail data
|
||||||
// to match updated sweep bounds.
|
// to match updated sweep bounds.
|
||||||
mChart.setVisibleRange(cycle.start, cycle.end, mHistory.getEnd());
|
mChart.setVisibleRange(cycle.start, cycle.end);
|
||||||
|
|
||||||
updateDetailData();
|
updateDetailData();
|
||||||
}
|
}
|
||||||
@@ -932,28 +956,40 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
final long start = mChart.getInspectStart();
|
final long start = mChart.getInspectStart();
|
||||||
final long end = mChart.getInspectEnd();
|
final long end = mChart.getInspectEnd();
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
final Context context = getActivity();
|
||||||
|
final NetworkStatsHistory.Entry entry;
|
||||||
|
|
||||||
if (isAppDetailMode()) {
|
if (isAppDetailMode()) {
|
||||||
if (mDetailHistory != null) {
|
if (mDetailHistory != null) {
|
||||||
final Context context = mChart.getContext();
|
entry = mDetailHistory.getValues(start, end, now, null);
|
||||||
final long now = System.currentTimeMillis();
|
|
||||||
final NetworkStatsHistory.Entry entry = mDetailHistory.getValues(
|
|
||||||
start, end, now, null);
|
|
||||||
|
|
||||||
mAppSubtitle.setText(
|
mAppSubtitle.setText(
|
||||||
getString(R.string.data_usage_received_sent,
|
getString(R.string.data_usage_received_sent,
|
||||||
Formatter.formatFileSize(context, entry.rxBytes),
|
Formatter.formatFileSize(context, entry.rxBytes),
|
||||||
Formatter.formatFileSize(context, entry.txBytes)));
|
Formatter.formatFileSize(context, entry.txBytes)));
|
||||||
|
} else {
|
||||||
|
entry = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLoaderManager().destroyLoader(LOADER_SUMMARY);
|
getLoaderManager().destroyLoader(LOADER_SUMMARY);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
entry = mHistory.getValues(start, end, now, null);
|
||||||
|
|
||||||
// kick off loader for detailed stats
|
// kick off loader for detailed stats
|
||||||
getLoaderManager().restartLoader(LOADER_SUMMARY,
|
getLoaderManager().restartLoader(LOADER_SUMMARY,
|
||||||
SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryForAllUid);
|
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 = formatDateRangeUtc(context, start, end);
|
||||||
|
|
||||||
|
mUsageSummary.setText(
|
||||||
|
getString(R.string.data_usage_total_during_range, totalPhrase, rangePhrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LoaderCallbacks<NetworkStats> mSummaryForAllUid = new LoaderCallbacks<
|
private final LoaderCallbacks<NetworkStats> mSummaryForAllUid = new LoaderCallbacks<
|
||||||
@@ -1022,10 +1058,6 @@ public class DataUsageSummary extends Fragment {
|
|||||||
public long start;
|
public long start;
|
||||||
public long end;
|
public long end;
|
||||||
|
|
||||||
private static final StringBuilder sBuilder = new StringBuilder(50);
|
|
||||||
private static final java.util.Formatter sFormatter = new java.util.Formatter(
|
|
||||||
sBuilder, Locale.getDefault());
|
|
||||||
|
|
||||||
CycleItem(CharSequence label) {
|
CycleItem(CharSequence label) {
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
@@ -1036,21 +1068,30 @@ public class DataUsageSummary extends Fragment {
|
|||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatDateRangeUtc(Context context, long start, long end) {
|
|
||||||
synchronized (sBuilder) {
|
|
||||||
sBuilder.setLength(0);
|
|
||||||
return DateUtils.formatDateRange(context, sFormatter, start, end,
|
|
||||||
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH,
|
|
||||||
Time.TIMEZONE_UTC).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return label.toString();
|
return label.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final StringBuilder sBuilder = new StringBuilder(50);
|
||||||
|
private static final java.util.Formatter sFormatter = new java.util.Formatter(
|
||||||
|
sBuilder, Locale.getDefault());
|
||||||
|
|
||||||
|
private static String formatDateRangeUtc(Context context, long start, long end) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
sBuilder.setLength(0);
|
||||||
|
return DateUtils.formatDateRange(
|
||||||
|
context, sFormatter, start, end, flags, Time.TIMEZONE_UTC).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special-case data usage cycle that triggers dialog to change
|
* Special-case data usage cycle that triggers dialog to change
|
||||||
* {@link NetworkPolicy#cycleDay}.
|
* {@link NetworkPolicy#cycleDay}.
|
||||||
@@ -1366,7 +1407,7 @@ public class DataUsageSummary extends Fragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to request user confirmation before setting
|
* Dialog to request user confirmation before setting
|
||||||
* {@link ConnectivityManager#setBackgroundDataSetting(boolean)}.
|
* {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
|
||||||
*/
|
*/
|
||||||
public static class ConfirmRestrictFragment extends DialogFragment {
|
public static class ConfirmRestrictFragment extends DialogFragment {
|
||||||
public static void show(DataUsageSummary parent) {
|
public static void show(DataUsageSummary parent) {
|
||||||
|
|||||||
@@ -61,8 +61,11 @@ public class ChartSweepView extends FrameLayout {
|
|||||||
private ChartAxis mAxis;
|
private ChartAxis mAxis;
|
||||||
private long mValue;
|
private long mValue;
|
||||||
|
|
||||||
private ChartSweepView mClampAfter;
|
private long mValidAfter;
|
||||||
private ChartSweepView mClampBefore;
|
private long mValidBefore;
|
||||||
|
private ChartSweepView mValidAfterDynamic;
|
||||||
|
private ChartSweepView mValidBeforeDynamic;
|
||||||
|
private long mValidBufferArea;
|
||||||
|
|
||||||
public static final int HORIZONTAL = 0;
|
public static final int HORIZONTAL = 0;
|
||||||
public static final int VERTICAL = 1;
|
public static final int VERTICAL = 1;
|
||||||
@@ -259,12 +262,25 @@ public class ChartSweepView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClampAfter(ChartSweepView clampAfter) {
|
/**
|
||||||
mClampAfter = clampAfter;
|
* Set valid range this sweep can move within, in {@link #mAxis} values. The
|
||||||
|
* most restrictive combination of all valid ranges is used.
|
||||||
|
*/
|
||||||
|
public void setValidRange(long validAfter, long validBefore) {
|
||||||
|
mValidAfter = validAfter;
|
||||||
|
mValidBefore = validBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClampBefore(ChartSweepView clampBefore) {
|
/**
|
||||||
mClampBefore = clampBefore;
|
* Set valid range this sweep can move within, defined by the given
|
||||||
|
* {@link ChartSweepView}. The most restrictive combination of all valid
|
||||||
|
* ranges is used.
|
||||||
|
*/
|
||||||
|
public void setValidRangeDynamic(
|
||||||
|
ChartSweepView validAfter, ChartSweepView validBefore, long bufferArea) {
|
||||||
|
mValidAfterDynamic = validAfter;
|
||||||
|
mValidBeforeDynamic = validBefore;
|
||||||
|
mValidBufferArea = bufferArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -285,6 +301,12 @@ public class ChartSweepView extends FrameLayout {
|
|||||||
|
|
||||||
if (accept) {
|
if (accept) {
|
||||||
mTracking = event.copy();
|
mTracking = event.copy();
|
||||||
|
|
||||||
|
// starting drag should activate entire chart
|
||||||
|
if (!parent.isActivated()) {
|
||||||
|
parent.setActivated(true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -336,31 +358,52 @@ public class ChartSweepView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
|
||||||
|
// ignored to keep LayoutTransition from animating us
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
|
||||||
|
// ignored to keep LayoutTransition from animating us
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getValidAfterValue() {
|
||||||
|
final ChartSweepView dynamic = mValidAfterDynamic;
|
||||||
|
final boolean dynamicEnabled = dynamic != null && dynamic.isEnabled();
|
||||||
|
return Math.max(mValidAfter,
|
||||||
|
dynamicEnabled ? dynamic.getValue() + mValidBufferArea : Long.MIN_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getValidBeforeValue() {
|
||||||
|
final ChartSweepView dynamic = mValidBeforeDynamic;
|
||||||
|
final boolean dynamicEnabled = dynamic != null && dynamic.isEnabled();
|
||||||
|
return Math.min(mValidBefore,
|
||||||
|
dynamicEnabled ? dynamic.getValue() - mValidBufferArea : Long.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute {@link Rect} in {@link #getParent()} coordinates that we should
|
* Compute {@link Rect} in {@link #getParent()} coordinates that we should
|
||||||
* be clamped inside of, usually from {@link #setClampAfter(ChartSweepView)}
|
* be clamped inside of, usually from {@link #setValidRange(long, long)}
|
||||||
* style rules.
|
* style rules.
|
||||||
*/
|
*/
|
||||||
private Rect computeClampRect(Rect parentContent) {
|
private Rect computeClampRect(Rect parentContent) {
|
||||||
final Rect clampRect = new Rect(parentContent);
|
final Rect clampRect = new Rect(parentContent);
|
||||||
|
|
||||||
final ChartSweepView after = mClampAfter;
|
float validAfterPoint = mAxis.convertToPoint(getValidAfterValue());
|
||||||
final ChartSweepView before = mClampBefore;
|
float validBeforePoint = mAxis.convertToPoint(getValidBeforeValue());
|
||||||
|
if (validAfterPoint > validBeforePoint) {
|
||||||
|
float swap = validBeforePoint;
|
||||||
|
validBeforePoint = validAfterPoint;
|
||||||
|
validAfterPoint = swap;
|
||||||
|
}
|
||||||
|
|
||||||
if (mFollowAxis == VERTICAL) {
|
if (mFollowAxis == VERTICAL) {
|
||||||
if (after != null) {
|
clampRect.bottom = clampRect.top + (int) validBeforePoint;
|
||||||
clampRect.top += after.getPoint();
|
clampRect.top += validAfterPoint;
|
||||||
}
|
|
||||||
if (before != null) {
|
|
||||||
clampRect.bottom -= clampRect.height() - before.getPoint();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (after != null) {
|
clampRect.right = clampRect.left + (int) validBeforePoint;
|
||||||
clampRect.left += after.getPoint();
|
clampRect.left += validAfterPoint;
|
||||||
}
|
|
||||||
if (before != null) {
|
|
||||||
clampRect.right -= clampRect.width() - before.getPoint();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return clampRect;
|
return clampRect;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.widget;
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.net.NetworkPolicy;
|
import android.net.NetworkPolicy;
|
||||||
@@ -47,6 +49,8 @@ public class DataUsageChartView extends ChartView {
|
|||||||
private ChartNetworkSeriesView mSeries;
|
private ChartNetworkSeriesView mSeries;
|
||||||
private ChartNetworkSeriesView mDetailSeries;
|
private ChartNetworkSeriesView mDetailSeries;
|
||||||
|
|
||||||
|
private NetworkStatsHistory mHistory;
|
||||||
|
|
||||||
private ChartSweepView mSweepLeft;
|
private ChartSweepView mSweepLeft;
|
||||||
private ChartSweepView mSweepRight;
|
private ChartSweepView mSweepRight;
|
||||||
private ChartSweepView mSweepWarning;
|
private ChartSweepView mSweepWarning;
|
||||||
@@ -88,10 +92,14 @@ public class DataUsageChartView extends ChartView {
|
|||||||
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
|
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
|
||||||
|
|
||||||
// prevent sweeps from crossing each other
|
// prevent sweeps from crossing each other
|
||||||
mSweepLeft.setClampBefore(mSweepRight);
|
mSweepLeft.setValidRangeDynamic(null, mSweepRight, HOUR_IN_MILLIS);
|
||||||
mSweepRight.setClampAfter(mSweepLeft);
|
mSweepRight.setValidRangeDynamic(mSweepLeft, null, HOUR_IN_MILLIS);
|
||||||
mSweepLimit.setClampBefore(mSweepWarning);
|
|
||||||
mSweepWarning.setClampAfter(mSweepLimit);
|
// TODO: assign these ranges as user changes data axis
|
||||||
|
mSweepWarning.setValidRange(0L, 5 * GB_IN_BYTES);
|
||||||
|
mSweepWarning.setValidRangeDynamic(null, mSweepLimit, MB_IN_BYTES);
|
||||||
|
mSweepLimit.setValidRange(0L, 5 * GB_IN_BYTES);
|
||||||
|
mSweepLimit.setValidRangeDynamic(mSweepWarning, null, MB_IN_BYTES);
|
||||||
|
|
||||||
mSweepLeft.addOnSweepListener(mSweepListener);
|
mSweepLeft.addOnSweepListener(mSweepListener);
|
||||||
mSweepRight.addOnSweepListener(mSweepListener);
|
mSweepRight.addOnSweepListener(mSweepListener);
|
||||||
@@ -116,6 +124,7 @@ public class DataUsageChartView extends ChartView {
|
|||||||
|
|
||||||
public void bindNetworkStats(NetworkStatsHistory stats) {
|
public void bindNetworkStats(NetworkStatsHistory stats) {
|
||||||
mSeries.bindNetworkStats(stats);
|
mSeries.bindNetworkStats(stats);
|
||||||
|
mHistory = stats;
|
||||||
updatePrimaryRange();
|
updatePrimaryRange();
|
||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
@@ -197,15 +206,6 @@ public class DataUsageChartView extends ChartView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|
||||||
if (!isActivated()) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.onInterceptTouchEvent(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getInspectStart() {
|
public long getInspectStart() {
|
||||||
return mSweepLeft.getValue();
|
return mSweepLeft.getValue();
|
||||||
}
|
}
|
||||||
@@ -222,18 +222,33 @@ public class DataUsageChartView extends ChartView {
|
|||||||
return mSweepLimit.getValue();
|
return mSweepLimit.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getStatsStart() {
|
||||||
|
return mHistory != null ? mHistory.getStart() : Long.MIN_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getStatsEnd() {
|
||||||
|
return mHistory != null ? mHistory.getEnd() : Long.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the exact time range that should be displayed, updating how
|
* Set the exact time range that should be displayed, updating how
|
||||||
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
|
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
|
||||||
* last "week" of available data, without triggering listener events.
|
* last "week" of available data, without triggering listener events.
|
||||||
*/
|
*/
|
||||||
public void setVisibleRange(long start, long end, long dataBoundary) {
|
public void setVisibleRange(long visibleStart, long visibleEnd) {
|
||||||
mHoriz.setBounds(start, end);
|
mHoriz.setBounds(visibleStart, visibleEnd);
|
||||||
|
|
||||||
|
final long validStart = Math.max(visibleStart, getStatsStart());
|
||||||
|
final long validEnd = Math.min(visibleEnd, getStatsEnd());
|
||||||
|
|
||||||
|
// prevent time sweeps from leaving valid data
|
||||||
|
mSweepLeft.setValidRange(validStart, validEnd);
|
||||||
|
mSweepRight.setValidRange(validStart, validEnd);
|
||||||
|
|
||||||
// default sweeps to last week of data
|
// default sweeps to last week of data
|
||||||
final long halfRange = (end + start) / 2;
|
final long halfRange = (visibleEnd + visibleStart) / 2;
|
||||||
final long sweepMax = Math.min(end, dataBoundary);
|
final long sweepMax = validEnd;
|
||||||
final long sweepMin = Math.max(start, (sweepMax - DateUtils.WEEK_IN_MILLIS));
|
final long sweepMin = Math.max(visibleStart, (sweepMax - DateUtils.WEEK_IN_MILLIS));
|
||||||
|
|
||||||
mSweepLeft.setValue(sweepMin);
|
mSweepLeft.setValue(sweepMin);
|
||||||
mSweepRight.setValue(sweepMax);
|
mSweepRight.setValue(sweepMax);
|
||||||
|
|||||||
Reference in New Issue
Block a user