Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12b5c753 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Data usage UI fixes; sweeps, combined history."

parents 295141dc 55d18a57
Loading
Loading
Loading
Loading
+20 −20
Original line number Original line Diff line number Diff line
@@ -14,7 +14,7 @@
     limitations under the License.
     limitations under the License.
-->
-->


<com.android.settings.widget.DataUsageChartView
<com.android.settings.widget.ChartDataUsageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
    android:id="@+id/chart"
    android:id="@+id/chart"
@@ -55,13 +55,29 @@
        settings:fillColor="#c0ba7f3e"
        settings:fillColor="#c0ba7f3e"
        settings:fillColorSecondary="#60ba7f3e" />
        settings:fillColorSecondary="#60ba7f3e" />


    <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"
        settings:neighborMargin="5dip" />

    <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"
        settings:neighborMargin="5dip" />

    <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"
        android:layout_height="wrap_content"
        android:layout_height="wrap_content"
        settings:sweepDrawable="@drawable/data_sweep_warning"
        settings:sweepDrawable="@drawable/data_sweep_warning"
        settings:followAxis="vertical"
        settings:followAxis="vertical"
        settings:neighborMargin="40dip"
        settings:neighborMargin="5dip"
        settings:labelSize="60dip"
        settings:labelSize="60dip"
        settings:labelTemplate="@string/data_usage_sweep_warning"
        settings:labelTemplate="@string/data_usage_sweep_warning"
        settings:labelColor="#f7931d" />
        settings:labelColor="#f7931d" />
@@ -72,25 +88,9 @@
        android:layout_height="wrap_content"
        android:layout_height="wrap_content"
        settings:sweepDrawable="@drawable/data_sweep_limit"
        settings:sweepDrawable="@drawable/data_sweep_limit"
        settings:followAxis="vertical"
        settings:followAxis="vertical"
        settings:neighborMargin="40dip"
        settings:neighborMargin="5dip"
        settings:labelSize="60dip"
        settings:labelSize="60dip"
        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
</com.android.settings.widget.ChartDataUsageView>
        android:id="@+id/sweep_left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        settings:sweepDrawable="@drawable/data_sweep_left"
        settings:followAxis="horizontal"
        settings:neighborMargin="5dip" />

    <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"
        settings:neighborMargin="5dip" />

</com.android.settings.widget.DataUsageChartView>
+126 −59
Original line number Original line Diff line number Diff line
@@ -122,12 +122,13 @@ import android.widget.TextView;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.Phone;
import com.android.settings.net.NetworkPolicyEditor;
import com.android.settings.net.NetworkPolicyEditor;
import com.android.settings.net.SummaryForAllUidLoader;
import com.android.settings.net.SummaryForAllUidLoader;
import com.android.settings.widget.DataUsageChartView;
import com.android.settings.widget.ChartDataUsageView;
import com.android.settings.widget.DataUsageChartView.DataUsageChartListener;
import com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
import com.android.settings.widget.PieChartView;
import com.android.settings.widget.PieChartView;
import com.google.android.collect.Lists;
import com.google.android.collect.Lists;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.Locale;
import java.util.Locale;


@@ -195,7 +196,7 @@ public class DataUsageSummary extends Fragment {
    private Spinner mCycleSpinner;
    private Spinner mCycleSpinner;
    private CycleAdapter mCycleAdapter;
    private CycleAdapter mCycleAdapter;


    private DataUsageChartView mChart;
    private ChartDataUsageView mChart;
    private TextView mUsageSummary;
    private TextView mUsageSummary;
    private TextView mEmpty;
    private TextView mEmpty;


@@ -216,8 +217,7 @@ public class DataUsageSummary extends Fragment {


    private NetworkTemplate mTemplate = null;
    private NetworkTemplate mTemplate = null;


    private static final int UID_NONE = -1;
    private int[] mAppDetailUids = null;
    private int mUid = UID_NONE;


    private Intent mAppSettingsIntent;
    private Intent mAppSettingsIntent;


@@ -307,7 +307,7 @@ public class DataUsageSummary extends Fragment {
        mCycleSpinner.setAdapter(mCycleAdapter);
        mCycleSpinner.setAdapter(mCycleAdapter);
        mCycleSpinner.setOnItemSelectedListener(mCycleListener);
        mCycleSpinner.setOnItemSelectedListener(mCycleListener);


        mChart = (DataUsageChartView) mHeader.findViewById(R.id.chart);
        mChart = (ChartDataUsageView) mHeader.findViewById(R.id.chart);
        mChart.setListener(mChartListener);
        mChart.setListener(mChartListener);


        {
        {
@@ -611,8 +611,9 @@ public class DataUsageSummary extends Fragment {
            mTemplate = buildTemplateMobile4g(getActiveSubscriberId(context));
            mTemplate = buildTemplateMobile4g(getActiveSubscriberId(context));


        } else if (TAB_WIFI.equals(currentTab)) {
        } else if (TAB_WIFI.equals(currentTab)) {
            // wifi doesn't have any controls
            mDataEnabledView.setVisibility(View.GONE);
            mDataEnabledView.setVisibility(View.GONE);
            setPreferenceTitle(mDisableAtLimitView, R.string.data_usage_disable_wifi_limit);
            mDisableAtLimitView.setVisibility(View.GONE);
            mTemplate = buildTemplateWifi();
            mTemplate = buildTemplateWifi();


        } else if (TAB_ETHERNET.equals(currentTab)) {
        } else if (TAB_ETHERNET.equals(currentTab)) {
@@ -649,12 +650,16 @@ public class DataUsageSummary extends Fragment {
    }
    }


    private boolean isAppDetailMode() {
    private boolean isAppDetailMode() {
        return mUid != UID_NONE;
        return mAppDetailUids != null;
    }

    private int getAppDetailPrimaryUid() {
        return mAppDetailUids[0];
    }
    }


    /**
    /**
     * Update UID details panels to match {@link #mUid}, showing or hiding them
     * Update UID details panels to match {@link #mAppDetailUids}, showing or
     * depending on {@link #isAppDetailMode()}.
     * hiding them depending on {@link #isAppDetailMode()}.
     */
     */
    private void updateAppDetail() {
    private void updateAppDetail() {
        final Context context = getActivity();
        final Context context = getActivity();
@@ -681,7 +686,8 @@ public class DataUsageSummary extends Fragment {
        mChart.bindNetworkPolicy(null);
        mChart.bindNetworkPolicy(null);


        // show icon and all labels appearing under this app
        // show icon and all labels appearing under this app
        final UidDetail detail = resolveDetailForUid(context, mUid);
        final int primaryUid = getAppDetailPrimaryUid();
        final UidDetail detail = resolveDetailForUid(context, primaryUid);
        mAppIcon.setImageDrawable(detail.icon);
        mAppIcon.setImageDrawable(detail.icon);


        mAppTitles.removeAllViews();
        mAppTitles.removeAllViews();
@@ -695,7 +701,7 @@ public class DataUsageSummary extends Fragment {


        // enable settings button when package provides it
        // enable settings button when package provides it
        // TODO: target torwards entire UID instead of just first package
        // TODO: target torwards entire UID instead of just first package
        final String[] packageNames = pm.getPackagesForUid(mUid);
        final String[] packageNames = pm.getPackagesForUid(primaryUid);
        if (packageNames != null && packageNames.length > 0) {
        if (packageNames != null && packageNames.length > 0) {
            mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
            mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
            mAppSettingsIntent.setPackage(packageNames[0]);
            mAppSettingsIntent.setPackage(packageNames[0]);
@@ -709,12 +715,40 @@ public class DataUsageSummary extends Fragment {
            mAppSettings.setEnabled(false);
            mAppSettings.setEnabled(false);
        }
        }


        updateDetailHistory();
        updateDetailData();

        if (NetworkPolicyManager.isUidValidForPolicy(context, primaryUid)
                && !getRestrictBackground() && isBandwidthControlEnabled()) {
            setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
            setPreferenceSummary(mAppRestrictView,
                    getString(R.string.data_usage_app_restrict_background_summary,
                            buildLimitedNetworksList()));

            mAppRestrictView.setVisibility(View.VISIBLE);
            mAppRestrict.setChecked(getAppRestrictBackground());

        } else {
            mAppRestrictView.setVisibility(View.GONE);
        }
    }

    /**
     * Update {@link #mDetailHistory} and related values based on
     * {@link #mAppDetailUids}.
     */
    private void updateDetailHistory() {
        try {
        try {
            mDetailHistoryDefault = null;
            mDetailHistoryForeground = null;

            // load stats for current uid and template
            // load stats for current uid and template
            mDetailHistoryDefault = mStatsService.getHistoryForUid(
            for (int uid : mAppDetailUids) {
                    mTemplate, mUid, SET_DEFAULT, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
                mDetailHistoryDefault = collectHistoryForUid(
            mDetailHistoryForeground = mStatsService.getHistoryForUid(
                        uid, SET_DEFAULT, mDetailHistoryDefault);
                    mTemplate, mUid, SET_FOREGROUND, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
                mDetailHistoryForeground = collectHistoryForUid(
                        uid, SET_FOREGROUND, mDetailHistoryForeground);
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // since we can't do much without history, and we don't want to
            // since we can't do much without history, and we don't want to
            // leave with half-baked UI, we bail hard.
            // leave with half-baked UI, we bail hard.
@@ -727,23 +761,24 @@ public class DataUsageSummary extends Fragment {


        // bind chart to historical stats
        // bind chart to historical stats
        mChart.bindDetailNetworkStats(mDetailHistory);
        mChart.bindDetailNetworkStats(mDetailHistory);
    }


        updateDetailData();
    /**

     * Collect {@link NetworkStatsHistory} for the requested UID, combining with
        if (NetworkPolicyManager.isUidValidForPolicy(context, mUid) && !getRestrictBackground()
     * an existing {@link NetworkStatsHistory} if provided.
                && isBandwidthControlEnabled()) {
     */
            setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
    private NetworkStatsHistory collectHistoryForUid(
            setPreferenceSummary(mAppRestrictView,
            int uid, int set, NetworkStatsHistory existing)
                    getString(R.string.data_usage_app_restrict_background_summary,
            throws RemoteException {
                            buildLimitedNetworksList()));
        final NetworkStatsHistory history = mStatsService.getHistoryForUid(

                mTemplate, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
            mAppRestrictView.setVisibility(View.VISIBLE);

            mAppRestrict.setChecked(getAppRestrictBackground());
        if (existing != null) {

            existing.recordEntireHistory(history);
            return existing;
        } else {
        } else {
            mAppRestrictView.setVisibility(View.GONE);
            return history;
        }
        }

    }
    }


    private void setPolicyCycleDay(int cycleDay) {
    private void setPolicyCycleDay(int cycleDay) {
@@ -764,8 +799,8 @@ public class DataUsageSummary extends Fragment {
        updatePolicy(false);
        updatePolicy(false);
    }
    }


    private boolean isNetworkPolicyModifiable() {
    private boolean isNetworkPolicyModifiable(NetworkPolicy policy) {
        return isBandwidthControlEnabled() && mDataEnabled.isChecked();
        return policy != null && isBandwidthControlEnabled() && mDataEnabled.isChecked();
    }
    }


    private boolean isBandwidthControlEnabled() {
    private boolean isBandwidthControlEnabled() {
@@ -810,9 +845,10 @@ public class DataUsageSummary extends Fragment {
    }
    }


    private boolean getAppRestrictBackground() {
    private boolean getAppRestrictBackground() {
        final int primaryUid = getAppDetailPrimaryUid();
        final int uidPolicy;
        final int uidPolicy;
        try {
        try {
            uidPolicy = mPolicyService.getUidPolicy(mUid);
            uidPolicy = mPolicyService.getUidPolicy(primaryUid);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            // since we can't do much without policy, we bail hard.
            // since we can't do much without policy, we bail hard.
            throw new RuntimeException("problem reading network policy", e);
            throw new RuntimeException("problem reading network policy", e);
@@ -823,9 +859,10 @@ public class DataUsageSummary extends Fragment {


    private void setAppRestrictBackground(boolean restrictBackground) {
    private void setAppRestrictBackground(boolean restrictBackground) {
        if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
        if (LOGD) Log.d(TAG, "setAppRestrictBackground()");
        final int primaryUid = getAppDetailPrimaryUid();
        try {
        try {
            mPolicyService.setUidPolicy(
            mPolicyService.setUidPolicy(primaryUid,
                    mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
                    restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw new RuntimeException("unable to save policy", e);
            throw new RuntimeException("unable to save policy", e);
        }
        }
@@ -851,8 +888,8 @@ public class DataUsageSummary extends Fragment {
            }
            }
        }
        }


        final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate, true);
        final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
        if (isNetworkPolicyModifiable()) {
        if (isNetworkPolicyModifiable(policy)) {
            mDisableAtLimitView.setVisibility(View.VISIBLE);
            mDisableAtLimitView.setVisibility(View.VISIBLE);
            mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
            mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
            if (!isAppDetailMode()) {
            if (!isAppDetailMode()) {
@@ -912,19 +949,28 @@ public class DataUsageSummary extends Fragment {
            }
            }


            // one last cycle entry to modify policy cycle day
            // one last cycle entry to modify policy cycle day
            mCycleAdapter.setChangePossible(isNetworkPolicyModifiable());
            mCycleAdapter.setChangePossible(isNetworkPolicyModifiable(policy));
        }
        }


        if (!hasCycles) {
        if (!hasCycles) {
            // no valid cycles; show all data
            // no policy defined cycles; show entry for each four-week period
            // TODO: offer simple ranges like "last week" etc
            long cycleEnd = historyEnd;
            mCycleAdapter.add(new CycleItem(context, historyStart, historyEnd));
            while (cycleEnd > historyStart) {
                final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
                mCycleAdapter.add(new CycleItem(context, cycleStart, cycleEnd));
                cycleEnd = cycleStart;
            }

            mCycleAdapter.setChangePossible(false);
            mCycleAdapter.setChangePossible(false);
        }
        }


        // force pick the current cycle (first item)
        // force pick the current cycle (first item)
        if (mCycleAdapter.getCount() > 0) {
            mCycleSpinner.setSelection(0);
            mCycleSpinner.setSelection(0);
            mCycleListener.onItemSelected(mCycleSpinner, null, 0, 0);
            mCycleListener.onItemSelected(mCycleSpinner, null, 0, 0);
        } else {
            updateDetailData();
        }
    }
    }


    private OnCheckedChangeListener mDataEnabledListener = new OnCheckedChangeListener() {
    private OnCheckedChangeListener mDataEnabledListener = new OnCheckedChangeListener() {
@@ -985,8 +1031,10 @@ public class DataUsageSummary extends Fragment {
    private OnItemClickListener mListListener = new OnItemClickListener() {
    private OnItemClickListener mListListener = new OnItemClickListener() {
        /** {@inheritDoc} */
        /** {@inheritDoc} */
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final Context context = view.getContext();
            final AppUsageItem app = (AppUsageItem) parent.getItemAtPosition(position);
            final AppUsageItem app = (AppUsageItem) parent.getItemAtPosition(position);
            AppDetailsFragment.show(DataUsageSummary.this, app.uid);
            final UidDetail detail = resolveDetailForUid(context, app.uids[0]);
            AppDetailsFragment.show(DataUsageSummary.this, app.uids, detail.label);
        }
        }
    };
    };


@@ -1065,6 +1113,7 @@ public class DataUsageSummary extends Fragment {
            entry = mHistory.getValues(start, end, now, null);
            entry = mHistory.getValues(start, end, now, null);


            // kick off loader for detailed stats
            // kick off loader for detailed stats
            // TODO: delay loader until animation is finished
            getLoaderManager().restartLoader(LOADER_SUMMARY,
            getLoaderManager().restartLoader(LOADER_SUMMARY,
                    SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryForAllUid);
                    SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryForAllUid);
        }
        }
@@ -1222,9 +1271,20 @@ public class DataUsageSummary extends Fragment {
    }
    }


    private static class AppUsageItem implements Comparable<AppUsageItem> {
    private static class AppUsageItem implements Comparable<AppUsageItem> {
        public int uid;
        public int[] uids;
        public long total;
        public long total;


        public AppUsageItem(int uid) {
            uids = new int[] { uid };
        }

        public void addUid(int uid) {
            if (contains(uids, uid)) return;
            final int length = uids.length;
            uids = Arrays.copyOf(uids, length + 1);
            uids[length] = uid;
        }

        /** {@inheritDoc} */
        /** {@inheritDoc} */
        public int compareTo(AppUsageItem another) {
        public int compareTo(AppUsageItem another) {
            return Long.compare(another.total, total);
            return Long.compare(another.total, total);
@@ -1244,9 +1304,7 @@ public class DataUsageSummary extends Fragment {
        public void bindStats(NetworkStats stats) {
        public void bindStats(NetworkStats stats) {
            mItems.clear();
            mItems.clear();


            final AppUsageItem systemItem = new AppUsageItem();
            final AppUsageItem systemItem = new AppUsageItem(android.os.Process.SYSTEM_UID);
            systemItem.uid = android.os.Process.SYSTEM_UID;

            final SparseArray<AppUsageItem> knownUids = new SparseArray<AppUsageItem>();
            final SparseArray<AppUsageItem> knownUids = new SparseArray<AppUsageItem>();


            NetworkStats.Entry entry = null;
            NetworkStats.Entry entry = null;
@@ -1260,8 +1318,7 @@ public class DataUsageSummary extends Fragment {
                if (isApp || uid == TrafficStats.UID_REMOVED) {
                if (isApp || uid == TrafficStats.UID_REMOVED) {
                    AppUsageItem item = knownUids.get(uid);
                    AppUsageItem item = knownUids.get(uid);
                    if (item == null) {
                    if (item == null) {
                        item = new AppUsageItem();
                        item = new AppUsageItem(uid);
                        item.uid = uid;
                        knownUids.put(uid, item);
                        knownUids.put(uid, item);
                        mItems.add(item);
                        mItems.add(item);
                    }
                    }
@@ -1269,6 +1326,7 @@ public class DataUsageSummary extends Fragment {
                    item.total += entry.rxBytes + entry.txBytes;
                    item.total += entry.rxBytes + entry.txBytes;
                } else {
                } else {
                    systemItem.total += entry.rxBytes + entry.txBytes;
                    systemItem.total += entry.rxBytes + entry.txBytes;
                    systemItem.addUid(uid);
                }
                }
            }
            }


@@ -1293,7 +1351,7 @@ public class DataUsageSummary extends Fragment {


        @Override
        @Override
        public long getItemId(int position) {
        public long getItemId(int position) {
            return mItems.get(position).uid;
            return mItems.get(position).uids[0];
        }
        }


        @Override
        @Override
@@ -1312,7 +1370,7 @@ public class DataUsageSummary extends Fragment {
                    android.R.id.progress);
                    android.R.id.progress);


            final AppUsageItem item = mItems.get(position);
            final AppUsageItem item = mItems.get(position);
            final UidDetail detail = resolveDetailForUid(context, item.uid);
            final UidDetail detail = resolveDetailForUid(context, item.uids[0]);


            icon.setImageDrawable(detail.icon);
            icon.setImageDrawable(detail.icon);
            title.setText(detail.label);
            title.setText(detail.label);
@@ -1323,7 +1381,6 @@ public class DataUsageSummary extends Fragment {


            return convertView;
            return convertView;
        }
        }

    }
    }


    /**
    /**
@@ -1331,11 +1388,11 @@ public class DataUsageSummary extends Fragment {
     * {@link DataUsageSummary}.
     * {@link DataUsageSummary}.
     */
     */
    public static class AppDetailsFragment extends Fragment {
    public static class AppDetailsFragment extends Fragment {
        private static final String EXTRA_UID = "uid";
        private static final String EXTRA_UIDS = "uids";


        public static void show(DataUsageSummary parent, int uid) {
        public static void show(DataUsageSummary parent, int[] uids, CharSequence label) {
            final Bundle args = new Bundle();
            final Bundle args = new Bundle();
            args.putInt(EXTRA_UID, uid);
            args.putIntArray(EXTRA_UIDS, uids);


            final AppDetailsFragment fragment = new AppDetailsFragment();
            final AppDetailsFragment fragment = new AppDetailsFragment();
            fragment.setArguments(args);
            fragment.setArguments(args);
@@ -1344,6 +1401,7 @@ public class DataUsageSummary extends Fragment {
            final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
            final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
            ft.add(fragment, TAG_APP_DETAILS);
            ft.add(fragment, TAG_APP_DETAILS);
            ft.addToBackStack(TAG_APP_DETAILS);
            ft.addToBackStack(TAG_APP_DETAILS);
            ft.setBreadCrumbTitle(label);
            ft.commit();
            ft.commit();
        }
        }


@@ -1351,7 +1409,7 @@ public class DataUsageSummary extends Fragment {
        public void onStart() {
        public void onStart() {
            super.onStart();
            super.onStart();
            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
            target.mUid = getArguments().getInt(EXTRA_UID);
            target.mAppDetailUids = getArguments().getIntArray(EXTRA_UIDS);
            target.updateBody();
            target.updateBody();
        }
        }


@@ -1359,7 +1417,7 @@ public class DataUsageSummary extends Fragment {
        public void onStop() {
        public void onStop() {
            super.onStop();
            super.onStop();
            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
            final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
            target.mUid = UID_NONE;
            target.mAppDetailUids = null;
            target.updateBody();
            target.updateBody();
        }
        }
    }
    }
@@ -1441,7 +1499,7 @@ public class DataUsageSummary extends Fragment {
        private static final String EXTRA_CYCLE_DAY = "cycleDay";
        private static final String EXTRA_CYCLE_DAY = "cycleDay";


        public static void show(DataUsageSummary parent) {
        public static void show(DataUsageSummary parent) {
            final NetworkPolicy policy = parent.mPolicyEditor.getPolicy(parent.mTemplate, false);
            final NetworkPolicy policy = parent.mPolicyEditor.getPolicy(parent.mTemplate);
            final Bundle args = new Bundle();
            final Bundle args = new Bundle();
            args.putInt(CycleEditorFragment.EXTRA_CYCLE_DAY, policy.cycleDay);
            args.putInt(CycleEditorFragment.EXTRA_CYCLE_DAY, policy.cycleDay);


@@ -1807,4 +1865,13 @@ public class DataUsageSummary extends Fragment {
        summary.setVisibility(View.VISIBLE);
        summary.setVisibility(View.VISIBLE);
        summary.setText(string);
        summary.setText(string);
    }
    }

    private static boolean contains(int[] haystack, int needle) {
        for (int value : haystack) {
            if (value == needle) {
                return true;
            }
        }
        return false;
    }
}
}
+51 −34
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
import static android.net.NetworkTemplate.buildTemplateMobile4g;
import static android.net.NetworkTemplate.buildTemplateMobile4g;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
@@ -40,7 +41,7 @@ import java.util.ArrayList;


/**
/**
 * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
 * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
 * about which policies can coexist.
 * about which policies can coexist. Not thread safe.
 */
 */
public class NetworkPolicyEditor {
public class NetworkPolicyEditor {
    // TODO: be more robust when missing policies from service
    // TODO: be more robust when missing policies from service
@@ -53,65 +54,81 @@ public class NetworkPolicyEditor {
    }
    }


    public void read() {
    public void read() {
        final NetworkPolicy[] policies;
        try {
        try {
            final NetworkPolicy[] policies = mPolicyService.getNetworkPolicies();
            policies = mPolicyService.getNetworkPolicies();
        } catch (RemoteException e) {
            throw new RuntimeException("problem reading policies", e);
        }

        boolean modified = false;
        mPolicies.clear();
        mPolicies.clear();
        for (NetworkPolicy policy : policies) {
        for (NetworkPolicy policy : policies) {
            // TODO: find better place to clamp these
            // TODO: find better place to clamp these
            if (policy.limitBytes < -1) {
            if (policy.limitBytes < -1) {
                policy.limitBytes = LIMIT_DISABLED;
                policy.limitBytes = LIMIT_DISABLED;
                modified = true;
            }
            }
            if (policy.warningBytes < -1) {
            if (policy.warningBytes < -1) {
                policy.warningBytes = WARNING_DISABLED;
                policy.warningBytes = WARNING_DISABLED;
                modified = true;
            }
            }


                mPolicies.add(policy);
            // drop any WIFI policies that were defined
            if (policy.template.getMatchRule() == MATCH_WIFI) {
                modified = true;
                continue;
            }
            }
        } catch (RemoteException e) {

            throw new RuntimeException("problem reading policies", e);
            mPolicies.add(policy);
        }
        }

        // when we cleaned policies above, write back changes
        if (modified) writeAsync();
    }
    }


    public void writeAsync() {
    public void writeAsync() {
        // TODO: consider making more robust by passing through service
        // TODO: consider making more robust by passing through service
        final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
        new AsyncTask<Void, Void, Void>() {
        new AsyncTask<Void, Void, Void>() {
            @Override
            @Override
            protected Void doInBackground(Void... params) {
            protected Void doInBackground(Void... params) {
                write();
                write(policies);
                return null;
                return null;
            }
            }
        }.execute();
        }.execute();
    }
    }


    public void write() {
    public void write(NetworkPolicy[] policies) {
        try {
        try {
            final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
            mPolicyService.setNetworkPolicies(policies);
            mPolicyService.setNetworkPolicies(policies);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw new RuntimeException("problem reading policies", e);
            throw new RuntimeException("problem writing policies", e);
        }
        }
    }
    }


    public boolean hasLimitedPolicy(NetworkTemplate template) {
    public boolean hasLimitedPolicy(NetworkTemplate template) {
        final NetworkPolicy policy = getPolicy(template, false);
        final NetworkPolicy policy = getPolicy(template);
        return policy != null && policy.limitBytes != LIMIT_DISABLED;
        return policy != null && policy.limitBytes != LIMIT_DISABLED;
    }
    }


    public NetworkPolicy getPolicy(NetworkTemplate template, boolean createDefault) {
    public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) {
        NetworkPolicy policy = getPolicy(template);
        if (policy == null) {
            policy = buildDefaultPolicy(template);
            mPolicies.add(policy);
        }
        return policy;
    }

    public NetworkPolicy getPolicy(NetworkTemplate template) {
        for (NetworkPolicy policy : mPolicies) {
        for (NetworkPolicy policy : mPolicies) {
            if (policy.template.equals(template)) {
            if (policy.template.equals(template)) {
                return policy;
                return policy;
            }
            }
        }
        }

        if (createDefault) {
            final NetworkPolicy policy = buildDefaultPolicy(template);
            mPolicies.add(policy);
            return policy;
        } else {
        return null;
        return null;
    }
    }
    }


    private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
    private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
        // TODO: move this into framework to share with NetworkPolicyManagerService
        // TODO: move this into framework to share with NetworkPolicyManagerService
@@ -124,21 +141,21 @@ public class NetworkPolicyEditor {
    }
    }


    public void setPolicyCycleDay(NetworkTemplate template, int cycleDay) {
    public void setPolicyCycleDay(NetworkTemplate template, int cycleDay) {
        final NetworkPolicy policy = getPolicy(template, true);
        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.cycleDay = cycleDay;
        policy.cycleDay = cycleDay;
        policy.lastSnooze = SNOOZE_NEVER;
        policy.lastSnooze = SNOOZE_NEVER;
        writeAsync();
        writeAsync();
    }
    }


    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
        final NetworkPolicy policy = getPolicy(template, true);
        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.warningBytes = warningBytes;
        policy.warningBytes = warningBytes;
        policy.lastSnooze = SNOOZE_NEVER;
        policy.lastSnooze = SNOOZE_NEVER;
        writeAsync();
        writeAsync();
    }
    }


    public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
    public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
        final NetworkPolicy policy = getPolicy(template, true);
        final NetworkPolicy policy = getOrCreatePolicy(template);
        policy.limitBytes = limitBytes;
        policy.limitBytes = limitBytes;
        policy.lastSnooze = SNOOZE_NEVER;
        policy.lastSnooze = SNOOZE_NEVER;
        writeAsync();
        writeAsync();
@@ -176,8 +193,8 @@ public class NetworkPolicyEditor {


        } else if (beforeSplit && !split) {
        } else if (beforeSplit && !split) {
            // combine, picking most restrictive policy
            // combine, picking most restrictive policy
            final NetworkPolicy policy3g = getPolicy(template3g, false);
            final NetworkPolicy policy3g = getPolicy(template3g);
            final NetworkPolicy policy4g = getPolicy(template4g, false);
            final NetworkPolicy policy4g = getPolicy(template4g);


            final NetworkPolicy restrictive = policy3g.compareTo(policy4g) < 0 ? policy3g
            final NetworkPolicy restrictive = policy3g.compareTo(policy4g) < 0 ? policy3g
                    : policy4g;
                    : policy4g;
@@ -190,7 +207,7 @@ public class NetworkPolicyEditor {


        } else if (!beforeSplit && split) {
        } else if (!beforeSplit && split) {
            // duplicate existing policy into two rules
            // duplicate existing policy into two rules
            final NetworkPolicy policyAll = getPolicy(templateAll, false);
            final NetworkPolicy policyAll = getPolicy(templateAll);
            mPolicies.remove(policyAll);
            mPolicies.remove(policyAll);
            mPolicies.add(
            mPolicies.add(
                    new NetworkPolicy(template3g, policyAll.cycleDay, policyAll.warningBytes,
                    new NetworkPolicy(template3g, policyAll.cycleDay, policyAll.warningBytes,
+107 −5

File changed.

Preview size limit exceeded, changes collapsed.

Loading