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.server.net;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Mockito.any;
23 import static org.mockito.Mockito.anyInt;
24 import static org.mockito.Mockito.clearInvocations;
25 import static org.mockito.Mockito.eq;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.reset;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.annotation.NonNull;
34 import android.annotation.Nullable;
35 import android.content.Context;
36 import android.net.NetworkTemplate;
37 import android.os.Build;
38 import android.os.test.TestLooper;
39 import android.telephony.NetworkRegistrationInfo;
40 import android.telephony.PhoneStateListener;
41 import android.telephony.ServiceState;
42 import android.telephony.SubscriptionManager;
43 import android.telephony.TelephonyManager;
44 
45 import com.android.internal.util.CollectionUtils;
46 import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener;
47 import com.android.testutils.DevSdkIgnoreRule;
48 import com.android.testutils.DevSdkIgnoreRunner;
49 
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 import org.mockito.ArgumentCaptor;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 
57 import java.util.ArrayList;
58 import java.util.List;
59 import java.util.concurrent.Executor;
60 import java.util.concurrent.Executors;
61 
62 @RunWith(DevSdkIgnoreRunner.class)
63 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
64 public final class NetworkStatsSubscriptionsMonitorTest {
65     private static final int TEST_SUBID1 = 3;
66     private static final int TEST_SUBID2 = 5;
67     private static final String TEST_IMSI1 = "466921234567890";
68     private static final String TEST_IMSI2 = "466920987654321";
69     private static final String TEST_IMSI3 = "466929999999999";
70 
71     @Mock private Context mContext;
72     @Mock private SubscriptionManager mSubscriptionManager;
73     @Mock private TelephonyManager mTelephonyManager;
74     @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate;
75     private final List<Integer> mTestSubList = new ArrayList<>();
76 
77     private final Executor mExecutor = Executors.newSingleThreadExecutor();
78     private NetworkStatsSubscriptionsMonitor mMonitor;
79     private TestLooper mTestLooper = new TestLooper();
80 
81     @Before
setUp()82     public void setUp() {
83         MockitoAnnotations.initMocks(this);
84 
85         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
86 
87         when(mContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
88                 .thenReturn(mSubscriptionManager);
89         when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
90                 .thenReturn(mTelephonyManager);
91 
92         mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mTestLooper.getLooper(),
93                 mExecutor, mDelegate);
94     }
95 
96     @Test
testStartStop()97     public void testStartStop() {
98         // Verify that addOnSubscriptionsChangedListener() is never called before start().
99         verify(mSubscriptionManager, never())
100                 .addOnSubscriptionsChangedListener(mExecutor, mMonitor);
101         mMonitor.start();
102         verify(mSubscriptionManager).addOnSubscriptionsChangedListener(mExecutor, mMonitor);
103 
104         // Verify that removeOnSubscriptionsChangedListener() is never called before stop()
105         verify(mSubscriptionManager, never()).removeOnSubscriptionsChangedListener(mMonitor);
106         mMonitor.stop();
107         verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(mMonitor);
108     }
109 
110     @NonNull
convertArrayListToIntArray(@onNull List<Integer> arrayList)111     private static int[] convertArrayListToIntArray(@NonNull List<Integer> arrayList) {
112         final int[] list = new int[arrayList.size()];
113         for (int i = 0; i < arrayList.size(); i++) {
114             list[i] = arrayList.get(i);
115         }
116         return list;
117     }
118 
setRatTypeForSub(List<RatTypeListener> listeners, int subId, int type)119     private void setRatTypeForSub(List<RatTypeListener> listeners,
120             int subId, int type) {
121         final ServiceState serviceState = mock(ServiceState.class);
122         when(serviceState.getDataNetworkType()).thenReturn(type);
123         final RatTypeListener match = CollectionUtils
124                 .find(listeners, it -> it.getSubId() == subId);
125         if (match == null) {
126             fail("Could not find listener with subId: " + subId);
127         }
128         match.onServiceStateChanged(serviceState);
129     }
130 
addTestSub(int subId, String subscriberId)131     private void addTestSub(int subId, String subscriberId) {
132         // add SubId to TestSubList.
133         if (mTestSubList.contains(subId)) fail("The subscriber list already contains this ID");
134 
135         mTestSubList.add(subId);
136 
137         final int[] subList = convertArrayListToIntArray(mTestSubList);
138         when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList);
139         when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
140         mMonitor.onSubscriptionsChanged();
141     }
142 
updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId)143     private void updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId) {
144         when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
145         mMonitor.onSubscriptionsChanged();
146     }
147 
removeTestSub(int subId)148     private void removeTestSub(int subId) {
149         // Remove subId from TestSubList.
150         mTestSubList.removeIf(it -> it == subId);
151         final int[] subList = convertArrayListToIntArray(mTestSubList);
152         when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList);
153         mMonitor.onSubscriptionsChanged();
154     }
155 
assertRatTypeChangedForSub(String subscriberId, int ratType)156     private void assertRatTypeChangedForSub(String subscriberId, int ratType) {
157         assertEquals(ratType, mMonitor.getRatTypeForSubscriberId(subscriberId));
158         final ArgumentCaptor<Integer> typeCaptor = ArgumentCaptor.forClass(Integer.class);
159         // Verify callback with the subscriberId and the RAT type should be as expected.
160         // It will fail if get a callback with an unexpected RAT type.
161         verify(mDelegate).onCollapsedRatTypeChanged(eq(subscriberId), typeCaptor.capture());
162         final int type = typeCaptor.getValue();
163         assertEquals(ratType, type);
164     }
165 
assertRatTypeNotChangedForSub(String subscriberId, int ratType)166     private void assertRatTypeNotChangedForSub(String subscriberId, int ratType) {
167         assertEquals(mMonitor.getRatTypeForSubscriberId(subscriberId), ratType);
168         // Should never get callback with any RAT type.
169         verify(mDelegate, never()).onCollapsedRatTypeChanged(eq(subscriberId), anyInt());
170     }
171 
172     @Test
testSubChangedAndRatTypeChanged()173     public void testSubChangedAndRatTypeChanged() {
174         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
175                 ArgumentCaptor.forClass(RatTypeListener.class);
176 
177         mMonitor.start();
178         // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
179         // before changing RAT type.
180         addTestSub(TEST_SUBID1, TEST_IMSI1);
181         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
182 
183         // Insert sim2.
184         addTestSub(TEST_SUBID2, TEST_IMSI2);
185         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
186         verify(mTelephonyManager, times(2)).listen(ratTypeListenerCaptor.capture(),
187                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
188         reset(mDelegate);
189 
190         // Set RAT type of sim1 to UMTS.
191         // Verify RAT type of sim1 after subscription gets onCollapsedRatTypeChanged() callback
192         // and others remain untouched.
193         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
194                 TelephonyManager.NETWORK_TYPE_UMTS);
195         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
196         assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
197         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
198         reset(mDelegate);
199 
200         // Set RAT type of sim2 to LTE.
201         // Verify RAT type of sim2 after subscription gets onCollapsedRatTypeChanged() callback
202         // and others remain untouched.
203         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID2,
204                 TelephonyManager.NETWORK_TYPE_LTE);
205         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
206         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_LTE);
207         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
208         reset(mDelegate);
209 
210         // Remove sim2 and verify that callbacks are fired and RAT type is correct for sim2.
211         // while the other two remain untouched.
212         removeTestSub(TEST_SUBID2);
213         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
214         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
215         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
216         assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN);
217         reset(mDelegate);
218 
219         // Set RAT type of sim1 to UNKNOWN. Then stop monitoring subscription changes
220         // and verify that the listener for sim1 is removed.
221         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
222                 TelephonyManager.NETWORK_TYPE_UNKNOWN);
223         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
224         reset(mDelegate);
225 
226         mMonitor.stop();
227         verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
228         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
229     }
230 
231 
232     @Test
test5g()233     public void test5g() {
234         mMonitor.start();
235         // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
236         // before changing RAT type. Also capture listener for later use.
237         addTestSub(TEST_SUBID1, TEST_IMSI1);
238         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
239         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
240                 ArgumentCaptor.forClass(RatTypeListener.class);
241         verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
242                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
243         final RatTypeListener listener = CollectionUtils
244                 .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1);
245         assertNotNull(listener);
246 
247         // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs
248         // NETWORK_TYPE_5G_NSA.
249         final ServiceState serviceState = mock(ServiceState.class);
250         when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE);
251         when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED);
252         listener.onServiceStateChanged(serviceState);
253         assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA);
254         reset(mDelegate);
255 
256         // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE.
257         when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE);
258         listener.onServiceStateChanged(serviceState);
259         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
260         reset(mDelegate);
261 
262         // Verify NR connected with other RAT type does not take effect.
263         when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS);
264         when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED);
265         listener.onServiceStateChanged(serviceState);
266         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
267         reset(mDelegate);
268 
269         // Set RAT type to 5G standalone mode, the RAT type should be NR.
270         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
271                 TelephonyManager.NETWORK_TYPE_NR);
272         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
273         reset(mDelegate);
274 
275         // Set NR state to none in standalone mode does not change anything.
276         when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR);
277         when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE);
278         listener.onServiceStateChanged(serviceState);
279         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
280     }
281 
282     @Test
testSubscriberIdUnavailable()283     public void testSubscriberIdUnavailable() {
284         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
285                 ArgumentCaptor.forClass(RatTypeListener.class);
286 
287         mMonitor.start();
288         // Insert sim1, set subscriberId to null which is normal in SIM PIN locked case.
289         // Verify RAT type is NETWORK_TYPE_UNKNOWN and service will not perform listener
290         // registration.
291         addTestSub(TEST_SUBID1, null);
292         verify(mTelephonyManager, never()).listen(any(), anyInt());
293         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
294 
295         // Set IMSI for sim1, verify the listener will be registered.
296         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
297         verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
298                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
299         reset(mTelephonyManager);
300         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
301 
302         // Set RAT type of sim1 to UMTS. Verify RAT type of sim1 is changed.
303         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
304                 TelephonyManager.NETWORK_TYPE_UMTS);
305         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
306         reset(mDelegate);
307 
308         // Set IMSI to null again to simulate somehow IMSI is not available, such as
309         // modem crash. Verify service should unregister listener.
310         updateSubscriberIdForTestSub(TEST_SUBID1, null);
311         verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
312                 eq(PhoneStateListener.LISTEN_NONE));
313         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
314         reset(mDelegate);
315         clearInvocations(mTelephonyManager);
316 
317         // Simulate somehow IMSI is back. Verify service will register with
318         // another listener and fire callback accordingly.
319         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
320                 ArgumentCaptor.forClass(RatTypeListener.class);
321         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
322         verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
323                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
324         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
325         reset(mDelegate);
326         clearInvocations(mTelephonyManager);
327 
328         // Set RAT type of sim1 to LTE. Verify RAT type of sim1 still works.
329         setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
330                 TelephonyManager.NETWORK_TYPE_LTE);
331         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
332         reset(mDelegate);
333 
334         mMonitor.stop();
335         verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor2.getValue()),
336                 eq(PhoneStateListener.LISTEN_NONE));
337         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
338     }
339 
340     /**
341      * Verify that when IMSI suddenly changed for a given subId, the service will register a new
342      * listener and unregister the old one, and report changes on updated IMSI. This is for modem
343      * feature that may be enabled for certain carrier, which changes to use a different IMSI while
344      * roaming on certain networks for multi-IMSI SIM cards, but the subId stays the same.
345      */
346     @Test
testSubscriberIdChanged()347     public void testSubscriberIdChanged() {
348         mMonitor.start();
349         // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback
350         // before changing RAT type.
351         addTestSub(TEST_SUBID1, TEST_IMSI1);
352         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
353                 ArgumentCaptor.forClass(RatTypeListener.class);
354         verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
355                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
356         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
357 
358         // Set RAT type of sim1 to UMTS.
359         // Verify RAT type of sim1 changes accordingly.
360         setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
361                 TelephonyManager.NETWORK_TYPE_UMTS);
362         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
363         reset(mDelegate);
364         clearInvocations(mTelephonyManager);
365 
366         // Simulate IMSI of sim1 changed to IMSI2. Verify the service will register with
367         // another listener and remove the old one. The RAT type of new IMSI stays at
368         // NETWORK_TYPE_UNKNOWN until received initial callback from telephony.
369         final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor2 =
370                 ArgumentCaptor.forClass(RatTypeListener.class);
371         updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI2);
372         verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor2.capture(),
373                 eq(PhoneStateListener.LISTEN_SERVICE_STATE));
374         verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
375                 eq(PhoneStateListener.LISTEN_NONE));
376         assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
377         assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN);
378         reset(mDelegate);
379 
380         // Set RAT type of sim1 to UMTS for new listener to simulate the initial callback received
381         // from telephony after registration. Verify RAT type of sim1 changes with IMSI2
382         // accordingly.
383         setRatTypeForSub(ratTypeListenerCaptor2.getAllValues(), TEST_SUBID1,
384                 TelephonyManager.NETWORK_TYPE_UMTS);
385         assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
386         assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UMTS);
387         reset(mDelegate);
388     }
389 }
390