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:
@@ -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
|
||||
|
@@ -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())
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user