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 */
16
17package com.android.systemui.statusbar.policy;
18
19import android.content.Intent;
20import android.net.ConnectivityManager;
21import android.net.NetworkCapabilities;
22import android.net.NetworkScoreManager;
23import android.net.wifi.WifiManager;
24import android.os.Looper;
25import android.telephony.PhoneStateListener;
26import android.telephony.ServiceState;
27import android.telephony.SignalStrength;
28import android.telephony.SubscriptionInfo;
29import android.telephony.SubscriptionManager;
30import android.telephony.TelephonyManager;
31import android.util.Log;
32import com.android.internal.telephony.cdma.EriInfo;
33import com.android.settingslib.net.DataUsageController;
34import com.android.systemui.statusbar.phone.SignalDrawable;
35import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
36import com.android.systemui.statusbar.policy.NetworkController.IconState;
37import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
38import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
39import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
40import com.android.systemui.SysuiTestCase;
41
42import org.junit.Before;
43import org.junit.Rule;
44import org.junit.rules.TestWatcher;
45import org.junit.runner.Description;
46import org.mockito.ArgumentCaptor;
47import org.mockito.Mockito;
48import org.mockito.invocation.InvocationOnMock;
49import org.mockito.stubbing.Answer;
50
51import java.io.PrintWriter;
52import java.io.StringWriter;
53import java.util.ArrayList;
54import java.util.List;
55
56import static junit.framework.Assert.assertEquals;
57
58import static org.mockito.Matchers.any;
59import static org.mockito.Matchers.anyBoolean;
60import static org.mockito.Matchers.anyInt;
61import static org.mockito.Matchers.anyString;
62import static org.mockito.Matchers.eq;
63import static org.mockito.Mockito.doAnswer;
64import static org.mockito.Mockito.mock;
65import static org.mockito.Mockito.when;
66
67public class NetworkControllerBaseTest extends SysuiTestCase {
68    private static final String TAG = "NetworkControllerBaseTest";
69    protected static final int DEFAULT_LEVEL = 2;
70    protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL;
71    protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL;
72    protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G;
73    protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G;
74
75    protected NetworkControllerImpl mNetworkController;
76    protected MobileSignalController mMobileSignalController;
77    protected PhoneStateListener mPhoneStateListener;
78    protected SignalStrength mSignalStrength;
79    protected ServiceState mServiceState;
80    protected ConnectivityManager mMockCm;
81    protected WifiManager mMockWm;
82    protected SubscriptionManager mMockSm;
83    protected TelephonyManager mMockTm;
84    protected Config mConfig;
85    protected CallbackHandler mCallbackHandler;
86    protected SubscriptionDefaults mMockSubDefaults;
87    protected NetworkScoreManager mMockNetworkScoreManager;
88    protected DeviceProvisionedController mMockProvisionController;
89    protected DeviceProvisionedListener mUserCallback;
90
91    protected int mSubId;
92
93    private NetworkCapabilities mNetCapabilities;
94
95    @Rule
96    public TestWatcher failWatcher = new TestWatcher() {
97        @Override
98        protected void failed(Throwable e, Description description) {
99            // Print out mNetworkController state if the test fails.
100            StringWriter sw = new StringWriter();
101            PrintWriter pw = new PrintWriter(sw);
102            mNetworkController.dump(null, pw, null);
103            pw.flush();
104            Log.d(TAG, sw.toString());
105        }
106    };
107
108    @Before
109    public void setUp() throws Exception {
110        mMockWm = mock(WifiManager.class);
111        mMockTm = mock(TelephonyManager.class);
112        mMockSm = mock(SubscriptionManager.class);
113        mMockCm = mock(ConnectivityManager.class);
114        mMockSubDefaults = mock(SubscriptionDefaults.class);
115        mNetCapabilities = new NetworkCapabilities();
116        mMockNetworkScoreManager = mock(NetworkScoreManager.class);
117
118        when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
119        when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
120                new NetworkCapabilities[] { mNetCapabilities });
121
122        mSignalStrength = mock(SignalStrength.class);
123        mServiceState = mock(ServiceState.class);
124
125        mConfig = new Config();
126        mConfig.hspaDataDistinguishable = true;
127        mCallbackHandler = mock(CallbackHandler.class);
128
129        mMockProvisionController = mock(DeviceProvisionedController.class);
130        when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true);
131        doAnswer(invocation -> {
132            mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
133            mUserCallback.onUserSetupChanged();
134            mUserCallback.onDeviceProvisionedChanged();
135            return null;
136        }).when(mMockProvisionController).addCallback(any());
137
138        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager,
139                mMockTm, mMockWm, mMockSm,
140                mConfig, Looper.getMainLooper(), mCallbackHandler,
141                mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
142                mMockSubDefaults, mMockProvisionController);
143        setupNetworkController();
144
145        // Trigger blank callbacks to always get the current state (some tests don't trigger
146        // changes from default state).
147        mNetworkController.addCallback(mock(SignalCallback.class));
148        mNetworkController.addEmergencyListener(null);
149    }
150
151    protected void setupNetworkController() {
152        // For now just pretend to be the data sim, so we can test that too.
153        mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
154        when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
155        setDefaultSubId(mSubId);
156        setSubscriptions(mSubId);
157        mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
158        mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
159    }
160
161    protected void setDefaultSubId(int subId) {
162        when(mMockSubDefaults.getDefaultDataSubId()).thenReturn(subId);
163        when(mMockSubDefaults.getDefaultVoiceSubId()).thenReturn(subId);
164    }
165
166    protected void setSubscriptions(int... subIds) {
167        List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>();
168        for (int subId : subIds) {
169            SubscriptionInfo subscription = mock(SubscriptionInfo.class);
170            when(subscription.getSubscriptionId()).thenReturn(subId);
171            subs.add(subscription);
172        }
173        when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs);
174        mNetworkController.doUpdateMobileControllers();
175    }
176
177    protected NetworkControllerImpl setUpNoMobileData() {
178      when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
179      NetworkControllerImpl networkControllerNoMobile
180              = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm,
181                        mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler,
182                        mock(AccessPointControllerImpl.class),
183                        mock(DataUsageController.class), mMockSubDefaults,
184                        mock(DeviceProvisionedController.class));
185
186      setupNetworkController();
187
188      return networkControllerNoMobile;
189
190    }
191
192    // 2 Bars 3G GSM.
193    public void setupDefaultSignal() {
194        setIsGsm(true);
195        setVoiceRegState(ServiceState.STATE_IN_SERVICE);
196        setGsmRoaming(false);
197        setLevel(DEFAULT_LEVEL);
198        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
199                TelephonyManager.NETWORK_TYPE_UMTS);
200        setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, true, true);
201    }
202
203    public void setConnectivity(int networkType, boolean inetCondition, boolean isConnected) {
204        Intent i = new Intent(ConnectivityManager.INET_CONDITION_ACTION);
205        // TODO: Separate out into several NetworkCapabilities.
206        if (isConnected) {
207            mNetCapabilities.addTransportType(networkType);
208        } else {
209            mNetCapabilities.removeTransportType(networkType);
210        }
211        if (inetCondition) {
212            mNetCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
213        } else {
214            mNetCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
215        }
216
217        mNetworkController.onReceive(mContext, i);
218    }
219
220    public void setGsmRoaming(boolean isRoaming) {
221        when(mServiceState.getRoaming()).thenReturn(isRoaming);
222        updateServiceState();
223    }
224
225    public void setCdmaRoaming(boolean isRoaming) {
226        when(mServiceState.getCdmaEriIconIndex()).thenReturn(isRoaming ?
227                EriInfo.ROAMING_INDICATOR_ON : EriInfo.ROAMING_INDICATOR_OFF);
228        when(mServiceState.getCdmaEriIconMode()).thenReturn(isRoaming ?
229                EriInfo.ROAMING_ICON_MODE_NORMAL : -1);
230        updateServiceState();
231    }
232
233    public void setVoiceRegState(int voiceRegState) {
234        when(mServiceState.getVoiceRegState()).thenReturn(voiceRegState);
235        updateServiceState();
236    }
237
238    public void setDataRegState(int dataRegState) {
239        when(mServiceState.getDataRegState()).thenReturn(dataRegState);
240        updateServiceState();
241    }
242
243    public void setIsEmergencyOnly(boolean isEmergency) {
244        when(mServiceState.isEmergencyOnly()).thenReturn(isEmergency);
245        updateServiceState();
246    }
247
248    public void setCdmaLevel(int level) {
249        when(mSignalStrength.getCdmaLevel()).thenReturn(level);
250        updateSignalStrength();
251    }
252
253    public void setLevel(int level) {
254        when(mSignalStrength.getLevel()).thenReturn(level);
255        updateSignalStrength();
256    }
257
258    public void setIsGsm(boolean gsm) {
259        when(mSignalStrength.isGsm()).thenReturn(gsm);
260        updateSignalStrength();
261    }
262
263    public void setCdmaEri(int index, int mode) {
264        // TODO: Figure this out.
265    }
266
267    private void updateSignalStrength() {
268        Log.d(TAG, "Sending Signal Strength: " + mSignalStrength);
269        mPhoneStateListener.onSignalStrengthsChanged(mSignalStrength);
270    }
271
272    protected void updateServiceState() {
273        Log.d(TAG, "Sending Service State: " + mServiceState);
274        mPhoneStateListener.onServiceStateChanged(mServiceState);
275    }
276
277    public void updateCallState(int state) {
278        // Inputs not currently used in NetworkControllerImpl.
279        mPhoneStateListener.onCallStateChanged(state, "0123456789");
280    }
281
282    public void updateDataConnectionState(int dataState, int dataNetType) {
283        when(mServiceState.getDataNetworkType()).thenReturn(dataNetType);
284        mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType);
285    }
286
287    public void updateDataActivity(int dataActivity) {
288        mPhoneStateListener.onDataActivity(dataActivity);
289    }
290
291    public void setCarrierNetworkChange(boolean enable) {
292        Log.d(TAG, "setCarrierNetworkChange(" + enable + ")");
293        mPhoneStateListener.onCarrierNetworkChange(enable);
294    }
295
296    protected void verifyHasNoSims(boolean hasNoSimsVisible) {
297        ArgumentCaptor<Boolean> hasNoSimsArg = ArgumentCaptor.forClass(Boolean.class);
298
299        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setNoSims(hasNoSimsArg.capture());
300        assertEquals("No sims", hasNoSimsVisible, (boolean) hasNoSimsArg.getValue());
301    }
302
303    protected void verifyLastQsMobileDataIndicators(boolean visible, int icon, int typeIcon,
304            boolean dataIn, boolean dataOut) {
305        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
306        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
307        ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class);
308        ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
309
310        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
311                    any(),
312                    iconArg.capture(),
313                    anyInt(),
314                    typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(),
315                    anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
316        IconState iconState = iconArg.getValue();
317        int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
318                false);
319        assertEquals("Visibility in, quick settings", visible, iconState.visible);
320        assertEquals("Signal icon in, quick settings", state, iconState.icon);
321        assertEquals("Data icon in, quick settings", typeIcon, (int) typeIconArg.getValue());
322        assertEquals("Data direction in, in quick settings", dataIn,
323                (boolean) dataInArg.getValue());
324        assertEquals("Data direction out, in quick settings", dataOut,
325                (boolean) dataOutArg.getValue());
326    }
327
328    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon) {
329        verifyLastMobileDataIndicators(visible, icon, typeIcon, false);
330    }
331
332    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
333            boolean roaming) {
334        verifyLastMobileDataIndicators(visible, icon, typeIcon, roaming, true);
335    }
336
337    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
338        boolean roaming, boolean inet) {
339        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
340        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
341
342        // TODO: Verify all fields.
343        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
344                iconArg.capture(),
345                any(),
346                typeIconArg.capture(),
347                anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(),
348                anyInt(), eq(roaming));
349        IconState iconState = iconArg.getValue();
350
351        int state = icon == -1 ? 0
352                : SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, !inet);
353        assertEquals("Signal icon in status bar", state, iconState.icon);
354        assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
355        assertEquals("Visibility in status bar", visible, iconState.visible);
356    }
357
358    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
359            boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) {
360        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
361        ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
362        ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
363        ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
364        ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class);
365        ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
366
367        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
368                iconArg.capture(),
369                qsIconArg.capture(),
370                typeIconArg.capture(),
371                qsTypeIconArg.capture(),
372                dataInArg.capture(),
373                dataOutArg.capture(),
374                anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
375
376        IconState iconState = iconArg.getValue();
377
378        int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
379                false);
380        assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
381        assertEquals("Signal icon in status bar", state, iconState.icon);
382        assertEquals("Visibility in status bar", visible, iconState.visible);
383
384        iconState = qsIconArg.getValue();
385        assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
386        assertEquals("Signal icon in quick settings", state, iconState.icon);
387        assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue());
388        assertEquals("Data direction in in quick settings", dataIn,
389                (boolean) dataInArg.getValue());
390        assertEquals("Data direction out in quick settings", dataOut,
391                (boolean) dataOutArg.getValue());
392    }
393
394   protected void assertNetworkNameEquals(String expected) {
395       assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
396   }
397}
398