Improve the latency of DataUsageList
Up to 30x faster. Currently it load the usage detail for every day at the beginning, so it's quite slow. To fix, - Not load the usage detail for every day at the beginning - Load only the cycles first - And only load the daily detail for the selected month Fix: 290856342 Test: manual - on DataUsageList (cell & wifi) Test: unit tests Change-Id: Ie18fa68f801743389bd6b6a28e236dcf1fea00e4
This commit is contained in:
@@ -31,9 +31,9 @@ import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.datausage.ChartDataUsagePreference.DataUsageSummaryNode;
|
||||
import com.android.settings.datausage.lib.NetworkCycleChartData;
|
||||
import com.android.settings.datausage.lib.NetworkUsageData;
|
||||
import com.android.settings.widget.UsageView;
|
||||
import com.android.settingslib.net.NetworkCycleChartData;
|
||||
import com.android.settingslib.net.NetworkCycleData;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -55,7 +55,7 @@ public class ChartDataUsagePreferenceTest {
|
||||
// Test bucket end date, 22 Mar 2018 00:00:00
|
||||
private static final long TIMESTAMP_END = 1521676800000L;
|
||||
|
||||
private List<NetworkCycleData> mNetworkCycleData;
|
||||
private List<NetworkUsageData> mNetworkCycleData;
|
||||
private NetworkCycleChartData mNetworkCycleChartData;
|
||||
private ChartDataUsagePreference mPreference;
|
||||
private Activity mActivity;
|
||||
@@ -79,6 +79,9 @@ public class ChartDataUsagePreferenceTest {
|
||||
final ArgumentCaptor<SparseIntArray> pointsCaptor =
|
||||
ArgumentCaptor.forClass(SparseIntArray.class);
|
||||
createTestNetworkData();
|
||||
mPreference.setTime(
|
||||
mNetworkCycleChartData.getTotal().getStartTime(),
|
||||
mNetworkCycleChartData.getTotal().getEndTime());
|
||||
mPreference.setNetworkCycleData(mNetworkCycleChartData);
|
||||
|
||||
mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
|
||||
@@ -95,6 +98,9 @@ public class ChartDataUsagePreferenceTest {
|
||||
final ArgumentCaptor<SparseIntArray> pointsCaptor =
|
||||
ArgumentCaptor.forClass(SparseIntArray.class);
|
||||
createTestNetworkData();
|
||||
mPreference.setTime(
|
||||
mNetworkCycleChartData.getTotal().getStartTime(),
|
||||
mNetworkCycleChartData.getTotal().getEndTime());
|
||||
mPreference.setNetworkCycleData(mNetworkCycleChartData);
|
||||
|
||||
mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
|
||||
@@ -110,39 +116,62 @@ public class ChartDataUsagePreferenceTest {
|
||||
public void calcPoints_shouldNotDrawPointForFutureDate() {
|
||||
final UsageView usageView = mock(UsageView.class);
|
||||
final ArgumentCaptor<SparseIntArray> pointsCaptor =
|
||||
ArgumentCaptor.forClass(SparseIntArray.class);
|
||||
ArgumentCaptor.forClass(SparseIntArray.class);
|
||||
final long tonight = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(12);
|
||||
mNetworkCycleData = new ArrayList<>();
|
||||
// add test usage data for last 5 days
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight - TimeUnit.DAYS.toMillis(5), tonight - TimeUnit.DAYS.toMillis(4), 743823454L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight - TimeUnit.DAYS.toMillis(4), tonight - TimeUnit.DAYS.toMillis(3), 64396L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight - TimeUnit.DAYS.toMillis(3), tonight - TimeUnit.DAYS.toMillis(2), 2832L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight - TimeUnit.DAYS.toMillis(2), tonight - TimeUnit.DAYS.toMillis(1), 83849690L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(5),
|
||||
tonight - TimeUnit.DAYS.toMillis(4),
|
||||
743823454L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(4),
|
||||
tonight - TimeUnit.DAYS.toMillis(3),
|
||||
64396L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(3),
|
||||
tonight - TimeUnit.DAYS.toMillis(2),
|
||||
2832L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(2),
|
||||
tonight - TimeUnit.DAYS.toMillis(1),
|
||||
83849690L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
|
||||
// add test usage data for next 5 days
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight + TimeUnit.DAYS.toMillis(1), tonight + TimeUnit.DAYS.toMillis(2), 0L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight + TimeUnit.DAYS.toMillis(2), tonight + TimeUnit.DAYS.toMillis(3), 0L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight + TimeUnit.DAYS.toMillis(3), tonight + TimeUnit.DAYS.toMillis(4), 0L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight + TimeUnit.DAYS.toMillis(4), tonight + TimeUnit.DAYS.toMillis(5), 0L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(
|
||||
tonight + TimeUnit.DAYS.toMillis(5), tonight + TimeUnit.DAYS.toMillis(6), 0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight + TimeUnit.DAYS.toMillis(1),
|
||||
tonight + TimeUnit.DAYS.toMillis(2),
|
||||
0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight + TimeUnit.DAYS.toMillis(2),
|
||||
tonight + TimeUnit.DAYS.toMillis(3),
|
||||
0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight + TimeUnit.DAYS.toMillis(3),
|
||||
tonight + TimeUnit.DAYS.toMillis(4),
|
||||
0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight + TimeUnit.DAYS.toMillis(4),
|
||||
tonight + TimeUnit.DAYS.toMillis(5),
|
||||
0L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(
|
||||
tonight + TimeUnit.DAYS.toMillis(5),
|
||||
tonight + TimeUnit.DAYS.toMillis(6),
|
||||
0L));
|
||||
|
||||
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
|
||||
builder.setUsageBuckets(mNetworkCycleData)
|
||||
.setStartTime(tonight - TimeUnit.DAYS.toMillis(5))
|
||||
.setEndTime(tonight + TimeUnit.DAYS.toMillis(6));
|
||||
mNetworkCycleChartData = builder.build();
|
||||
mNetworkCycleChartData = new NetworkCycleChartData(
|
||||
new NetworkUsageData(
|
||||
tonight - TimeUnit.DAYS.toMillis(5),
|
||||
tonight + TimeUnit.DAYS.toMillis(6),
|
||||
0),
|
||||
mNetworkCycleData
|
||||
);
|
||||
mPreference.setTime(
|
||||
mNetworkCycleChartData.getTotal().getStartTime(),
|
||||
mNetworkCycleChartData.getTotal().getEndTime());
|
||||
mPreference.setNetworkCycleData(mNetworkCycleChartData);
|
||||
|
||||
mPreference.calcPoints(usageView, mNetworkCycleData);
|
||||
@@ -170,6 +199,9 @@ public class ChartDataUsagePreferenceTest {
|
||||
final TextView labelStart = (TextView) mHolder.findViewById(R.id.label_start);
|
||||
final TextView labelEnd = (TextView) mHolder.findViewById(R.id.label_end);
|
||||
createTestNetworkData();
|
||||
mPreference.setTime(
|
||||
mNetworkCycleChartData.getTotal().getStartTime(),
|
||||
mNetworkCycleChartData.getTotal().getEndTime());
|
||||
mPreference.setNetworkCycleData(mNetworkCycleChartData);
|
||||
|
||||
mPreference.onBindViewHolder(mHolder);
|
||||
@@ -198,38 +230,33 @@ public class ChartDataUsagePreferenceTest {
|
||||
private void createTestNetworkData() {
|
||||
mNetworkCycleData = new ArrayList<>();
|
||||
// create 10 arbitrary network data
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 743823454L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 64396L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 2832L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 83849690L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 1883657L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 705259L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 216169L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 6069175L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521673200000L, 1521676800000L, 120389L));
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521676800000L, 1521678800000L, 29947L));
|
||||
|
||||
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
|
||||
builder.setUsageBuckets(mNetworkCycleData)
|
||||
.setStartTime(TIMESTAMP_START)
|
||||
.setEndTime(TIMESTAMP_END);
|
||||
mNetworkCycleChartData = builder.build();
|
||||
mNetworkCycleChartData = new NetworkCycleChartData(
|
||||
new NetworkUsageData(TIMESTAMP_START, TIMESTAMP_END, 0),
|
||||
mNetworkCycleData
|
||||
);
|
||||
}
|
||||
|
||||
private void createSomeSamePercentageNetworkData() {
|
||||
mNetworkCycleData = new ArrayList<>();
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 100));//33%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 1)); //33%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 0)); //33%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 0)); //33%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 200));//99%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 1)); //99%
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 1)); //100
|
||||
mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 0)); //100%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 100)); //33%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 1)); //33%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 0)); //33%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 0)); //33%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 200)); //99%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 1)); //99%
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 1)); //100
|
||||
mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 0)); //100%
|
||||
}
|
||||
|
||||
private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
|
||||
return new NetworkCycleData.Builder()
|
||||
.setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
|
||||
}
|
||||
}
|
||||
|
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.datausage;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.android.settings.datausage.lib.BillingCycleRepository;
|
||||
import com.android.settings.network.MobileDataEnabledListener;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.widget.LoadingViewController;
|
||||
import com.android.settingslib.NetworkPolicyEditor;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.net.NetworkCycleChartData;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = DataUsageListTest.ShadowDataUsageBaseFragment.class)
|
||||
public class DataUsageListTest {
|
||||
@Rule
|
||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private MobileDataEnabledListener mMobileDataEnabledListener;
|
||||
@Mock
|
||||
private TemplatePreference.NetworkServices mNetworkServices;
|
||||
@Mock
|
||||
private LoaderManager mLoaderManager;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private BillingCycleRepository mBillingCycleRepository;
|
||||
@Mock
|
||||
private DataUsageListHeaderController mDataUsageListHeaderController;
|
||||
|
||||
private Activity mActivity;
|
||||
|
||||
@Spy
|
||||
private TestDataUsageList mDataUsageList;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
FakeFeatureFactory.setupForTest();
|
||||
final ActivityController<Activity> mActivityController =
|
||||
Robolectric.buildActivity(Activity.class);
|
||||
mActivity = spy(mActivityController.get());
|
||||
mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
|
||||
mDataUsageList.mDataStateListener = mMobileDataEnabledListener;
|
||||
|
||||
doReturn(mActivity).when(mDataUsageList).getContext();
|
||||
doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
|
||||
doReturn(false).when(mUserManager).isGuestUser();
|
||||
ReflectionHelpers.setField(mDataUsageList, "mDataStateListener",
|
||||
mMobileDataEnabledListener);
|
||||
ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
|
||||
doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
|
||||
mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
|
||||
doNothing().when(mDataUsageList).updateSubscriptionInfoEntity();
|
||||
when(mBillingCycleRepository.isBandwidthControlEnabled()).thenReturn(true);
|
||||
mDataUsageList.mDataUsageListHeaderController = mDataUsageListHeaderController;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_isNotGuestUser_shouldNotFinish() {
|
||||
mDataUsageList.mTemplate = mock(NetworkTemplate.class);
|
||||
doReturn(false).when(mUserManager).isGuestUser();
|
||||
doNothing().when(mDataUsageList).processArgument();
|
||||
|
||||
mDataUsageList.onCreate(null);
|
||||
|
||||
verify(mDataUsageList, never()).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_isGuestUser_shouldFinish() {
|
||||
doReturn(true).when(mUserManager).isGuestUser();
|
||||
|
||||
mDataUsageList.onCreate(null);
|
||||
|
||||
verify(mDataUsageList).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resume_shouldListenDataStateChange() {
|
||||
mDataUsageList.onCreate(null);
|
||||
ReflectionHelpers.setField(
|
||||
mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
|
||||
ReflectionHelpers.setField(
|
||||
mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
|
||||
|
||||
mDataUsageList.onResume();
|
||||
|
||||
verify(mMobileDataEnabledListener).start(anyInt());
|
||||
|
||||
mDataUsageList.onPause();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pause_shouldUnlistenDataStateChange() {
|
||||
mDataUsageList.onCreate(null);
|
||||
ReflectionHelpers.setField(
|
||||
mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
|
||||
ReflectionHelpers.setField(
|
||||
mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
|
||||
|
||||
mDataUsageList.onResume();
|
||||
mDataUsageList.onPause();
|
||||
|
||||
verify(mMobileDataEnabledListener).stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processArgument_shouldGetTemplateFromArgument() {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
|
||||
args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
|
||||
mDataUsageList.setArguments(args);
|
||||
|
||||
mDataUsageList.processArgument();
|
||||
|
||||
assertThat(mDataUsageList.mTemplate).isNotNull();
|
||||
assertThat(mDataUsageList.mSubId).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
|
||||
intent.putExtra(Settings.EXTRA_SUB_ID, 3);
|
||||
doReturn(intent).when(mDataUsageList).getIntent();
|
||||
|
||||
mDataUsageList.processArgument();
|
||||
|
||||
assertThat(mDataUsageList.mTemplate).isNotNull();
|
||||
assertThat(mDataUsageList.mSubId).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onLoadFinished_networkCycleDataCallback_shouldShowCycleSpinner() {
|
||||
mDataUsageList.mTemplate = mock(NetworkTemplate.class);
|
||||
mDataUsageList.onCreate(null);
|
||||
mDataUsageList.updatePolicy();
|
||||
List<NetworkCycleChartData> mockData = Collections.emptyList();
|
||||
|
||||
mDataUsageList.mNetworkCycleDataCallbacks.onLoadFinished(null, mockData);
|
||||
|
||||
verify(mDataUsageListHeaderController).updateCycleData(mockData);
|
||||
verify(mDataUsageListHeaderController).setConfigButtonVisible(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPause_shouldDestroyLoaders() {
|
||||
mDataUsageList.onPause();
|
||||
|
||||
verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_CHART_DATA);
|
||||
}
|
||||
|
||||
@Implements(DataUsageBaseFragment.class)
|
||||
public static class ShadowDataUsageBaseFragment {
|
||||
@Implementation
|
||||
public void onCreate(Bundle icicle) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
public class TestDataUsageList extends DataUsageList {
|
||||
@Override
|
||||
protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
|
||||
return mock(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Preference> T findPreference(CharSequence key) {
|
||||
if (key.toString().equals("chart_data")) {
|
||||
return (T) mock(ChartDataUsagePreference.class);
|
||||
}
|
||||
return (T) mock(Preference.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
return new Intent();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
BillingCycleRepository createBillingCycleRepository() {
|
||||
return mBillingCycleRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isBillingCycleModifiable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.datausage
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.NetworkTemplate
|
||||
import android.os.Bundle
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
|
||||
import com.android.settings.datausage.TemplatePreference.NetworkServices
|
||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||
import com.android.settings.network.MobileDataEnabledListener
|
||||
import com.android.settings.testutils.FakeFeatureFactory
|
||||
import com.android.settingslib.NetworkPolicyEditor
|
||||
import com.android.settingslib.core.AbstractPreferenceController
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.doNothing
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.annotation.Implementation
|
||||
import org.robolectric.annotation.Implements
|
||||
import org.robolectric.util.ReflectionHelpers
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowDataUsageBaseFragment::class])
|
||||
class DataUsageListTest {
|
||||
@get:Rule
|
||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Mock
|
||||
private lateinit var mobileDataEnabledListener: MobileDataEnabledListener
|
||||
|
||||
@Mock
|
||||
private lateinit var networkServices: NetworkServices
|
||||
|
||||
@Mock
|
||||
private lateinit var userManager: UserManager
|
||||
|
||||
@Mock
|
||||
private lateinit var billingCycleRepository: BillingCycleRepository
|
||||
|
||||
@Mock
|
||||
private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Spy
|
||||
private val dataUsageList = TestDataUsageList()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
FakeFeatureFactory.setupForTest()
|
||||
networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
|
||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
||||
doReturn(context).`when`(dataUsageList).context
|
||||
doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
|
||||
doReturn(false).`when`(userManager).isGuestUser
|
||||
ReflectionHelpers.setField(dataUsageList, "services", networkServices)
|
||||
doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
|
||||
`when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
|
||||
dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onCreate_isNotGuestUser_shouldNotFinish() {
|
||||
dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
|
||||
doReturn(false).`when`(userManager).isGuestUser
|
||||
doNothing().`when`(dataUsageList).processArgument()
|
||||
dataUsageList.onCreate(null)
|
||||
verify(dataUsageList, never()).finish()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onCreate_isGuestUser_shouldFinish() {
|
||||
doReturn(true).`when`(userManager).isGuestUser
|
||||
dataUsageList.onCreate(null)
|
||||
verify(dataUsageList).finish()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resume_shouldListenDataStateChange() {
|
||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
||||
dataUsageList.onCreate(null)
|
||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
||||
ReflectionHelpers.setField(
|
||||
dataUsageList,
|
||||
"mVisibilityLoggerMixin",
|
||||
mock(VisibilityLoggerMixin::class.java),
|
||||
)
|
||||
ReflectionHelpers.setField(
|
||||
dataUsageList,
|
||||
"mPreferenceManager",
|
||||
mock(PreferenceManager::class.java),
|
||||
)
|
||||
dataUsageList.onResume()
|
||||
verify(mobileDataEnabledListener).start(ArgumentMatchers.anyInt())
|
||||
dataUsageList.onPause()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pause_shouldUnlistenDataStateChange() {
|
||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
||||
dataUsageList.onCreate(null)
|
||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
||||
ReflectionHelpers.setField(
|
||||
dataUsageList, "mVisibilityLoggerMixin", mock(
|
||||
VisibilityLoggerMixin::class.java
|
||||
)
|
||||
)
|
||||
ReflectionHelpers.setField(
|
||||
dataUsageList, "mPreferenceManager", mock(
|
||||
PreferenceManager::class.java
|
||||
)
|
||||
)
|
||||
dataUsageList.onResume()
|
||||
dataUsageList.onPause()
|
||||
verify(mobileDataEnabledListener).stop()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun processArgument_shouldGetTemplateFromArgument() {
|
||||
val args = Bundle()
|
||||
args.putParcelable(
|
||||
DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
|
||||
NetworkTemplate::class.java
|
||||
)
|
||||
)
|
||||
args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
|
||||
dataUsageList.arguments = args
|
||||
dataUsageList.processArgument()
|
||||
assertThat(dataUsageList.template).isNotNull()
|
||||
assertThat(dataUsageList.subId).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
|
||||
val intent = Intent()
|
||||
intent.putExtra(
|
||||
Settings.EXTRA_NETWORK_TEMPLATE, mock(
|
||||
NetworkTemplate::class.java
|
||||
)
|
||||
)
|
||||
intent.putExtra(Settings.EXTRA_SUB_ID, 3)
|
||||
doReturn(intent).`when`(dataUsageList).intent
|
||||
dataUsageList.processArgument()
|
||||
assertThat(dataUsageList.template).isNotNull()
|
||||
assertThat(dataUsageList.subId).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updatePolicy_setConfigButtonVisible() {
|
||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
||||
dataUsageList.onCreate(null)
|
||||
|
||||
dataUsageList.updatePolicy()
|
||||
|
||||
verify(dataUsageListHeaderController).setConfigButtonVisible(true)
|
||||
}
|
||||
|
||||
@Implements(DataUsageBaseFragment::class)
|
||||
class ShadowDataUsageBaseFragment {
|
||||
@Implementation
|
||||
fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
open inner class TestDataUsageList : DataUsageList() {
|
||||
override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Preference?> findPreference(key: CharSequence): T =
|
||||
mock(Preference::class.java) as T
|
||||
|
||||
public override fun getIntent() = Intent()
|
||||
|
||||
override fun createBillingCycleRepository() = billingCycleRepository
|
||||
|
||||
override fun isBillingCycleModifiable() = true
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user