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.network;
18 
19 import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
20 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GOOD;
21 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT;
22 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
23 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_POOR;
24 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
25 
26 import static com.google.common.truth.Truth.assertThat;
27 
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyBoolean;
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.Mockito.doNothing;
33 import static org.mockito.Mockito.doReturn;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.spy;
36 import static org.mockito.Mockito.times;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.when;
39 
40 import android.app.Activity;
41 import android.content.Context;
42 import android.content.Intent;
43 import android.graphics.drawable.Drawable;
44 import android.graphics.drawable.LayerDrawable;
45 import android.net.ConnectivityManager;
46 import android.net.Network;
47 import android.net.NetworkCapabilities;
48 import android.provider.Settings;
49 import android.telephony.SignalStrength;
50 import android.telephony.SubscriptionInfo;
51 import android.telephony.SubscriptionManager;
52 import android.telephony.TelephonyManager;
53 
54 import com.android.settings.R;
55 import com.android.settingslib.core.lifecycle.Lifecycle;
56 import com.android.settingslib.graph.SignalDrawable;
57 
58 import org.junit.After;
59 import org.junit.Before;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 import org.mockito.ArgumentCaptor;
63 import org.mockito.Mock;
64 import org.mockito.MockitoAnnotations;
65 import org.robolectric.Robolectric;
66 import org.robolectric.RobolectricTestRunner;
67 import org.robolectric.RuntimeEnvironment;
68 import org.robolectric.annotation.Config;
69 import org.robolectric.shadows.ShadowSubscriptionManager;
70 
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.List;
74 
75 import androidx.lifecycle.LifecycleOwner;
76 import androidx.preference.Preference;
77 import androidx.preference.PreferenceCategory;
78 import androidx.preference.PreferenceScreen;
79 
80 @RunWith(RobolectricTestRunner.class)
81 @Config(shadows = ShadowSubscriptionManager.class)
82 public class SubscriptionsPreferenceControllerTest {
83     private static final String KEY = "preference_group";
84 
85     @Mock
86     private PreferenceScreen mScreen;
87     @Mock
88     private PreferenceCategory mPreferenceCategory;
89     @Mock
90     private SubscriptionManager mSubscriptionManager;
91     @Mock
92     private ConnectivityManager mConnectivityManager;
93     @Mock
94     private TelephonyManager mTelephonyManager;
95     @Mock
96     private Network mActiveNetwork;
97     @Mock
98     private NetworkCapabilities mCapabilities;
99     @Mock
100     private Drawable mSignalStrengthIcon;
101 
102     private Context mContext;
103     private LifecycleOwner mLifecycleOwner;
104     private Lifecycle mLifecycle;
105     private SubscriptionsPreferenceController mController;
106     private int mOnChildUpdatedCount;
107     private SubscriptionsPreferenceController.UpdateListener mUpdateListener;
108 
109     @Before
setUp()110     public void setUp() {
111         MockitoAnnotations.initMocks(this);
112         mContext = spy(RuntimeEnvironment.application);
113         mLifecycleOwner = () -> mLifecycle;
114         mLifecycle = new Lifecycle(mLifecycleOwner);
115         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
116         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
117         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
118         when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
119         when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork)).thenReturn(mCapabilities);
120         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
121         when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
122         when(mPreferenceCategory.getContext()).thenReturn(mContext);
123         mOnChildUpdatedCount = 0;
124         mUpdateListener = () -> mOnChildUpdatedCount++;
125 
126         mController = spy(
127                 new SubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener,
128                         KEY, 5));
129         doReturn(mSignalStrengthIcon).when(mController).getIcon(anyInt(), anyInt(), anyBoolean());
130     }
131 
132     @After
tearDown()133     public void tearDown() {
134         SubscriptionUtil.setActiveSubscriptionsForTesting(null);
135     }
136 
137     @Test
isAvailable_oneSubscription_availableFalse()138     public void isAvailable_oneSubscription_availableFalse() {
139         setupMockSubscriptions(1);
140         assertThat(mController.isAvailable()).isFalse();
141     }
142 
143     @Test
isAvailable_twoSubscriptions_availableTrue()144     public void isAvailable_twoSubscriptions_availableTrue() {
145         setupMockSubscriptions(2);
146         assertThat(mController.isAvailable()).isTrue();
147     }
148 
149     @Test
isAvailable_fiveSubscriptions_availableTrue()150     public void isAvailable_fiveSubscriptions_availableTrue() {
151         setupMockSubscriptions(5);
152         assertThat(mController.isAvailable()).isTrue();
153     }
154 
155     @Test
isAvailable_airplaneModeOn_availableFalse()156     public void isAvailable_airplaneModeOn_availableFalse() {
157         setupMockSubscriptions(2);
158         assertThat(mController.isAvailable()).isTrue();
159         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
160         assertThat(mController.isAvailable()).isFalse();
161     }
162 
163     @Test
onAirplaneModeChanged_airplaneModeTurnedOn_eventFired()164     public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
165         setupMockSubscriptions(2);
166         mController.onResume();
167         mController.displayPreference(mScreen);
168         assertThat(mController.isAvailable()).isTrue();
169 
170         final int updateCountBeforeModeChange = mOnChildUpdatedCount;
171         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
172         mController.onAirplaneModeChanged(true);
173         assertThat(mController.isAvailable()).isFalse();
174         assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
175     }
176 
177     @Test
onAirplaneModeChanged_airplaneModeTurnedOff_eventFired()178     public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
179         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
180         setupMockSubscriptions(2);
181         mController.onResume();
182         mController.displayPreference(mScreen);
183         assertThat(mController.isAvailable()).isFalse();
184 
185         final int updateCountBeforeModeChange = mOnChildUpdatedCount;
186         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
187         mController.onAirplaneModeChanged(false);
188         assertThat(mController.isAvailable()).isTrue();
189         assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
190     }
191 
192     @Test
onSubscriptionsChanged_countBecameTwo_eventFired()193     public void onSubscriptionsChanged_countBecameTwo_eventFired() {
194         final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
195         SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 1));
196         mController.onResume();
197         mController.displayPreference(mScreen);
198         assertThat(mController.isAvailable()).isFalse();
199 
200         final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
201         SubscriptionUtil.setActiveSubscriptionsForTesting(subs);
202         mController.onSubscriptionsChanged();
203         assertThat(mController.isAvailable()).isTrue();
204         assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
205     }
206 
207     @Test
onSubscriptionsChanged_countBecameOne_eventFiredAndPrefsRemoved()208     public void onSubscriptionsChanged_countBecameOne_eventFiredAndPrefsRemoved() {
209         final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
210         mController.onResume();
211         mController.displayPreference(mScreen);
212         assertThat(mController.isAvailable()).isTrue();
213         verify(mPreferenceCategory, times(2)).addPreference(any(Preference.class));
214 
215         final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
216         SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 1));
217         mController.onSubscriptionsChanged();
218         assertThat(mController.isAvailable()).isFalse();
219         assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
220 
221         verify(mPreferenceCategory, times(2)).removePreference(any(Preference.class));
222     }
223 
224     @Test
onSubscriptionsChanged_subscriptionReplaced_preferencesChanged()225     public void onSubscriptionsChanged_subscriptionReplaced_preferencesChanged() {
226         final List<SubscriptionInfo> subs = setupMockSubscriptions(3);
227 
228         // Start out with only sub1 and sub2.
229         SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 2));
230         mController.onResume();
231         mController.displayPreference(mScreen);
232         final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
233         verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
234         assertThat(captor.getAllValues().size()).isEqualTo(2);
235         assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("sub1");
236         assertThat(captor.getAllValues().get(1).getTitle()).isEqualTo("sub2");
237 
238         // Now replace sub2 with sub3, and make sure the old preference was removed and the new
239         // preference was added.
240         final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
241         SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(subs.get(0), subs.get(2)));
242         mController.onSubscriptionsChanged();
243         assertThat(mController.isAvailable()).isTrue();
244         assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
245 
246         verify(mPreferenceCategory).removePreference(captor.capture());
247         assertThat(captor.getValue().getTitle()).isEqualTo("sub2");
248         verify(mPreferenceCategory, times(3)).addPreference(captor.capture());
249         assertThat(captor.getValue().getTitle()).isEqualTo("sub3");
250     }
251 
252 
253     /**
254      * Helper to create a specified number of subscriptions, display them, and then click on one and
255      * verify that the intent fires and has the right subscription id extra.
256      *
257      * @param subscriptionCount the number of subscriptions
258      * @param selectedPrefIndex index of the subscription to click on
259      */
runPreferenceClickTest(final int subscriptionCount, final int selectedPrefIndex)260     private void runPreferenceClickTest(final int subscriptionCount, final int selectedPrefIndex) {
261         final List<SubscriptionInfo> subs = setupMockSubscriptions(subscriptionCount);
262         final ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
263         mController.displayPreference(mScreen);
264         verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
265         final List<Preference> prefs = prefCaptor.getAllValues();
266         final Preference pref = prefs.get(selectedPrefIndex);
267         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
268         doNothing().when(mContext).startActivity(intentCaptor.capture());
269         pref.getOnPreferenceClickListener().onPreferenceClick(pref);
270         final Intent intent = intentCaptor.getValue();
271         assertThat(intent).isNotNull();
272         assertThat(intent.hasExtra(Settings.EXTRA_SUB_ID)).isTrue();
273         final int subIdFromIntent = intent.getIntExtra(Settings.EXTRA_SUB_ID,
274                 INVALID_SUBSCRIPTION_ID);
275         assertThat(subIdFromIntent).isEqualTo(
276                 subs.get(selectedPrefIndex).getSubscriptionId());
277     }
278 
279     @Test
twoPreferences_firstPreferenceClicked_correctIntentFires()280     public void twoPreferences_firstPreferenceClicked_correctIntentFires() {
281         runPreferenceClickTest(2, 0);
282     }
283 
284     @Test
twoPreferences_secondPreferenceClicked_correctIntentFires()285     public void twoPreferences_secondPreferenceClicked_correctIntentFires() {
286         runPreferenceClickTest(2, 1);
287     }
288 
289     @Test
threePreferences_secondPreferenceClicked_correctIntentFires()290     public void threePreferences_secondPreferenceClicked_correctIntentFires() {
291         runPreferenceClickTest(3, 1);
292     }
293 
294     @Test
threePreferences_thirdPreferenceClicked_correctIntentFires()295     public void threePreferences_thirdPreferenceClicked_correctIntentFires() {
296         runPreferenceClickTest(3, 2);
297     }
298 
299     @Test
getSummary_twoSubsOneDefaultForEverythingDataActive()300     public void getSummary_twoSubsOneDefaultForEverythingDataActive() {
301         setupMockSubscriptions(2);
302 
303         ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
304         ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
305         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
306         when(mCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
307 
308         assertThat(mController.getSummary(11, true)).isEqualTo(
309                 mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
310                         + mContext.getString(R.string.mobile_data_active));
311 
312         assertThat(mController.getSummary(22, false)).isEqualTo(
313                 mContext.getString(R.string.subscription_available));
314     }
315 
316     @Test
getSummary_twoSubsOneDefaultForEverythingDataNotActive()317     public void getSummary_twoSubsOneDefaultForEverythingDataNotActive() {
318         setupMockSubscriptions(2, 1, true);
319 
320         ShadowSubscriptionManager.setDefaultSmsSubscriptionId(1);
321         ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
322 
323         assertThat(mController.getSummary(1, true)).isEqualTo(
324                 mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
325                         + mContext.getString(R.string.default_for_mobile_data));
326 
327         assertThat(mController.getSummary(2, false)).isEqualTo(
328                 mContext.getString(R.string.subscription_available));
329     }
330 
331     @Test
getSummary_twoSubsOneDefaultForEverythingDataDisabled()332     public void getSummary_twoSubsOneDefaultForEverythingDataDisabled() {
333         setupMockSubscriptions(2);
334 
335         ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
336         ShadowSubscriptionManager.setDefaultSmsSubscriptionId(1);
337 
338         assertThat(mController.getSummary(1, true)).isEqualTo(
339                 mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
340                         + mContext.getString(R.string.mobile_data_off));
341 
342         assertThat(mController.getSummary(2, false)).isEqualTo(
343                 mContext.getString(R.string.subscription_available));
344     }
345 
346     @Test
getSummary_twoSubsOneForCallsAndDataOneForSms()347     public void getSummary_twoSubsOneForCallsAndDataOneForSms() {
348         setupMockSubscriptions(2, 1, true);
349 
350         ShadowSubscriptionManager.setDefaultSmsSubscriptionId(2);
351         ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
352 
353         assertThat(mController.getSummary(1, true)).isEqualTo(
354                 mContext.getString(R.string.default_for_calls) + System.lineSeparator()
355                         + mContext.getString(R.string.default_for_mobile_data));
356 
357         assertThat(mController.getSummary(2, false)).isEqualTo(
358                 mContext.getString(R.string.default_for_sms));
359     }
360 
361     @Test
setIcon_nullStrength_noCrash()362     public void setIcon_nullStrength_noCrash() {
363         final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
364         setMockSubSignalStrength(subs, 0, -1);
365         final Preference pref = mock(Preference.class);
366 
367         mController.setIcon(pref, 1, true /* isDefaultForData */);
368         verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
369     }
370 
371     @Test
setIcon_noSignal_correctLevels()372     public void setIcon_noSignal_correctLevels() {
373         final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
374         setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
375         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
376         setMockSubDataEnabled(subs, 0, true);
377         final Preference pref = mock(Preference.class);
378 
379         mController.setIcon(pref, 1, true /* isDefaultForData */);
380         verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(false));
381 
382         mController.setIcon(pref, 2, false /* isDefaultForData */);
383         verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
384     }
385 
386     @Test
setIcon_noSignal_withInflation_correctLevels()387     public void setIcon_noSignal_withInflation_correctLevels() {
388         final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
389         setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
390         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
391         final Preference pref = mock(Preference.class);
392         doReturn(true).when(mController).shouldInflateSignalStrength(anyInt());
393 
394         mController.setIcon(pref, 1, true /* isDefaultForData */);
395         verify(mController).getIcon(eq(1), eq(NUM_SIGNAL_STRENGTH_BINS + 1), eq(false));
396 
397         mController.setIcon(pref, 2, false /* isDefaultForData */);
398         verify(mController).getIcon(eq(1), eq(NUM_SIGNAL_STRENGTH_BINS + 1), eq(true));
399     }
400 
401     @Test
setIcon_greatSignal_correctLevels()402     public void setIcon_greatSignal_correctLevels() {
403         final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
404         setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_GREAT);
405         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GREAT);
406         final Preference pref = mock(Preference.class);
407 
408         mController.setIcon(pref, 1, true /* isDefaultForData */);
409         verify(mController).getIcon(eq(4), eq(NUM_SIGNAL_STRENGTH_BINS), eq(false));
410 
411         mController.setIcon(pref, 2, false /* isDefaultForData */);
412         verify(mController).getIcon(eq(4), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
413     }
414 
415     @Test
onSignalStrengthChanged_subTwoGoesFromGoodToGreat_correctLevels()416     public void onSignalStrengthChanged_subTwoGoesFromGoodToGreat_correctLevels() {
417         final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
418         setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_POOR);
419         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GOOD);
420 
421         mController.onResume();
422         mController.displayPreference(mScreen);
423 
424         // Now change the signal strength for the 2nd subscription from Good to Great
425         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GREAT);
426         mController.onSignalStrengthChanged();
427 
428         final ArgumentCaptor<Integer> level = ArgumentCaptor.forClass(Integer.class);
429         verify(mController, times(4)).getIcon(level.capture(), eq(NUM_SIGNAL_STRENGTH_BINS),
430                 eq(true));
431         assertThat(level.getAllValues().get(0)).isEqualTo(1);
432         assertThat(level.getAllValues().get(1)).isEqualTo(3); // sub2, first time
433         assertThat(level.getAllValues().get(2)).isEqualTo(1);
434         assertThat(level.getAllValues().get(3)).isEqualTo(4); // sub2, after change
435     }
436 
437     @Test
displayPreference_mobileDataOff_bothSubsHaveCutOut()438     public void displayPreference_mobileDataOff_bothSubsHaveCutOut() {
439         setupMockSubscriptions(2, 1, false);
440 
441         mController.onResume();
442         mController.displayPreference(mScreen);
443 
444         verify(mController, times(2)).getIcon(eq(SIGNAL_STRENGTH_GOOD),
445                 eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
446     }
447 
448     @Test
displayPreference_mobileDataOn_onlyNonDefaultSubHasCutOut()449     public void displayPreference_mobileDataOn_onlyNonDefaultSubHasCutOut() {
450         final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
451         setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_POOR);
452 
453         mController.onResume();
454         mController.displayPreference(mScreen);
455 
456         verify(mController).getIcon(eq(SIGNAL_STRENGTH_GOOD), eq(NUM_SIGNAL_STRENGTH_BINS),
457                 eq(false));
458         verify(mController).getIcon(eq(SIGNAL_STRENGTH_POOR), eq(NUM_SIGNAL_STRENGTH_BINS),
459                 eq(true));
460     }
461 
462 
463     @Test
onMobileDataEnabledChange_mobileDataTurnedOff_bothSubsHaveCutOut()464     public void onMobileDataEnabledChange_mobileDataTurnedOff_bothSubsHaveCutOut() {
465         final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
466 
467         mController.onResume();
468         mController.displayPreference(mScreen);
469 
470         setMockSubDataEnabled(subs, 0, false);
471         mController.onMobileDataEnabledChange();
472 
473         final ArgumentCaptor<Boolean> cutOutCaptor = ArgumentCaptor.forClass(Boolean.class);
474         verify(mController, times(4)).getIcon(eq(SIGNAL_STRENGTH_GOOD),
475                 eq(NUM_SIGNAL_STRENGTH_BINS), cutOutCaptor.capture());
476         assertThat(cutOutCaptor.getAllValues().get(0)).isEqualTo(false); // sub1, first time
477         assertThat(cutOutCaptor.getAllValues().get(1)).isEqualTo(true);
478         assertThat(cutOutCaptor.getAllValues().get(2)).isEqualTo(true); // sub1, second time
479         assertThat(cutOutCaptor.getAllValues().get(3)).isEqualTo(true);
480     }
481 
setupMockSubscriptions(int count)482     private List<SubscriptionInfo> setupMockSubscriptions(int count) {
483         return setupMockSubscriptions(count, 0, true);
484     }
485 
486     /** Helper method to setup several mock active subscriptions. The generated subscription id's
487      * start at 1.
488      *
489      * @param count How many subscriptions to create
490      * @param defaultDataSubId The subscription id of the default data subscription - pass
491      *                         INVALID_SUBSCRIPTION_ID if there should not be one
492      * @param mobileDataEnabled Whether mobile data should be considered enabled for the default
493      *                          data subscription
494      */
setupMockSubscriptions(int count, int defaultDataSubId, boolean mobileDataEnabled)495     private List<SubscriptionInfo> setupMockSubscriptions(int count, int defaultDataSubId,
496             boolean mobileDataEnabled) {
497         if (defaultDataSubId != INVALID_SUBSCRIPTION_ID) {
498             ShadowSubscriptionManager.setDefaultDataSubscriptionId(defaultDataSubId);
499         }
500         final ArrayList<SubscriptionInfo> infos = new ArrayList<>();
501         for (int i = 0; i < count; i++) {
502             final int subscriptionId = i + 1;
503             final SubscriptionInfo info = mock(SubscriptionInfo.class);
504             final TelephonyManager mgrForSub = mock(TelephonyManager.class);
505             final SignalStrength signalStrength = mock(SignalStrength.class);
506 
507             if (subscriptionId == defaultDataSubId) {
508                 when(mgrForSub.isDataEnabled()).thenReturn(mobileDataEnabled);
509             }
510             when(info.getSubscriptionId()).thenReturn(i + 1);
511             when(info.getDisplayName()).thenReturn("sub" + (i + 1));
512             doReturn(mgrForSub).when(mTelephonyManager).createForSubscriptionId(eq(subscriptionId));
513             when(mgrForSub.getSignalStrength()).thenReturn(signalStrength);
514             when(signalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GOOD);
515 
516             infos.add(info);
517         }
518         SubscriptionUtil.setActiveSubscriptionsForTesting(infos);
519         return infos;
520     }
521 
522     /**
523      * Helper method to set the signal strength returned for a mock subscription
524      * @param subs The list of subscriptions
525      * @param index The index in of the subscription in |subs| to change
526      * @param level The signal strength level to return for the subscription. Pass -1 to force
527      *              return of a null SignalStrength object for the subscription.
528      */
setMockSubSignalStrength(List<SubscriptionInfo> subs, int index, int level)529     private void setMockSubSignalStrength(List<SubscriptionInfo> subs, int index, int level) {
530         final TelephonyManager mgrForSub =
531                 mTelephonyManager.createForSubscriptionId(subs.get(index).getSubscriptionId());
532         if (level == -1) {
533             when(mgrForSub.getSignalStrength()).thenReturn(null);
534         } else {
535             final SignalStrength signalStrength = mgrForSub.getSignalStrength();
536             when(signalStrength.getLevel()).thenReturn(level);
537         }
538     }
539 
setMockSubDataEnabled(List<SubscriptionInfo> subs, int index, boolean enabled)540     private void setMockSubDataEnabled(List<SubscriptionInfo> subs, int index, boolean enabled) {
541         final TelephonyManager mgrForSub =
542                 mTelephonyManager.createForSubscriptionId(subs.get(index).getSubscriptionId());
543         when(mgrForSub.isDataEnabled()).thenReturn(enabled);
544     }
545 }
546