• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1   /*
2  * Copyright (C) 2019 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 package com.android.ons;
17 
18 import static org.junit.Assert.assertThrows;
19 import static org.mockito.Mockito.any;
20 import static org.mockito.Mockito.doReturn;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.when;
25 
26 import android.compat.testing.PlatformCompatChangeRule;
27 import android.content.BroadcastReceiver;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.os.Build;
32 import android.os.Looper;
33 import android.os.RemoteException;
34 import android.os.UserManager;
35 import android.platform.test.flag.junit.SetFlagsRule;
36 import android.telephony.AvailableNetworkInfo;
37 import android.telephony.CarrierConfigManager;
38 import android.telephony.SubscriptionInfo;
39 import android.telephony.SubscriptionManager;
40 import android.telephony.TelephonyFrameworkInitializer;
41 import android.telephony.TelephonyManager;
42 import android.util.Log;
43 
44 import androidx.test.runner.AndroidJUnit4;
45 
46 import com.android.internal.telephony.IOns;
47 import com.android.internal.telephony.ISetOpportunisticDataCallback;
48 import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
49 
50 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
51 
52 import org.junit.After;
53 import org.junit.Before;
54 import org.junit.Rule;
55 import org.junit.Test;
56 import org.junit.rules.TestRule;
57 import org.junit.runner.RunWith;
58 import org.mockito.ArgumentCaptor;
59 import org.mockito.Mock;
60 
61 import java.lang.reflect.Field;
62 import java.util.ArrayList;
63 import java.util.HashMap;
64 import java.util.List;
65 
66 @RunWith(AndroidJUnit4.class)
67 public class OpportunisticNetworkServiceTest extends ONSBaseTest {
68     // SetFlagsRule will be used for Telephony feature flag
69     @Rule
70     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
71     @Rule
72     public TestRule compatChangeRule = new PlatformCompatChangeRule();
73 
74     private static final String TAG = "ONSTest";
75     private String pkgForDebug;
76     private String pkgForFeature;
77     private int mResult;
78     private IOns iOpportunisticNetworkService;
79     private Looper mLooper;
80     private OpportunisticNetworkService mOpportunisticNetworkService;
81     private static final String CARRIER_APP_CONFIG_NAME = "carrierApp";
82     private static final String SYSTEM_APP_CONFIG_NAME = "systemApp";
83 
84     @Mock
85     private HashMap<String, ONSConfigInput> mockONSConfigInputHashMap;
86     @Mock
87     private ONSProfileSelector mockProfileSelector;
88     @Mock
89     private CarrierConfigManager mCarrierConfigManager;
90     @Mock
91     private ONSProfileActivator mONSProfileActivator;
92     @Mock
93     private UserManager mUserManager;
94     @Mock
95     private Context mMockContext;
96     @Mock
97     private PackageManager mPackageManager;
98 
99     @Before
setUp()100     public void setUp() throws Exception {
101         super.setUp("ONSTest");
102         pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
103         pkgForFeature = mContext != null ? mContext.getAttributionTag() : null;
104         Intent intent = new Intent(mContext, OpportunisticNetworkService.class);
105         new Thread(new Runnable() {
106             @Override
107             public void run() {
108                 Looper.prepare();
109                 mOpportunisticNetworkService = new OpportunisticNetworkService();
110                 mOpportunisticNetworkService.initialize(mContext);
111                 mOpportunisticNetworkService.mSubscriptionManager = mSubscriptionManager;
112                 mOpportunisticNetworkService.mPackageManager = mPackageManager;
113                 for (int retry = 2; retry > 0; retry--) {
114 
115                     iOpportunisticNetworkService = (IOns) mOpportunisticNetworkService.onBind(null);
116 
117                     if (iOpportunisticNetworkService != null) {
118                         break;
119                     }
120 
121                     try {
122                         Thread.sleep(100);
123                     } catch (Exception e) {
124                         Log.e(TAG, e.toString());
125                     }
126                 }
127                 mLooper = Looper.myLooper();
128                 setReady(true);
129                 Looper.loop();
130             }
131         }).start();
132         waitUntilReady(300);
133 
134         // In order not to affect the existing implementation, define a telephony feature
135         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA))
136                 .thenReturn(true);
137         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS))
138                 .thenReturn(true);
139     }
140 
141     @After
tearDown()142     public void tearDown() throws Exception {
143         super.tearDown();
144         mOpportunisticNetworkService.onDestroy();
145         if (mLooper != null) {
146             mLooper.quit();
147             mLooper.getThread().join();
148         }
149     }
150 
151     @Test
testCheckEnable()152     public void testCheckEnable() {
153         boolean isEnable = true;
154         try {
155             iOpportunisticNetworkService.setEnable(false, pkgForDebug);
156             isEnable = iOpportunisticNetworkService.isEnabled(pkgForDebug);
157         } catch (RemoteException ex) {
158             Log.e(TAG, "RemoteException", ex);
159         }
160         assertEquals(false, isEnable);
161     }
162 
163     @Test
testHandleSimStateChange()164     public void testHandleSimStateChange() {
165         mResult = -1;
166         ArrayList<String> mccMncs = new ArrayList<>();
167         mccMncs.add("310210");
168         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
169                 new ArrayList<Integer>());
170         List<AvailableNetworkInfo> availableNetworkInfos =
171                 new ArrayList<AvailableNetworkInfo>();
172         availableNetworkInfos.add(availableNetworkInfo);
173         IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
174             @Override
175             public void onComplete(int result) {
176                 mResult = result;
177                 Log.d(TAG, "result: " + result);
178             }
179         };
180         ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback,
181                 availableNetworkInfos.get(0).getSubId(), 1);
182         List<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>();
183 
184         // Case 1: There is no Carrier app using ONS.
185         doReturn(null).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
186         mOpportunisticNetworkService.mIsEnabled = true;
187         mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
188         mOpportunisticNetworkService.handleSimStateChange();
189         waitForMs(500);
190         verify(mockONSConfigInputHashMap, never()).get(SYSTEM_APP_CONFIG_NAME);
191 
192         // Case 2: There is a Carrier app using ONS and no System app input.
193         doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false);
194         doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
195         doReturn(null).when(mockONSConfigInputHashMap).get(SYSTEM_APP_CONFIG_NAME);
196         mOpportunisticNetworkService.mIsEnabled = true;
197         mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
198         mOpportunisticNetworkService.handleSimStateChange();
199         waitForMs(50);
200         verify(mockONSConfigInputHashMap,times(1)).get(SYSTEM_APP_CONFIG_NAME);
201     }
202 
203     @Test
testSystemPreferredDataWhileCarrierAppIsActive()204     public void testSystemPreferredDataWhileCarrierAppIsActive() {
205         mResult = -1;
206         ArrayList<String> mccMncs = new ArrayList<>();
207         mccMncs.add("310210");
208         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
209             new ArrayList<Integer>());
210         List<AvailableNetworkInfo> availableNetworkInfos =
211             new ArrayList<AvailableNetworkInfo>();
212         availableNetworkInfos.add(availableNetworkInfo);
213         IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
214             @Override
215             public void onComplete(int result) {
216                 mResult = result;
217                 Log.d(TAG, "result: " + result);
218             }
219         };
220         ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback,
221                 availableNetworkInfos.get(0).getSubId(), 1);
222         List<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>();
223 
224         doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false);
225         doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
226         mOpportunisticNetworkService.mIsEnabled = true;
227         mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
228 
229         mResult = -1;
230         ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
231             @Override
232             public void onComplete(int result) {
233                 Log.d(TAG, "callbackStub, mResult end:" + result);
234                 mResult = result;
235             }
236         };
237 
238         try {
239             IOns onsBinder = (IOns)mOpportunisticNetworkService.onBind(null);
240             onsBinder.setPreferredDataSubscriptionId(
241                     SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, callbackStub,
242                     pkgForDebug);
243         } catch (RemoteException ex) {
244             Log.e(TAG, "RemoteException", ex);
245         }
246         waitForMs(50);
247         assertEquals(TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED, mResult);
248     }
249 
250     @Test
testSetPreferredDataSubscriptionId()251     public void testSetPreferredDataSubscriptionId() {
252         mResult = -1;
253         ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
254             @Override
255             public void onComplete(int result) {
256                 Log.d(TAG, "callbackStub, mResult end:" + result);
257                 mResult = result;
258             }
259         };
260 
261         try {
262             assertNotNull(iOpportunisticNetworkService);
263             iOpportunisticNetworkService.setPreferredDataSubscriptionId(5, false, callbackStub,
264                     pkgForDebug);
265         } catch (RemoteException ex) {
266             Log.e(TAG, "RemoteException", ex);
267         }
268         assertEquals(
269                 TelephonyManager.SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE, mResult);
270     }
271 
272     @Test
testGetPreferredDataSubscriptionId()273     public void testGetPreferredDataSubscriptionId() {
274         assertNotNull(iOpportunisticNetworkService);
275         mResult = -1;
276         try {
277             mResult = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug,
278                     pkgForFeature);
279             Log.d(TAG, "testGetPreferredDataSubscriptionId: " + mResult);
280         } catch (RemoteException ex) {
281             Log.e(TAG, "RemoteException", ex);
282         }
283     }
284 
285     @Test
testUpdateAvailableNetworksWithInvalidArguments()286     public void testUpdateAvailableNetworksWithInvalidArguments() {
287         mResult = -1;
288         IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
289             @Override
290             public void onComplete(int result) {
291                 Log.d(TAG, "mResult end:" + result);
292                 mResult = result;
293             }
294         };
295 
296         ArrayList<String> mccMncs = new ArrayList<>();
297         mccMncs.add("310210");
298         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
299                 new ArrayList<Integer>());
300         List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>();
301         availableNetworkInfos.add(availableNetworkInfo);
302 
303         try {
304             iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, mCallback,
305                     pkgForDebug);
306         } catch (RemoteException ex) {
307             Log.e(TAG, "RemoteException", ex);
308         }
309         assertEquals(
310                 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE, mResult);
311     }
312 
313     @Test
testUpdateAvailableNetworksWithSuccess()314     public void testUpdateAvailableNetworksWithSuccess() {
315         mResult = -1;
316         IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
317             @Override
318             public void onComplete(int result) {
319                 Log.d(TAG, "mResult end:" + result);
320                 mResult = result;
321             }
322         };
323         List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>();
324         try {
325             iOpportunisticNetworkService.setEnable(false, pkgForDebug);
326             iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, mCallback,
327                     pkgForDebug);
328         } catch (RemoteException ex) {
329             Log.e(TAG, "RemoteException", ex);
330         }
331         assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS, mResult);
332     }
333 
334     @Test
testPriorityRuleOfActivatingAvailableNetworks()335     public void testPriorityRuleOfActivatingAvailableNetworks() {
336         ArrayList<String> mccMncs = new ArrayList<>();
337         mccMncs.add("310210");
338         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
339                 new ArrayList<Integer>());
340         List<AvailableNetworkInfo> availableNetworkInfos =
341                 new ArrayList<AvailableNetworkInfo>();
342         availableNetworkInfos.add(availableNetworkInfo);
343         mResult = -1;
344         IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
345             @Override
346             public void onComplete(int result) {
347                 mResult = result;
348                 Log.d(TAG, "result: " + result);
349             }
350         };
351         ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback,
352                 availableNetworkInfos.get(0).getSubId(), 1);
353         doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
354         doReturn(true).when(mockProfileSelector).hasOpportunisticSub(any());
355         doReturn(false).when(mockProfileSelector).containStandaloneOppSubs(any());
356         mOpportunisticNetworkService.mIsEnabled = true;
357         mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
358         mOpportunisticNetworkService.mProfileSelector = mockProfileSelector;
359 
360         // Assume carrier app has updated available networks at first.
361         // Then system app updated available networks which is not standalone.
362         try {
363             IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null);
364             onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug);
365         } catch (RemoteException ex) {
366             Log.e(TAG, "RemoteException", ex);
367         }
368         verify(mockProfileSelector, never()).startProfileSelection(any(), any());
369 
370         // System app updated available networks which contain standalone network.
371         doReturn(true).when(mockProfileSelector).containStandaloneOppSubs(any());
372         try {
373             IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null);
374             onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug);
375         } catch (RemoteException ex) {
376             Log.e(TAG, "RemoteException", ex);
377         }
378         verify(mockProfileSelector, times(1)).startProfileSelection(any(), any());
379 
380         // System app updated available networks which equal to null.
381         // Case1: start carrier app request, if there is a carrier app request.
382         availableNetworkInfos.clear();
383         try {
384             IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null);
385             onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug);
386         } catch (RemoteException ex) {
387             Log.e(TAG, "RemoteException", ex);
388         }
389         verify(mockProfileSelector, times(2)).startProfileSelection(any(), any());
390 
391         // System app updated available networks which equal to null.
392         // Case2: stop profile selection, if there is no any carrier app request.
393         doReturn(null).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
394         try {
395             IOns onsBinder = (IOns) mOpportunisticNetworkService.onBind(null);
396             onsBinder.updateAvailableNetworks(availableNetworkInfos, mCallback, pkgForDebug);
397         } catch (RemoteException ex) {
398             Log.e(TAG, "RemoteException", ex);
399         }
400         verify(mockProfileSelector, times(1)).stopProfileSelection(any());
401     }
402 
403     @Test
testCarrierConfigChangedUnlocked()404     public void testCarrierConfigChangedUnlocked() {
405         mOpportunisticNetworkService.mUserManager = mUserManager;
406         mOpportunisticNetworkService.mONSProfileActivator = mONSProfileActivator;
407         mOpportunisticNetworkService.mCarrierConfigManager = mCarrierConfigManager;
408         mOpportunisticNetworkService.registerCarrierConfigChangListener();
409         mOpportunisticNetworkService.mContext = mMockContext;
410 
411         CarrierConfigManager.CarrierConfigChangeListener CarrierConfigChangeListener;
412 
413         final ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerCaptor =
414                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
415 
416         verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
417                 listenerCaptor.capture());
418         CarrierConfigChangeListener = listenerCaptor.getAllValues().get(0);
419 
420         // CarrierConfigChange in lock state
421         when(mUserManager.isUserUnlocked()).thenReturn(false);
422         CarrierConfigChangeListener.onCarrierConfigChanged(0, 0, 0, 0);
423         verify(mONSProfileActivator, never()).handleCarrierConfigChange();
424 
425         // handle CarrierConfigChange when state is changed from lock to unlock
426         final ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
427                 ArgumentCaptor.forClass(BroadcastReceiver.class);
428 
429         verify(mMockContext).registerReceiver(broadcastReceiverCaptor.capture(), any());
430         broadcastReceiverCaptor.getValue().onReceive(mMockContext,
431                 new Intent(Intent.ACTION_USER_UNLOCKED));
432         verify(mONSProfileActivator, times(1)).handleCarrierConfigChange();
433 
434         // CarrierConfigChange in Unlock state
435         when(mUserManager.isUserUnlocked()).thenReturn(true);
436         CarrierConfigChangeListener.onCarrierConfigChanged(0, 0, 0, 0);
437         verify(mONSProfileActivator, times(2)).handleCarrierConfigChange();
438     }
439 
440     @Test
441     @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
testTelephonyFeatureAndCompatChanges()442     public void testTelephonyFeatureAndCompatChanges() throws Exception {
443         ArrayList<String> mccMncs = new ArrayList<>();
444         mccMncs.add("310210");
445         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
446                 new ArrayList<Integer>());
447         List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<>();
448         availableNetworkInfos.add(availableNetworkInfo);
449 
450         // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
451         try {
452             // FEATURE_TELEPHONY_DATA
453             iOpportunisticNetworkService.setPreferredDataSubscriptionId(
454                     SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null, pkgForDebug);
455             iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug, pkgForFeature);
456 
457             // FEATURE_TELEPHONY_RADIO_ACCESS
458             iOpportunisticNetworkService.setEnable(false, pkgForDebug);
459             iOpportunisticNetworkService.isEnabled(pkgForDebug);
460             iOpportunisticNetworkService.updateAvailableNetworks(availableNetworkInfos, null,
461                     pkgForDebug);
462         } catch (Exception e) {
463             fail("Not expect exception " + e.getMessage());
464         }
465 
466         // Replace field to set SDK version of vendor partition to Android V
467         int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM;
468         replaceInstance(OpportunisticNetworkService.class, "mVendorApiLevel",
469                 mOpportunisticNetworkService, vendorApiLevel);
470 
471         // FEATURE_TELEPHONY_DATA is not defined, expect UnsupportedOperationException.
472         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA))
473                 .thenReturn(false);
474 
475         assertThrows(UnsupportedOperationException.class,
476                 () -> iOpportunisticNetworkService.setPreferredDataSubscriptionId(
477                         SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null, pkgForDebug));
478         assertThrows(UnsupportedOperationException.class,
479                 () -> iOpportunisticNetworkService.getPreferredDataSubscriptionId(
480                         pkgForDebug, pkgForFeature));
481 
482         // FEATURE_TELEPHONY_DATA is not defined, expect UnsupportedOperationException.
483         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS))
484                 .thenReturn(false);
485         assertThrows(UnsupportedOperationException.class,
486                 () -> iOpportunisticNetworkService.setEnable(false, pkgForDebug));
487         assertThrows(UnsupportedOperationException.class,
488                 () -> iOpportunisticNetworkService.isEnabled(pkgForDebug));
489         assertThrows(UnsupportedOperationException.class,
490                 () -> iOpportunisticNetworkService.updateAvailableNetworks(
491                         availableNetworkInfos, null, pkgForDebug));
492     }
493 
replaceInstance(final Class c, final String instanceName, final Object obj, final Object newValue)494     private void replaceInstance(final Class c, final String instanceName, final Object obj,
495             final Object newValue) throws Exception {
496         Field field = c.getDeclaredField(instanceName);
497         field.setAccessible(true);
498         field.set(obj, newValue);
499     }
500 
getIOns()501     private IOns getIOns() {
502         return IOns.Stub.asInterface(
503                 TelephonyFrameworkInitializer
504                         .getTelephonyServiceManager()
505                         .getOpportunisticNetworkServiceRegisterer()
506                         .get());
507     }
508 
waitForMs(long ms)509     public static void waitForMs(long ms) {
510         try {
511             Thread.sleep(ms);
512         } catch (InterruptedException e) {
513             Log.d(TAG, "InterruptedException while waiting: " + e);
514         }
515     }
516 }
517