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); + } }