1/*
2 * Copyright (C) 2015 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 */
16package com.android.systemui.statusbar.policy;
17
18import android.content.Intent;
19import android.net.ConnectivityManager;
20import android.net.NetworkCapabilities;
21import android.os.Looper;
22import android.support.test.runner.AndroidJUnit4;
23import android.telephony.ServiceState;
24import android.telephony.SignalStrength;
25import android.telephony.SubscriptionInfo;
26import android.telephony.TelephonyManager;
27import android.test.suitebuilder.annotation.SmallTest;
28import android.testing.AndroidTestingRunner;
29import android.testing.TestableLooper.RunWithLooper;
30
31import com.android.internal.telephony.PhoneConstants;
32import com.android.internal.telephony.TelephonyIntents;
33import com.android.settingslib.graph.SignalDrawable;
34import com.android.settingslib.net.DataUsageController;
35import com.android.systemui.R;
36
37import org.junit.Test;
38import org.junit.runner.RunWith;
39import org.mockito.ArgumentCaptor;
40import org.mockito.Mockito;
41
42import java.util.ArrayList;
43import java.util.List;
44
45import static junit.framework.Assert.assertEquals;
46import static junit.framework.Assert.assertTrue;
47import static junit.framework.Assert.assertFalse;
48import static org.mockito.Mockito.mock;
49
50@SmallTest
51@RunWith(AndroidTestingRunner.class)
52@RunWithLooper
53public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
54
55    @Test
56    public void testNoIconWithoutMobile() {
57        // Turn off mobile network support.
58        Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
59        // Create a new NetworkController as this is currently handled in constructor.
60        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
61                mConfig, Looper.getMainLooper(), mCallbackHandler,
62                mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
63                mMockSubDefaults, mock(DeviceProvisionedController.class));
64        setupNetworkController();
65
66        verifyLastMobileDataIndicators(false, -1, 0);
67    }
68
69    @Test
70    public void testNoSimsIconPresent() {
71        // No Subscriptions.
72        mNetworkController.mMobileSignalControllers.clear();
73        mNetworkController.updateNoSims();
74
75        verifyHasNoSims(true);
76    }
77
78    @Test
79    public void testEmergencyOnly() {
80        setupDefaultSignal();
81        mNetworkController.recalculateEmergency();
82        verifyEmergencyOnly(false);
83
84        mMobileSignalController.getState().isEmergency = true;
85        mNetworkController.recalculateEmergency();
86        verifyEmergencyOnly(true);
87    }
88
89    @Test
90    public void testEmergencyOnlyNoSubscriptions() {
91        setupDefaultSignal();
92        setSubscriptions();
93        mNetworkController.mLastServiceState = new ServiceState();
94        mNetworkController.mLastServiceState.setEmergencyOnly(true);
95        mNetworkController.recalculateEmergency();
96        verifyEmergencyOnly(true);
97    }
98
99    @Test
100    public void testNoEmergencyOnlyWrongSubscription() {
101        setupDefaultSignal();
102        setDefaultSubId(42);
103        mNetworkController.recalculateEmergency();
104        verifyEmergencyOnly(false);
105    }
106
107    @Test
108    public void testNoEmengencyNoSubscriptions() {
109        setupDefaultSignal();
110        setSubscriptions();
111        mNetworkController.mLastServiceState = new ServiceState();
112        mNetworkController.mLastServiceState.setEmergencyOnly(false);
113        mNetworkController.recalculateEmergency();
114        verifyEmergencyOnly(false);
115    }
116
117    @Test
118    public void testNoSimlessIconWithoutMobile() {
119        // Turn off mobile network support.
120        Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
121        // Create a new NetworkController as this is currently handled in constructor.
122        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
123                mConfig, Looper.getMainLooper(), mCallbackHandler,
124                mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
125                mMockSubDefaults, mock(DeviceProvisionedController.class));
126        setupNetworkController();
127
128        // No Subscriptions.
129        mNetworkController.mMobileSignalControllers.clear();
130        mNetworkController.updateNoSims();
131
132        verifyHasNoSims(false);
133    }
134
135    @Test
136    public void testSignalStrength() {
137        for (int testStrength = 0;
138                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
139            setupDefaultSignal();
140            setLevel(testStrength);
141
142            verifyLastMobileDataIndicators(true,
143                    testStrength, DEFAULT_ICON);
144
145            // Verify low inet number indexing.
146            setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, true);
147            verifyLastMobileDataIndicators(true,
148                    testStrength, DEFAULT_ICON, false, false);
149        }
150    }
151
152    @Test
153    public void testCdmaSignalStrength() {
154        for (int testStrength = 0;
155                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
156            setupDefaultSignal();
157            setCdma();
158            setLevel(testStrength);
159
160            verifyLastMobileDataIndicators(true,
161                    testStrength,
162                    TelephonyIcons.ICON_1X);
163        }
164    }
165
166    @Test
167    public void testSignalRoaming() {
168        for (int testStrength = 0;
169                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
170            setupDefaultSignal();
171            setGsmRoaming(true);
172            setLevel(testStrength);
173
174            verifyLastMobileDataIndicators(true,
175                    testStrength,
176                    DEFAULT_ICON, true);
177        }
178    }
179
180    @Test
181    public void testCdmaSignalRoaming() {
182        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
183                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
184            setupDefaultSignal();
185            setCdma();
186            setCdmaRoaming(true);
187            setLevel(testStrength);
188
189            verifyLastMobileDataIndicators(true,
190                    testStrength,
191                    TelephonyIcons.ICON_1X, true);
192        }
193    }
194
195    @Test
196    public void testRoamingNoService_DoesNotCrash() {
197        setupDefaultSignal();
198        setCdma();
199        mServiceState = null;
200        updateServiceState();
201    }
202
203    @Test
204    public void testQsSignalStrength() {
205        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
206                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
207            setupDefaultSignal();
208            setLevel(testStrength);
209
210            verifyLastQsMobileDataIndicators(true,
211                    testStrength,
212                    DEFAULT_QS_ICON, false, false);
213        }
214    }
215
216    @Test
217    public void testCdmaQsSignalStrength() {
218        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
219                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
220            setupDefaultSignal();
221            setCdma();
222            setLevel(testStrength);
223
224            verifyLastQsMobileDataIndicators(true,
225                    testStrength,
226                    TelephonyIcons.ICON_1X, false, false);
227        }
228    }
229
230    @Test
231    public void testNoBangWithWifi() {
232        setupDefaultSignal();
233        setConnectivityViaBroadcast(mMobileSignalController.mTransportType, false, false);
234        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
235
236        verifyLastMobileDataIndicators(true, DEFAULT_LEVEL, 0);
237    }
238
239    // Some tests of actual NetworkController code, just internals not display stuff
240    // TODO: Put this somewhere else, maybe in its own file.
241    @Test
242    public void testHasCorrectMobileControllers() {
243        int[] testSubscriptions = new int[] { 1, 5, 3 };
244        int notTestSubscription = 0;
245        MobileSignalController mobileSignalController = Mockito.mock(MobileSignalController.class);
246
247        mNetworkController.mMobileSignalControllers.clear();
248        List<SubscriptionInfo> subscriptions = new ArrayList<>();
249        for (int i = 0; i < testSubscriptions.length; i++) {
250            // Force the test controllers into NetworkController.
251            mNetworkController.mMobileSignalControllers.put(testSubscriptions[i],
252                    mobileSignalController);
253
254            // Generate a list of subscriptions we will tell the NetworkController to use.
255            SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
256            Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
257            subscriptions.add(mockSubInfo);
258        }
259        assertTrue(mNetworkController.hasCorrectMobileControllers(subscriptions));
260
261        // Add a subscription that the NetworkController doesn't know about.
262        SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
263        Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(notTestSubscription);
264        subscriptions.add(mockSubInfo);
265        assertFalse(mNetworkController.hasCorrectMobileControllers(subscriptions));
266    }
267
268    @Test
269    public void testSetCurrentSubscriptions() {
270        // We will not add one controller to make sure it gets created.
271        int indexToSkipController = 0;
272        // We will not add one subscription to make sure it's controller gets removed.
273        int indexToSkipSubscription = 1;
274
275        int[] testSubscriptions = new int[] { 1, 5, 3 };
276        MobileSignalController[] mobileSignalControllers = new MobileSignalController[] {
277                Mockito.mock(MobileSignalController.class),
278                Mockito.mock(MobileSignalController.class),
279                Mockito.mock(MobileSignalController.class),
280        };
281        mNetworkController.mMobileSignalControllers.clear();
282        List<SubscriptionInfo> subscriptions = new ArrayList<>();
283        for (int i = 0; i < testSubscriptions.length; i++) {
284            if (i != indexToSkipController) {
285                // Force the test controllers into NetworkController.
286                mNetworkController.mMobileSignalControllers.put(testSubscriptions[i],
287                        mobileSignalControllers[i]);
288            }
289
290            if (i != indexToSkipSubscription) {
291                // Generate a list of subscriptions we will tell the NetworkController to use.
292                SubscriptionInfo mockSubInfo = Mockito.mock(SubscriptionInfo.class);
293                Mockito.when(mockSubInfo.getSubscriptionId()).thenReturn(testSubscriptions[i]);
294                Mockito.when(mockSubInfo.getSimSlotIndex()).thenReturn(testSubscriptions[i]);
295                subscriptions.add(mockSubInfo);
296            }
297        }
298
299        // We can only test whether unregister gets called if it thinks its in a listening
300        // state.
301        mNetworkController.mListening = true;
302        mNetworkController.setCurrentSubscriptions(subscriptions);
303
304        for (int i = 0; i < testSubscriptions.length; i++) {
305            if (i == indexToSkipController) {
306                // Make sure a controller was created despite us not adding one.
307                assertTrue(mNetworkController.mMobileSignalControllers.indexOfKey(
308                        testSubscriptions[i]) >= 0);
309            } else if (i == indexToSkipSubscription) {
310                // Make sure the controller that did exist was removed
311                assertFalse(mNetworkController.mMobileSignalControllers.indexOfKey(
312                        testSubscriptions[i]) >= 0);
313            } else {
314                // If a MobileSignalController is around it needs to not be unregistered.
315                Mockito.verify(mobileSignalControllers[i], Mockito.never())
316                        .unregisterListener();
317            }
318        }
319    }
320
321    @Test
322    public void testHistorySize() {
323        // Verify valid history size, otherwise it gits printed out the wrong order and whatnot.
324        assertEquals(0, SignalController.HISTORY_SIZE & (SignalController.HISTORY_SIZE - 1));
325    }
326
327    private void setCdma() {
328        setIsGsm(false);
329        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
330                TelephonyManager.NETWORK_TYPE_CDMA);
331        setCdmaRoaming(false);
332    }
333
334    @Test
335    public void testOnReceive_stringsUpdatedAction_spn() {
336        String expectedMNetworkName = "Test";
337        Intent intent = createStringsUpdatedIntent(true /* showSpn */,
338                expectedMNetworkName /* spn */,
339                false /* showPlmn */,
340                "NotTest" /* plmn */);
341
342        mNetworkController.onReceive(mContext, intent);
343
344        assertNetworkNameEquals(expectedMNetworkName);
345    }
346
347    @Test
348    public void testOnReceive_stringsUpdatedAction_plmn() {
349        String expectedMNetworkName = "Test";
350
351        Intent intent = createStringsUpdatedIntent(false /* showSpn */,
352                "NotTest" /* spn */,
353                true /* showPlmn */,
354                expectedMNetworkName /* plmn */);
355
356        mNetworkController.onReceive(mContext, intent);
357
358        assertNetworkNameEquals(expectedMNetworkName);
359    }
360
361    @Test
362    public void testOnReceive_stringsUpdatedAction_bothFalse() {
363        Intent intent = createStringsUpdatedIntent(false /* showSpn */,
364              "Irrelevant" /* spn */,
365              false /* showPlmn */,
366              "Irrelevant" /* plmn */);
367
368        mNetworkController.onReceive(mContext, intent);
369
370        String defaultNetworkName = mMobileSignalController
371            .getStringIfExists(
372                com.android.internal.R.string.lockscreen_carrier_default);
373        assertNetworkNameEquals(defaultNetworkName);
374    }
375
376    @Test
377    public void testOnReceive_stringsUpdatedAction_bothTrueAndNull() {
378        Intent intent = createStringsUpdatedIntent(true /* showSpn */,
379            null /* spn */,
380            true /* showPlmn */,
381            null /* plmn */);
382
383        mNetworkController.onReceive(mContext, intent);
384
385        String defaultNetworkName = mMobileSignalController.getStringIfExists(
386                com.android.internal.R.string.lockscreen_carrier_default);
387        assertNetworkNameEquals(defaultNetworkName);
388    }
389
390    @Test
391    public void testOnReceive_stringsUpdatedAction_bothTrueAndNonNull() {
392        String spn = "Test1";
393        String plmn = "Test2";
394
395        Intent intent = createStringsUpdatedIntent(true /* showSpn */,
396            spn /* spn */,
397            true /* showPlmn */,
398            plmn /* plmn */);
399
400        mNetworkController.onReceive(mContext, intent);
401
402        assertNetworkNameEquals(plmn
403                + mMobileSignalController.getStringIfExists(
404                        R.string.status_bar_network_name_separator)
405                + spn);
406    }
407
408    private Intent createStringsUpdatedIntent(boolean showSpn, String spn,
409            boolean showPlmn, String plmn) {
410
411        Intent intent = new Intent();
412        intent.setAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
413
414        intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn);
415        intent.putExtra(TelephonyIntents.EXTRA_SPN, spn);
416
417        intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
418        intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
419        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mSubId);
420
421        return intent;
422    }
423
424    @Test
425    public void testOnUpdateDataActivity_dataIn() {
426        setupDefaultSignal();
427
428        updateDataActivity(TelephonyManager.DATA_ACTIVITY_IN);
429
430        verifyLastQsMobileDataIndicators(true /* visible */,
431                DEFAULT_LEVEL /* icon */,
432                DEFAULT_QS_ICON /* typeIcon */,
433                true /* dataIn */,
434                false /* dataOut */);
435
436    }
437
438    @Test
439    public void testOnUpdateDataActivity_dataOut() {
440      setupDefaultSignal();
441
442      updateDataActivity(TelephonyManager.DATA_ACTIVITY_OUT);
443
444      verifyLastQsMobileDataIndicators(true /* visible */,
445              DEFAULT_LEVEL /* icon */,
446              DEFAULT_QS_ICON /* typeIcon */,
447              false /* dataIn */,
448              true /* dataOut */);
449    }
450
451    @Test
452    public void testOnUpdateDataActivity_dataInOut() {
453      setupDefaultSignal();
454
455      updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
456
457      verifyLastQsMobileDataIndicators(true /* visible */,
458              DEFAULT_LEVEL /* icon */,
459              DEFAULT_QS_ICON /* typeIcon */,
460              true /* dataIn */,
461              true /* dataOut */);
462
463    }
464
465    @Test
466    public void testOnUpdateDataActivity_dataActivityNone() {
467      setupDefaultSignal();
468
469      updateDataActivity(TelephonyManager.DATA_ACTIVITY_NONE);
470
471      verifyLastQsMobileDataIndicators(true /* visible */,
472              DEFAULT_LEVEL /* icon */,
473              DEFAULT_QS_ICON /* typeIcon */,
474              false /* dataIn */,
475              false /* dataOut */);
476
477    }
478
479    @Test
480    public void testCarrierNetworkChange_carrierNetworkChange() {
481      int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
482
483      setupDefaultSignal();
484      setLevel(strength);
485
486      // Verify baseline
487      verifyLastMobileDataIndicators(true /* visible */,
488              strength /* strengthIcon */,
489              DEFAULT_ICON /* typeIcon */);
490
491      // API call is made
492      setCarrierNetworkChange(true /* enabled */);
493
494      // Carrier network change is true, show special indicator
495      verifyLastMobileDataIndicators(true /* visible */,
496              SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
497              0 /* typeIcon */);
498
499      // Revert back
500      setCarrierNetworkChange(false /* enabled */);
501
502      // Verify back in previous state
503      verifyLastMobileDataIndicators(true /* visible */,
504              strength /* strengthIcon */,
505              DEFAULT_ICON /* typeIcon */);
506    }
507
508    @Test
509    public void testCarrierNetworkChange_roamingBeforeNetworkChange() {
510      int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
511
512      setupDefaultSignal();
513      setLevel(strength);
514      setGsmRoaming(true);
515
516      // Verify baseline
517      verifyLastMobileDataIndicators(true /* visible */,
518              strength /* strengthIcon */,
519              DEFAULT_ICON /* typeIcon */,
520              true /* roaming */);
521
522      // API call is made
523      setCarrierNetworkChange(true /* enabled */);
524
525      // Carrier network change is true, show special indicator, no roaming.
526      verifyLastMobileDataIndicators(true /* visible */,
527              SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
528              0 /* typeIcon */,
529              false /* roaming */);
530
531      // Revert back
532      setCarrierNetworkChange(false /* enabled */);
533
534      // Verify back in previous state
535      verifyLastMobileDataIndicators(true /* visible */,
536              strength /* strengthIcon */,
537              DEFAULT_ICON /* typeIcon */,
538              true /* roaming */);
539    }
540
541    @Test
542    public void testCarrierNetworkChange_roamingAfterNetworkChange() {
543      int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
544
545      setupDefaultSignal();
546      setLevel(strength);
547
548      // Verify baseline
549      verifyLastMobileDataIndicators(true /* visible */,
550              strength /* strengthIcon */,
551              DEFAULT_ICON /* typeIcon */,
552              false /* roaming */);
553
554      // API call is made
555      setCarrierNetworkChange(true /* enabled */);
556
557      // Carrier network change is true, show special indicator, no roaming.
558      verifyLastMobileDataIndicators(true /* visible */,
559              SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
560              0 /* typeIcon */,
561              false /* roaming */);
562
563      setGsmRoaming(true);
564
565      // Roaming should not show.
566      verifyLastMobileDataIndicators(true /* visible */,
567              SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
568              0 /* typeIcon */,
569              false /* roaming */);
570
571      // Revert back
572      setCarrierNetworkChange(false /* enabled */);
573
574      // Verify back in previous state
575      verifyLastMobileDataIndicators(true /* visible */,
576              strength /* strengthIcon */,
577              DEFAULT_ICON /* typeIcon */,
578              true /* roaming */);
579    }
580
581    private void verifyEmergencyOnly(boolean isEmergencyOnly) {
582        ArgumentCaptor<Boolean> emergencyOnly = ArgumentCaptor.forClass(Boolean.class);
583        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setEmergencyCallsOnly(
584                emergencyOnly.capture());
585        assertEquals(isEmergencyOnly, (boolean) emergencyOnly.getValue());
586    }
587}
588