1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.datausage; 18 19 import static android.content.pm.PackageManager.FEATURE_WIFI; 20 21 import static com.android.settings.core.BasePreferenceController.AVAILABLE; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.spy; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.when; 31 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.pm.PackageManager; 35 import android.net.NetworkTemplate; 36 import android.telephony.SubscriptionInfo; 37 import android.telephony.SubscriptionManager; 38 import android.telephony.SubscriptionPlan; 39 import android.telephony.TelephonyManager; 40 import android.util.RecurrenceRule; 41 42 import androidx.fragment.app.FragmentActivity; 43 import androidx.preference.PreferenceFragmentCompat; 44 import androidx.recyclerview.widget.RecyclerView; 45 46 import com.android.internal.logging.nano.MetricsProto; 47 import com.android.settings.R; 48 import com.android.settings.testutils.FakeFeatureFactory; 49 import com.android.settings.testutils.shadow.ShadowEntityHeaderController; 50 import com.android.settings.widget.EntityHeaderController; 51 import com.android.settingslib.NetworkPolicyEditor; 52 import com.android.settingslib.core.lifecycle.Lifecycle; 53 import com.android.settingslib.net.DataUsageController; 54 55 import org.junit.After; 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Answers; 60 import org.mockito.ArgumentCaptor; 61 import org.mockito.Mock; 62 import org.mockito.MockitoAnnotations; 63 import org.robolectric.Robolectric; 64 import org.robolectric.RobolectricTestRunner; 65 import org.robolectric.RuntimeEnvironment; 66 import org.robolectric.annotation.Config; 67 68 import java.time.Instant; 69 import java.time.ZoneId; 70 import java.util.ArrayList; 71 import java.util.List; 72 import java.util.concurrent.TimeUnit; 73 74 @RunWith(RobolectricTestRunner.class) 75 @Config(shadows = ShadowEntityHeaderController.class) 76 public class DataUsageSummaryPreferenceControllerTest { 77 78 private static final long UPDATE_BACKOFF_MS = TimeUnit.MINUTES.toMillis(13); 79 private static final long CYCLE_BACKOFF_MS = TimeUnit.DAYS.toMillis(6); 80 private static final long CYCLE_LENGTH_MS = TimeUnit.DAYS.toMillis(30); 81 private static final long USAGE1 = 373 * BillingCycleSettings.MIB_IN_BYTES; 82 private static final long LIMIT1 = BillingCycleSettings.GIB_IN_BYTES; 83 private static final String CARRIER_NAME = "z-mobile"; 84 private static final String PERIOD = "Feb"; 85 86 @Mock 87 private DataUsageController mDataUsageController; 88 @Mock 89 private DataUsageSummaryPreference mSummaryPreference; 90 @Mock 91 private NetworkPolicyEditor mPolicyEditor; 92 @Mock 93 private NetworkTemplate mNetworkTemplate; 94 @Mock 95 private SubscriptionInfo mSubscriptionInfo; 96 @Mock 97 private SubscriptionPlan mSubscriptionPlan; 98 @Mock 99 private Lifecycle mLifecycle; 100 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 101 private EntityHeaderController mHeaderController; 102 @Mock 103 private PreferenceFragmentCompat mPreferenceFragment; 104 @Mock 105 private TelephonyManager mTelephonyManager; 106 @Mock 107 private PackageManager mPm; 108 109 private DataUsageInfoController mDataInfoController; 110 111 private FakeFeatureFactory mFactory; 112 private FragmentActivity mActivity; 113 private Context mContext; 114 private DataUsageSummaryPreferenceController mController; 115 private int mDefaultSubscriptionId; 116 private List<SubscriptionPlan> mSubscriptionPlans; 117 118 @Before setUp()119 public void setUp() { 120 MockitoAnnotations.initMocks(this); 121 mContext = spy(RuntimeEnvironment.application); 122 123 doReturn("%1$s %2%s").when(mContext) 124 .getString(com.android.internal.R.string.fileSizeSuffix); 125 126 mDefaultSubscriptionId = 1234; 127 mSubscriptionPlans = new ArrayList<SubscriptionPlan>(); 128 129 mFactory = FakeFeatureFactory.setupForTest(); 130 when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class))) 131 .thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY); 132 ShadowEntityHeaderController.setUseMock(mHeaderController); 133 134 mDataInfoController = spy(new DataUsageInfoController()); 135 doReturn(-1L).when(mDataInfoController).getSummaryLimit(any()); 136 137 mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get()); 138 doReturn(mTelephonyManager).when(mActivity).getSystemService(TelephonyManager.class); 139 doReturn(mTelephonyManager).when(mTelephonyManager) 140 .createForSubscriptionId(mDefaultSubscriptionId); 141 doReturn(mPm).when(mActivity).getPackageManager(); 142 doReturn(false).when(mPm).hasSystemFeature(eq(FEATURE_WIFI)); 143 doReturn(TelephonyManager.SIM_STATE_READY).when(mTelephonyManager).getSimState(); 144 145 mController = spy(new DataUsageSummaryPreferenceController( 146 mDataUsageController, 147 mDataInfoController, 148 mNetworkTemplate, 149 mPolicyEditor, 150 R.string.cell_data_template, 151 mActivity, null, null, null, mDefaultSubscriptionId)); 152 doReturn(null).when(mController).getSubscriptionInfo( 153 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 154 doReturn(null).when(mController).getSubscriptionPlans( 155 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 156 157 doReturn(CARRIER_NAME).when(mSubscriptionInfo).getCarrierName(); 158 doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(mDefaultSubscriptionId); 159 doReturn(mSubscriptionPlans).when(mController).getSubscriptionPlans(mDefaultSubscriptionId); 160 } 161 162 @After tearDown()163 public void tearDown() { 164 ShadowEntityHeaderController.reset(); 165 } 166 167 @Test testSummaryUpdate_onePlan_basic()168 public void testSummaryUpdate_onePlan_basic() { 169 final long now = System.currentTimeMillis(); 170 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 171 172 final Intent intent = new Intent(); 173 174 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 175 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 176 createTestDataPlan(info.cycleStart, info.cycleEnd); 177 doReturn(intent).when(mController).createManageSubscriptionIntent(mDefaultSubscriptionId); 178 179 mController.updateState(mSummaryPreference); 180 181 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 182 verify(mSummaryPreference).setLimitInfo(captor.capture()); 183 CharSequence value = captor.getValue(); 184 assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit"); 185 186 // TODO (b/170330084): return intent instead of null for mSummaryPreference 187 verify(mSummaryPreference).setUsageInfo((info.cycleEnd / 1000) * 1000, 188 now - UPDATE_BACKOFF_MS, 189 CARRIER_NAME, 1 /* numPlans */, null /* launchIntent */); 190 verify(mSummaryPreference).setChartEnabled(true); 191 verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */, 192 false /* isSingleWifi */); 193 } 194 195 @Test testSummaryUpdate_noPlan_basic()196 public void testSummaryUpdate_noPlan_basic() { 197 final long now = System.currentTimeMillis(); 198 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 199 200 final Intent intent = new Intent(); 201 202 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 203 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 204 205 mController.updateState(mSummaryPreference); 206 207 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 208 verify(mSummaryPreference).setLimitInfo(captor.capture()); 209 CharSequence value = captor.getValue(); 210 assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit"); 211 212 verify(mSummaryPreference).setUsageInfo( 213 info.cycleEnd, 214 -1L /* snapshotTime */, 215 CARRIER_NAME, 216 0 /* numPlans */, 217 null /* launchIntent */); 218 verify(mSummaryPreference).setChartEnabled(true); 219 verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */, 220 false /* isSingleWifi */); 221 } 222 223 @Test testSummaryUpdate_noCarrier_basic()224 public void testSummaryUpdate_noCarrier_basic() { 225 final long now = System.currentTimeMillis(); 226 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 227 228 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 229 doReturn(null).when(mSubscriptionInfo).getCarrierName(); 230 setupTestDataUsage(LIMIT1, USAGE1, -1L /* snapshotTime */); 231 232 mController.updateState(mSummaryPreference); 233 234 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 235 verify(mSummaryPreference).setLimitInfo(captor.capture()); 236 CharSequence value = captor.getValue(); 237 assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit"); 238 239 verify(mSummaryPreference).setUsageInfo( 240 info.cycleEnd, 241 -1L /* snapshotTime */, 242 null /* carrierName */, 243 0 /* numPlans */, 244 null /* launchIntent */); 245 verify(mSummaryPreference).setChartEnabled(true); 246 verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */, 247 false /* isSingleWifi */); 248 } 249 250 @Test testSummaryUpdate_noPlanData_basic()251 public void testSummaryUpdate_noPlanData_basic() { 252 final long now = System.currentTimeMillis(); 253 254 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 255 256 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 257 doReturn(null).when(mSubscriptionInfo).getCarrierName(); 258 setupTestDataUsage(-1L /* dataPlanSize */, USAGE1, -1L /* snapshotTime */); 259 260 mController.updateState(mSummaryPreference); 261 262 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 263 verify(mSummaryPreference).setLimitInfo(captor.capture()); 264 CharSequence value = captor.getValue(); 265 assertThat(value.toString()).isEqualTo("512 MB data warning / 1.00 GB data limit"); 266 verify(mSummaryPreference).setUsageInfo( 267 info.cycleEnd, 268 -1L /* snapshotTime */, 269 null /* carrierName */, 270 0 /* numPlans */, 271 null /* launchIntent */); 272 verify(mSummaryPreference).setChartEnabled(false); 273 verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */, 274 false /* isSingleWifi */); 275 } 276 277 @Test testSummaryUpdate_noLimitNoWarning()278 public void testSummaryUpdate_noLimitNoWarning() { 279 final long now = System.currentTimeMillis(); 280 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 281 info.warningLevel = 0L; 282 info.limitLevel = 0L; 283 284 final Intent intent = new Intent(); 285 286 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 287 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 288 289 mController.updateState(mSummaryPreference); 290 verify(mSummaryPreference).setLimitInfo(null); 291 } 292 293 @Test testSummaryUpdate_warningOnly()294 public void testSummaryUpdate_warningOnly() { 295 final long now = System.currentTimeMillis(); 296 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 297 info.warningLevel = BillingCycleSettings.MIB_IN_BYTES; 298 info.limitLevel = 0L; 299 300 final Intent intent = new Intent(); 301 302 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 303 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 304 305 mController.updateState(mSummaryPreference); 306 307 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 308 verify(mSummaryPreference).setLimitInfo(captor.capture()); 309 CharSequence value = captor.getValue(); 310 assertThat(value.toString()).isEqualTo("1.00 MB data warning"); 311 } 312 313 @Test testSummaryUpdate_limitOnly()314 public void testSummaryUpdate_limitOnly() { 315 final long now = System.currentTimeMillis(); 316 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 317 info.warningLevel = 0L; 318 info.limitLevel = BillingCycleSettings.MIB_IN_BYTES; 319 320 final Intent intent = new Intent(); 321 322 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 323 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 324 325 mController.updateState(mSummaryPreference); 326 327 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 328 verify(mSummaryPreference).setLimitInfo(captor.capture()); 329 CharSequence value = captor.getValue(); 330 assertThat(value.toString()).isEqualTo("1.00 MB data limit"); 331 } 332 333 @Test testSummaryUpdate_limitAndWarning()334 public void testSummaryUpdate_limitAndWarning() { 335 final long now = System.currentTimeMillis(); 336 final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now); 337 info.warningLevel = BillingCycleSettings.MIB_IN_BYTES; 338 info.limitLevel = BillingCycleSettings.MIB_IN_BYTES; 339 340 final Intent intent = new Intent(); 341 342 doReturn(info).when(mDataUsageController).getDataUsageInfo(any()); 343 setupTestDataUsage(LIMIT1, USAGE1, now - UPDATE_BACKOFF_MS); 344 345 mController.updateState(mSummaryPreference); 346 347 ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); 348 verify(mSummaryPreference).setLimitInfo(captor.capture()); 349 CharSequence value = captor.getValue(); 350 assertThat(value.toString()).isEqualTo("1.00 MB data warning / 1.00 MB data limit"); 351 verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */, 352 false /* isSingleWifi */); 353 } 354 355 @Test testMobileData_preferenceAvailable()356 public void testMobileData_preferenceAvailable() { 357 assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); 358 } 359 360 @Test testMobileData_noSimWifi_preferenceDisabled()361 public void testMobileData_noSimWifi_preferenceDisabled() { 362 final int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 363 mController.init(subscriptionId); 364 mController.mDataUsageController = mDataUsageController; 365 doReturn(true).when(mPm).hasSystemFeature(eq(FEATURE_WIFI)); 366 assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); 367 } 368 369 @Test testMobileData_entityHeaderSet()370 public void testMobileData_entityHeaderSet() { 371 final RecyclerView recyclerView = new RecyclerView(mActivity); 372 373 mController = spy(new DataUsageSummaryPreferenceController( 374 mDataUsageController, 375 mDataInfoController, 376 mNetworkTemplate, 377 mPolicyEditor, 378 R.string.cell_data_template, 379 mActivity, mLifecycle, mHeaderController, mPreferenceFragment, 380 mDefaultSubscriptionId)); 381 382 when(mPreferenceFragment.getListView()).thenReturn(recyclerView); 383 384 mController.onStart(); 385 386 verify(mHeaderController) 387 .setRecyclerView(any(RecyclerView.class), any(Lifecycle.class)); 388 } 389 createTestDataUsageInfo(long now)390 private DataUsageController.DataUsageInfo createTestDataUsageInfo(long now) { 391 DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo(); 392 info.carrier = CARRIER_NAME; 393 info.period = PERIOD; 394 info.startDate = now; 395 info.limitLevel = LIMIT1; 396 info.warningLevel = LIMIT1 >> 1; 397 info.usageLevel = USAGE1; 398 info.cycleStart = now - CYCLE_BACKOFF_MS; 399 info.cycleEnd = info.cycleStart + CYCLE_LENGTH_MS; 400 return info; 401 } 402 setupTestDataUsage(long dataPlanSize, long dataUsageSize, long snapshotTime)403 private void setupTestDataUsage(long dataPlanSize, long dataUsageSize, long snapshotTime) { 404 doReturn(dataPlanSize).when(mSubscriptionPlan).getDataLimitBytes(); 405 doReturn(dataUsageSize).when(mSubscriptionPlan).getDataUsageBytes(); 406 doReturn(snapshotTime).when(mSubscriptionPlan).getDataUsageTime(); 407 408 doReturn(dataPlanSize).when(mDataInfoController).getSummaryLimit(any()); 409 } 410 createTestDataPlan(long startTime, long endTime)411 private void createTestDataPlan(long startTime, long endTime) { 412 final RecurrenceRule recurrenceRule = new RecurrenceRule( 413 Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()), 414 Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()), 415 null); 416 doReturn(recurrenceRule).when(mSubscriptionPlan).getCycleRule(); 417 mSubscriptionPlans.add(mSubscriptionPlan); 418 } 419 } 420