blob: 4e929add22d64b5629ced75d0a9d30513afd2b41 [file] [log] [blame]
Jeff Sharkey4dfa6602011-06-13 00:42:03 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import static android.net.NetworkPolicyManager.POLICY_NONE;
20import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
21import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
22import static com.android.settings.DataUsageSummary.getHistoryBounds;
23
Jeff Sharkey4c72ae52011-06-14 15:01:18 -070024import android.app.AlertDialog;
25import android.app.Dialog;
26import android.app.DialogFragment;
Jeff Sharkey4dfa6602011-06-13 00:42:03 -070027import android.app.Fragment;
28import android.content.Context;
Jeff Sharkey4c72ae52011-06-14 15:01:18 -070029import android.content.DialogInterface;
Jeff Sharkey4dfa6602011-06-13 00:42:03 -070030import android.content.Intent;
31import android.content.pm.PackageManager;
32import android.graphics.Color;
33import android.net.INetworkPolicyManager;
34import android.net.INetworkStatsService;
35import android.net.NetworkStatsHistory;
36import android.os.Bundle;
37import android.os.RemoteException;
38import android.os.ServiceManager;
39import android.preference.CheckBoxPreference;
40import android.preference.Preference;
41import android.text.format.DateUtils;
42import android.text.format.Formatter;
43import android.util.Log;
44import android.view.LayoutInflater;
45import android.view.View;
46import android.view.View.OnClickListener;
47import android.view.ViewGroup;
48import android.widget.Button;
49import android.widget.FrameLayout;
50import android.widget.LinearLayout;
51import android.widget.TextView;
52
53import com.android.settings.widget.DataUsageChartView;
54import com.android.settings.widget.DataUsageChartView.DataUsageChartListener;
55
56public class DataUsageAppDetail extends Fragment {
57 private static final String TAG = "DataUsage";
58 private static final boolean LOGD = true;
59
60 private int mUid;
61
Jeff Sharkey4c72ae52011-06-14 15:01:18 -070062 private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
63
Jeff Sharkey4dfa6602011-06-13 00:42:03 -070064 private INetworkStatsService mStatsService;
65 private INetworkPolicyManager mPolicyService;
66
67 private CheckBoxPreference mRestrictBackground;
68 private View mRestrictBackgroundView;
69
70 private FrameLayout mChartContainer;
71 private TextView mTitle;
72 private TextView mText1;
73 private Button mAppSettings;
74 private LinearLayout mSwitches;
75
76 private DataUsageChartView mChart;
77
78 private int mUidPolicy;
79 private NetworkStatsHistory mHistory;
80
81 @Override
82 public void onCreate(Bundle savedInstanceState) {
83 super.onCreate(savedInstanceState);
84
85 mStatsService = INetworkStatsService.Stub.asInterface(
86 ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
87 mPolicyService = INetworkPolicyManager.Stub.asInterface(
88 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
89 }
90
91 @Override
92 public View onCreateView(LayoutInflater inflater, ViewGroup container,
93 Bundle savedInstanceState) {
94
95 final Context context = inflater.getContext();
96 final View view = inflater.inflate(R.layout.data_usage_detail, container, false);
97
98 mChartContainer = (FrameLayout) view.findViewById(R.id.chart_container);
99 mTitle = (TextView) view.findViewById(android.R.id.title);
100 mText1 = (TextView) view.findViewById(android.R.id.text1);
101 mAppSettings = (Button) view.findViewById(R.id.data_usage_app_settings);
102 mSwitches = (LinearLayout) view.findViewById(R.id.switches);
103
104 mRestrictBackground = new CheckBoxPreference(context);
105 mRestrictBackground.setTitle(R.string.data_usage_app_restrict_background);
106 mRestrictBackground.setSummary(R.string.data_usage_app_restrict_background_summary);
107
108 // kick refresh once to force-create views
109 refreshPreferenceViews();
110
111 mSwitches.addView(mRestrictBackgroundView);
112 mRestrictBackgroundView.setOnClickListener(mRestrictBackgroundListener);
113
114 mAppSettings.setOnClickListener(mAppSettingsListener);
115
116 mChart = new DataUsageChartView(context);
117 mChartContainer.addView(mChart);
118
119 mChart.setListener(mChartListener);
120 mChart.setChartColor(Color.parseColor("#d88d3a"), Color.parseColor("#c0ba7f3e"),
121 Color.parseColor("#88566abc"));
122
123 return view;
124 }
125
126 @Override
127 public void onResume() {
128 super.onResume();
129
130 final Context context = getActivity();
131
132 mUid = getArguments().getInt(Intent.EXTRA_UID);
133 mTitle.setText(context.getPackageManager().getNameForUid(mUid));
134
135 updateBody();
136 }
137
138 private void updateBody() {
139 try {
140 // load stats for current uid and template
141 // TODO: read template from extras
142 mUidPolicy = mPolicyService.getUidPolicy(mUid);
143 mHistory = mStatsService.getHistoryForUid(mUid, TEMPLATE_MOBILE_ALL);
144 } catch (RemoteException e) {
145 // since we can't do much without policy or history, and we don't
146 // want to leave with half-baked UI, we bail hard.
147 throw new RuntimeException("problem reading network stats", e);
148 }
149
150 // bind chart to historical stats
151 mChart.bindNetworkStats(mHistory);
152
153 // show entire history known
154 final long[] bounds = getHistoryBounds(mHistory);
155 mChart.setVisibleRange(bounds[0], bounds[1] + DateUtils.WEEK_IN_MILLIS, bounds[1]);
156 updateDetailData();
157
158 // update policy checkbox
159 final boolean restrictBackground = (mUidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0;
160 mRestrictBackground.setChecked(restrictBackground);
161
162 // kick preference views so they rebind from changes above
163 refreshPreferenceViews();
164 }
165
166 private void updateDetailData() {
167 if (LOGD) Log.d(TAG, "updateDetailData()");
168
169 final Context context = mChart.getContext();
170 final long[] range = mChart.getInspectRange();
171 final long[] total = mHistory.getTotalData(range[0], range[1], null);
172 final long totalCombined = total[0] + total[1];
173 mText1.setText(Formatter.formatFileSize(context, totalCombined));
174 }
175
Jeff Sharkey4c72ae52011-06-14 15:01:18 -0700176 private void setRestrictBackground(boolean restrictBackground) {
177 if (LOGD) Log.d(TAG, "setRestrictBackground()");
178 try {
179 mPolicyService.setUidPolicy(
180 mUid, restrictBackground ? POLICY_REJECT_PAID_BACKGROUND : POLICY_NONE);
181 } catch (RemoteException e) {
182 throw new RuntimeException("unable to save policy", e);
183 }
184
185 mRestrictBackground.setChecked(restrictBackground);
186 refreshPreferenceViews();
187 }
188
Jeff Sharkey4dfa6602011-06-13 00:42:03 -0700189 /**
190 * Force rebind of hijacked {@link Preference} views.
191 */
192 private void refreshPreferenceViews() {
193 mRestrictBackgroundView = mRestrictBackground.getView(mRestrictBackgroundView, mSwitches);
194 }
195
196 private DataUsageChartListener mChartListener = new DataUsageChartListener() {
197 /** {@inheritDoc} */
198 public void onInspectRangeChanged() {
199 if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
200 updateDetailData();
201 }
202
203 /** {@inheritDoc} */
204 public void onWarningChanged() {
205 // ignored
206 }
207
208 /** {@inheritDoc} */
209 public void onLimitChanged() {
210 // ignored
211 }
212 };
213
214 private OnClickListener mAppSettingsListener = new OnClickListener() {
215 /** {@inheritDoc} */
216 public void onClick(View v) {
217 // TODO: target torwards entire UID instead of just first package
218 final PackageManager pm = getActivity().getPackageManager();
219 final String packageName = pm.getPackagesForUid(mUid)[0];
220
221 final Intent intent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
222 intent.setPackage(packageName);
223 startActivity(intent);
224 }
225 };
226
227 private OnClickListener mRestrictBackgroundListener = new OnClickListener() {
228 /** {@inheritDoc} */
229 public void onClick(View v) {
230 final boolean restrictBackground = !mRestrictBackground.isChecked();
Jeff Sharkey4dfa6602011-06-13 00:42:03 -0700231
Jeff Sharkey4c72ae52011-06-14 15:01:18 -0700232 if (restrictBackground) {
233 // enabling restriction; show confirmation dialog which
234 // eventually calls setRestrictBackground() once user confirms.
235 ConfirmRestrictFragment.show(DataUsageAppDetail.this);
236 } else {
237 setRestrictBackground(false);
Jeff Sharkey4dfa6602011-06-13 00:42:03 -0700238 }
239 }
240 };
241
Jeff Sharkey4c72ae52011-06-14 15:01:18 -0700242 /**
243 * Dialog to request user confirmation before setting
244 * {@link #POLICY_REJECT_PAID_BACKGROUND}.
245 */
246 public static class ConfirmRestrictFragment extends DialogFragment {
247 public static void show(DataUsageAppDetail parent) {
248 final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment();
249 dialog.setTargetFragment(parent, 0);
250 dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT);
251 }
252
253 @Override
254 public Dialog onCreateDialog(Bundle savedInstanceState) {
255 final Context context = getActivity();
256
257 final AlertDialog.Builder builder = new AlertDialog.Builder(context);
258 builder.setTitle(R.string.data_usage_app_restrict_dialog_title);
259 builder.setMessage(R.string.data_usage_app_restrict_dialog);
260
261 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
262 public void onClick(DialogInterface dialog, int which) {
263 final DataUsageAppDetail target = (DataUsageAppDetail) getTargetFragment();
264 if (target != null) {
265 target.setRestrictBackground(true);
266 }
267 }
268 });
269 builder.setNegativeButton(android.R.string.cancel, null);
270
271 return builder.create();
272 }
273 }
274
Jeff Sharkey4dfa6602011-06-13 00:42:03 -0700275}