diff options
Diffstat (limited to 'src')
4 files changed, 217 insertions, 29 deletions
diff --git a/src/com/android/settings/DataUsageAppDetail.java b/src/com/android/settings/DataUsageAppDetail.java index c7c89ee..4e929ad 100644 --- a/src/com/android/settings/DataUsageAppDetail.java +++ b/src/com/android/settings/DataUsageAppDetail.java @@ -21,8 +21,12 @@ import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND; import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL; import static com.android.settings.DataUsageSummary.getHistoryBounds; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; import android.app.Fragment; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Color; @@ -55,6 +59,8 @@ public class DataUsageAppDetail extends Fragment { private int mUid; + private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict"; + private INetworkStatsService mStatsService; private INetworkPolicyManager mPolicyService; @@ -167,6 +173,19 @@ public class DataUsageAppDetail extends Fragment { mText1.setText(Formatter.formatFileSize(context, totalCombined)); } + private void setRestrictBackground(boolean restrictBackground) { + if (LOGD) Log.d(TAG, "setRestrictBackground()"); + try { + mPolicyService.setUidPolicy( + mUid, restrictBackground ? POLICY_REJECT_PAID_BACKGROUND : POLICY_NONE); + } catch (RemoteException e) { + throw new RuntimeException("unable to save policy", e); + } + + mRestrictBackground.setChecked(restrictBackground); + refreshPreferenceViews(); + } + /** * Force rebind of hijacked {@link Preference} views. */ @@ -209,16 +228,48 @@ public class DataUsageAppDetail extends Fragment { /** {@inheritDoc} */ public void onClick(View v) { final boolean restrictBackground = !mRestrictBackground.isChecked(); - mRestrictBackground.setChecked(restrictBackground); - refreshPreferenceViews(); - - try { - mPolicyService.setUidPolicy( - mUid, restrictBackground ? POLICY_REJECT_PAID_BACKGROUND : POLICY_NONE); - } catch (RemoteException e) { - throw new RuntimeException("unable to save policy", e); + + if (restrictBackground) { + // enabling restriction; show confirmation dialog which + // eventually calls setRestrictBackground() once user confirms. + ConfirmRestrictFragment.show(DataUsageAppDetail.this); + } else { + setRestrictBackground(false); } } }; + /** + * Dialog to request user confirmation before setting + * {@link #POLICY_REJECT_PAID_BACKGROUND}. + */ + public static class ConfirmRestrictFragment extends DialogFragment { + public static void show(DataUsageAppDetail parent) { + final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment(); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.data_usage_app_restrict_dialog_title); + builder.setMessage(R.string.data_usage_app_restrict_dialog); + + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + final DataUsageAppDetail target = (DataUsageAppDetail) getTargetFragment(); + if (target != null) { + target.setRestrictBackground(true); + } + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + + return builder.create(); + } + } + } diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index 19caed8..beb3ed4 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -25,8 +25,12 @@ import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL; import static android.net.TrafficStats.TEMPLATE_WIFI; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; import android.app.Fragment; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.INetworkPolicyManager; @@ -61,6 +65,7 @@ import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.NumberPicker; import android.widget.Spinner; import android.widget.TabHost; import android.widget.TabHost.OnTabChangeListener; @@ -90,6 +95,9 @@ public class DataUsageSummary extends Fragment { private static final String TAB_MOBILE = "mobile"; private static final String TAB_WIFI = "wifi"; + private static final String TAG_CONFIRM_LIMIT = "confirmLimit"; + private static final String TAG_CYCLE_EDITOR = "cycleEditor"; + private static final long KB_IN_BYTES = 1024; private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; @@ -365,6 +373,24 @@ public class DataUsageSummary extends Fragment { refreshPreferenceViews(); } + private void setPolicyCycleDay(int cycleDay) { + if (LOGD) Log.d(TAG, "setPolicyCycleDay()"); + mPolicyModifier.setPolicyCycleDay(mTemplate, cycleDay); + updatePolicy(true); + } + + private void setPolicyWarningBytes(long warningBytes) { + if (LOGD) Log.d(TAG, "setPolicyWarningBytes()"); + mPolicyModifier.setPolicyWarningBytes(mTemplate, warningBytes); + updatePolicy(false); + } + + private void setPolicyLimitBytes(long limitBytes) { + if (LOGD) Log.d(TAG, "setPolicyLimitBytes()"); + mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes); + updatePolicy(false); + } + /** * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for * current {@link #mTemplate}. @@ -474,14 +500,13 @@ public class DataUsageSummary extends Fragment { /** {@inheritDoc} */ public void onClick(View v) { final boolean disableAtLimit = !mDisableAtLimit.isChecked(); - mDisableAtLimit.setChecked(disableAtLimit); - refreshPreferenceViews(); - - // TODO: create policy if none exists - // TODO: show interstitial warning dialog to user - final long limitBytes = disableAtLimit ? 5 * GB_IN_BYTES : LIMIT_DISABLED; - mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes); - updatePolicy(false); + if (disableAtLimit) { + // enabling limit; show confirmation dialog which eventually + // calls setPolicyLimitBytes() once user confirms. + ConfirmLimitFragment.show(DataUsageSummary.this); + } else { + setPolicyLimitBytes(LIMIT_DISABLED); + } } }; @@ -504,12 +529,15 @@ public class DataUsageSummary extends Fragment { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { final CycleItem cycle = (CycleItem) parent.getItemAtPosition(position); if (cycle instanceof CycleChangeItem) { - // TODO: show "define cycle" dialog - // also reset back to first cycle - Log.d(TAG, "CHANGE CYCLE DIALOG!!"); + // show cycle editor; will eventually call setPolicyCycleDay() + // when user finishes editing. + CycleEditorFragment.show(DataUsageSummary.this); + + // reset spinner to something other than "change cycle..." + mCycleSpinner.setSelection(0); } else { - if (LOGD) Log.d(TAG, "shoiwng cycle " + cycle); + if (LOGD) Log.d(TAG, "showing cycle " + cycle); // update chart to show selected cycle, and update detail data // to match updated sweep bounds. @@ -558,19 +586,12 @@ public class DataUsageSummary extends Fragment { /** {@inheritDoc} */ public void onWarningChanged() { - if (LOGD) Log.d(TAG, "onWarningChanged()"); - final long warningBytes = mChart.getWarningBytes(); - mPolicyModifier.setPolicyWarningBytes(mTemplate, warningBytes); - updatePolicy(false); + setPolicyWarningBytes(mChart.getWarningBytes()); } /** {@inheritDoc} */ public void onLimitChanged() { - if (LOGD) Log.d(TAG, "onLimitChanged()"); - final long limitBytes = mDisableAtLimit.isChecked() ? mChart.getLimitBytes() - : LIMIT_DISABLED; - mPolicyModifier.setPolicyLimitBytes(mTemplate, limitBytes); - updatePolicy(false); + setPolicyLimitBytes(mChart.getLimitBytes()); } }; @@ -696,5 +717,116 @@ public class DataUsageSummary extends Fragment { } + /** + * Dialog to request user confirmation before setting + * {@link NetworkPolicy#limitBytes}. + */ + public static class ConfirmLimitFragment extends DialogFragment { + public static final String EXTRA_MESSAGE_ID = "messageId"; + public static final String EXTRA_LIMIT_BYTES = "limitBytes"; + + public static void show(DataUsageSummary parent) { + final Bundle args = new Bundle(); + + // TODO: customize default limits based on network template + switch (parent.mTemplate) { + case TEMPLATE_MOBILE_3G_LOWER: { + args.putInt(EXTRA_MESSAGE_ID, R.string.data_usage_limit_dialog_3g); + args.putLong(EXTRA_LIMIT_BYTES, 5 * GB_IN_BYTES); + break; + } + case TEMPLATE_MOBILE_4G: { + args.putInt(EXTRA_MESSAGE_ID, R.string.data_usage_limit_dialog_4g); + args.putLong(EXTRA_LIMIT_BYTES, 5 * GB_IN_BYTES); + break; + } + case TEMPLATE_MOBILE_ALL: { + args.putInt(EXTRA_MESSAGE_ID, R.string.data_usage_limit_dialog_mobile); + args.putLong(EXTRA_LIMIT_BYTES, 5 * GB_IN_BYTES); + break; + } + } + + final ConfirmLimitFragment dialog = new ConfirmLimitFragment(); + dialog.setArguments(args); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG_CONFIRM_LIMIT); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final int messageId = getArguments().getInt(EXTRA_MESSAGE_ID); + final long limitBytes = getArguments().getLong(EXTRA_LIMIT_BYTES); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.data_usage_limit_dialog_title); + builder.setMessage(messageId); + + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + final DataUsageSummary target = (DataUsageSummary) getTargetFragment(); + if (target != null) { + target.setPolicyLimitBytes(limitBytes); + } + } + }); + + return builder.create(); + } + } + + /** + * Dialog to edit {@link NetworkPolicy#cycleDay}. + */ + public static class CycleEditorFragment extends DialogFragment { + public static final String EXTRA_CYCLE_DAY = "cycleDay"; + + public static void show(DataUsageSummary parent) { + final NetworkPolicy policy = parent.mPolicyModifier.getPolicy(parent.mTemplate); + final Bundle args = new Bundle(); + args.putInt(CycleEditorFragment.EXTRA_CYCLE_DAY, policy.cycleDay); + + final CycleEditorFragment dialog = new CycleEditorFragment(); + dialog.setArguments(args); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG_CYCLE_EDITOR); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); + + final View view = dialogInflater.inflate(R.layout.data_usage_cycle_editor, null, false); + final NumberPicker cycleDayPicker = (NumberPicker) view.findViewById(R.id.cycle_day); + + final int oldCycleDay = getArguments().getInt(EXTRA_CYCLE_DAY, 1); + + cycleDayPicker.setMinValue(1); + cycleDayPicker.setMaxValue(31); + cycleDayPicker.setValue(oldCycleDay); + cycleDayPicker.setWrapSelectorWheel(true); + + builder.setTitle(R.string.data_usage_cycle_editor_title); + builder.setView(view); + + builder.setPositiveButton(R.string.data_usage_cycle_editor_positive, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + final int cycleDay = cycleDayPicker.getValue(); + final DataUsageSummary target = (DataUsageSummary) getTargetFragment(); + if (target != null) { + target.setPolicyCycleDay(cycleDay); + } + } + }); + + return builder.create(); + } + } } diff --git a/src/com/android/settings/net/NetworkPolicyModifier.java b/src/com/android/settings/net/NetworkPolicyModifier.java index 1d8aca3..d90609e 100644 --- a/src/com/android/settings/net/NetworkPolicyModifier.java +++ b/src/com/android/settings/net/NetworkPolicyModifier.java @@ -36,6 +36,8 @@ import java.util.ArrayList; * about which policies can coexist. */ public class NetworkPolicyModifier { + // TODO: refactor to "Editor" + // TODO: be more robust when missing policies from service private INetworkPolicyManager mPolicyService; private String mSubscriberId; diff --git a/src/com/android/settings/widget/DataUsageChartView.java b/src/com/android/settings/widget/DataUsageChartView.java index 9dbffcd..6c62fa8 100644 --- a/src/com/android/settings/widget/DataUsageChartView.java +++ b/src/com/android/settings/widget/DataUsageChartView.java @@ -127,6 +127,8 @@ public class DataUsageChartView extends ChartView { } else { mSweepDataWarn.setVisibility(View.INVISIBLE); } + + requestLayout(); } private OnSweepListener mSweepListener = new OnSweepListener() { @@ -195,6 +197,7 @@ public class DataUsageChartView extends ChartView { requestLayout(); mSeries.generatePath(); + mSeries.invalidate(); } public static class TimeAxis implements ChartAxis { |