1 /*
2  * Copyright (C) 2006 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.internal.telephony;
18 
19 import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG;
20 import static android.telephony.TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED;
21 import static android.telephony.TelephonyManager.EXTRA_SIM_STATE;
22 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION;
23 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
24 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
25 import static android.telephony.TelephonyManager.SIM_STATE_LOADED;
26 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
27 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
29 
30 import static com.android.internal.telephony.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS;
31 import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED;
32 import static com.android.internal.telephony.PhoneSwitcher.EVENT_IMS_RADIO_TECH_CHANGED;
33 import static com.android.internal.telephony.PhoneSwitcher.EVENT_MULTI_SIM_CONFIG_CHANGED;
34 import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED;
35 
36 import static org.junit.Assert.assertEquals;
37 import static org.junit.Assert.assertFalse;
38 import static org.junit.Assert.assertNotNull;
39 import static org.junit.Assert.assertTrue;
40 import static org.mockito.ArgumentMatchers.any;
41 import static org.mockito.ArgumentMatchers.anyBoolean;
42 import static org.mockito.ArgumentMatchers.anyInt;
43 import static org.mockito.ArgumentMatchers.anyLong;
44 import static org.mockito.Matchers.eq;
45 import static org.mockito.Mockito.clearInvocations;
46 import static org.mockito.Mockito.doAnswer;
47 import static org.mockito.Mockito.doReturn;
48 import static org.mockito.Mockito.never;
49 import static org.mockito.Mockito.times;
50 import static org.mockito.Mockito.verify;
51 
52 import android.content.Context;
53 import android.content.Intent;
54 import android.net.ConnectivityManager;
55 import android.net.NetworkCapabilities;
56 import android.net.NetworkProvider;
57 import android.net.NetworkRequest;
58 import android.net.TelephonyNetworkSpecifier;
59 import android.os.AsyncResult;
60 import android.os.Handler;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.os.Messenger;
64 import android.telephony.PhoneCapability;
65 import android.telephony.SubscriptionInfo;
66 import android.telephony.SubscriptionManager;
67 import android.telephony.data.ApnSetting;
68 import android.test.suitebuilder.annotation.SmallTest;
69 import android.testing.AndroidTestingRunner;
70 import android.testing.TestableLooper;
71 
72 import com.android.internal.telephony.dataconnection.DataEnabledSettings;
73 
74 import org.junit.After;
75 import org.junit.Before;
76 import org.junit.Test;
77 import org.junit.runner.RunWith;
78 import org.mockito.ArgumentCaptor;
79 import org.mockito.Mock;
80 
81 import java.util.concurrent.CompletableFuture;
82 import java.util.concurrent.LinkedBlockingQueue;
83 
84 @RunWith(AndroidTestingRunner.class)
85 @TestableLooper.RunWithLooper
86 public class PhoneSwitcherTest extends TelephonyTest {
87     private static final int ACTIVE_PHONE_SWITCH = 1;
88     private static final int EVENT_RADIO_ON = 108;
89     private static final int EVENT_MODEM_COMMAND_DONE = 112;
90 
91     @Mock
92     private CommandsInterface mCommandsInterface0;
93     @Mock
94     private CommandsInterface mCommandsInterface1;
95     @Mock
96     private Phone mPhone2; // mPhone as phone 1 is already defined in TelephonyTest.
97     @Mock
98     private Phone mImsPhone;
99     @Mock
100     private DataEnabledSettings mDataEnabledSettings2;
101     @Mock
102     private Handler mActivePhoneSwitchHandler;
103     @Mock
104     private GsmCdmaCall mActiveCall;
105     @Mock
106     private GsmCdmaCall mHoldingCall;
107     @Mock
108     private GsmCdmaCall mInactiveCall;
109     @Mock
110     private ISetOpportunisticDataCallback mSetOpptDataCallback1;
111     @Mock
112     private ISetOpportunisticDataCallback mSetOpptDataCallback2;
113     @Mock
114     CompletableFuture<Boolean> mFuturePhone;
115     @Mock
116     PhoneSwitcher.ImsRegTechProvider mMockImsRegTechProvider;
117     @Mock
118     private SubscriptionInfo mSubscriptionInfo;
119 
120     private PhoneSwitcher mPhoneSwitcher;
121     private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
122     private ConnectivityManager mConnectivityManager;
123     // The messenger of PhoneSwitcher used to receive network requests.
124     private Messenger mNetworkProviderMessenger = null;
125     private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
126     private int[][] mSlotIndexToSubId;
127     private boolean[] mDataAllowed;
128     private int mActiveModemCount = 2;
129     private int mSupportedModemCount = 2;
130     private int mMaxDataAttachModemCount = 1;
131 
132     @Before
setUp()133     public void setUp() throws Exception {
134         super.setUp(getClass().getSimpleName());
135 
136         PhoneCapability phoneCapability = new PhoneCapability(1, 1, null, false, new int[0]);
137         doReturn(phoneCapability).when(mPhoneConfigurationManager).getCurrentPhoneCapability();
138 
139         doReturn(Call.State.ACTIVE).when(mActiveCall).getState();
140         doReturn(Call.State.IDLE).when(mInactiveCall).getState();
141         doReturn(Call.State.HOLDING).when(mHoldingCall).getState();
142 
143         replaceInstance(Phone.class, "mCi", mPhone, mCommandsInterface0);
144         replaceInstance(Phone.class, "mCi", mPhone2, mCommandsInterface1);
145     }
146 
147     @After
tearDown()148     public void tearDown() throws Exception {
149         super.tearDown();
150     }
151 
152     /**
153      * Test that a single phone case results in our phone being active and the RIL called
154      */
155     @Test
156     @SmallTest
testRegister()157     public void testRegister() throws Exception {
158         initialize();
159 
160         // verify nothing has been done while there are no inputs
161         assertFalse("data allowed initially", mDataAllowed[0]);
162         assertFalse("data allowed initially", mDataAllowed[1]);
163 
164         NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
165 
166         assertFalse("phone active after request", mPhoneSwitcher
167                 .shouldApplyNetworkRequest(internetNetworkRequest, 0));
168 
169         // not registered yet - shouldn't inc
170         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
171 
172         mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
173                 ACTIVE_PHONE_SWITCH, null);
174 
175         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
176         clearInvocations(mActivePhoneSwitchHandler);
177 
178         setDefaultDataSubId(0);
179 
180         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
181 
182         setSlotIndexToSubId(0, 0);
183         mSubChangedListener.onSubscriptionsChanged();
184         processAllMessages();
185 
186         AsyncResult res = new AsyncResult(1, null,  null);
187         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
188         processAllMessages();
189         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
190         clearInvocations(mActivePhoneSwitchHandler);
191         assertTrue("data not allowed", mDataAllowed[0]);
192 
193         // now try various things that should cause the active phone to switch:
194         // 1 lose default via default sub change
195         // 2 gain default via default sub change
196         // 3 lose default via sub->phone change
197         // 4 gain default via sub->phone change
198         // 5 lose default network request
199         // 6 gain subscription-specific request
200         // 7 lose via sub->phone change
201         // 8 gain via sub->phone change
202         // 9 lose subscription-specific request
203         // 10 don't switch phones when in emergency mode
204 
205         // 1 lose default via default sub change
206         setDefaultDataSubId(1);
207 
208         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
209         processAllMessages();
210         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
211         clearInvocations(mActivePhoneSwitchHandler);
212         assertFalse("data allowed", mDataAllowed[0]);
213 
214         setSlotIndexToSubId(1, 1);
215         mSubChangedListener.onSubscriptionsChanged();
216         processAllMessages();
217 
218         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
219         processAllMessages();
220         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
221         clearInvocations(mActivePhoneSwitchHandler);
222         assertFalse("data allowed", mDataAllowed[0]);
223         assertTrue("data not allowed", mDataAllowed[1]);
224 
225         // 2 gain default via default sub change
226         setDefaultDataSubId(0);
227 
228         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
229         processAllMessages();
230         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
231         clearInvocations(mActivePhoneSwitchHandler);
232         assertFalse("data allowed", mDataAllowed[1]);
233         assertTrue("data not allowed", mDataAllowed[0]);
234 
235         // 3 lose default via sub->phone change
236         setSlotIndexToSubId(0, 2);
237         mSubChangedListener.onSubscriptionsChanged();
238         processAllMessages();
239         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
240         processAllMessages();
241 
242         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
243         clearInvocations(mActivePhoneSwitchHandler);
244         assertFalse("data allowed", mDataAllowed[0]);
245         assertFalse("data allowed", mDataAllowed[1]);
246 
247         // 4 gain default via sub->phone change
248         setSlotIndexToSubId(0, 0);
249         mSubChangedListener.onSubscriptionsChanged();
250         processAllMessages();
251 
252         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
253         processAllMessages();
254         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
255         clearInvocations(mActivePhoneSwitchHandler);
256         assertTrue("data not allowed", mDataAllowed[0]);
257         assertFalse("data allowed", mDataAllowed[1]);
258 
259         // 5 lose default network request
260         releaseNetworkRequest(internetNetworkRequest);
261 
262         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
263         processAllMessages();
264         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
265         clearInvocations(mActivePhoneSwitchHandler);
266         assertFalse("data allowed", mDataAllowed[0]);
267         assertFalse("data allowed", mDataAllowed[1]);
268 
269         // 6 gain subscription-specific request
270         NetworkRequest specificInternetRequest = addInternetNetworkRequest(0, 50);
271 
272         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
273         processAllMessages();
274         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
275         clearInvocations(mActivePhoneSwitchHandler);
276         assertTrue("data not allowed", mDataAllowed[0]);
277         assertFalse("data allowed", mDataAllowed[1]);
278 
279         // 7 lose via sub->phone change
280         setSlotIndexToSubId(0, 1);
281         mSubChangedListener.onSubscriptionsChanged();
282         processAllMessages();
283 
284         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
285         processAllMessages();
286         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
287         clearInvocations(mActivePhoneSwitchHandler);
288         assertFalse("data allowed", mDataAllowed[0]);
289         assertFalse("data allowed", mDataAllowed[1]);
290 
291         // 8 gain via sub->phone change
292         setSlotIndexToSubId(0, 0);
293         mSubChangedListener.onSubscriptionsChanged();
294         processAllMessages();
295 
296         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
297         processAllMessages();
298         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
299         clearInvocations(mActivePhoneSwitchHandler);
300         assertTrue("data not allowed", mDataAllowed[0]);
301         assertFalse("data allowed", mDataAllowed[1]);
302 
303         // 9 lose subscription-specific request
304         releaseNetworkRequest(specificInternetRequest);
305 
306         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
307         processAllMessages();
308         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
309         clearInvocations(mActivePhoneSwitchHandler);
310         assertFalse("data allowed", mDataAllowed[0]);
311         assertFalse("data allowed", mDataAllowed[1]);
312 
313         // 10 don't switch phones when in emergency mode
314         // not ready yet - Phone turns out to be hard to stub out
315 //        phones[0].setInEmergencyCall(true);
316 //        connectivityServiceMock.addDefaultRequest();
317 //        processAllMessages();
318 //        if (testHandler.getActivePhoneSwitchCount() != 11) {
319 //            fail("after release of request, ActivePhoneSwitchCount not 11!");
320 //        }
321 //        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
322 //        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
323 //
324 //        phones[0].setInEmergencyCall(false);
325 //        connectivityServiceMock.addDefaultRequest();
326 //        processAllMessages();
327 //        if (testHandler.getActivePhoneSwitchCount() != 12) {
328 //            fail("after release of request, ActivePhoneSwitchCount not 11!");
329 //        }
330 //        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
331 //        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
332     }
333 
334     /**
335      * Test a multi-sim case with limited active phones:
336      * - lose default via default sub change
337      * - lose default via sub->phone change
338      * - gain default via sub->phone change
339      * - gain default via default sub change
340      * - lose default network request
341      * - gain subscription-specific request
342      * - lose via sub->phone change
343      * - gain via sub->phone change
344      * - lose subscription-specific request
345      * - tear down low priority phone when new request comes in
346      * - tear down low priority phone when sub change causes split
347      * - bring up low priority phone when sub change causes join
348      * - don't switch phones when in emergency mode
349      */
350     @Test
351     @SmallTest
testPrioritization()352     public void testPrioritization() throws Exception {
353         initialize();
354 
355         addInternetNetworkRequest(null, 50);
356         setSlotIndexToSubId(0, 0);
357         setSlotIndexToSubId(1, 1);
358         setDefaultDataSubId(0);
359         mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
360                 ACTIVE_PHONE_SWITCH, null);
361         processAllMessages();
362         // verify initial conditions
363         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
364 
365         assertTrue("data not allowed", mDataAllowed[0]);
366         assertFalse("data allowed", mDataAllowed[1]);
367 
368         // now start a higher priority connection on the other sub
369         addMmsNetworkRequest(1);
370 
371         AsyncResult res = new AsyncResult(1, null,  null);
372         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
373         processAllMessages();
374 
375         // After gain of network request, mActivePhoneSwitchHandler should be notified 2 times.
376         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
377         assertFalse("data allowed", mDataAllowed[0]);
378         assertTrue("data not allowed", mDataAllowed[1]);
379     }
380 
381     /**
382      * Verify we don't send spurious DATA_ALLOWED calls when another NetworkProvider
383      * wins (ie, switch to wifi).
384      */
385     @Test
386     @SmallTest
testHigherPriorityDefault()387     public void testHigherPriorityDefault() throws Exception {
388         initialize();
389 
390         addInternetNetworkRequest(null, 50);
391 
392         setSlotIndexToSubId(0, 0);
393         setSlotIndexToSubId(1, 1);
394         setDefaultDataSubId(0);
395 
396         // Phone 0 should be active
397         assertTrue("data not allowed", mDataAllowed[0]);
398         assertFalse("data allowed", mDataAllowed[1]);
399 
400         addInternetNetworkRequest(null, 100);
401 
402         // should be no change
403         assertTrue("data not allowed", mDataAllowed[0]);
404         assertFalse("data allowed", mDataAllowed[1]);
405 
406         addInternetNetworkRequest(null, 0);
407         // should be no change
408         assertTrue("data not allowed", mDataAllowed[0]);
409         assertFalse("data allowed", mDataAllowed[1]);
410     }
411 
412     /**
413      * Verify testSetPreferredData.
414      * When preferredData is set, it overwrites defaultData sub to be active sub in single
415      * active phone mode. If it's unset (to DEFAULT_SUBSCRIPTION_ID), defaultData sub becomes
416      * active one.
417      */
418     @Test
419     @SmallTest
testSetPreferredData()420     public void testSetPreferredData() throws Exception {
421         initialize();
422 
423         // Phone 0 has sub 1, phone 1 has sub 2.
424         // Sub 1 is default data sub.
425         // Both are active subscriptions are active sub, as they are in both active slots.
426         setSlotIndexToSubId(0, 1);
427         setSlotIndexToSubId(1, 2);
428         setDefaultDataSubId(1);
429 
430         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
431 
432         // Notify phoneSwitcher about default data sub and default network request.
433         addInternetNetworkRequest(null, 50);
434         // Phone 0 (sub 1) should be activated as it has default data sub.
435         assertTrue(mDataAllowed[0]);
436 
437         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
438         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, null);
439         processAllMessages();
440         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
441         processAllMessages();
442         assertFalse(mDataAllowed[0]);
443         assertTrue(mDataAllowed[1]);
444 
445         // Unset preferred sub should make default data sub (phone 0 / sub 1) activated again.
446         mPhoneSwitcher.trySetOpportunisticDataSubscription(
447                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
448         processAllMessages();
449         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
450         processAllMessages();
451         assertTrue(mDataAllowed[0]);
452         assertFalse(mDataAllowed[1]);
453     }
454 
455     @Test
456     @SmallTest
testSetPreferredDataModemCommand()457     public void testSetPreferredDataModemCommand() throws Exception {
458         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
459         initialize();
460         mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
461                 ACTIVE_PHONE_SWITCH, null);
462         mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
463                 ACTIVE_PHONE_SWITCH, null);
464         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
465         clearInvocations(mMockRadioConfig);
466         clearInvocations(mActivePhoneSwitchHandler);
467 
468         // Phone 0 has sub 1, phone 1 has sub 2.
469         // Sub 1 is default data sub.
470         // Both are active subscriptions are active sub, as they are in both active slots.
471         setSlotIndexToSubId(0, 1);
472         setSlotIndexToSubId(1, 2);
473         setDefaultDataSubId(1);
474         // Phone 0 (sub 1) should be preferred data phone as it has default data sub.
475         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
476         AsyncResult res = new AsyncResult(1, null,  null);
477         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
478         processAllMessages();
479         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
480         clearInvocations(mMockRadioConfig);
481         clearInvocations(mActivePhoneSwitchHandler);
482 
483         // Notify phoneSwitcher about default data sub and default network request.
484         // It shouldn't change anything.
485         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
486         NetworkRequest mmsRequest = addMmsNetworkRequest(2);
487         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
488         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
489         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
490         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
491         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
492         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));
493 
494         // Set sub 2 as preferred sub should make phone 1 preferredDataModem
495         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
496         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, null);
497         processAllMessages();
498         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
499         processAllMessages();
500         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
501         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
502         processAllMessages();
503         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
504         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
505         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
506         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
507         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));
508 
509         clearInvocations(mMockRadioConfig);
510         clearInvocations(mActivePhoneSwitchHandler);
511 
512         // Unset preferred sub should make phone0 preferredDataModem again.
513         mPhoneSwitcher.trySetOpportunisticDataSubscription(
514                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
515         processAllMessages();
516         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
517         processAllMessages();
518 
519         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
520         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
521         processAllMessages();
522         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
523         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
524         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
525         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
526         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));
527 
528         // SetDataAllowed should never be triggered.
529         verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
530         verify(mCommandsInterface1, never()).setDataAllowed(anyBoolean(), any());
531 
532         // Set preferred data modem should be triggered after radio on or available.
533         clearInvocations(mMockRadioConfig);
534         Message.obtain(mPhoneSwitcher, EVENT_RADIO_ON, res).sendToTarget();
535         processAllMessages();
536         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
537     }
538 
539     @Test
540     @SmallTest
testSetPreferredDataWithValidation()541     public void testSetPreferredDataWithValidation() throws Exception {
542         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
543         initialize();
544 
545         // Mark sub 2 as opportunistic.
546         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
547         // Phone 0 has sub 1, phone 1 has sub 2.
548         // Sub 1 is default data sub.
549         // Both are active subscriptions are active sub, as they are in both active slots.
550         setSlotIndexToSubId(0, 1);
551         setSlotIndexToSubId(1, 2);
552         setDefaultDataSubId(1);
553 
554         // Phone 0 (sub 1) should be activated as it has default data sub.
555         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
556 
557         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
558         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, null);
559         processAllMessages();
560         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
561                 eq(mPhoneSwitcher.mValidationCallback));
562         // Validation failed. Preferred data sub should remain 1, data phone should remain 0.
563         mPhoneSwitcher.mValidationCallback.onValidationDone(false, 2);
564         processAllMessages();
565         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
566 
567         // Validation succeeds. Preferred data sub changes to 2, data phone changes to 1.
568         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, null);
569         processAllMessages();
570         mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
571         processAllMessages();
572         assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId());
573 
574         // Switching data back to primary (subId 1) with customized validation timeout.
575         long timeout = 1234;
576         mContextFixture.getCarrierConfigBundle().putLong(
577                 KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, timeout);
578         mPhoneSwitcher.trySetOpportunisticDataSubscription(
579                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, null);
580         processAllMessages();
581         verify(mCellularNetworkValidator).validate(eq(1), eq(timeout), eq(false),
582                 eq(mPhoneSwitcher.mValidationCallback));
583         mPhoneSwitcher.mValidationCallback.onValidationDone(true, 1);
584         processAllMessages();
585         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
586     }
587 
mockImsRegTech(int phoneId, int regTech)588     private void mockImsRegTech(int phoneId, int regTech) {
589         doReturn(regTech).when(mMockImsRegTechProvider).get(any(), eq(phoneId));
590         mPhoneSwitcher.mImsRegTechProvider = mMockImsRegTechProvider;
591     }
592 
593     @Test
594     @SmallTest
testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds()595     public void testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds() throws Exception {
596         initialize();
597         setAllPhonesInactive();
598 
599         // Phone 0 has sub 1, phone 1 has sub 2.
600         // Sub 1 is default data sub.
601         // Both are active subscriptions are active sub, as they are in both active slots.
602         setSlotIndexToSubId(0, 1);
603         setSlotIndexToSubId(1, 2);
604         setDefaultDataSubId(1);
605         processAllMessages();
606 
607         // Phone 0 should be the default data phoneId.
608         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
609 
610         // Phone2 has active IMS call on LTE. And data of DEFAULT apn is enabled. This should
611         // trigger data switch.
612         doReturn(mImsPhone).when(mPhone2).getImsPhone();
613         doReturn(true).when(mDataEnabledSettings2).isDataEnabled(ApnSetting.TYPE_DEFAULT);
614         mockImsRegTech(1, REGISTRATION_TECH_LTE);
615         notifyPhoneAsInCall(mImsPhone);
616 
617         // Phone 1 should become the default data phone.
618         assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId());
619     }
620 
621     @Test
622     @SmallTest
testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds()623     public void testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds() throws Exception {
624         initialize();
625         setAllPhonesInactive();
626 
627         // Phone 0 has sub 1, phone 1 has sub 2.
628         // Sub 1 is default data sub.
629         // Both are active subscriptions are active sub, as they are in both active slots.
630         setSlotIndexToSubId(0, 1);
631         setSlotIndexToSubId(1, 2);
632         setDefaultDataSubId(1);
633         processAllMessages();
634 
635         // Phone 0 should be the default data phoneId.
636         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
637 
638         // Phone2 has active call, but data is turned off. So no data switching should happen.
639         doReturn(mImsPhone).when(mPhone2).getImsPhone();
640         doReturn(true).when(mDataEnabledSettings2).isDataEnabled(ApnSetting.TYPE_DEFAULT);
641         mockImsRegTech(1, REGISTRATION_TECH_IWLAN);
642         notifyPhoneAsInCall(mImsPhone);
643 
644         // Phone 0 should remain the default data phone.
645         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
646     }
647 
648     @Test
649     @SmallTest
testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE()650     public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception {
651         initialize();
652         setAllPhonesInactive();
653 
654         // Phone 0 has sub 1, phone 1 has sub 2.
655         // Sub 1 is default data sub.
656         // Both are active subscriptions are active sub, as they are in both active slots.
657         setSlotIndexToSubId(0, 1);
658         setSlotIndexToSubId(1, 2);
659         setDefaultDataSubId(1);
660         processAllMessages();
661 
662         // Phone 0 should be the default data phoneId.
663         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
664 
665         // Phone 1 has active IMS call on CROSS_SIM. And data of DEFAULT apn is enabled. This should
666         // not trigger data switch.
667         doReturn(mImsPhone).when(mPhone2).getImsPhone();
668         doReturn(true).when(mDataEnabledSettings2).isDataEnabled(ApnSetting.TYPE_DEFAULT);
669         mockImsRegTech(1, REGISTRATION_TECH_CROSS_SIM);
670         notifyPhoneAsInCall(mImsPhone);
671 
672         // Phone 0 should remain the default data phone.
673         assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
674 
675         // Phone 1 has has handed over the call to LTE. And data of DEFAULT apn is enabled.
676         // This should trigger data switch.
677         mockImsRegTech(1, REGISTRATION_TECH_LTE);
678         notifyImsRegistrationTechChange(mPhone2);
679 
680         // Phone 1 should become the default data phone.
681         assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId());
682     }
683 
684     @Test
685     @SmallTest
testNonDefaultDataPhoneInCall()686     public void testNonDefaultDataPhoneInCall() throws Exception {
687         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
688         initialize();
689         // Phone 0 has sub 1, phone 1 has sub 2.
690         // Sub 1 is default data sub.
691         // Both are active subscriptions are active sub, as they are in both active slots.
692         setSlotIndexToSubId(0, 1);
693         setSlotIndexToSubId(1, 2);
694         setDefaultDataSubId(1);
695         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
696         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
697         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
698         clearInvocations(mMockRadioConfig);
699         setAllPhonesInactive();
700         // Initialization done.
701 
702         // Phone2 has active call, but data is turned off. So no data switching should happen.
703         notifyDataEnabled(false);
704         notifyPhoneAsInCall(mPhone2);
705         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
706         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
707         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
708 
709         // Phone2 has active call. So data switch to it.
710         notifyDataEnabled(true);
711         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
712         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
713         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
714         clearInvocations(mMockRadioConfig);
715 
716         // Phone2 call ended. So data switch back to default data sub.
717         notifyPhoneAsInactive(mPhone2);
718         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
719         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
720         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
721         clearInvocations(mMockRadioConfig);
722 
723         // Phone2 has holding call, but data is turned off. So no data switching should happen.
724         notifyPhoneAsInHoldingCall(mPhone2);
725         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
726         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
727         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
728     }
729 
730 
731     @Test
732     @SmallTest
testNetworkRequestOnNonDefaultData()733     public void testNetworkRequestOnNonDefaultData() throws Exception {
734         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
735         initialize();
736         // Phone 0 has sub 1, phone 1 has sub 2.
737         // Sub 1 is default data sub.
738         // Both are active subscriptions are active sub, as they are in both active slots.
739         setSlotIndexToSubId(0, 1);
740         setSlotIndexToSubId(1, 2);
741         setDefaultDataSubId(1);
742         NetworkRequest internetRequest = addInternetNetworkRequest(2, 50);
743         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
744         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
745 
746         // Restricted network request will should be applied.
747         internetRequest = addInternetNetworkRequest(2, 50, true);
748         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
749         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
750     }
751 
752     @Test
753     @SmallTest
testEmergencyOverrideSuccessBeforeCallStarts()754     public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
755         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
756         initialize();
757         // Phone 0 has sub 1, phone 1 has sub 2.
758         // Sub 1 is default data sub.
759         // Both are active subscriptions are active sub, as they are in both active slots.
760         setMsimDefaultDataSubId(1);
761         clearInvocations(mMockRadioConfig);
762 
763         // override the phone ID in prep for emergency call
764         mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
765         sendPreferredDataSuccessResult(1);
766         processAllMessages();
767         verify(mFuturePhone).complete(true);
768 
769         // Make sure the correct broadcast is sent out for the overridden phone ID
770         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
771     }
772 
773     @Test
774     @SmallTest
testEmergencyOverrideNoDdsChange()775     public void testEmergencyOverrideNoDdsChange() throws Exception {
776         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
777         initialize();
778         // Phone 0 has sub 1, phone 1 has sub 2.
779         // Sub 1 is default data sub.
780         // Both are active subscriptions are active sub, as they are in both active slots.
781         setMsimDefaultDataSubId(1);
782         clearInvocations(mMockRadioConfig);
783 
784         // override the phone ID in prep for emergency call
785         mPhoneSwitcher.overrideDefaultDataForEmergency(0, 1, mFuturePhone);
786         processAllMessages();
787         // The radio command should never be called because the DDS hasn't changed.
788         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
789         processAllMessages();
790         verify(mFuturePhone).complete(true);
791     }
792 
793     @Test
794     @SmallTest
testEmergencyOverrideEndSuccess()795     public void testEmergencyOverrideEndSuccess() throws Exception {
796         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
797         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
798         initialize();
799         // Phone 0 has sub 1, phone 1 has sub 2.
800         // Sub 1 is default data sub.
801         // Both are active subscriptions are active sub, as they are in both active slots.
802         setMsimDefaultDataSubId(1);
803         setAllPhonesInactive();
804         clearInvocations(mMockRadioConfig);
805         clearInvocations(mTelephonyRegistryManager);
806 
807         // override the phone ID in prep for emergency call
808 
809         mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
810         sendPreferredDataSuccessResult(1);
811         processAllMessages();
812         verify(mFuturePhone).complete(true);
813 
814         // Start and end the emergency call, which will start override timer
815         notifyPhoneAsInCall(mPhone2);
816         notifyPhoneAsInactive(mPhone2);
817 
818         clearInvocations(mTelephonyRegistryManager);
819         // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
820         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
821         processAllMessages();
822         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
823         AsyncResult res = new AsyncResult(1, null,  null);
824         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
825         processAllMessages();
826 
827         // Make sure the correct broadcast is sent out for the phone ID
828         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
829     }
830 
831     @Test
832     @SmallTest
testEmergencyOverrideEcbmStartEnd()833     public void testEmergencyOverrideEcbmStartEnd() throws Exception {
834         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
835         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
836         initialize();
837         // Phone 0 has sub 1, phone 1 has sub 2.
838         // Sub 1 is default data sub.
839         // Both are active subscriptions are active sub, as they are in both active slots.
840         setMsimDefaultDataSubId(1);
841         setAllPhonesInactive();
842         clearInvocations(mMockRadioConfig);
843         clearInvocations(mTelephonyRegistryManager);
844 
845         // override the phone ID in prep for emergency call
846         mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
847         sendPreferredDataSuccessResult(1);
848         processAllMessages();
849         verify(mFuturePhone).complete(true);
850 
851         // Start and end the emergency call, which will start override timer
852         notifyPhoneAsInCall(mPhone2);
853         notifyPhoneAsInactive(mPhone2);
854         // Start ECBM
855         Message ecbmMessage = getEcbmRegistration(mPhone2);
856         notifyEcbmStart(mPhone2, ecbmMessage);
857 
858         // DDS should not be switched back until ECBM ends, make sure there is no further
859         // interaction.
860         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 2000);
861         processAllMessages();
862         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
863         // Make sure the correct broadcast is sent out for the phone ID
864         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
865 
866         // End ECBM
867         clearInvocations(mTelephonyRegistryManager);
868         ecbmMessage = getEcbmRegistration(mPhone2);
869         notifyEcbmEnd(mPhone2, ecbmMessage);
870         // Verify that the DDS is successfully switched back after 1 second.
871         moveTimeForward(1000);
872         processAllMessages();
873         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
874         AsyncResult res = new AsyncResult(1, null,  null);
875         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
876         processAllMessages();
877         // Make sure the correct broadcast is sent out for the phone ID
878         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
879     }
880 
881     @Test
882     @SmallTest
testEmergencyOverrideNoCallStart()883     public void testEmergencyOverrideNoCallStart() throws Exception {
884         PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
885         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
886         initialize();
887         // Phone 0 has sub 1, phone 1 has sub 2.
888         // Sub 1 is default data sub.
889         // Both are active subscriptions are active sub, as they are in both active slots.
890         setMsimDefaultDataSubId(1);
891         setAllPhonesInactive();
892         clearInvocations(mMockRadioConfig);
893         clearInvocations(mTelephonyRegistryManager);
894 
895         // override the phone ID in prep for emergency call
896         mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
897         sendPreferredDataSuccessResult(1);
898         processAllMessages();
899         verify(mFuturePhone).complete(true);
900 
901         // Do not start the call and make sure the override is removed once the timeout expires
902         moveTimeForward(PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS);
903         processAllMessages();
904         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
905         AsyncResult res = new AsyncResult(1, null,  null);
906         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
907         processAllMessages();
908 
909         // Make sure the correct broadcast is sent out for the phone ID
910         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
911     }
912 
913     @Test
914     @SmallTest
testEmergencyOverrideMultipleOverrideRequests()915     public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
916         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
917         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
918         initialize();
919         // Phone 0 has sub 1, phone 1 has sub 2.
920         // Sub 1 is default data sub.
921         // Both are active subscriptions are active sub, as they are in both active slots.
922         setMsimDefaultDataSubId(1);
923         setAllPhonesInactive();
924         clearInvocations(mMockRadioConfig);
925         clearInvocations(mTelephonyRegistryManager);
926 
927         // override the phone ID in prep for emergency call
928         LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
929         CompletableFuture<Boolean> futurePhone = new CompletableFuture<>();
930         futurePhone.whenComplete((r, error) -> queue.offer(r));
931         mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, futurePhone);
932         sendPreferredDataSuccessResult(1);
933         processAllMessages();
934         Boolean result = queue.poll();
935         assertNotNull(result);
936         assertTrue(result);
937 
938         // try override the phone ID again while there is an existing override for a different phone
939         futurePhone = new CompletableFuture<>();
940         futurePhone.whenComplete((r, error) -> queue.offer(r));
941         mPhoneSwitcher.overrideDefaultDataForEmergency(0, 1, futurePhone);
942         processAllMessages();
943         result = queue.poll();
944         assertNotNull(result);
945         assertFalse(result);
946         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
947 
948         // Start and end the emergency call, which will start override timer
949         notifyPhoneAsInCall(mPhone2);
950         notifyPhoneAsInactive(mPhone2);
951 
952         // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
953         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
954         processAllMessages();
955         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
956         AsyncResult res = new AsyncResult(1, null,  null);
957         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
958         processAllMessages();
959 
960         // Make sure the correct broadcast is sent out for the phone ID
961         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
962     }
963 
964     @Test
965     @SmallTest
testSetPreferredDataCallback()966     public void testSetPreferredDataCallback() throws Exception {
967         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
968         initialize();
969 
970         // Mark sub 2 as opportunistic.
971         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
972         // Phone 0 has sub 1, phone 1 has sub 2.
973         // Sub 1 is default data sub.
974         // Both are active subscriptions are active sub, as they are in both active slots.
975         setSlotIndexToSubId(0, 1);
976         setSlotIndexToSubId(1, 2);
977         setDefaultDataSubId(1);
978 
979         // Validating on sub 10 which is inactive.
980         mPhoneSwitcher.trySetOpportunisticDataSubscription(10, true, mSetOpptDataCallback1);
981         processAllMessages();
982         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
983 
984         // Switch to active subId without validating. Should always succeed.
985         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
986         processAllMessages();
987         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
988         processAllMessages();
989         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
990 
991         // Validating on sub 1 and fails.
992         clearInvocations(mSetOpptDataCallback1);
993         mPhoneSwitcher.trySetOpportunisticDataSubscription(1, true, mSetOpptDataCallback1);
994         processAllMessages();
995         mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
996         processAllMessages();
997         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
998 
999         // Validating on sub 2 and succeeds.
1000         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
1001         processAllMessages();
1002         mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
1003         processAllMessages();
1004         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1005 
1006         // Switching data back to primary and validation fails.
1007         clearInvocations(mSetOpptDataCallback2);
1008         mPhoneSwitcher.trySetOpportunisticDataSubscription(
1009                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1010         processAllMessages();
1011         mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
1012         processAllMessages();
1013         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1014 
1015         // Switching data back to primary and succeeds.
1016         clearInvocations(mSetOpptDataCallback2);
1017         mPhoneSwitcher.trySetOpportunisticDataSubscription(
1018                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1019         processAllMessages();
1020         mPhoneSwitcher.mValidationCallback.onValidationDone(true, 1);
1021         processAllMessages();
1022         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1023 
1024         // Back to back call on same subId.
1025         clearInvocations(mSetOpptDataCallback1);
1026         clearInvocations(mSetOpptDataCallback2);
1027         clearInvocations(mCellularNetworkValidator);
1028         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
1029         processAllMessages();
1030         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1031                 eq(mPhoneSwitcher.mValidationCallback));
1032         doReturn(true).when(mCellularNetworkValidator).isValidating();
1033         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
1034         processAllMessages();
1035         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1036         verify(mSetOpptDataCallback2, never()).onComplete(anyInt());
1037         // Validation succeeds.
1038         doReturn(false).when(mCellularNetworkValidator).isValidating();
1039         mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
1040         processAllMessages();
1041         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1042 
1043         mPhoneSwitcher.trySetOpportunisticDataSubscription(
1044                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
1045         processAllMessages();
1046         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
1047         processAllMessages();
1048         clearInvocations(mSetOpptDataCallback1);
1049         clearInvocations(mSetOpptDataCallback2);
1050         clearInvocations(mCellularNetworkValidator);
1051         // Back to back call, call 1 to switch to subId 2, call 2 to switch back.
1052         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
1053         processAllMessages();
1054         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1055                 eq(mPhoneSwitcher.mValidationCallback));
1056         doReturn(true).when(mCellularNetworkValidator).isValidating();
1057         mPhoneSwitcher.trySetOpportunisticDataSubscription(
1058                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1059         processAllMessages();
1060         // Call 1 should be cancelled and failed. Call 2 return success immediately as there's no
1061         // change.
1062         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1063         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1064     }
1065 
1066     @Test
1067     @SmallTest
testMultiSimConfigChange()1068     public void testMultiSimConfigChange() throws Exception {
1069         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1070         mActiveModemCount = 1;
1071         initialize();
1072         sendPreferredDataSuccessResult(0);
1073 
1074         // Phone 0 has sub 1, phone 1 has sub 2.
1075         // Sub 1 is default data sub.
1076         // Both are active subscriptions are active sub, as they are in both active slots.
1077         setSlotIndexToSubId(0, 1);
1078         setDefaultDataSubId(1);
1079 
1080         setNumPhones(2, 2);
1081         AsyncResult result = new AsyncResult(null, 2, null);
1082         Message.obtain(mPhoneSwitcher, EVENT_MULTI_SIM_CONFIG_CHANGED, result).sendToTarget();
1083         processAllMessages();
1084 
1085         verify(mPhone2).registerForEmergencyCallToggle(any(), anyInt(), any());
1086         verify(mPhone2).registerForPreciseCallStateChanged(any(), anyInt(), any());
1087         verify(mDataEnabledSettings2).registerForDataEnabledChanged(any(), anyInt(), any());
1088 
1089         clearInvocations(mMockRadioConfig);
1090         setSlotIndexToSubId(1, 2);
1091         setDefaultDataSubId(2);
1092         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1093     }
1094 
1095     @Test
1096     @SmallTest
testValidationOffSwitch_shouldSwitchOnNetworkAvailable()1097     public void testValidationOffSwitch_shouldSwitchOnNetworkAvailable() throws Exception {
1098         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1099         initialize();
1100         // Phone 0 has sub 1, phone 1 has sub 2.
1101         // Sub 1 is default data sub.
1102         // Both are active subscriptions are active sub, as they are in both active slots.
1103         setSlotIndexToSubId(0, 1);
1104         setSlotIndexToSubId(1, 2);
1105         setDefaultDataSubId(1);
1106         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1107         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
1108         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
1109         clearInvocations(mMockRadioConfig);
1110         setAllPhonesInactive();
1111         // Initialization done.
1112 
1113         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
1114         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1115         processAllMessages();
1116         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1117                 eq(mPhoneSwitcher.mValidationCallback));
1118         doReturn(true).when(mCellularNetworkValidator).isValidating();
1119 
1120         // Network available on different sub. Should do nothing.
1121         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
1122         processAllMessages();
1123         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1124 
1125         // Network available on corresponding sub. Should confirm switch.
1126         mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
1127         processAllMessages();
1128         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1129     }
1130 
1131     @Test
1132     @SmallTest
testValidationOffSwitch_shouldSwitchOnTimeOut()1133     public void testValidationOffSwitch_shouldSwitchOnTimeOut() throws Exception {
1134         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1135         initialize();
1136         // Phone 0 has sub 1, phone 1 has sub 2.
1137         // Sub 1 is default data sub.
1138         // Both are active subscriptions are active sub, as they are in both active slots.
1139         setSlotIndexToSubId(0, 1);
1140         setSlotIndexToSubId(1, 2);
1141         setDefaultDataSubId(1);
1142         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1143         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
1144         assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
1145         clearInvocations(mMockRadioConfig);
1146         setAllPhonesInactive();
1147         // Initialization done.
1148 
1149         doReturn(true).when(mSubscriptionController).isOpportunistic(2);
1150         mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1151         processAllMessages();
1152         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1153                 eq(mPhoneSwitcher.mValidationCallback));
1154         doReturn(true).when(mCellularNetworkValidator).isValidating();
1155 
1156         // Validation failed on different sub. Should do nothing.
1157         mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
1158         processAllMessages();
1159         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1160 
1161         // Network available on corresponding sub. Should confirm switch.
1162         mPhoneSwitcher.mValidationCallback.onValidationDone(false, 2);
1163         processAllMessages();
1164         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1165     }
1166 
1167     @Test
testRetry_DDS_switch_Failure()1168     public void testRetry_DDS_switch_Failure() throws Exception {
1169         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1170         mActiveModemCount = 2;
1171         initialize();
1172         setSlotIndexToSubId(0, 1);
1173         setDefaultDataSubId(1);
1174 
1175         clearInvocations(mMockRadioConfig);
1176         // for exceptions OP_NOT_ALLOWED_DURING_VOICE_CALL and INVALID_SIM_STATE,
1177         // modem retry not invoked.
1178         AsyncResult res1 = new AsyncResult(0, null,
1179                 new CommandException(CommandException.Error.INVALID_SIM_STATE));
1180         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res1).sendToTarget();
1181         processAllMessages();
1182         moveTimeForward(5000);
1183         processAllMessages();
1184         verify(mMockRadioConfig, times(0)).setPreferredDataModem(eq(0), any());
1185 
1186         doReturn(0).when(mSubscriptionController).getPhoneId(anyInt());
1187         AsyncResult res2 = new AsyncResult(0, null,
1188                 new CommandException(CommandException.Error.NETWORK_NOT_READY));
1189         Message.obtain(mPhoneSwitcher, EVENT_MODEM_COMMAND_DONE, res2).sendToTarget();
1190         processAllMessages();
1191         moveTimeForward(5000);
1192         processAllMessages();
1193 
1194         verify(mMockRadioConfig, times(1)).setPreferredDataModem(eq(0), any());
1195 
1196         clearInvocations(mMockRadioConfig);
1197         doReturn(mSubscriptionInfo).when(mSubscriptionController)
1198             .getActiveSubscriptionInfoForSimSlotIndex(eq(0), any(), any());
1199         doReturn(true).when(mSubscriptionInfo).areUiccApplicationsEnabled();
1200         doReturn(mIccCard).when(mPhone).getIccCard();
1201         doReturn(true).when(mIccCard).isEmptyProfile();
1202         final Intent intent1 = new Intent(ACTION_SIM_APPLICATION_STATE_CHANGED);
1203         intent1.putExtra(EXTRA_SIM_STATE, SIM_STATE_LOADED);
1204         intent1.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
1205         mContext.sendBroadcast(intent1);
1206         processAllMessages();
1207 
1208         verify(mMockRadioConfig, times(0)).setPreferredDataModem(eq(0), any());
1209 
1210         doReturn(false).when(mIccCard).isEmptyProfile();
1211         final Intent intent2 = new Intent(ACTION_SIM_APPLICATION_STATE_CHANGED);
1212         intent2.putExtra(EXTRA_SIM_STATE, SIM_STATE_LOADED);
1213         intent2.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
1214         mContext.sendBroadcast(intent2);
1215         processAllMessages();
1216 
1217         verify(mMockRadioConfig, times(1)).setPreferredDataModem(eq(0), any());
1218     }
1219 
1220     /* Private utility methods start here */
1221 
setAllPhonesInactive()1222     private void setAllPhonesInactive() {
1223         doReturn(mInactiveCall).when(mPhone).getForegroundCall();
1224         doReturn(mInactiveCall).when(mPhone).getBackgroundCall();
1225         doReturn(mInactiveCall).when(mPhone).getRingingCall();
1226         doReturn(mInactiveCall).when(mPhone2).getForegroundCall();
1227         doReturn(mInactiveCall).when(mPhone2).getBackgroundCall();
1228         doReturn(mInactiveCall).when(mPhone2).getRingingCall();
1229         doReturn(mInactiveCall).when(mImsPhone).getForegroundCall();
1230         doReturn(mInactiveCall).when(mImsPhone).getBackgroundCall();
1231         doReturn(mInactiveCall).when(mImsPhone).getRingingCall();
1232     }
1233 
notifyPhoneAsInCall(Phone phone)1234     private void notifyPhoneAsInCall(Phone phone) {
1235         doReturn(mActiveCall).when(phone).getForegroundCall();
1236         mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1237         processAllMessages();
1238     }
1239 
notifyPhoneAsInHoldingCall(Phone phone)1240     private void notifyPhoneAsInHoldingCall(Phone phone) {
1241         doReturn(mHoldingCall).when(phone).getBackgroundCall();
1242         mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1243         processAllMessages();
1244     }
1245 
notifyPhoneAsInactive(Phone phone)1246     private void notifyPhoneAsInactive(Phone phone) {
1247         doReturn(mInactiveCall).when(phone).getForegroundCall();
1248         mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1249         processAllMessages();
1250     }
1251 
notifyDataEnabled(boolean dataEnabled)1252     private void notifyDataEnabled(boolean dataEnabled) {
1253         doReturn(dataEnabled).when(mDataEnabledSettings).isDataEnabled(anyInt());
1254         doReturn(dataEnabled).when(mDataEnabledSettings2).isDataEnabled(anyInt());
1255         mPhoneSwitcher.sendEmptyMessage(EVENT_DATA_ENABLED_CHANGED);
1256         processAllMessages();
1257     }
1258 
notifyImsRegistrationTechChange(Phone phone)1259     private void notifyImsRegistrationTechChange(Phone phone) {
1260         mPhoneSwitcher.sendEmptyMessage(EVENT_IMS_RADIO_TECH_CHANGED);
1261         processAllMessages();
1262     }
1263 
getEcbmRegistration(Phone phone)1264     private Message getEcbmRegistration(Phone phone) {
1265         ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1266         ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
1267 
1268         verify(phone).registerForEmergencyCallToggle(handlerCaptor.capture(), intCaptor.capture(),
1269                 any());
1270         assertNotNull(handlerCaptor.getValue());
1271         assertNotNull(intCaptor.getValue());
1272         Message message = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
1273         return message;
1274     }
1275 
notifyEcbmStart(Phone phone, Message ecmMessage)1276     private void notifyEcbmStart(Phone phone, Message ecmMessage) {
1277         doReturn(mInactiveCall).when(phone).getForegroundCall();
1278         doReturn(true).when(phone).isInEcm();
1279         ecmMessage.sendToTarget();
1280         processAllMessages();
1281     }
1282 
notifyEcbmEnd(Phone phone, Message ecmMessage)1283     private void notifyEcbmEnd(Phone phone, Message ecmMessage) {
1284         doReturn(false).when(phone).isInEcm();
1285         ecmMessage.sendToTarget();
1286         processAllMessages();
1287     }
1288 
sendPreferredDataSuccessResult(int phoneId)1289     private void sendPreferredDataSuccessResult(int phoneId) {
1290         // make sure the radio command is called and then send a success result
1291         processAllMessages();
1292         ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
1293         verify(mMockRadioConfig).setPreferredDataModem(eq(phoneId), msgCaptor.capture());
1294         assertNotNull(msgCaptor.getValue());
1295         // Send back successful result
1296         AsyncResult.forMessage(msgCaptor.getValue(), null, null);
1297         msgCaptor.getValue().sendToTarget();
1298         processAllMessages();
1299     }
1300 
setMsimDefaultDataSubId(int defaultDataSub)1301     private void setMsimDefaultDataSubId(int defaultDataSub) throws Exception {
1302         for (int i = 0; i < mActiveModemCount; i++) {
1303             setSlotIndexToSubId(i, i + 1);
1304         }
1305         setDefaultDataSubId(defaultDataSub);
1306         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1307         for (int i = 0; i < mActiveModemCount; i++) {
1308             if (defaultDataSub == (i + 1)) {
1309                 // sub id is always phoneId+1 for testing
1310                 assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, i));
1311             } else {
1312                 assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, i));
1313             }
1314         }
1315     }
1316 
sendDefaultDataSubChanged()1317     private void sendDefaultDataSubChanged() {
1318         final Intent intent = new Intent(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
1319         mContext.sendBroadcast(intent);
1320         processAllMessages();
1321     }
1322 
initialize()1323     private void initialize() throws Exception {
1324         setNumPhones(mActiveModemCount, mSupportedModemCount);
1325 
1326         initializeSubControllerMock();
1327         initializeCommandInterfacesMock();
1328         initializeTelRegistryMock();
1329         initializeConnManagerMock();
1330 
1331         mPhoneSwitcher = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper());
1332         processAllMessages();
1333 
1334         verify(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
1335     }
1336 
1337     /**
1338      * Certain variables needs initialized depending on number of phones.
1339      */
setNumPhones(int activeModemCount, int supportedModemCount)1340     private void setNumPhones(int activeModemCount, int supportedModemCount) throws Exception {
1341         mDataAllowed = new boolean[supportedModemCount];
1342         mSlotIndexToSubId = new int[supportedModemCount][];
1343         doReturn(0).when(mPhone).getPhoneId();
1344         doReturn(1).when(mPhone2).getPhoneId();
1345         doReturn(true).when(mPhone2).isUserDataEnabled();
1346         doReturn(mDataEnabledSettings2).when(mPhone2).getDataEnabledSettings();
1347         for (int i = 0; i < supportedModemCount; i++) {
1348             mSlotIndexToSubId[i] = new int[1];
1349             mSlotIndexToSubId[i][0] = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1350         }
1351 
1352         doReturn(activeModemCount).when(mTelephonyManager).getPhoneCount();
1353         doReturn(activeModemCount).when(mTelephonyManager).getActiveModemCount();
1354         doReturn(supportedModemCount).when(mTelephonyManager).getSupportedModemCount();
1355 
1356         if (activeModemCount == 1) {
1357             mPhones = new Phone[]{mPhone};
1358         } else if (activeModemCount == 2) {
1359             mPhones = new Phone[]{mPhone, mPhone2};
1360         }
1361 
1362         replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
1363     }
1364 
initializeCommandInterfacesMock()1365     private void initializeCommandInterfacesMock() {
1366         // Tell PhoneSwitcher that radio is on.
1367         doAnswer(invocation -> {
1368             Handler handler = (Handler) invocation.getArguments()[0];
1369             int message = (int) invocation.getArguments()[1];
1370             Object obj = invocation.getArguments()[2];
1371             handler.obtainMessage(message, obj).sendToTarget();
1372             return null;
1373         }).when(mCommandsInterface0).registerForAvailable(any(), anyInt(), any());
1374 
1375         // Store values of dataAllowed in mDataAllowed[] for easier checking.
1376         doAnswer(invocation -> {
1377             mDataAllowed[0] = (boolean) invocation.getArguments()[0];
1378             return null;
1379         }).when(mCommandsInterface0).setDataAllowed(anyBoolean(), any());
1380 
1381         if (mSupportedModemCount > 1) {
1382             doAnswer(invocation -> {
1383                 mDataAllowed[1] = (boolean) invocation.getArguments()[0];
1384                 return null;
1385             }).when(mCommandsInterface1).setDataAllowed(anyBoolean(), any());
1386         }
1387     }
1388 
1389     /**
1390      * Store subChangedListener of PhoneSwitcher so that testing can notify
1391      * PhoneSwitcher of sub change.
1392      */
initializeTelRegistryMock()1393     private void initializeTelRegistryMock() throws Exception {
1394         doAnswer(invocation -> {
1395             SubscriptionManager.OnSubscriptionsChangedListener subChangedListener =
1396                     (SubscriptionManager.OnSubscriptionsChangedListener) invocation.getArguments()[0];
1397             mSubChangedListener = subChangedListener;
1398             mSubChangedListener.onSubscriptionsChanged();
1399             return null;
1400         }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
1401     }
1402 
1403     /**
1404      * Capture mNetworkProviderMessenger so that testing can request or release
1405      * network requests on PhoneSwitcher.
1406      */
initializeConnManagerMock()1407     private void initializeConnManagerMock() {
1408         mConnectivityManager = (ConnectivityManager)
1409                 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
1410 
1411         doAnswer(invocation -> {
1412             mNetworkProviderMessenger =
1413                     ((NetworkProvider) invocation.getArgument(0)).getMessenger();
1414             return null;
1415         }).when(mConnectivityManager).registerNetworkProvider(any());
1416     }
1417 
1418     /**
1419      * Capture mNetworkProviderMessenger so that testing can request or release
1420      * network requests on PhoneSwitcher.
1421      */
initializeSubControllerMock()1422     private void initializeSubControllerMock() {
1423         doReturn(mDefaultDataSub).when(mSubscriptionController).getDefaultDataSubId();
1424         doAnswer(invocation -> {
1425             int phoneId = (int) invocation.getArguments()[0];
1426             if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
1427                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1428             } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1429                 return mSlotIndexToSubId[0][0];
1430             } else {
1431                 return mSlotIndexToSubId[phoneId][0];
1432             }
1433         }).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
1434 
1435         doAnswer(invocation -> {
1436             int subId = (int) invocation.getArguments()[0];
1437 
1438             if (!SubscriptionManager.isUsableSubIdValue(subId)) return false;
1439 
1440             for (int i = 0; i < mSlotIndexToSubId.length; i++) {
1441                 if (mSlotIndexToSubId[i][0] == subId) return true;
1442             }
1443             return false;
1444         }).when(mSubscriptionController).isActiveSubId(anyInt());
1445     }
1446 
setDefaultDataSubId(int defaultDataSub)1447     private void setDefaultDataSubId(int defaultDataSub) {
1448         mDefaultDataSub = defaultDataSub;
1449         doReturn(mDefaultDataSub).when(mSubscriptionController).getDefaultDataSubId();
1450         sendDefaultDataSubChanged();
1451     }
1452 
setSlotIndexToSubId(int slotId, int subId)1453     private void setSlotIndexToSubId(int slotId, int subId) {
1454         mSlotIndexToSubId[slotId][0] = subId;
1455     }
1456 
1457     /**
1458      * Create an internet PDN network request and send it to PhoneSwitcher.
1459      */
addInternetNetworkRequest(Integer subId, int score)1460     private NetworkRequest addInternetNetworkRequest(Integer subId, int score) throws Exception {
1461         return addInternetNetworkRequest(subId, score, false);
1462     }
1463 
addInternetNetworkRequest(Integer subId, int score, boolean restricted)1464     private NetworkRequest addInternetNetworkRequest(Integer subId, int score, boolean restricted)
1465             throws Exception {
1466         NetworkCapabilities netCap = (new NetworkCapabilities())
1467                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
1468                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1469         if (restricted) {
1470             netCap.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
1471         }
1472 
1473         if (subId != null) {
1474             netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
1475                     .setSubscriptionId(subId).build());
1476         }
1477         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
1478                 0, NetworkRequest.Type.REQUEST);
1479 
1480         Message message = Message.obtain();
1481         message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
1482         message.arg1 = score;
1483         message.obj = networkRequest;
1484         mNetworkProviderMessenger.send(message);
1485         processAllMessages();
1486 
1487         return networkRequest;
1488     }
1489 
1490     /**
1491      * Create a mms PDN network request and send it to PhoneSwitcher.
1492      */
addMmsNetworkRequest(Integer subId)1493     private NetworkRequest addMmsNetworkRequest(Integer subId) throws Exception {
1494         NetworkCapabilities netCap = (new NetworkCapabilities())
1495                 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
1496                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1497                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1498         if (subId != null) {
1499             netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
1500                     .setSubscriptionId(subId).build());
1501         }
1502         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
1503                 1, NetworkRequest.Type.REQUEST);
1504 
1505         Message message = Message.obtain();
1506         message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
1507         message.arg1 = 50; // Score
1508         message.obj = networkRequest;
1509         mNetworkProviderMessenger.send(message);
1510         processAllMessages();
1511 
1512         return networkRequest;
1513     }
1514 
1515     /**
1516      * Tell PhoneSwitcher to release a network request.
1517      */
releaseNetworkRequest(NetworkRequest networkRequest)1518     private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
1519         Message message = Message.obtain();
1520         message.what = android.net.NetworkProvider.CMD_CANCEL_REQUEST;
1521         message.obj = networkRequest;
1522         mNetworkProviderMessenger.send(message);
1523         processAllMessages();
1524     }
1525 }
1526