• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.car.settings.datausage;
18 
19 import static com.android.car.settings.common.PreferenceController.AVAILABLE;
20 import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.when;
26 import static org.robolectric.shadow.api.Shadow.extract;
27 
28 import android.content.Context;
29 import android.net.NetworkTemplate;
30 import android.telephony.SubscriptionInfo;
31 import android.telephony.SubscriptionManager;
32 import android.telephony.SubscriptionPlan;
33 import android.telephony.TelephonyManager;
34 import android.text.TextUtils;
35 import android.text.format.Formatter;
36 
37 import androidx.lifecycle.Lifecycle;
38 
39 import com.android.car.settings.CarSettingsRobolectricTestRunner;
40 import com.android.car.settings.R;
41 import com.android.car.settings.common.PreferenceControllerTestHelper;
42 import com.android.car.settings.testutils.ShadowDataUsageController;
43 import com.android.car.settings.testutils.ShadowSubscriptionManager;
44 import com.android.car.settings.testutils.ShadowTelephonyManager;
45 import com.android.settingslib.net.DataUsageController;
46 
47 import com.google.android.collect.Lists;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 import org.robolectric.RuntimeEnvironment;
56 import org.robolectric.annotation.Config;
57 import org.robolectric.shadow.api.Shadow;
58 
59 import java.time.Period;
60 import java.time.ZonedDateTime;
61 import java.util.concurrent.TimeUnit;
62 
63 @RunWith(CarSettingsRobolectricTestRunner.class)
64 @Config(shadows = {ShadowTelephonyManager.class, ShadowSubscriptionManager.class,
65         ShadowDataUsageController.class})
66 public class DataUsageSummaryPreferenceControllerTest {
67 
68     private static final CharSequence TEST_CARRIER_NAME = "TEST_CARRIER_NAME";
69 
70     private Context mContext;
71     private DataUsageSummaryPreference mDataUsageSummaryPreference;
72     private DataUsageSummaryPreferenceController mController;
73     private PreferenceControllerTestHelper<DataUsageSummaryPreferenceController> mControllerHelper;
74     private NetworkTemplate mNetworkTemplate;
75     @Mock
76     private DataUsageController mDataUsageController;
77 
78     @Before
setUp()79     public void setUp() {
80         MockitoAnnotations.initMocks(this);
81 
82         SubscriptionInfo info = mock(SubscriptionInfo.class);
83         when(info.getSubscriptionId()).thenReturn(1);
84         ShadowSubscriptionManager.setDefaultDataSubscriptionInfo(info);
85         ShadowDataUsageController.setInstance(mDataUsageController);
86 
87         mContext = RuntimeEnvironment.application;
88         mDataUsageSummaryPreference = new DataUsageSummaryPreference(mContext);
89         mControllerHelper = new PreferenceControllerTestHelper<>(mContext,
90                 DataUsageSummaryPreferenceController.class, mDataUsageSummaryPreference);
91         mController = mControllerHelper.getController();
92 
93         mNetworkTemplate = DataUsageUtils.getMobileNetworkTemplate(
94                 mContext.getSystemService(TelephonyManager.class),
95                 DataUsageUtils.getDefaultSubscriptionId(
96                         mContext.getSystemService(SubscriptionManager.class)));
97     }
98 
99     @After
tearDown()100     public void tearDown() {
101         ShadowTelephonyManager.reset();
102         ShadowSubscriptionManager.reset();
103         ShadowDataUsageController.reset();
104     }
105 
106     @Test
getAvailabilityStatus_hasSim_isAvailable()107     public void getAvailabilityStatus_hasSim_isAvailable() {
108         getShadowTelephonyManager().setSimState(TelephonyManager.SIM_STATE_LOADED);
109         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
110     }
111 
112     @Test
getAvailabilityStatus_noSim_isConditionallyUnavailable()113     public void getAvailabilityStatus_noSim_isConditionallyUnavailable() {
114         getShadowTelephonyManager().setSimState(TelephonyManager.SIM_STATE_UNKNOWN);
115         assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
116     }
117 
118     @Test
refreshUi_hasUsage_titleSet()119     public void refreshUi_hasUsage_titleSet() {
120         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
121         info.usageLevel = 10000;
122         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
123 
124         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
125         mController.refreshUi();
126 
127         String usedValueString = Formatter.formatBytes(mContext.getResources(), info.usageLevel,
128                 Formatter.FLAG_CALCULATE_ROUNDED | Formatter.FLAG_IEC_UNITS).value;
129         assertThat(mDataUsageSummaryPreference.getTitle().toString()).contains(usedValueString);
130     }
131 
132     @Test
refreshUi_noLimits_doesntSetDataLimitText()133     public void refreshUi_noLimits_doesntSetDataLimitText() {
134         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
135         info.usageLevel = 10000;
136         info.limitLevel = -1;
137         info.warningLevel = -1;
138         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
139 
140         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
141         mController.refreshUi();
142 
143         assertThat(mDataUsageSummaryPreference.getDataLimitText()).isNull();
144     }
145 
146     @Test
refreshUi_hasLimit_setsDataLimitText()147     public void refreshUi_hasLimit_setsDataLimitText() {
148         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
149         info.usageLevel = 10000;
150         info.limitLevel = 100000;
151         info.warningLevel = -1;
152         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
153 
154         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
155         mController.refreshUi();
156 
157         assertThat(mDataUsageSummaryPreference.getDataLimitText().toString()).isEqualTo(
158                 TextUtils.expandTemplate(mContext.getText(R.string.cell_data_limit),
159                         DataUsageUtils.bytesToIecUnits(mContext, info.limitLevel)).toString());
160     }
161 
162     @Test
refreshUi_hasWarning_setsDataLimitText()163     public void refreshUi_hasWarning_setsDataLimitText() {
164         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
165         info.usageLevel = 10000;
166         info.limitLevel = -1;
167         info.warningLevel = 50000;
168         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
169 
170         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
171         mController.refreshUi();
172 
173         assertThat(mDataUsageSummaryPreference.getDataLimitText().toString()).isEqualTo(
174                 TextUtils.expandTemplate(mContext.getText(R.string.cell_data_warning),
175                         DataUsageUtils.bytesToIecUnits(mContext, info.warningLevel)).toString());
176     }
177 
178     @Test
refreshUi_hasWarningAndLimit_setsDataLimitText()179     public void refreshUi_hasWarningAndLimit_setsDataLimitText() {
180         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
181         info.usageLevel = 10000;
182         info.limitLevel = 100000;
183         info.warningLevel = 50000;
184         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
185 
186         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
187         mController.refreshUi();
188 
189         assertThat(mDataUsageSummaryPreference.getDataLimitText().toString()).isEqualTo(
190                 TextUtils.expandTemplate(mContext.getText(R.string.cell_data_warning_and_limit),
191                         DataUsageUtils.bytesToIecUnits(mContext, info.warningLevel),
192                         DataUsageUtils.bytesToIecUnits(mContext, info.limitLevel)).toString());
193     }
194 
195     @Test
refreshUi_endTimeIsGreaterThanOneDay_setsBillingCycleText()196     public void refreshUi_endTimeIsGreaterThanOneDay_setsBillingCycleText() {
197         int numDays = 20;
198         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
199         // Add an extra hour to account for the difference in time when the test calls
200         // System.currentTimeMillis() vs when the code calls it.
201         info.cycleEnd = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(numDays)
202                 + TimeUnit.HOURS.toMillis(1);
203         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
204 
205         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
206         mController.refreshUi();
207 
208         assertThat(mDataUsageSummaryPreference.getRemainingBillingCycleText().toString())
209                 .isEqualTo(
210                         mContext.getResources().getQuantityString(R.plurals.billing_cycle_days_left,
211                                 numDays, numDays));
212     }
213 
214     @Test
refreshUi_endTimeIsLessThanOneDay_setsBillingCycleText()215     public void refreshUi_endTimeIsLessThanOneDay_setsBillingCycleText() {
216         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
217         info.cycleEnd = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(22);
218         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
219 
220         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
221         mController.refreshUi();
222 
223         assertThat(mDataUsageSummaryPreference.getRemainingBillingCycleText().toString())
224                 .isEqualTo(
225                         mContext.getString(R.string.billing_cycle_less_than_one_day_left));
226     }
227 
228     @Test
refreshUi_endTimeIsNow_setsBillingCycleText()229     public void refreshUi_endTimeIsNow_setsBillingCycleText() {
230         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
231         info.cycleEnd = System.currentTimeMillis();
232         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
233 
234         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
235         mController.refreshUi();
236 
237         assertThat(mDataUsageSummaryPreference.getRemainingBillingCycleText().toString())
238                 .isEqualTo(
239                         mContext.getString(R.string.billing_cycle_none_left));
240     }
241 
242     @Test
refreshUi_hasCarrierName_hasRecentUpdate_setsCarrierInfoText()243     public void refreshUi_hasCarrierName_hasRecentUpdate_setsCarrierInfoText() {
244         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
245         info.usageLevel = 10000;
246         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
247 
248         setCarrierName(TEST_CARRIER_NAME);
249         setSubscriptionPlan(/* usageBytes= */ 1000L, System.currentTimeMillis());
250 
251         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
252         mController.refreshUi();
253 
254         assertThat(mDataUsageSummaryPreference.getCarrierInfoText()).isEqualTo(
255                 TextUtils.expandTemplate(mContext.getText(R.string.carrier_and_update_now_text),
256                         TEST_CARRIER_NAME));
257     }
258 
259     @Test
refreshUi_hasCarrierName_hasOldUpdate_setsCarrierInfoText()260     public void refreshUi_hasCarrierName_hasOldUpdate_setsCarrierInfoText() {
261         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
262         info.usageLevel = 10000;
263         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
264 
265         int numDays = 15;
266         setCarrierName(TEST_CARRIER_NAME);
267         setSubscriptionPlan(/* usageBytes= */ 1000L,
268                 System.currentTimeMillis() - TimeUnit.DAYS.toMillis(numDays));
269 
270         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
271         mController.refreshUi();
272 
273         assertThat(mDataUsageSummaryPreference.getCarrierInfoText()).isEqualTo(
274                 TextUtils.expandTemplate(mContext.getText(R.string.carrier_and_update_text),
275                         TEST_CARRIER_NAME, numDays + " days"));
276     }
277 
278     @Test
refreshUi_noCarrierName_hasRecentUpdate_setsCarrierInfoText()279     public void refreshUi_noCarrierName_hasRecentUpdate_setsCarrierInfoText() {
280         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
281         info.usageLevel = 10000;
282         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
283 
284         setSubscriptionPlan(/* usageBytes= */ 1000L, System.currentTimeMillis());
285 
286         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
287         mController.refreshUi();
288 
289         assertThat(mDataUsageSummaryPreference.getCarrierInfoText().toString()).isEqualTo(
290                 mContext.getString(R.string.no_carrier_update_now_text));
291     }
292 
293     @Test
refreshUi_noCarrierName_hasOldUpdate_setsCarrierInfoText()294     public void refreshUi_noCarrierName_hasOldUpdate_setsCarrierInfoText() {
295         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
296         info.usageLevel = 10000;
297         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
298 
299         int numDays = 15;
300         setSubscriptionPlan(/* usageBytes= */ 1000L,
301                 System.currentTimeMillis() - TimeUnit.DAYS.toMillis(numDays));
302 
303         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
304         mController.refreshUi();
305 
306         assertThat(mDataUsageSummaryPreference.getCarrierInfoText()).isEqualTo(
307                 TextUtils.expandTemplate(mContext.getText(R.string.no_carrier_update_text),
308                         null, numDays + " days"));
309     }
310 
311     @Test
refreshUi_hasUpdateTimeOlderThanWarning_setsCarrierInfoStyle()312     public void refreshUi_hasUpdateTimeOlderThanWarning_setsCarrierInfoStyle() {
313         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
314         info.usageLevel = 10000;
315         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
316 
317 
318         // Subtract an extra hour to account fo the difference in calls to
319         // System.currentTimeMillis().
320         setSubscriptionPlan(/* usageBytes= */ 1000L,
321                 System.currentTimeMillis() - DataUsageSummaryPreferenceController.WARNING_AGE
322                         - TimeUnit.HOURS.toMillis(1));
323 
324         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
325         mController.refreshUi();
326 
327         assertThat(mDataUsageSummaryPreference.getCarrierInfoTextStyle()).isEqualTo(
328                 R.style.DataUsageSummaryCarrierInfoWarningTextAppearance);
329     }
330 
331     @Test
refreshUi_hasUpdateTimeYoungerThanWarning_setsCarrierInfoStyle()332     public void refreshUi_hasUpdateTimeYoungerThanWarning_setsCarrierInfoStyle() {
333         DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
334         info.usageLevel = 10000;
335         when(mDataUsageController.getDataUsageInfo(mNetworkTemplate)).thenReturn(info);
336 
337         // Subtract an extra hour to account fo the difference in calls to
338         // System.currentTimeMillis().
339         setSubscriptionPlan(/* usageBytes= */ 1000L,
340                 System.currentTimeMillis() - DataUsageSummaryPreferenceController.WARNING_AGE
341                         + TimeUnit.HOURS.toMillis(1));
342 
343         mControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
344         mController.refreshUi();
345 
346         assertThat(mDataUsageSummaryPreference.getCarrierInfoTextStyle()).isEqualTo(
347                 R.style.DataUsageSummaryCarrierInfoTextAppearance);
348     }
349 
getShadowTelephonyManager()350     private ShadowTelephonyManager getShadowTelephonyManager() {
351         return (ShadowTelephonyManager) extract(
352                 mContext.getSystemService(TelephonyManager.class));
353     }
354 
getShadowSubscriptionManager()355     private ShadowSubscriptionManager getShadowSubscriptionManager() {
356         return Shadow.extract(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE));
357     }
358 
setCarrierName(CharSequence name)359     private void setCarrierName(CharSequence name) {
360         SubscriptionInfo subInfo = new SubscriptionInfo(/* id= */ 0, /* iccId= */ "",
361                 /* simSlotIndex= */ 0, /* displayName= */ "", name,
362                 /* nameSource= */ 0, /* iconTint= */ 0, /* number= */ "",
363                 /* roaming= */ 0, /* icon= */ null, /* mcc= */ "", /* mnc= */ "",
364                 /* countryIso= */ "", /* isEmbedded= */ false,
365                 /* accessRules= */ null, /* cardString= */ "");
366         ShadowSubscriptionManager.setDefaultDataSubscriptionInfo(subInfo);
367     }
368 
setSubscriptionPlan(long usageBytes, long snapshotMillis)369     private void setSubscriptionPlan(long usageBytes, long snapshotMillis) {
370         ZonedDateTime start = ZonedDateTime.now();
371         ZonedDateTime end = ZonedDateTime.now().plusDays(30);
372         SubscriptionPlan plan = new SubscriptionPlan.Builder(start, end, Period.ofMonths(1))
373                 .setDataLimit(/* dataLimitBytes= */ 5000000000L,
374                         SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
375                 .setDataUsage(usageBytes, snapshotMillis)
376                 .build();
377         getShadowSubscriptionManager().setSubscriptionPlans(Lists.newArrayList(plan));
378     }
379 }
380