1 /*
2  * Copyright (C) 2020 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.SIGNAL_STRENGTH_GOOD;
20 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT;
21 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.eq;;
29 import static org.mockito.Mockito.doReturn;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.never;
32 import static org.mockito.Mockito.spy;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
35 
36 import android.content.Context;
37 import android.content.Intent;
38 import android.graphics.drawable.Drawable;
39 import android.net.ConnectivityManager;
40 import android.net.Network;
41 import android.net.NetworkCapabilities;
42 import android.net.wifi.WifiManager;
43 import android.os.Looper;
44 import android.os.UserManager;
45 import android.provider.Settings;
46 import android.telephony.AccessNetworkConstants;
47 import android.telephony.NetworkRegistrationInfo;
48 import android.telephony.ServiceState;
49 import android.telephony.SignalStrength;
50 import android.telephony.SubscriptionInfo;
51 import android.telephony.SubscriptionManager;
52 import android.telephony.TelephonyDisplayInfo;
53 import android.telephony.TelephonyManager;
54 import android.text.Html;
55 
56 import androidx.lifecycle.LifecycleOwner;
57 import androidx.lifecycle.LifecycleRegistry;
58 import androidx.preference.Preference;
59 import androidx.preference.PreferenceCategory;
60 import androidx.preference.PreferenceManager;
61 import androidx.preference.PreferenceScreen;
62 import androidx.test.annotation.UiThreadTest;
63 import androidx.test.core.app.ApplicationProvider;
64 import androidx.test.ext.junit.runners.AndroidJUnit4;
65 
66 import com.android.settings.Utils;
67 import com.android.settings.network.SubscriptionsPreferenceController.SubsPrefCtrlInjector;
68 import com.android.settings.testutils.ResourcesUtils;
69 import com.android.settings.wifi.WifiPickerTrackerHelper;
70 import com.android.settingslib.core.lifecycle.Lifecycle;
71 import com.android.settingslib.mobile.MobileMappings;
72 
73 import org.junit.After;
74 import org.junit.Before;
75 import org.junit.Test;
76 import org.junit.runner.RunWith;
77 import org.mockito.Mock;
78 import org.mockito.MockitoAnnotations;
79 
80 import java.util.ArrayList;
81 import java.util.Arrays;
82 import java.util.List;
83 
84 @RunWith(AndroidJUnit4.class)
85 public class SubscriptionsPreferenceControllerTest {
86     private static final String KEY = "preference_group";
87 
88     @Mock
89     private UserManager mUserManager;
90     @Mock
91     private SubscriptionManager mSubscriptionManager;
92     @Mock
93     private ConnectivityManager mConnectivityManager;
94     @Mock
95     private TelephonyManager mTelephonyManager;
96     @Mock
97     private TelephonyManager mTelephonyManagerForSub;
98     @Mock
99     private Network mActiveNetwork;
100     @Mock
101     private Lifecycle mLifecycle;
102     @Mock
103     private LifecycleOwner mLifecycleOwner;
104     @Mock
105     private WifiPickerTrackerHelper mWifiPickerTrackerHelper;
106     @Mock
107     private WifiManager mWifiManager;
108 
109     private LifecycleRegistry mLifecycleRegistry;
110     private int mOnChildUpdatedCount;
111     private Context mContext;
112     private SubscriptionsPreferenceController.UpdateListener mUpdateListener;
113     private PreferenceCategory mPreferenceCategory;
114     private PreferenceScreen mPreferenceScreen;
115     private PreferenceManager mPreferenceManager;
116     private NetworkCapabilities mNetworkCapabilities;
117     private FakeSubscriptionsPreferenceController mController;
118     private static SubsPrefCtrlInjector sInjector;
119 
120     @Before
setUp()121     public void setUp() {
122         MockitoAnnotations.initMocks(this);
123         mContext = spy(ApplicationProvider.getApplicationContext());
124         if (Looper.myLooper() == null) {
125             Looper.prepare();
126         }
127         mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
128 
129         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
130         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
131         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
132         when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
133         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
134         when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
135         when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork))
136                 .thenReturn(mNetworkCapabilities);
137         when(mUserManager.isAdminUser()).thenReturn(true);
138         when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
139         when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
140 
141         mPreferenceManager = new PreferenceManager(mContext);
142         mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
143         mPreferenceScreen.setInitialExpandedChildrenCount(3);
144         mPreferenceCategory = new PreferenceCategory(mContext);
145         mPreferenceCategory.setKey(KEY);
146         mPreferenceCategory.setOrderingAsAdded(true);
147         mPreferenceScreen.addPreference(mPreferenceCategory);
148 
149         mOnChildUpdatedCount = 0;
150         mUpdateListener = () -> mOnChildUpdatedCount++;
151 
152         sInjector = spy(new SubsPrefCtrlInjector());
153         mController =  new FakeSubscriptionsPreferenceController(mContext, mLifecycle,
154                 mUpdateListener, KEY, 5);
155         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
156     }
157 
158     @After
tearDown()159     public void tearDown() {
160         SubscriptionUtil.setActiveSubscriptionsForTesting(null);
161     }
162 
163     @Test
isAvailable_oneSubAndProviderOn_availableTrue()164     public void isAvailable_oneSubAndProviderOn_availableTrue() {
165         setupMockSubscriptions(1);
166 
167         assertThat(mController.isAvailable()).isTrue();
168     }
169 
170     @Test
isAvailable_fiveSubscriptions_availableTrue()171     public void isAvailable_fiveSubscriptions_availableTrue() {
172         setupMockSubscriptions(5);
173 
174         assertThat(mController.isAvailable()).isTrue();
175     }
176 
177     @Test
isAvailable_airplaneModeOnWifiOff_availableFalse()178     public void isAvailable_airplaneModeOnWifiOff_availableFalse() {
179         setupMockSubscriptions(2);
180 
181         assertThat(mController.isAvailable()).isTrue();
182         when(mWifiManager.isWifiEnabled()).thenReturn(false);
183 
184         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
185 
186         assertThat(mController.isAvailable()).isFalse();
187     }
188 
189     @Test
isAvailable_airplaneModeOnWifiOnWithNoCarrierNetwork_availableFalse()190     public void isAvailable_airplaneModeOnWifiOnWithNoCarrierNetwork_availableFalse() {
191         setupMockSubscriptions(2);
192 
193         assertThat(mController.isAvailable()).isTrue();
194         when(mWifiManager.isWifiEnabled()).thenReturn(true);
195         doReturn(false).when(mWifiPickerTrackerHelper).isCarrierNetworkActive();
196 
197         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
198 
199         assertThat(mController.isAvailable()).isFalse();
200     }
201 
202     @Test
isAvailable_airplaneModeOnWifiOffWithCarrierNetwork_availableTrue()203     public void isAvailable_airplaneModeOnWifiOffWithCarrierNetwork_availableTrue() {
204         setupMockSubscriptions(1);
205 
206         when(mWifiManager.isWifiEnabled()).thenReturn(false);
207         doReturn(true).when(mWifiPickerTrackerHelper).isCarrierNetworkActive();
208 
209         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
210 
211         assertThat(mController.isAvailable()).isFalse();
212     }
213 
214     @Test
isAvailable_airplaneModeOff_availableFalse()215     public void isAvailable_airplaneModeOff_availableFalse() {
216         setupMockSubscriptions(2);
217 
218         assertThat(mController.isAvailable()).isTrue();
219         when(mWifiManager.isWifiEnabled()).thenReturn(true);
220         doReturn(true).when(mWifiPickerTrackerHelper).isCarrierNetworkActive();
221 
222         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
223 
224         assertThat(mController.isAvailable()).isTrue();
225     }
226 
227     @Test
228     @UiThreadTest
displayPreference_providerAndHasSim_showPreference()229     public void displayPreference_providerAndHasSim_showPreference() {
230         final List<SubscriptionInfo> sub = setupMockSubscriptions(1);
231         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
232         doReturn(sub).when(mSubscriptionManager).getAvailableSubscriptionInfoList();
233 
234         mController.onResume();
235         mController.displayPreference(mPreferenceScreen);
236 
237         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
238         assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub1");
239     }
240 
241     @Test
242     @UiThreadTest
displayPreference_providerAndHasMultiSim_showDataSubPreference()243     public void displayPreference_providerAndHasMultiSim_showDataSubPreference() {
244         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
245         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
246         doReturn(sub).when(mSubscriptionManager).getAvailableSubscriptionInfoList();
247 
248         mController.onResume();
249         mController.displayPreference(mPreferenceScreen);
250 
251         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
252         assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub1");
253     }
254 
255     @Test
256     @UiThreadTest
displayPreference_providerAndHasMultiSimAndActive_connectedAndRat()257     public void displayPreference_providerAndHasMultiSimAndActive_connectedAndRat() {
258         final CharSequence expectedSummary =
259                 Html.fromHtml("Connected / 5G", Html.FROM_HTML_MODE_LEGACY);
260         final String networkType = "5G";
261         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
262         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
263         setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true,
264                 true, ServiceState.STATE_IN_SERVICE);
265         doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
266         doReturn(networkType)
267                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
268 
269         mController.onResume();
270         mController.displayPreference(mPreferenceScreen);
271 
272         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
273     }
274 
275     @Test
276     @UiThreadTest
displayPreference_providerAndHasMultiSimAndActiveCarrierWifi_connectedAndWPlus()277     public void displayPreference_providerAndHasMultiSimAndActiveCarrierWifi_connectedAndWPlus() {
278         final CharSequence expectedSummary =
279                 Html.fromHtml("Connected / W+", Html.FROM_HTML_MODE_LEGACY);
280         final String networkType = "W+";
281         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
282         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
283         setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
284                 true, ServiceState.STATE_IN_SERVICE);
285         doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
286         doReturn(networkType)
287                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(true));
288         doReturn(true).when(mWifiPickerTrackerHelper).isCarrierNetworkActive();
289         mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper);
290 
291         mController.onResume();
292         mController.displayPreference(mPreferenceScreen);
293 
294         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
295     }
296 
297     @Test
298     @UiThreadTest
displayPreference_providerAndHasMultiSimButMobileDataOff_notAutoConnect()299     public void displayPreference_providerAndHasMultiSimButMobileDataOff_notAutoConnect() {
300         final String dataOffSummary =
301                 ResourcesUtils.getResourcesString(mContext, "mobile_data_off_summary");
302         final CharSequence expectedSummary =
303                 Html.fromHtml(dataOffSummary, Html.FROM_HTML_MODE_LEGACY);
304         final String networkType = "5G";
305         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
306         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
307         setupGetIconConditions(sub.get(0).getSubscriptionId(), false, false,
308                 true, ServiceState.STATE_IN_SERVICE);
309         doReturn(networkType)
310                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
311 
312         mController.onResume();
313         mController.displayPreference(mPreferenceScreen);
314 
315         assertThat(mPreferenceCategory.getPreference(0).getSummary())
316             .isEqualTo(expectedSummary.toString());
317     }
318 
319     @Test
320     @UiThreadTest
displayPreference_providerAndHasMultiSimAndNotActive_showRatOnly()321     public void displayPreference_providerAndHasMultiSimAndNotActive_showRatOnly() {
322         final CharSequence expectedSummary = Html.fromHtml("5G", Html.FROM_HTML_MODE_LEGACY);
323         final String networkType = "5G";
324         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
325         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
326         setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
327                 true, ServiceState.STATE_IN_SERVICE);
328         doReturn(networkType)
329                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
330         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
331 
332         mController.onResume();
333         mController.displayPreference(mPreferenceScreen);
334 
335         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
336     }
337 
338     @Test
339     @UiThreadTest
displayPreference_providerAndNoSim_noPreference()340     public void displayPreference_providerAndNoSim_noPreference() {
341         doReturn(null).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
342 
343         mController.onResume();
344         mController.displayPreference(mPreferenceScreen);
345 
346         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
347     }
348 
349     @Test
350     @UiThreadTest
onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndActive_connectedAndRat()351     public void onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndActive_connectedAndRat() {
352         final CharSequence expectedSummary =
353                 Html.fromHtml("Connected / LTE", Html.FROM_HTML_MODE_LEGACY);
354         final String networkType = "LTE";
355         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
356         final TelephonyDisplayInfo telephonyDisplayInfo =
357                 new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
358                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
359         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
360         setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true,
361                 true, ServiceState.STATE_IN_SERVICE);
362         doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
363         doReturn(networkType)
364                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
365         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
366 
367         mController.onResume();
368         mController.displayPreference(mPreferenceScreen);
369         mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
370 
371         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
372     }
373 
374     @Test
375     @UiThreadTest
onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndNotActive_showRat()376     public void onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndNotActive_showRat() {
377         final CharSequence expectedSummary =
378                 Html.fromHtml("LTE", Html.FROM_HTML_MODE_LEGACY);
379         final String networkType = "LTE";
380         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
381         final TelephonyDisplayInfo telephonyDisplayInfo =
382                 new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
383                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
384         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
385         setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
386                 true, ServiceState.STATE_IN_SERVICE);
387         doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
388         doReturn(networkType)
389                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
390 
391         mController.onResume();
392         mController.displayPreference(mPreferenceScreen);
393         mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
394 
395         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
396     }
397 
398     @Test
399     @UiThreadTest
onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndOutOfService_noConnection()400     public void onTelephonyDisplayInfoChanged_providerAndHasMultiSimAndOutOfService_noConnection() {
401         final String noConnectionSummary =
402                 ResourcesUtils.getResourcesString(mContext, "mobile_data_no_connection");
403         final CharSequence expectedSummary =
404                 Html.fromHtml(noConnectionSummary, Html.FROM_HTML_MODE_LEGACY);
405         final String networkType = "LTE";
406         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
407         final TelephonyDisplayInfo telephonyDisplayInfo =
408                 new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
409                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
410         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
411         setupGetIconConditions(sub.get(0).getSubscriptionId(), false, true,
412                 false, ServiceState.STATE_OUT_OF_SERVICE);
413         doReturn(mock(MobileMappings.Config.class)).when(sInjector).getConfig(mContext);
414         doReturn(networkType)
415                 .when(sInjector).getNetworkType(any(), any(), any(), anyInt(), eq(false));
416 
417         mController.onResume();
418         mController.displayPreference(mPreferenceScreen);
419         mController.onTelephonyDisplayInfoChanged(telephonyDisplayInfo);
420 
421         assertThat(mPreferenceCategory.getPreference(0).getSummary()).isEqualTo(expectedSummary);
422     }
423 
424     @Test
425     @UiThreadTest
onAirplaneModeChanged_providerAndHasSim_noPreference()426     public void onAirplaneModeChanged_providerAndHasSim_noPreference() {
427         setupMockSubscriptions(1);
428         mController.onResume();
429         mController.displayPreference(mPreferenceScreen);
430         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
431 
432         mController.onAirplaneModeChanged(true);
433 
434         assertThat(mController.isAvailable()).isFalse();
435         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
436     }
437 
438     @Test
439     @UiThreadTest
dataSubscriptionChanged_providerAndHasMultiSim_showSubId1Preference()440     public void dataSubscriptionChanged_providerAndHasMultiSim_showSubId1Preference() {
441         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
442         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
443         doReturn(sub).when(mSubscriptionManager).getAvailableSubscriptionInfoList();
444         Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
445 
446         mController.onResume();
447         mController.displayPreference(mPreferenceScreen);
448         mController.mConnectionChangeReceiver.onReceive(mContext, intent);
449 
450         assertThat(mController.isAvailable()).isTrue();
451         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
452         assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub1");
453     }
454 
455     @Test
456     @UiThreadTest
dataSubscriptionChanged_providerAndHasMultiSim_showSubId2Preference()457     public void dataSubscriptionChanged_providerAndHasMultiSim_showSubId2Preference() {
458         final List<SubscriptionInfo> sub = setupMockSubscriptions(2);
459         final int subId = sub.get(0).getSubscriptionId();
460         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
461         doReturn(sub).when(mSubscriptionManager).getAvailableSubscriptionInfoList();
462         Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
463 
464         mController.onResume();
465         mController.displayPreference(mPreferenceScreen);
466 
467         assertThat(mController.isAvailable()).isTrue();
468         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
469         assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub1");
470 
471         doReturn(sub.get(1)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
472 
473         mController.mConnectionChangeReceiver.onReceive(mContext, intent);
474 
475         assertThat(mController.isAvailable()).isTrue();
476         assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
477         assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo("sub2");
478     }
479 
480     @Test
481     @UiThreadTest
getIcon_cellularIsActive_iconColorIsAccentDefaultColor()482     public void getIcon_cellularIsActive_iconColorIsAccentDefaultColor() {
483         final List<SubscriptionInfo> sub = setupMockSubscriptions(1);
484         doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
485         Drawable icon = mock(Drawable.class);
486         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
487         doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(false));
488         setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true,
489                 true, ServiceState.STATE_IN_SERVICE);
490 
491         mController.onResume();
492         mController.displayPreference(mPreferenceScreen);
493 
494         verify(icon).setTint(Utils.getColorAccentDefaultColor(mContext));
495     }
496 
497     @Test
498     @UiThreadTest
getIcon_dataStateConnectedAndMobileDataOn_iconIsSignalIcon()499     public void getIcon_dataStateConnectedAndMobileDataOn_iconIsSignalIcon() {
500         final List<SubscriptionInfo> subs = setupMockSubscriptions(1);
501         final int subId = subs.get(0).getSubscriptionId();
502         doReturn(subs.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
503         Drawable icon = mock(Drawable.class);
504         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
505         doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(false));
506         setupGetIconConditions(subId, false, true,
507                 true, ServiceState.STATE_IN_SERVICE);
508         mController.onResume();
509         mController.displayPreference(mPreferenceScreen);
510         Drawable actualIcon = mPreferenceCategory.getPreference(0).getIcon();
511 
512         assertThat(icon).isEqualTo(actualIcon);
513     }
514 
515     @Test
516     @UiThreadTest
getIcon_voiceInServiceAndMobileDataOff_iconIsSignalIcon()517     public void getIcon_voiceInServiceAndMobileDataOff_iconIsSignalIcon() {
518         final List<SubscriptionInfo> subs = setupMockSubscriptions(1);
519         final int subId = subs.get(0).getSubscriptionId();
520         doReturn(subs.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
521         Drawable icon = mock(Drawable.class);
522         when(mTelephonyManager.isDataEnabled()).thenReturn(false);
523         doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(true));
524 
525         setupGetIconConditions(subId, false, false,
526                 false, ServiceState.STATE_IN_SERVICE);
527 
528         mController.onResume();
529         mController.displayPreference(mPreferenceScreen);
530         Drawable actualIcon = mPreferenceCategory.getPreference(0).getIcon();
531         ServiceState ss = mock(ServiceState.class);
532         NetworkRegistrationInfo regInfo = new NetworkRegistrationInfo.Builder()
533                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
534                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
535                 .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
536                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
537                 .build();
538         doReturn(ss).when(mTelephonyManagerForSub).getServiceState();
539         doReturn(regInfo).when(ss).getNetworkRegistrationInfo(
540                 NetworkRegistrationInfo.DOMAIN_PS,
541                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
542 
543         assertThat(icon).isEqualTo(actualIcon);
544     }
545 
546     @Test
connectCarrierNetwork_isDataEnabled_helperConnect()547     public void connectCarrierNetwork_isDataEnabled_helperConnect() {
548         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
549         mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper);
550 
551         mController.connectCarrierNetwork();
552 
553         verify(mWifiPickerTrackerHelper).connectCarrierNetwork(any());
554     }
555 
556     @Test
connectCarrierNetwork_isNotDataEnabled_helperNeverConnect()557     public void connectCarrierNetwork_isNotDataEnabled_helperNeverConnect() {
558         when(mTelephonyManager.isDataEnabled()).thenReturn(false);
559         mController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper);
560 
561         mController.connectCarrierNetwork();
562 
563         verify(mWifiPickerTrackerHelper, never()).connectCarrierNetwork(any());
564     }
565 
setupGetIconConditions(int subId, boolean isActiveCellularNetwork, boolean isDataEnable, boolean dataState, int servicestate)566     private void setupGetIconConditions(int subId, boolean isActiveCellularNetwork,
567             boolean isDataEnable, boolean dataState, int servicestate) {
568         doReturn(mTelephonyManagerForSub).when(mTelephonyManager).createForSubscriptionId(subId);
569         doReturn(isActiveCellularNetwork).when(sInjector).isActiveCellularNetwork(mContext);
570         doReturn(isDataEnable).when(mTelephonyManagerForSub).isDataEnabled();
571         ServiceState ss = mock(ServiceState.class);
572         NetworkRegistrationInfo regInfo = new NetworkRegistrationInfo.Builder()
573                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
574                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
575                 .setRegistrationState(dataState ? NetworkRegistrationInfo.REGISTRATION_STATE_HOME
576                         : NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING)
577                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
578                 .build();
579         doReturn(ss).when(mTelephonyManagerForSub).getServiceState();
580         doReturn(servicestate).when(ss).getState();
581         doReturn(regInfo).when(ss).getNetworkRegistrationInfo(
582                 NetworkRegistrationInfo.DOMAIN_PS,
583                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
584     }
585 
setupMockSubscriptions(int count)586     private List<SubscriptionInfo> setupMockSubscriptions(int count) {
587         return setupMockSubscriptions(count, 0, true);
588     }
589 
590     /** Helper method to setup several mock active subscriptions. The generated subscription id's
591      * start at 1.
592      *
593      * @param count How many subscriptions to create
594      * @param defaultDataSubId The subscription id of the default data subscription - pass
595      *                         INVALID_SUBSCRIPTION_ID if there should not be one
596      * @param mobileDataEnabled Whether mobile data should be considered enabled for the default
597      *                          data subscription
598      */
setupMockSubscriptions(int count, int defaultDataSubId, boolean mobileDataEnabled)599     private List<SubscriptionInfo> setupMockSubscriptions(int count, int defaultDataSubId,
600             boolean mobileDataEnabled) {
601         if (defaultDataSubId != INVALID_SUBSCRIPTION_ID) {
602             when(sInjector.getDefaultDataSubscriptionId()).thenReturn(defaultDataSubId);
603         }
604         final ArrayList<SubscriptionInfo> infos = new ArrayList<>();
605         for (int i = 0; i < count; i++) {
606             final int subscriptionId = i + 1;
607             final SubscriptionInfo info = mock(SubscriptionInfo.class);
608             final TelephonyManager mgrForSub = mock(TelephonyManager.class);
609             final SignalStrength signalStrength = mock(SignalStrength.class);
610 
611             if (subscriptionId == defaultDataSubId) {
612                 when(mgrForSub.isDataEnabled()).thenReturn(mobileDataEnabled);
613             }
614             when(info.getSubscriptionId()).thenReturn(subscriptionId);
615             when(info.getDisplayName()).thenReturn("sub" + (subscriptionId));
616             doReturn(mgrForSub).when(mTelephonyManager).createForSubscriptionId(eq(subscriptionId));
617             when(mgrForSub.getSignalStrength()).thenReturn(signalStrength);
618             when(signalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GOOD);
619             doReturn(true).when(sInjector).canSubscriptionBeDisplayed(mContext, subscriptionId);
620             infos.add(info);
621         }
622         SubscriptionUtil.setActiveSubscriptionsForTesting(infos);
623         return infos;
624     }
625 
626     private static class FakeSubscriptionsPreferenceController
627             extends SubscriptionsPreferenceController {
628 
629         /**
630          * @param context            the context for the UI where we're placing these preferences
631          * @param lifecycle          for listening to lifecycle events for the UI
632          * @param updateListener     called to let our parent controller know that our
633          *                           availability has
634          *                           changed, or that one or more of the preferences we've placed
635          *                           in the
636          *                           PreferenceGroup has changed
637          * @param preferenceGroupKey the key used to lookup the PreferenceGroup where Preferences
638          *                          will
639          *                           be placed
640          * @param startOrder         the order that should be given to the first Preference
641          *                           placed into
642          *                           the PreferenceGroup; the second will use startOrder+1, third
643          *                           will
644          *                           use startOrder+2, etc. - this is useful for when the parent
645          *                           wants
646          *                           to have other preferences in the same PreferenceGroup and wants
647          */
FakeSubscriptionsPreferenceController(Context context, Lifecycle lifecycle, UpdateListener updateListener, String preferenceGroupKey, int startOrder)648         FakeSubscriptionsPreferenceController(Context context, Lifecycle lifecycle,
649                 UpdateListener updateListener, String preferenceGroupKey, int startOrder) {
650             super(context, lifecycle, updateListener, preferenceGroupKey, startOrder);
651         }
652 
653         @Override
createSubsPrefCtrlInjector()654         protected SubsPrefCtrlInjector createSubsPrefCtrlInjector() {
655             return sInjector;
656         }
657     }
658 }
659