summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/DataUsageAppDetail.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/DataUsageAppDetail.java')
-rw-r--r--src/com/android/settings/DataUsageAppDetail.java309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/com/android/settings/DataUsageAppDetail.java b/src/com/android/settings/DataUsageAppDetail.java
new file mode 100644
index 0000000..6294ad3
--- /dev/null
+++ b/src/com/android/settings/DataUsageAppDetail.java
@@ -0,0 +1,309 @@
+/*
+ * 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;
+
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+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;
+import android.net.INetworkPolicyManager;
+import android.net.INetworkStatsService;
+import android.net.NetworkPolicyManager;
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.settings.widget.DataUsageChartView;
+import com.android.settings.widget.DataUsageChartView.DataUsageChartListener;
+
+public class DataUsageAppDetail extends Fragment {
+ private static final String TAG = "DataUsage";
+ private static final boolean LOGD = true;
+
+ public static final String EXTRA_UID = "uid";
+ public static final String EXTRA_NETWORK_TEMPLATE = "networkTemplate";
+
+ private int mUid;
+ private NetworkTemplate mTemplate;
+
+ private Intent mAppSettingsIntent;
+
+ private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
+
+ private INetworkStatsService mStatsService;
+ private INetworkPolicyManager mPolicyService;
+
+ private CheckBoxPreference mRestrictBackground;
+ private View mRestrictBackgroundView;
+
+ private FrameLayout mChartContainer;
+ private TextView mTitle;
+ private TextView mText1;
+ private Button mAppSettings;
+ private LinearLayout mSwitches;
+
+ private DataUsageChartView mChart;
+ private NetworkStatsHistory mHistory;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mStatsService = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ mPolicyService = INetworkPolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ final Context context = inflater.getContext();
+ final View view = inflater.inflate(R.layout.data_usage_detail, container, false);
+
+ mChartContainer = (FrameLayout) view.findViewById(R.id.chart_container);
+ mTitle = (TextView) view.findViewById(android.R.id.title);
+ mText1 = (TextView) view.findViewById(android.R.id.text1);
+ mAppSettings = (Button) view.findViewById(R.id.data_usage_app_settings);
+ mSwitches = (LinearLayout) view.findViewById(R.id.switches);
+
+ mRestrictBackground = new CheckBoxPreference(context);
+ mRestrictBackground.setTitle(R.string.data_usage_app_restrict_background);
+ mRestrictBackground.setSummary(R.string.data_usage_app_restrict_background_summary);
+
+ // kick refresh once to force-create views
+ refreshPreferenceViews();
+
+ mSwitches.addView(mRestrictBackgroundView);
+ mRestrictBackgroundView.setOnClickListener(mRestrictBackgroundListener);
+
+ mAppSettings.setOnClickListener(mAppSettingsListener);
+
+ mChart = new DataUsageChartView(context);
+ mChartContainer.addView(mChart);
+
+ mChart.setListener(mChartListener);
+ mChart.setChartColor(Color.parseColor("#d88d3a"), Color.parseColor("#c0ba7f3e"),
+ Color.parseColor("#88566abc"));
+
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ updateBody();
+ }
+
+ private void updateBody() {
+ final PackageManager pm = getActivity().getPackageManager();
+
+ mUid = getArguments().getInt(EXTRA_UID);
+ mTemplate = getArguments().getParcelable(EXTRA_NETWORK_TEMPLATE);
+
+ mTitle.setText(pm.getNameForUid(mUid));
+
+ // enable settings button when package provides it
+ // TODO: target torwards entire UID instead of just first package
+ final String[] packageNames = pm.getPackagesForUid(mUid);
+ if (packageNames != null && packageNames.length > 0) {
+ mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
+ mAppSettingsIntent.setPackage(packageNames[0]);
+ mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
+
+ final boolean matchFound = pm.resolveActivity(mAppSettingsIntent, 0) != null;
+ mAppSettings.setEnabled(matchFound);
+
+ } else {
+ mAppSettingsIntent = null;
+ mAppSettings.setEnabled(false);
+ }
+
+ try {
+ // load stats for current uid and template
+ // TODO: read template from extras
+ mHistory = mStatsService.getHistoryForUid(mTemplate, mUid, NetworkStats.TAG_NONE);
+ } catch (RemoteException e) {
+ // since we can't do much without history, and we don't want to
+ // leave with half-baked UI, we bail hard.
+ throw new RuntimeException("problem reading network stats", e);
+ }
+
+ // bind chart to historical stats
+ mChart.bindNetworkStats(mHistory);
+
+ // show entire history known
+ final long[] bounds = getHistoryBounds(mHistory);
+ mChart.setVisibleRange(bounds[0], bounds[1] + DateUtils.WEEK_IN_MILLIS, bounds[1]);
+ updateDetailData();
+
+ final Context context = getActivity();
+ if (NetworkPolicyManager.isUidValidForPolicy(context, mUid)) {
+ mRestrictBackgroundView.setVisibility(View.VISIBLE);
+
+ final int uidPolicy;
+ try {
+ uidPolicy = mPolicyService.getUidPolicy(mUid);
+ } catch (RemoteException e) {
+ // since we can't do much without policy, we bail hard.
+ throw new RuntimeException("problem reading network policy", e);
+ }
+
+ // update policy checkbox
+ final boolean restrictBackground = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ mRestrictBackground.setChecked(restrictBackground);
+
+ // kick preference views so they rebind from changes above
+ refreshPreferenceViews();
+
+ } else {
+ mRestrictBackgroundView.setVisibility(View.GONE);
+ }
+ }
+
+ private void updateDetailData() {
+ if (LOGD) Log.d(TAG, "updateDetailData()");
+
+ final Context context = mChart.getContext();
+ final long[] range = mChart.getInspectRange();
+ final long[] total = mHistory.getTotalData(range[0], range[1], null);
+ final long totalCombined = total[0] + total[1];
+ mText1.setText(Formatter.formatFileSize(context, totalCombined));
+ }
+
+ private void setRestrictBackground(boolean restrictBackground) {
+ if (LOGD) Log.d(TAG, "setRestrictBackground()");
+ try {
+ mPolicyService.setUidPolicy(
+ mUid, restrictBackground ? POLICY_REJECT_METERED_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.
+ */
+ private void refreshPreferenceViews() {
+ mRestrictBackgroundView = mRestrictBackground.getView(mRestrictBackgroundView, mSwitches);
+ }
+
+ private DataUsageChartListener mChartListener = new DataUsageChartListener() {
+ /** {@inheritDoc} */
+ public void onInspectRangeChanged() {
+ if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
+ updateDetailData();
+ }
+
+ /** {@inheritDoc} */
+ public void onWarningChanged() {
+ // ignored
+ }
+
+ /** {@inheritDoc} */
+ public void onLimitChanged() {
+ // ignored
+ }
+ };
+
+ private OnClickListener mAppSettingsListener = new OnClickListener() {
+ /** {@inheritDoc} */
+ public void onClick(View v) {
+ // TODO: target torwards entire UID instead of just first package
+ startActivity(mAppSettingsIntent);
+ }
+ };
+
+ private OnClickListener mRestrictBackgroundListener = new OnClickListener() {
+ /** {@inheritDoc} */
+ public void onClick(View v) {
+ final boolean restrictBackground = !mRestrictBackground.isChecked();
+
+ 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_METERED_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();
+ }
+ }
+
+}