fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2017 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.Mockito.when;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.AppItem;
import com.android.settingslib.net.UidDetail;
import com.android.settingslib.net.UidDetailProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AppDataUsagePreferenceTest {
private static final String FIFTY_PERCENT = "50%";
@Mock
private UidDetailProvider mUidDetailProvider;
private AppItem mAppItem;
private UidDetail mUidDetail;
private AppDataUsagePreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mAppItem = new AppItem(123);
mUidDetail = new UidDetail();
mUidDetail.icon = new ColorDrawable(Color.BLUE);
mUidDetail.label = "title";
}
@Test
public void createPref_hasCachedUidDetail_shouldSetAppInfo() {
when(mUidDetailProvider.getUidDetail(mAppItem.key, false /* blocking */))
.thenReturn(mUidDetail);
mPreference = new AppDataUsagePreference(RuntimeEnvironment.application, mAppItem,
50 /* percent */, mUidDetailProvider);
assertThat(mPreference.getTitle()).isEqualTo(mUidDetail.label);
assertThat(mPreference.getIcon()).isEqualTo(mUidDetail.icon);
}
@Test
public void createPref_noCachedUidDetail_shouldSetAppInfo() {
when(mUidDetailProvider.getUidDetail(mAppItem.key, true /* blocking */))
.thenReturn(mUidDetail);
mPreference = new AppDataUsagePreference(RuntimeEnvironment.application, mAppItem,
50 /* percent */, mUidDetailProvider);
assertThat(mPreference.getTitle()).isEqualTo(mUidDetail.label);
assertThat(mPreference.getIcon()).isEqualTo(mUidDetail.icon);
}
@Test
public void createPref_progressBarShouldSetPercentageContentDescription() {
when(mUidDetailProvider.getUidDetail(mAppItem.key, true /* blocking */))
.thenReturn(mUidDetail);
mPreference = new AppDataUsagePreference(RuntimeEnvironment.application, mAppItem,
50 /* percent */, mUidDetailProvider);
final View view = LayoutInflater.from(RuntimeEnvironment.application).inflate(
com.android.settingslib.widget.preference.app.R.layout.preference_app, null);
final PreferenceViewHolder preferenceViewHolder =
PreferenceViewHolder.createInstanceForTests(view);
final ProgressBar progressBar = (ProgressBar) preferenceViewHolder.findViewById(
android.R.id.progress);
mPreference.onBindViewHolder(preferenceViewHolder);
assertThat(progressBar.getContentDescription()).isEqualTo(FIFTY_PERCENT);
}
}

View File

@@ -0,0 +1,327 @@
/*
* Copyright (C) 2017 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.junit.Assert.assertTrue;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.os.Process;
import android.telephony.SubscriptionManager;
import android.util.ArraySet;
import android.util.Range;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.datausage.lib.NetworkUsageDetailsData;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.net.UidDetail;
import com.android.settingslib.net.UidDetailProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowSubscriptionManager;
import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowRestrictedLockUtilsInternal.class})
public class AppDataUsageTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private EntityHeaderController mHeaderController;
@Mock
private PackageManager mPackageManager;
private AppDataUsage mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowEntityHeaderController.setUseMock(mHeaderController);
when(mHeaderController.setUid(anyInt())).thenReturn(mHeaderController);
}
@After
public void tearDown() {
ShadowEntityHeaderController.reset();
}
@Test
@Config(shadows = ShadowFragment.class)
public void onCreate_appUid_shouldGetAppLabelFromAppInfo() throws NameNotFoundException {
mFragment = spy(new TestFragment());
final FragmentActivity activity = spy(Robolectric.setupActivity(FragmentActivity.class));
doReturn(mPackageManager).when(activity).getPackageManager();
doReturn(activity).when(mFragment).getActivity();
doReturn(RuntimeEnvironment.application).when(mFragment).getContext();
ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider",
FakeFeatureFactory.setupForTest().dashboardFeatureProvider);
final String packageName = "testPackage";
final int uid = (Process.FIRST_APPLICATION_UID + Process.LAST_APPLICATION_UID) / 2;
doReturn(new String[]{packageName}).when(mPackageManager).getPackagesForUid(uid);
final String label = "testLabel";
final AppItem appItem = new AppItem(uid);
appItem.uids.put(uid, true);
final ApplicationInfo info = spy(new ApplicationInfo());
doReturn(label).when(info).loadLabel(mPackageManager);
when(mPackageManager.getApplicationInfoAsUser(
eq(packageName), anyInt() /* flags */, anyInt() /* userId */)).thenReturn(info);
final Bundle args = new Bundle();
args.putParcelable(AppDataUsage.ARG_APP_ITEM, appItem);
args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
mFragment.setArguments(args);
mFragment.onCreate(Bundle.EMPTY);
assertThat(mFragment.mLabel).isEqualTo(label);
}
@Test
@Config(shadows = ShadowFragment.class)
public void onCreate_notAppUid_shouldGetAppLabelFromUidDetailProvider() {
mFragment = spy(new TestFragment());
ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider",
FakeFeatureFactory.setupForTest().dashboardFeatureProvider);
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();
final String label = "testLabel";
final int uid = Process.SYSTEM_UID;
final UidDetail uidDetail = new UidDetail();
uidDetail.label = label;
when(uidDetailProvider.getUidDetail(eq(uid), anyBoolean() /* blocking */)).
thenReturn(uidDetail);
final AppItem appItem = new AppItem(uid);
appItem.uids.put(uid, true);
final Bundle args = new Bundle();
args.putParcelable(AppDataUsage.ARG_APP_ITEM, appItem);
args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
mFragment.setArguments(args);
mFragment.onCreate(Bundle.EMPTY);
assertThat(mFragment.mLabel).isEqualTo(label);
}
@Test
public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
mFragment = spy(new TestFragment());
when(mFragment.getPreferenceManager())
.thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
mFragment.addEntityHeader();
verify(mHeaderController).setHasAppInfoLink(false);
}
@Test
public void bindAppHeader_workApp_shouldSetWorkAppUid()
throws PackageManager.NameNotFoundException {
final int fakeUserId = 100;
mFragment = spy(new TestFragment());
final ArraySet<String> packages = new ArraySet<>();
packages.add("pkg");
final AppItem appItem = new AppItem(123456789);
ReflectionHelpers.setField(mFragment, "mPackageManager", mPackageManager);
ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
ReflectionHelpers.setField(mFragment, "mPackages", packages);
when(mPackageManager.getPackageUidAsUser(anyString(), anyInt()))
.thenReturn(fakeUserId);
when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
when(mFragment.getPreferenceManager())
.thenReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS));
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
mFragment.addEntityHeader();
verify(mHeaderController).setHasAppInfoLink(true);
verify(mHeaderController).setUid(fakeUserId);
}
@Test
public void changePreference_backgroundData_shouldUpdateUI() {
mFragment = spy(new TestFragment());
final AppItem appItem = new AppItem(123456789);
final RestrictedSwitchPreference pref = mock(RestrictedSwitchPreference.class);
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
ReflectionHelpers.setField(mFragment, "mRestrictBackground", pref);
ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
doNothing().when(mFragment).updatePrefs();
mFragment.onPreferenceChange(pref, true /* value */);
verify(mFragment).updatePrefs();
}
@Test
public void updatePrefs_restrictedByAdmin_shouldDisablePreference() {
mFragment = spy(new TestFragment());
final int testUid = 123123;
final AppItem appItem = new AppItem(testUid);
final RestrictedSwitchPreference restrictBackgroundPref
= mock(RestrictedSwitchPreference.class);
final RestrictedSwitchPreference unrestrictedDataPref
= mock(RestrictedSwitchPreference.class);
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
final NetworkPolicyManager networkPolicyManager = mock(NetworkPolicyManager.class);
ReflectionHelpers.setField(mFragment, "mAppItem", appItem);
ReflectionHelpers.setField(mFragment, "mRestrictBackground", restrictBackgroundPref);
ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref);
ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend);
ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager);
ReflectionHelpers.setField(mFragment, "mContext", RuntimeEnvironment.application);
when(mFragment.getListView()).thenReturn(mock(RecyclerView.class));
ShadowRestrictedLockUtilsInternal.setRestricted(true);
doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager)
.getUidPolicy(testUid);
mFragment.updatePrefs();
verify(restrictBackgroundPref).setDisabledByAdmin(any(EnforcedAdmin.class));
verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class));
}
@Test
public void bindData_shouldUpdateUsageSummary() {
mFragment = spy(new TestFragment());
final Context context = RuntimeEnvironment.application;
ReflectionHelpers.setField(mFragment, "mContext", context);
final long backgroundBytes = 1234L;
final long foregroundBytes = 5678L;
final NetworkUsageDetailsData appUsage = new NetworkUsageDetailsData(
new Range<>(1L, 2L),
backgroundBytes + foregroundBytes,
foregroundBytes,
backgroundBytes
);
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);
mFragment.bindData(appUsage);
verify(totalPref).setSummary(
DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes));
verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes));
verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes));
}
@Test
@Config(shadows = {ShadowDataUsageUtils.class, ShadowSubscriptionManager.class,
ShadowFragment.class})
public void onCreate_noNetworkTemplateAndInvalidDataSubscription_shouldUseWifiTemplate() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
ShadowSubscriptionManager.setDefaultDataSubscriptionId(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mFragment = spy(new TestFragment());
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();
args.putInt(AppInfoBase.ARG_PACKAGE_UID, 123123);
mFragment.setArguments(args);
mFragment.onCreate(Bundle.EMPTY);
assertThat(mFragment.mTemplate.getMatchRule())
.isEqualTo(NetworkTemplate.MATCH_WIFI);
assertTrue(mFragment.mTemplate.getSubscriberIds().isEmpty());
assertTrue(mFragment.mTemplate.getWifiNetworkKeys().isEmpty());
}
private static class TestFragment extends AppDataUsage {
@Override
protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
return mock(clazz);
}
@Override
void initCycle(List<Integer> uidList) {
}
@Override
public boolean isSimHardwareVisible(Context context) {
return true;
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2016 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 android.net.NetworkPolicy.CYCLE_NONE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
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.nullable;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.NetworkPolicyManager;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.SwitchPreference;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settingslib.NetworkPolicyEditor;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class BillingCycleSettingsTest {
private static final int LIMIT_BYTES = 123;
@Mock
private BillingCycleSettings mMockBillingCycleSettings;
private BillingCycleSettings.ConfirmLimitFragment mConfirmLimitFragment;
@Mock
private PreferenceManager mMockPreferenceManager;
@Mock
private NetworkPolicyEditor mNetworkPolicyEditor;
@Mock
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private PackageManager mMockPackageManager;
private Context mContext;
@Mock
private Preference mBillingCycle;
@Mock
private Preference mDataWarning;
@Mock
private Preference mDataLimit;
@Mock
private SwitchPreference mEnableDataWarning;
@Mock
private SwitchPreference mEnableDataLimit;
private SharedPreferences mSharedPreferences;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mConfirmLimitFragment = new BillingCycleSettings.ConfirmLimitFragment();
mConfirmLimitFragment.setTargetFragment(mMockBillingCycleSettings, 0);
mSharedPreferences = RuntimeEnvironment.application.getSharedPreferences(
"testSharedPreferences", Context.MODE_PRIVATE);
when(mMockBillingCycleSettings.getPreferenceManager()).thenReturn(mMockPreferenceManager);
when(mMockPreferenceManager.getSharedPreferences()).thenReturn(mSharedPreferences);
final Bundle args = new Bundle();
args.putLong(BillingCycleSettings.ConfirmLimitFragment.EXTRA_LIMIT_BYTES, LIMIT_BYTES);
mConfirmLimitFragment.setArguments(args);
mSharedPreferences.edit().putBoolean(
BillingCycleSettings.KEY_SET_DATA_LIMIT, false).apply();
}
@Test
public void testDataUsageLimit_shouldNotBeSetOnCancel() {
mConfirmLimitFragment.onClick(null, DialogInterface.BUTTON_NEGATIVE);
assertThat(mSharedPreferences.getBoolean(BillingCycleSettings.KEY_SET_DATA_LIMIT, true))
.isFalse();
verify(mMockBillingCycleSettings, never()).setPolicyLimitBytes(anyLong());
}
@Test
public void testDataUsageLimit_shouldBeSetOnConfirmation() {
mConfirmLimitFragment.onClick(null, DialogInterface.BUTTON_POSITIVE);
assertThat(mSharedPreferences.getBoolean(BillingCycleSettings.KEY_SET_DATA_LIMIT, false))
.isTrue();
verify(mMockBillingCycleSettings).setPolicyLimitBytes(LIMIT_BYTES);
}
@Test
public void testDataUsageSummary_shouldBeNull() {
final BillingCycleSettings billingCycleSettings = spy(new BillingCycleSettings());
when(billingCycleSettings.getContext()).thenReturn(mContext);
billingCycleSettings.setUpForTest(mNetworkPolicyEditor, mBillingCycle,
mDataLimit, mDataWarning, mEnableDataLimit, mEnableDataWarning);
doReturn("some-string").when(billingCycleSettings).getString(anyInt(), anyInt());
when(mNetworkPolicyEditor.getPolicyCycleDay(any())).thenReturn(CYCLE_NONE + 1);
when(mNetworkPolicyEditor.getPolicyLimitBytes(any())).thenReturn(2000L);
when(mNetworkPolicyEditor.getPolicyWarningBytes(any())).thenReturn(1000L);
billingCycleSettings.updatePrefs();
verify(mBillingCycle).setSummary(null);
}
@Test
@Config(shadows = ShadowFragment.class)
@Ignore
public void onCreate_emptyArguments_shouldSetDefaultNetworkTemplate() {
final BillingCycleSettings billingCycleSettings = spy(new BillingCycleSettings());
when(billingCycleSettings.getContext()).thenReturn(mContext);
when(billingCycleSettings.getArguments()).thenReturn(Bundle.EMPTY);
final FragmentActivity activity = mock(FragmentActivity.class);
when(billingCycleSettings.getActivity()).thenReturn(activity);
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
doNothing().when(billingCycleSettings)
.onCreatePreferences(any(Bundle.class), nullable(String.class));
when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
.thenReturn(mNetworkPolicyManager);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.hasSystemFeature(any())).thenReturn(true);
final SwitchPreference preference = mock(SwitchPreference.class);
when(billingCycleSettings.findPreference(anyString())).thenReturn(preference);
billingCycleSettings.onCreate(Bundle.EMPTY);
assertThat(billingCycleSettings.mNetworkTemplate).isNotNull();
}
}

View File

@@ -0,0 +1,265 @@
/*
* 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.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
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 org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
public class ChartDataUsagePreferenceTest {
// Test cycle start date, 20 Mar 2018 22:00: GMT
private static final long TIMESTAMP_START = 1521583200000L;
// Test bucket end date, 22 Mar 2018 00:00:00
private static final long TIMESTAMP_END = 1521676800000L;
private List<NetworkUsageData> mNetworkCycleData;
private NetworkCycleChartData mNetworkCycleChartData;
private ChartDataUsagePreference mPreference;
private Activity mActivity;
private PreferenceViewHolder mHolder;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mActivity = spy(Robolectric.setupActivity(Activity.class));
mPreference = new ChartDataUsagePreference(mActivity, null /* attrs */);
LayoutInflater inflater = LayoutInflater.from(mActivity);
View view = inflater.inflate(mPreference.getLayoutResource(), null /* root */,
false /* attachToRoot */);
mHolder = spy(PreferenceViewHolder.createInstanceForTests(view));
}
@Test
public void calcPoints_dataAvailableFromCycleStart_shouldAddDataPointsOnly() {
final UsageView usageView = mock(UsageView.class);
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));
verify(usageView).addPath(pointsCaptor.capture());
final SparseIntArray points = pointsCaptor.getValue();
// the point should be normal usage data
assertThat(points.valueAt(1)).isNotEqualTo(-1);
}
@Ignore("b/313568482")
@Test
public void calcPoints_dataNotAvailableAtCycleStart_shouldIndicateStartOfData() {
final UsageView usageView = mock(UsageView.class);
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));
verify(usageView).addPath(pointsCaptor.capture());
final SparseIntArray points = pointsCaptor.getValue();
// indicator that no data is available
assertThat(points.keyAt(1)).isEqualTo(points.keyAt(2) - 1);
assertThat(points.valueAt(1)).isEqualTo(-1);
}
@Ignore("b/313568482")
@Test
public void calcPoints_shouldNotDrawPointForFutureDate() {
final UsageView usageView = mock(UsageView.class);
final ArgumentCaptor<SparseIntArray> pointsCaptor =
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(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(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));
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);
verify(usageView).addPath(pointsCaptor.capture());
final SparseIntArray points = pointsCaptor.getValue();
// should only have 7 points: 1 test point indicating the start of data, starting point 0,
// and 5 actual data point for each day
assertThat(points.size()).isEqualTo(7);
assertThat(points.keyAt(0)).isEqualTo(-1);
assertThat(points.keyAt(1)).isEqualTo(0);
assertThat(points.keyAt(2)).isEqualTo(TimeUnit.DAYS.toMinutes(1));
assertThat(points.keyAt(3)).isEqualTo(TimeUnit.DAYS.toMinutes(2));
assertThat(points.keyAt(4)).isEqualTo(TimeUnit.DAYS.toMinutes(3));
assertThat(points.keyAt(5)).isEqualTo(TimeUnit.DAYS.toMinutes(4));
assertThat(points.keyAt(6)).isEqualTo(TimeUnit.DAYS.toMinutes(5));
}
@Test
public void notifyChange_nonEmptyDataUsage_shouldHaveSingleContentDescription() {
final UsageView chart = (UsageView) mHolder.findViewById(R.id.data_usage);
final TextView labelTop = (TextView) mHolder.findViewById(R.id.label_top);
final TextView labelMiddle = (TextView) mHolder.findViewById(R.id.label_middle);
final TextView labelBottom = (TextView) mHolder.findViewById(R.id.label_bottom);
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);
assertThat(chart.getContentDescription()).isNotNull();
assertThat(labelTop.getContentDescription()).isNull();
assertThat(labelMiddle.getContentDescription()).isNull();
assertThat(labelBottom.getContentDescription()).isNull();
assertThat(labelStart.getContentDescription()).isNull();
assertThat(labelEnd.getContentDescription()).isNull();
}
@Test
public void getDensedStatsData_someSamePercentageNodes_getDifferentPercentageNodes() {
createSomeSamePercentageNetworkData();
final List<DataUsageSummaryNode> densedStatsData =
mPreference.getDensedStatsData(mNetworkCycleData);
assertThat(mNetworkCycleData.size()).isEqualTo(8);
assertThat(densedStatsData.size()).isEqualTo(3);
assertThat(densedStatsData.get(0).getDataUsagePercentage()).isEqualTo(33);
assertThat(densedStatsData.get(1).getDataUsagePercentage()).isEqualTo(99);
assertThat(densedStatsData.get(2).getDataUsagePercentage()).isEqualTo(100);
}
private void createTestNetworkData() {
mNetworkCycleData = new ArrayList<>();
// create 10 arbitrary network data
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));
mNetworkCycleChartData = new NetworkCycleChartData(
new NetworkUsageData(TIMESTAMP_START, TIMESTAMP_END, 0),
mNetworkCycleData
);
}
private void createSomeSamePercentageNetworkData() {
mNetworkCycleData = new ArrayList<>();
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%
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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 org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
import com.android.settingslib.net.DataUsageController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class DataUsagePreferenceTest {
@Mock
private DataUsageController mController;
private Context mContext;
private DataUsagePreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = spy(new DataUsagePreference(mContext, null /* attrs */));
doReturn(mController).when(mPreference).getDataUsageController();
}
@Test
public void setTemplate_noDataUsage_shouldDisablePreference() {
doReturn(0L).when(mController).getHistoricalUsageLevel(any(NetworkTemplate.class));
mPreference.setTemplate(new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
.setMeteredness(NetworkStats.METERED_YES).build(),
5 /* subId */);
verify(mPreference).setEnabled(false);
verify(mPreference).setIntent(null);
}
@Test
public void setTemplate_hasDataUsage_shouldNotDisablePreference() {
doReturn(200L).when(mController).getHistoricalUsageLevel(any(NetworkTemplate.class));
mPreference.setTemplate(new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
.setMeteredness(NetworkStats.METERED_YES).build(),
5 /* subId */);
verify(mPreference, never()).setEnabled(false);
verify(mPreference).setIntent(any(Intent.class));
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2016 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.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.res.Resources;
import android.os.UserManager;
import android.telephony.SubscriptionManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowDashboardFragment;
import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
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.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowSubscriptionManager;
@Config(shadows = {
ShadowUtils.class,
ShadowDataUsageUtils.class,
ShadowDashboardFragment.class,
ShadowUserManager.class,
})
@RunWith(RobolectricTestRunner.class)
public class DataUsageSummaryTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private UserManager mUserManager;
private DataUsageSummary mDataUsageSummary;
/**
* This set up is contrived to get a passing test so that the build doesn't block without tests.
* These tests should be updated as code gets refactored to improve testability.
*/
@Before
public void setUp() {
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(false).when(mUserManager).isGuestUser();
ShadowUserManager.getShadow().setIsAdminUser(true);
Resources mResources = spy(mContext.getResources());
doReturn(mResources).when(mContext).getResources();
doReturn(true).when(mResources).getBoolean(R.bool.config_show_sim_info);
mDataUsageSummary = spy(new DataUsageSummary());
doReturn(mContext).when(mDataUsageSummary).getContext();
doNothing().when(mDataUsageSummary).enableProxySubscriptionManager(any());
doReturn(true).when(mDataUsageSummary).removePreference(anyString());
doNothing().when(mDataUsageSummary).addWifiSection();
}
@Test
public void formatUsage_shouldLookLikeFormatFileSize() {
final long usage = 2147483648L; // 2GB
final String formattedUsage =
DataUsageSummary.formatUsage(mContext, "^1", usage).toString();
final CharSequence formattedInIECUnit = DataUsageUtils.formatDataUsage(mContext, usage);
assertThat(formattedUsage).isEqualTo(formattedInIECUnit);
}
@Test
@Config(shadows = ShadowSubscriptionManager.class)
public void configuration_withSim_shouldShowMobileAndWifi() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
ShadowSubscriptionManager.setDefaultDataSubscriptionId(1);
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(true).when(dataUsageSummary).hasActiveSubscription();
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
doNothing().when(dataUsageSummary).addWifiSection();
doNothing().when(dataUsageSummary).addMobileSection(1);
dataUsageSummary.onCreate(null);
verify(dataUsageSummary).addWifiSection();
verify(dataUsageSummary).addMobileSection(anyInt());
}
@Test
public void configuration_withoutSim_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(false).when(dataUsageSummary).hasActiveSubscription();
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
doNothing().when(dataUsageSummary).addWifiSection();
doNothing().when(dataUsageSummary).addMobileSection(1);
dataUsageSummary.onCreate(null);
verify(dataUsageSummary).addWifiSection();
verify(dataUsageSummary, never()).addMobileSection(anyInt());
}
@Test
public void configuration_withoutMobile_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = false;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(false).when(dataUsageSummary).hasActiveSubscription();
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
doNothing().when(dataUsageSummary).addWifiSection();
doNothing().when(dataUsageSummary).addMobileSection(1);
dataUsageSummary.onCreate(null);
verify(dataUsageSummary).addWifiSection();
verify(dataUsageSummary, never()).addMobileSection(anyInt());
}
@Test
@Config(shadows = ShadowSubscriptionManager.class)
public void configuration_invalidDataSusbscription_shouldShowWifiSectionOnly() {
ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
ShadowSubscriptionManager.setDefaultDataSubscriptionId(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
doNothing().when(dataUsageSummary).enableProxySubscriptionManager(any());
doReturn(false).when(dataUsageSummary).hasActiveSubscription();
doReturn(mContext).when(dataUsageSummary).getContext();
doReturn(true).when(dataUsageSummary).removePreference(anyString());
doNothing().when(dataUsageSummary).addWifiSection();
doNothing().when(dataUsageSummary).addMobileSection(1);
dataUsageSummary.onCreate(null);
verify(dataUsageSummary).addWifiSection();
verify(dataUsageSummary, never()).addMobileSection(anyInt());
}
@Test
public void onCreate_isNotGuestUser_shouldNotFinish() {
doReturn(false).when(mUserManager).isGuestUser();
mDataUsageSummary.onCreate(null);
verify(mDataUsageSummary, never()).finish();
}
@Test
public void onCreate_isGuestUser_shouldFinish() {
doReturn(true).when(mUserManager).isGuestUser();
mDataUsageSummary.onCreate(null);
verify(mDataUsageSummary).finish();
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2017 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.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.telephony.TelephonyManager;
import android.util.DataUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
public final class DataUsageUtilsTest {
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private NetworkStatsManager mNetworkStatsManager;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final ShadowApplication shadowContext = ShadowApplication.getInstance();
mContext = RuntimeEnvironment.application;
shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
shadowContext.setSystemService(Context.NETWORK_STATS_SERVICE, mNetworkStatsManager);
}
@Test
public void mobileDataStatus_whenNetworkIsSupported() {
when(mTelephonyManager.isDataCapable()).thenReturn(true);
final boolean hasMobileData = DataUsageUtils.hasMobileData(mContext);
assertThat(hasMobileData).isTrue();
}
@Test
public void mobileDataStatus_whenNetworkIsNotSupported() {
when(mTelephonyManager.isDataCapable()).thenReturn(false);
final boolean hasMobileData = DataUsageUtils.hasMobileData(mContext);
assertThat(hasMobileData).isFalse();
}
@Test
public void formatDataUsage_useIECUnit() {
final CharSequence formattedDataUsage = DataUsageUtils.formatDataUsage(
mContext, DataUnit.GIBIBYTES.toBytes(1));
assertThat(formattedDataUsage).isEqualTo("1.00 GB");
}
@Test
public void hasEthernet_shouldQueryEthernetSummaryForUser() throws Exception {
ShadowPackageManager pm = shadowOf(RuntimeEnvironment.application.getPackageManager());
pm.setSystemFeature(PackageManager.FEATURE_ETHERNET, true);
final String subscriber = "TestSub";
when(mTelephonyManager.getSubscriberId()).thenReturn(subscriber);
DataUsageUtils.hasEthernet(mContext);
verify(mNetworkStatsManager).querySummaryForUser(eq(ConnectivityManager.TYPE_ETHERNET),
eq(subscriber), anyLong() /* startTime */, anyLong() /* endTime */);
}
}

View File

@@ -0,0 +1,273 @@
/*
* 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.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
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.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Process;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowRestrictedLockUtils.class,
ShadowRestrictedLockUtilsInternal.class,
UnrestrictedDataAccessPreferenceControllerTest.ShadowAppStateBaseBridge.class
})
public class UnrestrictedDataAccessPreferenceControllerTest {
@Mock
private ApplicationsState mState;
@Mock
private ApplicationsState.Session mSession;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private PreferenceManager mPreferenceManager;
private PreferenceScreen mPreferenceScreen;
private UnrestrictedDataAccess mFragment;
private UnrestrictedDataAccessPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFeatureFactory = FakeFeatureFactory.setupForTest();
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mState);
when(mState.newSession(any())).thenReturn(mSession);
mController = spy(new UnrestrictedDataAccessPreferenceController(mContext, "pref_key"));
}
@Test
public void shouldAddPreference_forApps_shouldBeTrue() {
final int uid = Process.FIRST_APPLICATION_UID + 10;
final AppEntry entry = createAppEntry(uid);
assertThat(UnrestrictedDataAccessPreferenceController.shouldAddPreference(entry)).isTrue();
}
@Test
public void shouldAddPreference_forNonApps_shouldBeFalse() {
final int uid = Process.FIRST_APPLICATION_UID - 10;
final AppEntry entry = createAppEntry(uid);
assertThat(UnrestrictedDataAccessPreferenceController.shouldAddPreference(entry)).isFalse();
}
@Test
public void logSpecialPermissionChange() {
mController.logSpecialPermissionChange(true, "app");
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_UNL_DATA_ALLOW), eq("app"));
mController.logSpecialPermissionChange(false, "app");
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_UNL_DATA_DENY), eq("app"));
}
@Test
public void onRebuildComplete_restricted_shouldBeDisabled() {
mFragment = spy(new UnrestrictedDataAccess());
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
mController.setParentFragment(mFragment);
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(0).when(mPreferenceScreen).getPreferenceCount();
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
final String testPkg1 = "com.example.one";
final String testPkg2 = "com.example.two";
ShadowRestrictedLockUtilsInternal.setRestrictedPkgs(testPkg2);
doAnswer((invocation) -> {
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
final AppEntry entry = preference.getEntry();
// Verify preference is disabled by admin and the summary is changed accordingly.
if (testPkg1.equals(entry.info.packageName)) {
assertThat(preference.isDisabledByAdmin()).isFalse();
assertThat(preference.getSummary()).isEqualTo("");
} else if (testPkg2.equals(entry.info.packageName)) {
assertThat(preference.isDisabledByAdmin()).isTrue();
assertThat(preference.getSummary()).isEqualTo(
mContext.getString(
com.android.settingslib.widget.restricted.R.string.disabled_by_admin));
}
assertThat(preference.isChecked()).isFalse();
preference.performClick();
// Verify that when the preference is clicked, support details intent is launched
// if the preference is disabled by admin, otherwise the switch is toggled.
if (testPkg1.equals(entry.info.packageName)) {
assertThat(preference.isChecked()).isTrue();
assertThat(ShadowRestrictedLockUtils.hasAdminSupportDetailsIntentLaunched())
.isFalse();
} else if (testPkg2.equals(entry.info.packageName)) {
assertThat(preference.isChecked()).isFalse();
assertThat(ShadowRestrictedLockUtils.hasAdminSupportDetailsIntentLaunched())
.isTrue();
}
ShadowRestrictedLockUtils.clearAdminSupportDetailsIntentLaunch();
return null;
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
mController.onRebuildComplete(createAppEntries(testPkg1, testPkg2));
}
@Test
public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
mFragment = spy(new UnrestrictedDataAccess());
mContext = spy(mContext);
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
mController.setParentFragment(mFragment);
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(0).when(mPreferenceScreen).getPreferenceCount();
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
final String testPkg = "com.example.disabled";
doNothing().when(mContext).startActivity(any());
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
doAnswer((invocation) -> {
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
// Verify preference is disabled by ecm and the summary is changed accordingly.
assertThat(preference.isDisabledByEcm()).isTrue();
assertThat(preference.getSummary().toString()).isEqualTo(
mContext.getString(
com.android.settingslib.R.string.disabled_by_app_ops_text));
assertThat(preference.isChecked()).isFalse();
preference.performClick();
// Verify that when the preference is clicked, ecm details intent is launched
assertThat(preference.isChecked()).isFalse();
verify(mContext).startActivity(any());
return null;
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
mController.onRebuildComplete(createAppEntries(testPkg));
verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
}
@Test
public void onRebuildComplete_ecmNotRestricted_notDisabled() {
mFragment = spy(new UnrestrictedDataAccess());
mContext = spy(mContext);
doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
mController.setParentFragment(mFragment);
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(0).when(mPreferenceScreen).getPreferenceCount();
final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
final String testPkg = "com.example.enabled";
doNothing().when(mContext).startActivity(any());
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
doAnswer((invocation) -> {
final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
assertThat(preference.isDisabledByEcm()).isFalse();
assertThat(preference.getSummary()).isEqualTo("");
assertThat(preference.isChecked()).isFalse();
preference.performClick();
// Verify that when the preference is clicked, ecm details intent is not launched
assertThat(preference.isChecked()).isTrue();
verify(mContext, never()).startActivity(any());
return null;
}).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
mController.onRebuildComplete(createAppEntries(testPkg));
verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
}
private ArrayList<AppEntry> createAppEntries(String... packageNames) {
final ArrayList<AppEntry> appEntries = new ArrayList<>();
for (int i = 0; i < packageNames.length; ++i) {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = packageNames[i];
info.uid = Process.FIRST_APPLICATION_UID + i;
info.sourceDir = info.packageName;
final AppEntry appEntry = spy(new AppEntry(mContext, info, i));
appEntry.extraInfo = new DataUsageState(false, false);
doNothing().when(appEntry).ensureLabel(any(Context.class));
ReflectionHelpers.setField(appEntry, "info", info);
appEntries.add(appEntry);
}
return appEntries;
}
private AppEntry createAppEntry(int uid) {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "com.example.three";
info.uid = uid;
info.sourceDir = info.packageName;
return new AppEntry(mContext, info, uid);
}
@Implements(AppStateBaseBridge.class)
public static class ShadowAppStateBaseBridge {
public void __constructor__(ApplicationsState appState,
AppStateBaseBridge.Callback callback) {
}
}
}