Also bind policy checkbox correctly. Bug: 4691427 Change-Id: Ib05b39c391bf59582106afff5599d62a04c3c75b
302 lines
11 KiB
Java
302 lines
11 KiB
Java
/*
|
|
* 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 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;
|
|
import android.net.INetworkPolicyManager;
|
|
import android.net.INetworkStatsService;
|
|
import android.net.NetworkPolicyManager;
|
|
import android.net.NetworkStatsHistory;
|
|
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;
|
|
|
|
private int mUid;
|
|
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(Intent.EXTRA_UID);
|
|
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(mUid, TEMPLATE_MOBILE_ALL);
|
|
} 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();
|
|
}
|
|
}
|
|
|
|
}
|