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
This commit is contained in:
Doris Ling
2019-02-08 17:22:32 -08:00
parent ca5786fd27
commit 3d238da4b5
4 changed files with 150 additions and 4 deletions

View File

@@ -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<Long> 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<NetworkCycleDataForUid> 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

View File

@@ -109,6 +109,7 @@ public class DataUsageList extends DataUsageBaseFragment {
@VisibleForTesting
int mNetworkType;
private List<NetworkCycleChartData> mCycleData;
private ArrayList<Long> 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())

View File

@@ -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<Long> 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<Long> 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<NetworkCycleDataForUid> 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();

View File

@@ -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<NetworkCycleChartData> 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> 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<Long> cycles =
(ArrayList) arguments.getSerializable(AppDataUsage.ARG_NETWORK_CYCLES);
assertThat(cycles).hasSize(2);
assertThat(cycles.get(0)).isEqualTo(endTime);
assertThat(cycles.get(1)).isEqualTo(startTime);
}
}