Use the new loader to show app data usage details.
- this is for showing the detail usage (total, background, and
foreground) for a specific app for each billing cycle.
Bug: 111751694
Test: make RunSettingsRoboTests
Change-Id: I8e02872a4204b682089ea117811b50966e785c55
diff --git a/src/com/android/settings/datausage/AppDataUsageV2.java b/src/com/android/settings/datausage/AppDataUsageV2.java
index 6d6089e..4e8325b 100644
--- a/src/com/android/settings/datausage/AppDataUsageV2.java
+++ b/src/com/android/settings/datausage/AppDataUsageV2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2018 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
@@ -22,13 +22,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
-import android.net.INetworkStatsSession;
-import android.net.NetworkPolicy;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
@@ -51,11 +46,13 @@
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoaderCompat;
+import com.android.settingslib.net.NetworkCycleDataForUid;
+import com.android.settingslib.net.NetworkCycleDataForUidLoader;
import com.android.settingslib.net.UidDetail;
import com.android.settingslib.net.UidDetailProvider;
+import java.util.List;
+
public class AppDataUsageV2 extends DataUsageBaseFragment implements OnPreferenceChangeListener,
DataSaverBackend.Listener {
@@ -73,7 +70,7 @@
private static final String KEY_CYCLE = "cycle";
private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
- private static final int LOADER_CHART_DATA = 2;
+ private static final int LOADER_APP_USAGE_DATA = 2;
private static final int LOADER_APP_PREF = 3;
private PackageManager mPackageManager;
@@ -88,14 +85,10 @@
private Drawable mIcon;
private CharSequence mLabel;
private String mPackageName;
- private INetworkStatsSession mStatsSession;
private CycleAdapter mCycleAdapter;
- private long mStart;
- private long mEnd;
- private ChartData mChartData;
+ private List<NetworkCycleDataForUid> mUsageData;
private NetworkTemplate mTemplate;
- private NetworkPolicy mPolicy;
private AppItem mAppItem;
private Intent mAppSettingsIntent;
private SpinnerPreference mCycle;
@@ -108,12 +101,6 @@
mPackageManager = getPackageManager();
final Bundle args = getArguments();
- try {
- mStatsSession = services.mStatsService.openSession();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null;
mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE)
: null;
@@ -209,20 +196,12 @@
}
@Override
- public void onDestroy() {
- TrafficStats.closeQuietly(mStatsSession);
- super.onDestroy();
- }
-
- @Override
public void onResume() {
super.onResume();
if (mDataSaverBackend != null) {
mDataSaverBackend.addListener(this);
}
- mPolicy = services.mPolicyEditor.getPolicy(mTemplate);
- getLoaderManager().restartLoader(LOADER_CHART_DATA,
- ChartDataLoaderCompat.buildArgs(mTemplate, mAppItem), mChartDataCallbacks);
+ getLoaderManager().restartLoader(LOADER_APP_USAGE_DATA, null /* args */, mUidDataCallbacks);
updatePrefs();
}
@@ -300,19 +279,17 @@
}
}
- private void bindData() {
+ @VisibleForTesting
+ void bindData(int position) {
final long backgroundBytes, foregroundBytes;
- if (mChartData == null || mStart == 0) {
+ if (mUsageData == null || position >= mUsageData.size()) {
backgroundBytes = foregroundBytes = 0;
mCycle.setVisible(false);
} else {
mCycle.setVisible(true);
- final long now = System.currentTimeMillis();
- NetworkStatsHistory.Entry entry = null;
- entry = mChartData.detailDefault.getValues(mStart, mEnd, now, entry);
- backgroundBytes = entry.rxBytes + entry.txBytes;
- entry = mChartData.detailForeground.getValues(mStart, mEnd, now, entry);
- foregroundBytes = entry.rxBytes + entry.txBytes;
+ final NetworkCycleDataForUid data = mUsageData.get(position);
+ backgroundBytes = data.getBackgroudUsage();
+ foregroundBytes = data.getForegroudUsage();
}
final long totalBytes = backgroundBytes + foregroundBytes;
final Context context = getContext();
@@ -376,11 +353,7 @@
new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
-
- mStart = cycle.start;
- mEnd = cycle.end;
- bindData();
+ bindData(position);
}
@Override
@@ -389,24 +362,30 @@
}
};
- private final LoaderManager.LoaderCallbacks<ChartData> mChartDataCallbacks =
- new LoaderManager.LoaderCallbacks<ChartData>() {
- @Override
- public Loader<ChartData> onCreateLoader(int id, Bundle args) {
- return new ChartDataLoaderCompat(getActivity(), mStatsSession, args);
- }
+ private final LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>> mUidDataCallbacks =
+ new LoaderManager.LoaderCallbacks<List<NetworkCycleDataForUid>>() {
+ @Override
+ public Loader<List<NetworkCycleDataForUid>> onCreateLoader(int id, Bundle args) {
+ return NetworkCycleDataForUidLoader.builder(getContext())
+ .setUid(mAppItem.key)
+ .setRetrieveDetail(true)
+ .setNetworkTemplate(mTemplate)
+ .setSubscriberId(mTemplate.getSubscriberId())
+ .build();
+ }
- @Override
- public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
- mChartData = data;
- mCycleAdapter.updateCycleList(mPolicy, mChartData);
- bindData();
- }
+ @Override
+ public void onLoadFinished(Loader<List<NetworkCycleDataForUid>> loader,
+ List<NetworkCycleDataForUid> data) {
+ mUsageData = data;
+ mCycleAdapter.updateCycleList(data);
+ bindData(0 /* position */);
+ }
- @Override
- public void onLoaderReset(Loader<ChartData> loader) {
- }
- };
+ @Override
+ public void onLoaderReset(Loader<List<NetworkCycleDataForUid>> loader) {
+ }
+ };
private final LoaderManager.LoaderCallbacks<ArraySet<Preference>> mAppPrefCallbacks =
new LoaderManager.LoaderCallbacks<ArraySet<Preference>>() {
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
index d979b68..8796a39 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageV2Test.java
@@ -19,6 +19,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doNothing;
@@ -28,12 +29,14 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.Bundle;
import android.util.ArraySet;
import android.view.View;
+import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -45,6 +48,7 @@
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.net.NetworkCycleDataForUid;
import org.junit.After;
import org.junit.Before;
@@ -57,6 +61,9 @@
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
public class AppDataUsageV2Test {
@@ -172,4 +179,49 @@
verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
}
+
+ @Test
+ public void bindData_noAppUsageData_shouldHideCycleSpinner() {
+ mFragment = spy(new AppDataUsageV2());
+ final SpinnerPreference cycle = mock(SpinnerPreference.class);
+ ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+ final Preference preference = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mBackgroundUsage", preference);
+ ReflectionHelpers.setField(mFragment, "mForegroundUsage", preference);
+ ReflectionHelpers.setField(mFragment, "mTotalUsage", preference);
+ doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
+
+ mFragment.bindData(0 /* position */);
+
+ verify(cycle).setVisible(false);
+ }
+
+ @Test
+ public void bindData_hasAppUsageData_shouldShowCycleSpinnerAndUpdateUsageSummary() {
+ mFragment = spy(new AppDataUsageV2());
+ final Context context = RuntimeEnvironment.application;
+ doReturn(context).when(mFragment).getContext();
+ final long backgroundBytes = 1234L;
+ final long foregroundBytes = 5678L;
+ final List<NetworkCycleDataForUid> appUsage = new ArrayList<>();
+ appUsage.add(new NetworkCycleDataForUid.Builder()
+ .setBackgroundUsage(backgroundBytes).setForegroundUsage(foregroundBytes).build());
+ ReflectionHelpers.setField(mFragment, "mUsageData", appUsage);
+ final Preference backgroundPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref);
+ final Preference foregroundPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref);
+ final Preference totalPref = mock(Preference.class);
+ ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref);
+ final SpinnerPreference cycle = mock(SpinnerPreference.class);
+ ReflectionHelpers.setField(mFragment, "mCycle", cycle);
+
+ mFragment.bindData(0 /* position */);
+
+ verify(cycle).setVisible(true);
+ verify(totalPref).setSummary(
+ DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
+ verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
+ verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
+ }
}