From 3d238da4b5093ade28b2ec2e0ed8fcc36b72aa0a Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Fri, 8 Feb 2019 17:22:32 -0800 Subject: [PATCH] Show app usage data for the correct cycle. - when launching the app data usage from the data usage list, pass the info about the current cycle that the user is looking at, and select the same cycle by default when the page is first launched to match the data on the previous page. Change-Id: Ic91bd8ee78db4d76551dff4b132c1b74d4b3c19d Fixes: 123192721 Test: make RunSettingsRoboTests --- .../settings/datausage/AppDataUsage.java | 34 +++++++++- .../settings/datausage/DataUsageList.java | 16 ++++- .../settings/datausage/AppDataUsageTest.java | 68 +++++++++++++++++++ .../settings/datausage/DataUsageListTest.java | 36 ++++++++++ 4 files changed, 150 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java index 15c77540540..8bab2566649 100644 --- a/src/com/android/settings/datausage/AppDataUsage.java +++ b/src/com/android/settings/datausage/AppDataUsage.java @@ -52,6 +52,7 @@ import com.android.settingslib.net.NetworkCycleDataForUidLoader; import com.android.settingslib.net.UidDetail; import com.android.settingslib.net.UidDetailProvider; +import java.util.ArrayList; import java.util.List; public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceChangeListener, @@ -59,8 +60,10 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC private static final String TAG = "AppDataUsage"; - public static final String ARG_APP_ITEM = "app_item"; - public static final String ARG_NETWORK_TEMPLATE = "network_template"; + static final String ARG_APP_ITEM = "app_item"; + static final String ARG_NETWORK_TEMPLATE = "network_template"; + static final String ARG_NETWORK_CYCLES = "network_cycles"; + static final String ARG_SELECTED_CYCLE = "selected_cycle"; private static final String KEY_TOTAL_USAGE = "total_usage"; private static final String KEY_FOREGROUND_USAGE = "foreground_usage"; @@ -99,6 +102,8 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC private RestrictedSwitchPreference mUnrestrictedData; private DataSaverBackend mDataSaverBackend; private Context mContext; + private ArrayList mCycles; + private long mSelectedCycle; @Override public void onCreate(Bundle icicle) { @@ -110,6 +115,10 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC mAppItem = (args != null) ? (AppItem) args.getParcelable(ARG_APP_ITEM) : null; mTemplate = (args != null) ? (NetworkTemplate) args.getParcelable(ARG_NETWORK_TEMPLATE) : null; + mCycles = (args != null) ? (ArrayList) args.getSerializable(ARG_NETWORK_CYCLES) + : null; + mSelectedCycle = (args != null) ? args.getLong(ARG_SELECTED_CYCLE) : 0L; + if (mTemplate == null) { mTemplate = DataUsageUtils.getDefaultTemplate(mContext, SubscriptionManager.getDefaultDataSubscriptionId()); @@ -393,6 +402,9 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } else { builder.addUid(mAppItem.key); } + if (mCycles != null) { + builder.setCycles(mCycles); + } return builder.build(); } @@ -401,7 +413,23 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC List data) { mUsageData = data; mCycleAdapter.updateCycleList(data); - bindData(0 /* position */); + if (mSelectedCycle > 0L) { + final int numCycles = data.size(); + int position = 0; + for (int i = 0; i < numCycles; i++) { + final NetworkCycleDataForUid cycleData = data.get(i); + if (cycleData.getEndTime() == mSelectedCycle) { + position = i; + break; + } + } + if (position > 0) { + mCycle.setSelection(position); + } + bindData(position); + } else { + bindData(0 /* position */); + } } @Override diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java index 8eeb925f5e1..e5158ffd63a 100644 --- a/src/com/android/settings/datausage/DataUsageList.java +++ b/src/com/android/settings/datausage/DataUsageList.java @@ -109,6 +109,7 @@ public class DataUsageList extends DataUsageBaseFragment { @VisibleForTesting int mNetworkType; private List mCycleData; + private ArrayList mCycles; private LoadingViewController mLoadingViewController; private UidDetailProvider mUidDetailProvider; @@ -411,10 +412,23 @@ public class DataUsageList extends DataUsageBaseFragment { } } - private void startAppDataUsage(AppItem item) { + @VisibleForTesting + void startAppDataUsage(AppItem item) { final Bundle args = new Bundle(); args.putParcelable(AppDataUsage.ARG_APP_ITEM, item); args.putParcelable(AppDataUsage.ARG_NETWORK_TEMPLATE, mTemplate); + if (mCycles == null) { + mCycles = new ArrayList<>(); + for (NetworkCycleChartData data : mCycleData) { + if (mCycles.isEmpty()) { + mCycles.add(data.getEndTime()); + } + mCycles.add(data.getStartTime()); + } + } + args.putSerializable(AppDataUsage.ARG_NETWORK_CYCLES, mCycles); + args.putLong(AppDataUsage.ARG_SELECTED_CYCLE, + mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getEndTime()); new SubSettingLauncher(getContext()) .setDestination(AppDataUsage.class.getName()) diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java index 4561ab67589..6cecd98a2a0 100644 --- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java @@ -345,6 +345,70 @@ public class AppDataUsageTest { assertThat(uids.get(2)).isEqualTo(789); } + @Test + public void onCreateLoader_hasCyclesSpecified_shouldQueryDataUsageForSpecifiedCycles() { + final long startTime = 1521583200000L; + final long endTime = 1521676800000L; + ArrayList testCycles = new ArrayList<>(); + testCycles.add(endTime); + testCycles.add(startTime); + final int uid = 123; + final AppItem appItem = new AppItem(uid); + appItem.category = AppItem.CATEGORY_APP; + appItem.addUid(uid); + + mFragment = new AppDataUsage(); + ReflectionHelpers.setField(mFragment, "mContext", RuntimeEnvironment.application); + ReflectionHelpers.setField(mFragment, "mCycles", testCycles); + ReflectionHelpers.setField(mFragment, "mAppItem", appItem); + ReflectionHelpers.setField(mFragment, "mTemplate", + NetworkTemplate.buildTemplateWifiWildcard()); + + final NetworkCycleDataForUidLoader loader = (NetworkCycleDataForUidLoader) + mFragment.mUidDataCallbacks.onCreateLoader(0 /* id */, Bundle.EMPTY /* args */); + + final ArrayList cycles = loader.getCycles(); + assertThat(cycles).hasSize(2); + assertThat(cycles.get(0)).isEqualTo(endTime); + assertThat(cycles.get(1)).isEqualTo(startTime); + } + + @Test + public void onLoadFinished_hasSelectedCycleSpecified_shouldSelectSpecifiedCycle() { + final long now = System.currentTimeMillis(); + final long tenDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 10); + final long twentyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 20); + final long thirtyDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 30); + final List data = new ArrayList<>(); + NetworkCycleDataForUid.Builder builder = new NetworkCycleDataForUid.Builder(); + builder.setStartTime(thirtyDaysAgo).setEndTime(twentyDaysAgo).setTotalUsage(9876L); + data.add(builder.build()); + builder = new NetworkCycleDataForUid.Builder(); + builder.setStartTime(twentyDaysAgo).setEndTime(tenDaysAgo).setTotalUsage(5678L); + data.add(builder.build()); + builder = new NetworkCycleDataForUid.Builder(); + builder.setStartTime(tenDaysAgo).setEndTime(now).setTotalUsage(1234L); + data.add(builder.build()); + + mFragment = new AppDataUsage(); + ReflectionHelpers.setField(mFragment, "mContext", RuntimeEnvironment.application); + ReflectionHelpers.setField(mFragment, "mCycleAdapter", mock(CycleAdapter.class)); + ReflectionHelpers.setField(mFragment, "mSelectedCycle", tenDaysAgo); + 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.mUidDataCallbacks.onLoadFinished(null /* loader */, data); + + verify(cycle).setSelection(1); + } + + @Test @Config(shadows = {ShadowDataUsageUtils.class, ShadowSubscriptionManager.class}) public void onCreate_noNetworkTemplateAndInvalidDataSubscription_shouldUseWifiTemplate() { ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true; @@ -355,6 +419,10 @@ public class AppDataUsageTest { mFragment = spy(new AppDataUsage()); doReturn(Robolectric.setupActivity(FragmentActivity.class)).when(mFragment).getActivity(); doReturn(RuntimeEnvironment.application).when(mFragment).getContext(); + final UidDetailProvider uidDetailProvider = mock(UidDetailProvider.class); + doReturn(uidDetailProvider).when(mFragment).getUidDetailProvider(); + doReturn(new UidDetail()).when(uidDetailProvider).getUidDetail(anyInt(), anyBoolean()); + ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider", FakeFeatureFactory.setupForTest().dashboardFeatureProvider); final Bundle args = new Bundle(); diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java index 427550cdd6a..7d042ce3c44 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java @@ -30,19 +30,27 @@ import android.net.ConnectivityManager; import android.net.NetworkTemplate; import android.os.Bundle; import android.provider.Settings; +import android.widget.Spinner; +import com.android.settings.SettingsActivity; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.AppItem; import com.android.settingslib.NetworkPolicyEditor; import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; +import com.android.settingslib.net.NetworkCycleChartData; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.util.ReflectionHelpers; +import java.util.ArrayList; +import java.util.List; + import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceManager; @@ -124,4 +132,32 @@ public class DataUsageListTest { assertThat(mDataUsageList.mTemplate).isNotNull(); assertThat(mDataUsageList.mSubId).isEqualTo(3); } + + @Test + public void startAppDataUsage_shouldAddCyclesInfoToLaunchArguments() { + final long startTime = 1521583200000L; + final long endTime = 1521676800000L; + final List data = new ArrayList<>(); + final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder(); + builder.setStartTime(startTime) + .setEndTime(endTime); + data.add(builder.build()); + ReflectionHelpers.setField(mDataUsageList, "mCycleData", data); + final Spinner spinner = mock(Spinner.class); + when(spinner.getSelectedItemPosition()).thenReturn(0); + ReflectionHelpers.setField(mDataUsageList, "mCycleSpinner", spinner); + final ArgumentCaptor intent = ArgumentCaptor.forClass(Intent.class); + + mDataUsageList.startAppDataUsage(new AppItem()); + + verify(mContext).startActivity(intent.capture()); + final Bundle arguments = + intent.getValue().getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS); + assertThat(arguments.getLong(AppDataUsage.ARG_SELECTED_CYCLE)).isEqualTo(endTime); + final ArrayList cycles = + (ArrayList) arguments.getSerializable(AppDataUsage.ARG_NETWORK_CYCLES); + assertThat(cycles).hasSize(2); + assertThat(cycles.get(0)).isEqualTo(endTime); + assertThat(cycles.get(1)).isEqualTo(startTime); + } }