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

Commit 2581c096 authored by Doris Ling's avatar Doris Ling Committed by Android (Google) Code Review
Browse files

Merge "Use the loader to get usage data for each billing cycle."

parents 67793945 654adf9c
Loading
Loading
Loading
Loading
+74 −13
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.FeatureFlagUtils;
import android.util.Pair;
import android.util.SparseIntArray;

import androidx.annotation.VisibleForTesting;
@@ -31,7 +33,11 @@ import androidx.preference.PreferenceViewHolder;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.FeatureFlags;
import com.android.settings.widget.UsageView;
import com.android.settingslib.net.NetworkCycleData;

import java.util.List;

public class ChartDataUsagePreference extends Preference {

@@ -45,7 +51,9 @@ public class ChartDataUsagePreference extends Preference {
    private NetworkPolicy mPolicy;
    private long mStart;
    private long mEnd;
    @Deprecated
    private NetworkStatsHistory mNetwork;
    private NetworkCycleData mNetworkCycleData;
    private int mSecondaryColor;
    private int mSeriesColor;

@@ -60,13 +68,25 @@ public class ChartDataUsagePreference extends Preference {
    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);
        UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
        if (mNetwork == null) return;
        final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
            if (mNetworkCycleData == null) {
                return;
            }
        } else {
            if (mNetwork == null) {
                return;
            }
        }

        int top = getTop();
        final int top = getTop();
        chart.clearPaths();
        chart.configureGraph(toInt(mEnd - mStart), top);
        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
            calcPoints(chart, mNetworkCycleData.usageBuckets);
        } else {
            calcPoints(chart);
        }
        chart.setBottomLabels(new CharSequence[] {
                Utils.formatDateRange(getContext(), mStart, mStart),
                Utils.formatDateRange(getContext(), mEnd, mEnd),
@@ -76,8 +96,11 @@ public class ChartDataUsagePreference extends Preference {
    }

    public int getTop() {
        NetworkStatsHistory.Entry entry = null;
        long totalData = 0;
        if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
            totalData = mNetworkCycleData.totalUsage;
        } else {
            NetworkStatsHistory.Entry entry = null;
            final int start = mNetwork.getIndexBefore(mStart);
            final int end = mNetwork.getIndexAfter(mEnd);

@@ -87,10 +110,12 @@ public class ChartDataUsagePreference extends Preference {
                // increment by current bucket total
                totalData += entry.rxBytes + entry.txBytes;
            }
        }
        long policyMax = mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
        return (int) (Math.max(totalData, policyMax) / RESOLUTION);
    }

    @Deprecated
    @VisibleForTesting
    void calcPoints(UsageView chart) {
        SparseIntArray points = new SparseIntArray();
@@ -123,6 +148,33 @@ public class ChartDataUsagePreference extends Preference {
        }
    }

    @VisibleForTesting
    void calcPoints(UsageView chart, List<NetworkCycleData> usageSummary) {
        if (usageSummary == null) {
            return;
        }
        final SparseIntArray points = new SparseIntArray();
        points.put(0, 0);

        long totalData = 0;
        for (NetworkCycleData data : usageSummary) {
            final long startTime = data.startTime;
            final long endTime = data.endTime;

            // increment by current bucket total
            totalData += data.totalUsage;

            if (points.size() == 1) {
                points.put(toInt(data.startTime - mStart) - 1, -1);
            }
            points.put(toInt(startTime - mStart + 1), (int) (totalData / RESOLUTION));
            points.put(toInt(endTime - mStart), (int) (totalData / RESOLUTION));
        }
        if (points.size() > 1) {
            chart.addPath(points);
        }
    }

    private int toInt(long l) {
        // Don't need that much resolution on these times.
        return (int) (l / (1000 * 60));
@@ -168,6 +220,7 @@ public class ChartDataUsagePreference extends Preference {
        notifyChanged();
    }

    @Deprecated
    public void setVisibleRange(long start, long end) {
        mStart = start;
        mEnd = end;
@@ -182,11 +235,19 @@ public class ChartDataUsagePreference extends Preference {
        return mEnd;
    }

    @Deprecated
    public void setNetworkStats(NetworkStatsHistory network) {
        mNetwork = network;
        notifyChanged();
    }

    public void setNetworkCycleData(NetworkCycleData data) {
        mNetworkCycleData = data;
        mStart = data.startTime;
        mEnd = data.endTime;
        notifyChanged();
    }

    public void setColors(int seriesColor, int secondaryColor) {
        mSeriesColor = seriesColor;
        mSecondaryColor = secondaryColor;
+35 −1
Original line number Diff line number Diff line
@@ -25,9 +25,11 @@ import android.widget.ArrayAdapter;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.net.ChartData;
import com.android.settingslib.net.NetworkCycleData;

import java.time.ZonedDateTime;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
@@ -68,6 +70,7 @@ public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
     * {@link NetworkStatsHistory} data. Always selects the newest item,
     * updating the inspection range on chartData.
     */
    @Deprecated
    public boolean updateCycleList(NetworkPolicy policy, ChartData chartData) {
        // stash away currently selected cycle to try restoring below
        final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
@@ -149,6 +152,37 @@ public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
        return true;
    }

    /**
     * Rebuild list based on network data. Always selects the newest item,
     * updating the inspection range on chartData.
     */
    public boolean updateCycleList(List<NetworkCycleData> cycleData) {
        // stash away currently selected cycle to try restoring below
        final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
            mSpinner.getSelectedItem();
        clear();

        final Context context = getContext();
        for (NetworkCycleData data : cycleData) {
            add(new CycleAdapter.CycleItem(context, data.startTime, data.endTime));
        }

        // force pick the current cycle (first item)
        if (getCount() > 0) {
            final int position = findNearestPosition(previousItem);
            mSpinner.setSelection(position);

            // only force-update cycle when changed; skipping preserves any
            // user-defined inspection region.
            final CycleAdapter.CycleItem selectedItem = getItem(position);
            if (!Objects.equals(selectedItem, previousItem)) {
                mListener.onItemSelected(null, null, position, 0);
                return false;
            }
        }
        return true;
    }

    /**
     * List item that reflects a specific data usage cycle.
     */
+2 −2
Original line number Diff line number Diff line
@@ -352,7 +352,7 @@ public class DataUsageList extends DataUsageBaseFragment {
    /**
     * Bind the given {@link NetworkStats}, or {@code null} to clear list.
     */
    public void bindStats(NetworkStats stats, int[] restrictedUids) {
    private void bindStats(NetworkStats stats, int[] restrictedUids) {
        ArrayList<AppItem> items = new ArrayList<>();
        long largest = 0;

@@ -464,7 +464,7 @@ public class DataUsageList extends DataUsageBaseFragment {
     * @param entry        the network stats entry to extract data usage from.
     * @param itemCategory the item is categorized on the list view by this category. Must be
     */
    private static long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
    private long accumulate(int collapseKey, final SparseArray<AppItem> knownItems,
            NetworkStats.Entry entry, int itemCategory, ArrayList<AppItem> items, long largest) {
        final int uid = entry.uid;
        AppItem item = knownItems.get(collapseKey);
+33 −52
Original line number Diff line number Diff line
@@ -14,12 +14,11 @@

package com.android.settings.datausage;

import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.telephony.TelephonyManager.SIM_STATE_READY;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStats.Bucket;
@@ -28,15 +27,12 @@ import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -64,9 +60,10 @@ import com.android.settings.core.SubSettingLauncher;
import com.android.settings.datausage.CycleAdapter.SpinnerInterface;
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.AppItem;
import com.android.settingslib.net.ChartData;
import com.android.settingslib.net.ChartDataLoaderCompat;
import com.android.settingslib.net.NetworkStatsDetailLoader;
import com.android.settingslib.net.NetworkCycleDataLoader;
import com.android.settingslib.net.NetworkCycleData;
import com.android.settingslib.net.NetworkStatsSummaryLoader;
import com.android.settingslib.net.UidDetailProvider;

import java.util.ArrayList;
@@ -101,8 +98,8 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
                }
            };

    private INetworkStatsSession mStatsSession;
    private ChartDataUsagePreference mChart;
    private TelephonyManager mTelephonyManager;

    @VisibleForTesting
    NetworkTemplate mTemplate;
@@ -110,7 +107,7 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    @VisibleForTesting
    int mNetworkType;
    private ChartData mChartData;
    private List<NetworkCycleData> mCycleData;

    private LoadingViewController mLoadingViewController;
    private UidDetailProvider mUidDetailProvider;
@@ -120,7 +117,6 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
    private PreferenceGroup mApps;
    private View mHeader;


    @Override
    public int getMetricsCategory() {
        return MetricsEvent.DATA_USAGE_LIST;
@@ -129,21 +125,15 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Context context = getActivity();
        final Activity activity = getActivity();

        if (!isBandwidthControlEnabled()) {
            Log.w(TAG, "No bandwidth control; leaving");
            getActivity().finish();
        }

        try {
            mStatsSession = services.mStatsService.openSession();
        } catch (RemoteException e) {
            throw new RuntimeException(e);
            activity.finish();
        }

        mUidDetailProvider = new UidDetailProvider(context);

        mUidDetailProvider = new UidDetailProvider(activity);
        mTelephonyManager = activity.getSystemService(TelephonyManager.class);
        mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
        mChart = (ChartDataUsagePreference) findPreference(KEY_CHART_DATA);
        mApps = (PreferenceGroup) findPreference(KEY_APPS_GROUP);
@@ -233,8 +223,6 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
        mUidDetailProvider.clearCache();
        mUidDetailProvider = null;

        TrafficStats.closeQuietly(mStatsSession);

        super.onDestroy();
    }

@@ -277,7 +265,7 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
        // TODO: consider chaining two loaders together instead of reloading
        // network history when showing app detail.
        getLoaderManager().restartLoader(LOADER_CHART_DATA,
                ChartDataLoaderCompat.buildArgs(mTemplate, null), mChartDataCallbacks);
                ChartDataLoaderCompat.buildArgs(mTemplate, null), mNetworkCycleDataCallbacks);

        // detail mode can change visible menus, invalidate
        getActivity().invalidateOptionsMenu();
@@ -316,7 +304,7 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
        }

        // generate cycle list based on policy and available history
        if (mCycleAdapter.updateCycleList(policy, mChartData)) {
        if (mCycleAdapter.updateCycleList(mCycleData)) {
            updateDetailData();
        }
    }
@@ -329,30 +317,20 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
    private void updateDetailData() {
        if (LOGD) Log.d(TAG, "updateDetailData()");

        final long start = mChart.getInspectStart();
        final long end = mChart.getInspectEnd();
        final long now = System.currentTimeMillis();

        final Context context = getActivity();

        NetworkStatsHistory.Entry entry = null;
        if (mChartData != null) {
            entry = mChartData.network.getValues(start, end, now, null);
        }

        // kick off loader for detailed stats
        getLoaderManager().restartLoader(LOADER_SUMMARY, null /* args */,
                mNetworkStatsDetailCallbacks);

        final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(context, totalBytes);
        final long totalBytes = mCycleData != null
            ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).totalUsage : 0;
        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
        mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
    }

    /**
     * Bind the given {@link NetworkStats}, or {@code null} to clear list.
     */
    public void bindStats(NetworkStats stats, int[] restrictedUids) {
    private void bindStats(NetworkStats stats, int[] restrictedUids) {
        mApps.removeAll();
        if (stats == null) {
            if (LOGD) {
@@ -496,7 +474,7 @@ public class DataUsageListV2 extends DataUsageBaseFragment {

            // update chart to show selected cycle, and update detail data
            // to match updated sweep bounds.
            mChart.setVisibleRange(cycle.start, cycle.end);
            mChart.setNetworkCycleData(mCycleData.get(position));

            updateDetailData();
        }
@@ -507,27 +485,30 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
        }
    };

    private final LoaderCallbacks<ChartData> mChartDataCallbacks = new LoaderCallbacks<
            ChartData>() {
    private final LoaderCallbacks<List<NetworkCycleData>> mNetworkCycleDataCallbacks =
            new LoaderCallbacks<List<NetworkCycleData>>() {
        @Override
        public Loader<ChartData> onCreateLoader(int id, Bundle args) {
            return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
        public Loader<List<NetworkCycleData>> onCreateLoader(int id, Bundle args) {
            return new NetworkCycleDataLoader.Builder(getContext())
                    .setNetworkPolicy(services.mPolicyEditor.getPolicy(mTemplate))
                    .setNetworkType(mNetworkType)
                    .setNetworkTemplate(mTemplate)
                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
                    .build();
        }

        @Override
        public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
        public void onLoadFinished(Loader<List<NetworkCycleData>> loader,
                List<NetworkCycleData> data) {
            mLoadingViewController.showContent(false /* animate */);
            mChartData = data;
            mChart.setNetworkStats(mChartData.network);

            mCycleData = data;
            // calculate policy cycles based on available data
            updatePolicy();
        }

        @Override
        public void onLoaderReset(Loader<ChartData> loader) {
            mChartData = null;
            mChart.setNetworkStats(null);
        public void onLoaderReset(Loader<List<NetworkCycleData>> loader) {
            mCycleData = null;
        }
    };

@@ -535,11 +516,11 @@ public class DataUsageListV2 extends DataUsageBaseFragment {
            new LoaderCallbacks<NetworkStats>() {
        @Override
        public Loader<NetworkStats> onCreateLoader(int id, Bundle args) {
            return new NetworkStatsDetailLoader.Builder(getContext())
            return new NetworkStatsSummaryLoader.Builder(getContext())
                    .setStartTime(mChart.getInspectStart())
                    .setEndTime(mChart.getInspectEnd())
                    .setNetworkType(mNetworkType)
                    .setSubscriptionId(mSubId)
                    .setSubscriberId(mTelephonyManager.getSubscriberId(mSubId))
                    .build();
        }