1 /*
2  * Copyright (C) 2021 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.systemui.statusbar.connectivity;
18 
19 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
20 import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
21 import static android.telephony.TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED;
22 import static android.telephony.TelephonyManager.EXTRA_CARRIER_ID;
23 import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;
24 
25 import static com.android.settingslib.mobile.TelephonyIcons.NR_5G_PLUS;
26 
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertFalse;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.when;
34 
35 import android.content.Intent;
36 import android.net.NetworkCapabilities;
37 import android.os.Handler;
38 import android.os.Looper;
39 import android.telephony.NetworkRegistrationInfo;
40 import android.telephony.ServiceState;
41 import android.telephony.TelephonyManager;
42 import android.testing.TestableLooper;
43 import android.testing.TestableLooper.RunWithLooper;
44 
45 import androidx.test.ext.junit.runners.AndroidJUnit4;
46 import androidx.test.filters.SmallTest;
47 
48 import com.android.settingslib.SignalIcon.MobileIconGroup;
49 import com.android.settingslib.mobile.TelephonyIcons;
50 import com.android.settingslib.net.DataUsageController;
51 import com.android.systemui.dump.DumpManager;
52 import com.android.systemui.log.LogBuffer;
53 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
54 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
55 import com.android.systemui.util.CarrierConfigTracker;
56 
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 
60 import java.util.HashMap;
61 
62 @SmallTest
63 @RunWith(AndroidJUnit4.class)
64 @RunWithLooper
65 public class NetworkControllerDataTest extends NetworkControllerBaseTest {
66 
67     @Test
test3gDataIcon()68     public void test3gDataIcon() {
69         setupDefaultSignal();
70 
71         verifyDataIndicators(TelephonyIcons.ICON_3G);
72     }
73 
74     @Test
test2gDataIcon()75     public void test2gDataIcon() {
76         setupDefaultSignal();
77         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
78                 TelephonyManager.NETWORK_TYPE_GSM);
79 
80         verifyDataIndicators(TelephonyIcons.ICON_G);
81     }
82 
83     @Test
testCdmaDataIcon()84     public void testCdmaDataIcon() {
85         setupDefaultSignal();
86         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
87                 TelephonyManager.NETWORK_TYPE_CDMA);
88 
89         verifyDataIndicators(TelephonyIcons.ICON_1X);
90     }
91 
92     @Test
testEdgeDataIcon()93     public void testEdgeDataIcon() {
94         setupDefaultSignal();
95         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
96                 TelephonyManager.NETWORK_TYPE_EDGE);
97 
98         verifyDataIndicators(TelephonyIcons.ICON_E);
99     }
100 
101     @Test
testLteDataIcon()102     public void testLteDataIcon() {
103         setupDefaultSignal();
104         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
105                 TelephonyManager.NETWORK_TYPE_LTE);
106 
107         verifyDataIndicators(TelephonyIcons.ICON_LTE);
108     }
109 
110     @Test
testHspaDataIcon()111     public void testHspaDataIcon() {
112         setupDefaultSignal();
113         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
114                 TelephonyManager.NETWORK_TYPE_HSPA);
115 
116         verifyDataIndicators(TelephonyIcons.ICON_H);
117     }
118 
119 
120     @Test
testHspaPlusDataIcon()121     public void testHspaPlusDataIcon() {
122         setupDefaultSignal();
123         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
124                 TelephonyManager.NETWORK_TYPE_HSPAP);
125 
126         verifyDataIndicators(TelephonyIcons.ICON_H_PLUS);
127     }
128 
129 
130     @Test
testWfcNoDataIcon()131     public void testWfcNoDataIcon() {
132         setupDefaultSignal();
133         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
134                 TelephonyManager.NETWORK_TYPE_IWLAN);
135 
136         verifyDataIndicators(0);
137     }
138 
139     @Test
test4gDataIcon()140     public void test4gDataIcon() {
141         // Switch to showing 4g icon and re-initialize the NetworkController.
142         mConfig.show4gForLte = true;
143         mNetworkController = new NetworkControllerImpl(
144                 mContext,
145                 mMockCm,
146                 mMockTm,
147                 mTelephonyListenerManager,
148                 mMockWm,
149                 mMockSm,
150                 mConfig,
151                 Looper.getMainLooper(),
152                 mFakeExecutor,
153                 mCallbackHandler,
154                 mock(AccessPointControllerImpl.class),
155                 mock(StatusBarPipelineFlags.class),
156                 mock(DataUsageController.class),
157                 mMockSubDefaults,
158                 mock(DeviceProvisionedController.class),
159                 mMockBd,
160                 mUserTracker,
161                 mDemoModeController,
162                 mock(CarrierConfigTracker.class),
163                 mWifiStatusTrackerFactory,
164                 mMobileFactory,
165                 new Handler(TestableLooper.get(this).getLooper()),
166                 mock(DumpManager.class),
167                 mock(LogBuffer.class));
168         setupNetworkController();
169 
170         setupDefaultSignal();
171         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
172                 TelephonyManager.NETWORK_TYPE_LTE);
173 
174         verifyDataIndicators(TelephonyIcons.ICON_4G);
175     }
176 
177     @Test
testNoInternetIcon_withDefaultSub()178     public void testNoInternetIcon_withDefaultSub() {
179         setupNetworkController();
180         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
181         setupDefaultSignal();
182         updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
183         setConnectivityViaCallbackInNetworkController(
184                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
185 
186         // Verify that a SignalDrawable with a cut out is used to display data disabled.
187         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
188                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
189                 false, true, NO_DATA_STRING, NO_DATA_STRING, false);
190     }
191 
192     @Test
testDataDisabledIcon_withDefaultSub()193     public void testDataDisabledIcon_withDefaultSub() {
194         setupNetworkController();
195         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
196         setupDefaultSignal();
197         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
198         setConnectivityViaCallbackInNetworkController(
199                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
200 
201         // Verify that a SignalDrawable with a cut out is used to display data disabled.
202         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
203                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
204                 false, true, NO_DATA_STRING, NO_DATA_STRING, false);
205     }
206 
207     @Test
testNonDefaultSIM_showsFullSignal_connected()208     public void testNonDefaultSIM_showsFullSignal_connected() {
209         setupNetworkController();
210         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
211         setupDefaultSignal();
212         setDefaultSubId(mSubId + 1);
213         updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
214         setConnectivityViaCallbackInNetworkController(
215                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
216 
217         // Verify that a SignalDrawable with a cut out is used to display data disabled.
218         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
219                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
220                 false, false, NOT_DEFAULT_DATA_STRING, NOT_DEFAULT_DATA_STRING, false);
221     }
222 
223     @Test
testNonDefaultSIM_showsFullSignal_disconnected()224     public void testNonDefaultSIM_showsFullSignal_disconnected() {
225         setupNetworkController();
226         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
227         setupDefaultSignal();
228         setDefaultSubId(mSubId + 1);
229         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
230         setConnectivityViaCallbackInNetworkController(
231                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
232 
233         // Verify that a SignalDrawable with a cut out is used to display data disabled.
234         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
235                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
236                 false, false, NOT_DEFAULT_DATA_STRING, NOT_DEFAULT_DATA_STRING, false);
237     }
238 
239     @Test
testDataDisabledIcon_UserNotSetup()240     public void testDataDisabledIcon_UserNotSetup() {
241         setupNetworkController();
242         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
243         setupDefaultSignal();
244         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
245         setConnectivityViaCallbackInNetworkController(
246                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
247         when(mMockProvisionController.isCurrentUserSetup()).thenReturn(false);
248         mUserCallback.onUserSetupChanged();
249         TestableLooper.get(this).processAllMessages();
250 
251         // Don't show the X until the device is setup.
252         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
253                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, false, false, null, null, false);
254     }
255 
256     @Test
testAlwaysShowDataRatIcon()257     public void testAlwaysShowDataRatIcon() {
258         setupDefaultSignal();
259         when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
260         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED,
261                 TelephonyManager.NETWORK_TYPE_GSM);
262 
263         // Switch to showing data RAT icon when data is disconnected
264         // and re-initialize the NetworkController.
265         mConfig.alwaysShowDataRatIcon = true;
266         mNetworkController.handleConfigurationChanged();
267 
268         setConnectivityViaCallbackInNetworkController(
269                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
270         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, TelephonyIcons.ICON_G,
271                 true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, false, false, null, null, false);
272     }
273 
274     @Test
test4gDataIconConfigChange()275     public void test4gDataIconConfigChange() {
276         setupDefaultSignal();
277         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
278                 TelephonyManager.NETWORK_TYPE_LTE);
279 
280         // Switch to showing 4g icon and re-initialize the NetworkController.
281         mConfig.show4gForLte = true;
282         // Can't send the broadcast as that would actually read the config from
283         // the context.  Instead we'll just poke at a function that does all of
284         // the after work.
285         mNetworkController.handleConfigurationChanged();
286 
287         verifyDataIndicators(TelephonyIcons.ICON_4G);
288     }
289 
290     @Test
testDataChangeWithoutConnectionState()291     public void testDataChangeWithoutConnectionState() {
292         setupDefaultSignal();
293         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
294                 TelephonyManager.NETWORK_TYPE_LTE);
295 
296         verifyDataIndicators(TelephonyIcons.ICON_LTE);
297 
298         NetworkRegistrationInfo fakeRegInfo = new NetworkRegistrationInfo.Builder()
299                 .setTransportType(TRANSPORT_TYPE_WWAN)
300                 .setDomain(DOMAIN_PS)
301                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_HSPA)
302                 .build();
303         when(mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN))
304                 .thenReturn(fakeRegInfo);
305         when(mTelephonyDisplayInfo.getNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
306         updateServiceState();
307         verifyDataIndicators(TelephonyIcons.ICON_H);
308     }
309 
310     @Test
testDataActivity()311     public void testDataActivity() {
312         setupDefaultSignal();
313 
314         testDataActivity(TelephonyManager.DATA_ACTIVITY_NONE, false, false);
315         testDataActivity(TelephonyManager.DATA_ACTIVITY_IN, true, false);
316         testDataActivity(TelephonyManager.DATA_ACTIVITY_OUT, false, true);
317         testDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT, true, true);
318     }
319 
320     @Test
testUpdateDataNetworkName()321     public void testUpdateDataNetworkName() {
322         setupDefaultSignal();
323         String newDataName = "TestDataName";
324         when(mServiceState.getOperatorAlphaShort()).thenReturn(newDataName);
325         updateServiceState();
326         assertDataNetworkNameEquals(newDataName);
327     }
328 
329     @Test
testIsDataInService_true()330     public void testIsDataInService_true() {
331         setupDefaultSignal();
332         assertTrue(mNetworkController.isMobileDataNetworkInService());
333     }
334 
335     @Test
testIsDataInService_noSignal_false()336     public void testIsDataInService_noSignal_false() {
337         assertFalse(mNetworkController.isMobileDataNetworkInService());
338     }
339 
340     @Test
testIsDataInService_notInService_false()341     public void testIsDataInService_notInService_false() {
342         setupDefaultSignal();
343         setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
344         setDataRegInService(false);
345         assertFalse(mNetworkController.isMobileDataNetworkInService());
346     }
347 
348     @Test
mobileSignalController_getsCarrierId()349     public void mobileSignalController_getsCarrierId() {
350         when(mMockTm.getSimCarrierId()).thenReturn(1);
351         setupDefaultSignal();
352 
353         assertEquals(1, mMobileSignalController.getState().getCarrierId());
354     }
355 
356     @Test
mobileSignalController_updatesCarrierId_onChange()357     public void mobileSignalController_updatesCarrierId_onChange() {
358         when(mMockTm.getSimCarrierId()).thenReturn(1);
359         setupDefaultSignal();
360 
361         // Updates are sent down through this broadcast, we can send the intent directly
362         Intent intent = new Intent(ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
363         intent.putExtra(EXTRA_SUBSCRIPTION_ID, mSubId);
364         intent.putExtra(EXTRA_CARRIER_ID, 2);
365 
366         mMobileSignalController.handleBroadcast(intent);
367 
368         assertEquals(2, mMobileSignalController.getState().getCarrierId());
369     }
370 
371     @Test
networkTypeIcon_hasCarrierIdOverride()372     public void networkTypeIcon_hasCarrierIdOverride() {
373         int fakeCarrier = 1;
374         int fakeIconOverride = 12345;
375         int testDataNetType = 100;
376         String testDataString = "100";
377         HashMap<String, MobileIconGroup> testMap = new HashMap<>();
378         testMap.put(testDataString, NR_5G_PLUS);
379 
380         // Pretend that there is an override for this icon, and this carrier ID
381         NetworkTypeResIdCache mockCache = mock(NetworkTypeResIdCache.class);
382         when(mockCache.get(eq(NR_5G_PLUS), eq(fakeCarrier), any())).thenReturn(fakeIconOverride);
383 
384         // Turn off the default mobile mapping, so we can override
385         mMobileMappingsProxy.setUseRealImpl(false);
386         mMobileMappingsProxy.setIconMap(testMap);
387         // Use the mocked cache
388         mMobileSignalController.mCurrentState.setNetworkTypeResIdCache(mockCache);
389         // Rebuild the network map
390         mMobileSignalController.setConfiguration(mConfig);
391         when(mMockTm.getSimCarrierId()).thenReturn(fakeCarrier);
392 
393         setupDefaultSignal();
394         updateDataConnectionState(TelephonyManager.DATA_CONNECTED, testDataNetType);
395 
396         verifyDataIndicators(fakeIconOverride);
397     }
398 
testDataActivity(int direction, boolean in, boolean out)399     private void testDataActivity(int direction, boolean in, boolean out) {
400         updateDataActivity(direction);
401 
402         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON, true,
403                 DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out);
404     }
405 
verifyDataIndicators(int dataIcon)406     private void verifyDataIndicators(int dataIcon) {
407         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, dataIcon,
408                 true, DEFAULT_QS_SIGNAL_STRENGTH, dataIcon, false,
409                 false);
410     }
411 }
412 
413