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.data;
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.RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
27 import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERED;
28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
29 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
30 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
31 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
32 
33 import static com.android.internal.telephony.data.AutoDataSwitchController.EVALUATION_REASON_VOICE_CALL_END;
34 import static com.android.internal.telephony.data.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS;
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.ArgumentMatchers.anyString;
45 import static org.mockito.Matchers.eq;
46 import static org.mockito.Mockito.clearInvocations;
47 import static org.mockito.Mockito.doAnswer;
48 import static org.mockito.Mockito.doNothing;
49 import static org.mockito.Mockito.doReturn;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.never;
52 import static org.mockito.Mockito.times;
53 import static org.mockito.Mockito.verify;
54 
55 import android.content.Intent;
56 import android.net.ConnectivityManager;
57 import android.net.NetworkCapabilities;
58 import android.net.NetworkRequest;
59 import android.net.TelephonyNetworkSpecifier;
60 import android.os.AsyncResult;
61 import android.os.Handler;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.telephony.AccessNetworkConstants;
65 import android.telephony.NetworkRegistrationInfo;
66 import android.telephony.PhoneCapability;
67 import android.telephony.ServiceState;
68 import android.telephony.SubscriptionInfo;
69 import android.telephony.SubscriptionManager;
70 import android.telephony.TelephonyDisplayInfo;
71 import android.telephony.TelephonyManager;
72 import android.testing.AndroidTestingRunner;
73 import android.testing.TestableLooper;
74 
75 import com.android.ims.ImsException;
76 import com.android.internal.telephony.Call;
77 import com.android.internal.telephony.CommandException;
78 import com.android.internal.telephony.CommandsInterface;
79 import com.android.internal.telephony.GsmCdmaCall;
80 import com.android.internal.telephony.ISetOpportunisticDataCallback;
81 import com.android.internal.telephony.ISub;
82 import com.android.internal.telephony.Phone;
83 import com.android.internal.telephony.PhoneFactory;
84 import com.android.internal.telephony.ServiceStateTracker;
85 import com.android.internal.telephony.TelephonyTest;
86 import com.android.internal.telephony.imsphone.ImsPhone;
87 import com.android.internal.telephony.imsphone.ImsPhoneCall;
88 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
89 import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
90 
91 import org.junit.After;
92 import org.junit.Before;
93 import org.junit.Test;
94 import org.junit.runner.RunWith;
95 import org.mockito.ArgumentCaptor;
96 
97 import java.lang.reflect.Field;
98 import java.util.Map;
99 import java.util.concurrent.CompletableFuture;
100 import java.util.concurrent.LinkedBlockingQueue;
101 
102 @RunWith(AndroidTestingRunner.class)
103 @TestableLooper.RunWithLooper
104 public class PhoneSwitcherTest extends TelephonyTest {
105     private static final int ACTIVE_PHONE_SWITCH = 1;
106     private static final int EVENT_RADIO_ON = 108;
107     private static final int EVENT_MODEM_COMMAND_DONE = 112;
108     private static final int EVENT_EVALUATE_AUTO_SWITCH = 111;
109     private static final int EVENT_IMS_RADIO_TECH_CHANGED = 120;
110     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117;
111     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 109;
112     private static final int EVENT_SERVICE_STATE_CHANGED = 114;
113 
114     // Mocked classes
115     CompletableFuture<Boolean> mFuturePhone;
116     private CommandsInterface mCommandsInterface0;
117     private CommandsInterface mCommandsInterface1;
118     private ServiceStateTracker mSST2;
119     private Phone mImsPhone;
120     private DataSettingsManager mDataSettingsManager2;
121     private Handler mActivePhoneSwitchHandler;
122     private GsmCdmaCall mActiveCall;
123     private GsmCdmaCall mHoldingCall;
124     private GsmCdmaCall mInactiveCall;
125     private GsmCdmaCall mDialCall;
126     private GsmCdmaCall mIncomingCall;
127     private GsmCdmaCall mAlertingCall;
128     private ISetOpportunisticDataCallback mSetOpptDataCallback1;
129     private ISetOpportunisticDataCallback mSetOpptDataCallback2;
130     PhoneSwitcher.ImsRegTechProvider mMockImsRegTechProvider;
131     PhoneSwitcher.ImsRegisterCallback mMockImsRegisterCallback;
132     private SubscriptionInfo mSubscriptionInfo;
133     private ISub mMockedIsub;
134     private AutoDataSwitchController mAutoDataSwitchController;
135 
136     private PhoneSwitcher mPhoneSwitcherUT;
137     private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
138     private Map<Integer, DataSettingsManager.DataSettingsManagerCallback>
139             mDataSettingsManagerCallbacks;
140     private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
141     private int[][] mSlotIndexToSubId;
142     private boolean[] mDataAllowed;
143     private int mActiveModemCount = 2;
144     private int mSupportedModemCount = 2;
145     private int mMaxDataAttachModemCount = 1;
146     private AutoDataSwitchController.AutoDataSwitchControllerCallback mAutoDataSwitchCallback;
147     private TelephonyDisplayInfo mTelephonyDisplayInfo = new TelephonyDisplayInfo(
148             TelephonyManager.NETWORK_TYPE_NR,
149             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false);
150     private SubscriptionManagerServiceCallback mSubscriptionManagerServiceCallback;
151 
152     @Before
setUp()153     public void setUp() throws Exception {
154         super.setUp(getClass().getSimpleName());
155         mFuturePhone = mock(CompletableFuture.class);
156         mCommandsInterface0 = mock(CommandsInterface.class);
157         mCommandsInterface1 = mock(CommandsInterface.class);
158         mSST2 = mock(ServiceStateTracker.class);
159         mImsPhone = mock(Phone.class);
160         mDataSettingsManager2 = mock(DataSettingsManager.class);
161         mActivePhoneSwitchHandler = mock(Handler.class);
162         mActiveCall = mock(GsmCdmaCall.class);
163         mHoldingCall = mock(GsmCdmaCall.class);
164         mInactiveCall = mock(GsmCdmaCall.class);
165         mDialCall = mock(GsmCdmaCall.class);
166         mIncomingCall = mock(GsmCdmaCall.class);
167         mAlertingCall = mock(GsmCdmaCall.class);
168         mSetOpptDataCallback1 = mock(ISetOpportunisticDataCallback.class);
169         mSetOpptDataCallback2 = mock(ISetOpportunisticDataCallback.class);
170         mMockImsRegTechProvider = mock(PhoneSwitcher.ImsRegTechProvider.class);
171         mMockImsRegisterCallback = mock(PhoneSwitcher.ImsRegisterCallback.class);
172         mSubscriptionInfo = mock(SubscriptionInfo.class);
173         mMockedIsub = mock(ISub.class);
174         mAutoDataSwitchController = mock(AutoDataSwitchController.class);
175 
176         PhoneCapability phoneCapability = new PhoneCapability(1, 1, null, false, new int[0]);
177         doReturn(phoneCapability).when(mPhoneConfigurationManager).getCurrentPhoneCapability();
178 
179         doReturn(Call.State.ACTIVE).when(mActiveCall).getState();
180         doReturn(Call.State.IDLE).when(mInactiveCall).getState();
181         doReturn(Call.State.HOLDING).when(mHoldingCall).getState();
182         doReturn(Call.State.DIALING).when(mDialCall).getState();
183         doReturn(Call.State.INCOMING).when(mIncomingCall).getState();
184         doReturn(Call.State.ALERTING).when(mAlertingCall).getState();
185 
186         doReturn(true).when(mInactiveCall).isIdle();
187         doReturn(false).when(mActiveCall).isIdle();
188         doReturn(false).when(mHoldingCall).isIdle();
189 
190         replaceInstance(Phone.class, "mCi", mPhone, mCommandsInterface0);
191         replaceInstance(Phone.class, "mCi", mPhone2, mCommandsInterface1);
192 
193         doReturn(1).when(mMockedIsub).getDefaultDataSubId();
194         doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
195         doReturn(mPhone).when(mPhone).getImsPhone();
196         mServiceManagerMockedServices.put("isub", mIBinder);
197 
198         doReturn(mTelephonyDisplayInfo).when(mDisplayInfoController).getTelephonyDisplayInfo();
199         doReturn(true).when(mFeatureFlags).ddsCallback();
200     }
201 
202     @After
tearDown()203     public void tearDown() throws Exception {
204         mPhoneSwitcherUT = null;
205         mSubChangedListener = null;
206         mTelephonyDisplayInfo = null;
207         super.tearDown();
208     }
209 
210     /**
211      * Test that a single phone case results in our phone being active and the RIL called
212      */
213     @Test
testRegister()214     public void testRegister() throws Exception {
215         initialize();
216 
217         // verify nothing has been done while there are no inputs
218         assertTrue("data should be always allowed for emergency", mDataAllowed[0]);
219         assertFalse("data allowed initially", mDataAllowed[1]);
220 
221         NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
222 
223         assertFalse("phone active after request", mPhoneSwitcherUT
224                 .shouldApplyNetworkRequest(new TelephonyNetworkRequest(
225                         internetNetworkRequest, mPhone, mFeatureFlags), 0));
226 
227         // not registered yet - shouldn't inc
228         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
229 
230         mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
231                 ACTIVE_PHONE_SWITCH, null);
232 
233         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
234         clearInvocations(mActivePhoneSwitchHandler);
235 
236         setDefaultDataSubId(0);
237 
238         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
239 
240         setSlotIndexToSubId(0, 0);
241         mSubChangedListener.onSubscriptionsChanged();
242         processAllMessages();
243 
244         AsyncResult res = new AsyncResult(1, null,  null);
245         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
246         processAllMessages();
247         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
248         clearInvocations(mActivePhoneSwitchHandler);
249         assertTrue("data not allowed", mDataAllowed[0]);
250 
251         // now try various things that should cause the active phone to switch:
252         // 1 lose default via default sub change
253         // 2 gain default via default sub change
254         // 3 lose default via sub->phone change
255         // 4 gain default via sub->phone change
256         // 5 lose default network request
257         // 6 gain subscription-specific request
258         // 7 lose via sub->phone change
259         // 8 gain via sub->phone change
260         // 9 lose subscription-specific request
261         // 10 don't switch phones when in emergency mode
262 
263         // 1 lose default via default sub change
264         setDefaultDataSubId(1);
265 
266         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
267         processAllMessages();
268         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
269         clearInvocations(mActivePhoneSwitchHandler);
270         assertFalse("data allowed", mDataAllowed[0]);
271 
272         setSlotIndexToSubId(1, 1);
273         clearInvocations(mAutoDataSwitchController);
274         mSubChangedListener.onSubscriptionsChanged();
275         processAllMessages();
276 
277         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
278         processAllMessages();
279         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
280         verify(mAutoDataSwitchController).notifySubscriptionsMappingChanged();
281         clearInvocations(mActivePhoneSwitchHandler);
282         assertFalse("data allowed", mDataAllowed[0]);
283         assertTrue("data not allowed", mDataAllowed[1]);
284 
285         // 2 gain default via default sub change
286         setDefaultDataSubId(0);
287 
288         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
289         processAllMessages();
290         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
291         clearInvocations(mActivePhoneSwitchHandler);
292         assertFalse("data allowed", mDataAllowed[1]);
293         assertTrue("data not allowed", mDataAllowed[0]);
294 
295         // 3 lose default via sub->phone change
296         setSlotIndexToSubId(0, 2);
297         clearInvocations(mAutoDataSwitchController);
298         mSubChangedListener.onSubscriptionsChanged();
299         processAllMessages();
300         verify(mAutoDataSwitchController).notifySubscriptionsMappingChanged();
301         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
302         processAllMessages();
303 
304         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
305         clearInvocations(mActivePhoneSwitchHandler);
306         assertFalse("data allowed", mDataAllowed[0]);
307         assertFalse("data allowed", mDataAllowed[1]);
308 
309         // 4 gain default via sub->phone change
310         setSlotIndexToSubId(0, 0);
311         mSubChangedListener.onSubscriptionsChanged();
312         processAllMessages();
313 
314         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
315         processAllMessages();
316         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
317         clearInvocations(mActivePhoneSwitchHandler);
318         assertTrue("data not allowed", mDataAllowed[0]);
319         assertFalse("data allowed", mDataAllowed[1]);
320 
321         // 5 lose default network request
322         releaseNetworkRequest(internetNetworkRequest);
323 
324         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
325         processAllMessages();
326         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
327         clearInvocations(mActivePhoneSwitchHandler);
328         assertTrue("data not allowed", mDataAllowed[0]);
329         assertFalse("data allowed", mDataAllowed[1]);
330 
331         // 6 gain subscription-specific request
332         NetworkRequest specificInternetRequest = addInternetNetworkRequest(0, 50);
333 
334         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
335         processAllMessages();
336         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
337         clearInvocations(mActivePhoneSwitchHandler);
338         assertTrue("data not allowed", mDataAllowed[0]);
339         assertFalse("data allowed", mDataAllowed[1]);
340 
341         // 7 lose via sub->phone change
342         setSlotIndexToSubId(0, 1);
343         mSubChangedListener.onSubscriptionsChanged();
344         processAllMessages();
345 
346         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
347         processAllMessages();
348         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
349         clearInvocations(mActivePhoneSwitchHandler);
350         assertFalse("data allowed", mDataAllowed[0]);
351         assertFalse("data allowed", mDataAllowed[1]);
352 
353         // 8 gain via sub->phone change
354         setSlotIndexToSubId(0, 0);
355         mSubChangedListener.onSubscriptionsChanged();
356         processAllMessages();
357 
358         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
359         processAllMessages();
360         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
361         clearInvocations(mActivePhoneSwitchHandler);
362         assertTrue("data not allowed", mDataAllowed[0]);
363         assertFalse("data allowed", mDataAllowed[1]);
364 
365         // 9 lose subscription-specific request
366         releaseNetworkRequest(specificInternetRequest);
367 
368         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
369         processAllMessages();
370         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
371         clearInvocations(mActivePhoneSwitchHandler);
372         assertTrue("data not allowed", mDataAllowed[0]);
373         assertFalse("data allowed", mDataAllowed[1]);
374 
375         // 10 don't switch phones when in emergency mode
376         // not ready yet - Phone turns out to be hard to stub out
377 //        phones[0].setInEmergencyCall(true);
378 //        connectivityServiceMock.addDefaultRequest();
379 //        processAllMessages();
380 //        if (testHandler.getActivePhoneSwitchCount() != 11) {
381 //            fail("after release of request, ActivePhoneSwitchCount not 11!");
382 //        }
383 //        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
384 //        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
385 //
386 //        phones[0].setInEmergencyCall(false);
387 //        connectivityServiceMock.addDefaultRequest();
388 //        processAllMessages();
389 //        if (testHandler.getActivePhoneSwitchCount() != 12) {
390 //            fail("after release of request, ActivePhoneSwitchCount not 11!");
391 //        }
392 //        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
393 //        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
394     }
395 
396     /** Test Data Auto Switch **/
397     @Test
testAutoDataSwitch_retry()398     public void testAutoDataSwitch_retry() throws Exception {
399         initialize();
400         // Phone 0 has sub 1, phone 1 has sub 2.
401         // Sub 1 is default data sub.
402         setSlotIndexToSubId(0, 1);
403         setSlotIndexToSubId(1, 2);
404         setDefaultDataSubId(1);
405 
406         mAutoDataSwitchCallback.onRequireValidation(1/*Phone2*/, true);
407         processAllFutureMessages();
408 
409         // Mock validation failed, expect retry attempt
410         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
411                 eq(mPhoneSwitcherUT.mValidationCallback));
412         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2/*Phone2*/);
413         processAllMessages();
414 
415         verify(mAutoDataSwitchController).evaluateRetryOnValidationFailed();
416 
417         // Test clear failed count upon switch succeeded.
418         mAutoDataSwitchCallback.onRequireValidation(1/*Phone2*/, true);
419         processAllFutureMessages();
420         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2/*Phone2*/);
421         processAllMessages();
422 
423         verify(mAutoDataSwitchController).resetFailedCount();
424     }
425 
426     @Test
testAutoDataSwitch_setNotification()427     public void testAutoDataSwitch_setNotification() throws Exception {
428         initialize();
429         // Phone 0 has sub 1, phone 1 has sub 2.
430         // Sub 1 is default data sub.
431         setSlotIndexToSubId(0, 1);
432         setSlotIndexToSubId(1, 2);
433         setDefaultDataSubId(1);
434 
435         // Verify no notification check if switch failed.
436         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, new AsyncResult(1/*phoneId*/,
437                 null, new Throwable())).sendToTarget();
438         processAllMessages();
439         verify(mAutoDataSwitchController, never()).displayAutoDataSwitchNotification(
440                 anyInt(), anyBoolean());
441 
442         // Verify for switch not due to auto
443         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, new AsyncResult(1/*phoneId*/,
444                 null, null)).sendToTarget();
445         processAllMessages();
446         verify(mAutoDataSwitchController).displayAutoDataSwitchNotification(1/*phoneId*/, false);
447 
448         // Verify for switch due to auto
449         mAutoDataSwitchCallback.onRequireValidation(1/*Phone2*/, false);
450         processAllMessages();
451         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2/*Phone2*/);
452         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, new AsyncResult(1/*phoneId*/,
453                 null, null)).sendToTarget();
454         processAllMessages();
455 
456         verify(mAutoDataSwitchController).displayAutoDataSwitchNotification(1/*phoneId*/, true);
457     }
458 
459     @Test
testAutoDataSwitch_exemptPingTest()460     public void testAutoDataSwitch_exemptPingTest() throws Exception {
461         initialize();
462 
463         // Phone 0 has sub 1, phone 1 has sub 2.
464         // Sub 1 is default data sub.
465         setSlotIndexToSubId(0, 1);
466         setSlotIndexToSubId(1, 2);
467 
468         //Attempting to switch to nDDS, switch even if validation failed
469         mAutoDataSwitchCallback.onRequireValidation(1/*Phone2*/, false);
470         processAllFutureMessages();
471 
472         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
473                 eq(mPhoneSwitcherUT.mValidationCallback));
474         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2/*Phone2*/);
475         processAllMessages();
476 
477         assertEquals(2, mPhoneSwitcherUT.getActiveDataSubId()); // switch succeeds
478     }
479 
480     /**
481      * Test a multi-sim case with limited active phones:
482      * - lose default via default sub change
483      * - lose default via sub->phone change
484      * - gain default via sub->phone change
485      * - gain default via default sub change
486      * - lose default network request
487      * - gain subscription-specific request
488      * - lose via sub->phone change
489      * - gain via sub->phone change
490      * - lose subscription-specific request
491      * - tear down low priority phone when new request comes in
492      * - tear down low priority phone when sub change causes split
493      * - bring up low priority phone when sub change causes join
494      * - don't switch phones when in emergency mode
495      */
496     @Test
testPrioritization()497     public void testPrioritization() throws Exception {
498         initialize();
499 
500         addInternetNetworkRequest(null, 50);
501         setSlotIndexToSubId(0, 0);
502         setSlotIndexToSubId(1, 1);
503         setDefaultDataSubId(0);
504         mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
505                 ACTIVE_PHONE_SWITCH, null);
506         processAllMessages();
507         // verify initial conditions
508         verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
509 
510         assertTrue("data not allowed", mDataAllowed[0]);
511         assertFalse("data allowed", mDataAllowed[1]);
512 
513         // now start a higher priority connection on the other sub
514         addMmsNetworkRequest(1);
515 
516         AsyncResult res = new AsyncResult(1, null,  null);
517         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
518         processAllMessages();
519 
520         // After gain of network request, mActivePhoneSwitchHandler should be notified 2 times.
521         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
522         assertFalse("data allowed", mDataAllowed[0]);
523         assertTrue("data not allowed", mDataAllowed[1]);
524     }
525 
526     /**
527      * Verify we don't send spurious DATA_ALLOWED calls when another NetworkProvider
528      * wins (ie, switch to wifi).
529      */
530     @Test
testHigherPriorityDefault()531     public void testHigherPriorityDefault() throws Exception {
532         initialize();
533 
534         addInternetNetworkRequest(null, 50);
535 
536         setSlotIndexToSubId(0, 0);
537         setSlotIndexToSubId(1, 1);
538         setDefaultDataSubId(0);
539 
540         // Phone 0 should be active
541         assertTrue("data not allowed", mDataAllowed[0]);
542         assertFalse("data allowed", mDataAllowed[1]);
543 
544         addInternetNetworkRequest(null, 100);
545 
546         // should be no change
547         assertTrue("data not allowed", mDataAllowed[0]);
548         assertFalse("data allowed", mDataAllowed[1]);
549 
550         addInternetNetworkRequest(null, 0);
551         // should be no change
552         assertTrue("data not allowed", mDataAllowed[0]);
553         assertFalse("data allowed", mDataAllowed[1]);
554     }
555 
556     /**
557      * Verify testSetPreferredData.
558      * When preferredData is set, it overwrites defaultData sub to be active sub in single
559      * active phone mode. If it's unset (to DEFAULT_SUBSCRIPTION_ID), defaultData sub becomes
560      * active one.
561      */
562     @Test
testSetPreferredData()563     public void testSetPreferredData() throws Exception {
564         initialize();
565 
566         // Phone 0 has sub 1, phone 1 has sub 2.
567         // Sub 1 is default data sub.
568         // Both are active subscriptions are active sub, as they are in both active slots.
569         setSlotIndexToSubId(0, 1);
570         setSlotIndexToSubId(1, 2);
571         setDefaultDataSubId(1);
572 
573         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
574                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
575                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
576 
577         // Notify phoneSwitcher about default data sub and default network request.
578         addInternetNetworkRequest(null, 50);
579         // Phone 0 (sub 1) should be activated as it has default data sub.
580         assertTrue(mDataAllowed[0]);
581 
582         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
583         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, null);
584         processAllMessages();
585         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
586         processAllMessages();
587         assertFalse(mDataAllowed[0]);
588         assertTrue(mDataAllowed[1]);
589 
590         // Unset preferred sub should make default data sub (phone 0 / sub 1) activated again.
591         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
592                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
593         processAllMessages();
594         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 1);
595         processAllMessages();
596         assertTrue(mDataAllowed[0]);
597         assertFalse(mDataAllowed[1]);
598     }
599 
600     /**
601      * TestSetPreferredData in the event of different priorities.
602      * The following events can set preferred data subId with priority in the order of
603      * 1. Emergency call
604      * 2. Voice call (when data during call feature is enabled).
605      * 3. CBRS requests OR Auto switch requests - only one case applies at a time
606      */
607     @Test
testSetPreferredDataCasePriority_CbrsWaitsForVoiceCall()608     public void testSetPreferredDataCasePriority_CbrsWaitsForVoiceCall() throws Exception {
609         initialize();
610         setAllPhonesInactive();
611 
612         // Phone 0 has sub 1, phone 1 has sub 2.
613         // Sub 1 is default data sub.
614         // Both are active subscriptions are active sub, as they are in both active slots.
615         setSlotIndexToSubId(0, 1);
616         setSlotIndexToSubId(1, 2);
617         // single visible sub, as the other one is CBRS
618         doReturn(new int[1]).when(mSubscriptionManagerService).getActiveSubIdList(true);
619         setDefaultDataSubId(1);
620 
621         // Notify phoneSwitcher about default data sub and default network request.
622         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
623         // Phone 0 (sub 1) should be activated as it has default data sub.
624         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
625         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
626                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
627         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
628                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
629 
630         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
631         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, null);
632         processAllMessages();
633         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
634         // A higher priority event occurring E.g. Phone1 has active IMS call on LTE.
635         doReturn(mImsPhone).when(mPhone).getImsPhone();
636         doReturn(true).when(mPhone).isUserDataEnabled();
637         doReturn(true).when(mDataSettingsManager).isDataEnabled();
638         mockImsRegTech(0, REGISTRATION_TECH_LTE);
639         notifyPhoneAsInCall(mPhone);
640 
641         // switch shouldn't occur due to the higher priority event
642         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
643                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
644         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
645                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
646         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
647         assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
648 
649         // The higher priority event ends, time to switch to auto selected subId.
650         notifyPhoneAsInactive(mPhone);
651 
652         assertEquals(2, mPhoneSwitcherUT.getActiveDataSubId());
653         assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
654         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
655                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
656         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
657                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
658     }
659 
660     @Test
testSetPreferredData_NoAutoSwitchWhenCbrs()661     public void testSetPreferredData_NoAutoSwitchWhenCbrs() throws Exception {
662         initialize();
663         setAllPhonesInactive();
664 
665         // Phone 0 has sub 1, phone 1 has sub 2.
666         // Sub 1 is default data sub.
667         // Both are active subscriptions are active sub, as they are in both active slots.
668         setSlotIndexToSubId(0, 1);
669         setSlotIndexToSubId(1, 2);
670         setDefaultDataSubId(1);
671 
672         clearInvocations(mCellularNetworkValidator);
673         doReturn(new int[1]).when(mSubscriptionManagerService).getActiveSubIdList(true);
674         prepareIdealAutoSwitchCondition();
675         processAllFutureMessages();
676 
677         verify(mCellularNetworkValidator, never()).validate(eq(2), anyLong(), eq(false),
678                 eq(mPhoneSwitcherUT.mValidationCallback));
679         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
680     }
681 
682     @Test
testSetAutoSelectedValidationFeatureNotSupported()683     public void testSetAutoSelectedValidationFeatureNotSupported() throws Exception {
684         doReturn(false).when(mCellularNetworkValidator).isValidationFeatureSupported();
685         initialize();
686 
687         // Phone 0 has sub 1, phone 1 has sub 2.
688         // Sub 1 is default data sub.
689         // Both are active subscriptions are active sub, as they are in both active slots.
690         setSlotIndexToSubId(0, 1);
691         setSlotIndexToSubId(1, 2);
692         setDefaultDataSubId(1);
693 
694         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
695                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
696                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
697 
698         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
699         processAllMessages();
700         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
701         processAllMessages();
702         assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
703 
704         // Switch to the default sub, verify AutoSelectedDataSubId is the default value.
705         clearInvocations(mSetOpptDataCallback1);
706         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(SubscriptionManager
707                 .DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback1);
708         processAllMessages();
709         assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
710                 mPhoneSwitcherUT.getAutoSelectedDataSubId());
711     }
712 
713     @Test
testSetPreferredDataModemCommand()714     public void testSetPreferredDataModemCommand() throws Exception {
715         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
716         initialize();
717         mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
718                 ACTIVE_PHONE_SWITCH, null);
719         mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
720                 ACTIVE_PHONE_SWITCH, null);
721         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
722         clearInvocations(mMockRadioConfig);
723         clearInvocations(mActivePhoneSwitchHandler);
724 
725         // Phone 0 has sub 1, phone 1 has sub 2.
726         // Sub 1 is default data sub.
727         // Both are active subscriptions are active sub, as they are in both active slots.
728         setSlotIndexToSubId(0, 1);
729         setSlotIndexToSubId(1, 2);
730         setDefaultDataSubId(1);
731         // Phone 0 (sub 1) should be preferred data phone as it has default data sub.
732         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
733         AsyncResult res = new AsyncResult(1, null,  null);
734         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
735         processAllMessages();
736         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
737         clearInvocations(mMockRadioConfig);
738         clearInvocations(mActivePhoneSwitchHandler);
739 
740         // Notify phoneSwitcher about default data sub and default network request.
741         // It shouldn't change anything.
742         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
743         NetworkRequest mmsRequest = addMmsNetworkRequest(2);
744         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
745         verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
746         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
747                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
748         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
749                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
750         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
751                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
752         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
753                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
754 
755         // Set sub 2 as preferred sub should make phone 1 preferredDataModem
756         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
757                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
758                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
759 
760         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, null);
761         processAllMessages();
762         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
763         processAllMessages();
764         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
765         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
766         processAllMessages();
767         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
768         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
769                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
770         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
771                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
772         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
773                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
774         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
775                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
776 
777         clearInvocations(mMockRadioConfig);
778         clearInvocations(mActivePhoneSwitchHandler);
779 
780         // Unset preferred sub should make phone0 preferredDataModem again.
781         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
782                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
783         processAllMessages();
784         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 1);
785         processAllMessages();
786 
787         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
788         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
789         processAllMessages();
790         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
791         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
792                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
793         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
794                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
795         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
796                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
797         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
798                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
799 
800         // SetDataAllowed should never be triggered.
801         verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
802         verify(mCommandsInterface1, never()).setDataAllowed(anyBoolean(), any());
803 
804         // Set preferred data modem should be triggered after radio on or available.
805         clearInvocations(mMockRadioConfig);
806         Message.obtain(mPhoneSwitcherUT, EVENT_RADIO_ON, res).sendToTarget();
807         processAllMessages();
808         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
809     }
810 
811     @Test
testSetPreferredDataWithValidation()812     public void testSetPreferredDataWithValidation() throws Exception {
813         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
814         initialize();
815 
816         // Phone 0 has sub 1, phone 1 has sub 2.
817         // Sub 1 is default data sub.
818         // Both are active subscriptions are active sub, as they are in both active slots.
819         setSlotIndexToSubId(0, 1);
820         setSlotIndexToSubId(1, 2);
821         setDefaultDataSubId(1);
822 
823         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
824                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
825                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
826 
827         // Phone 0 (sub 1) should be activated as it has default data sub.
828         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
829 
830         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
831         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, null);
832         processAllMessages();
833         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
834                 eq(mPhoneSwitcherUT.mValidationCallback));
835         // Validation failed. Preferred data sub should remain 1, data phone should remain 0.
836         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2);
837         processAllMessages();
838         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
839 
840         // Validation succeeds. Preferred data sub changes to 2, data phone changes to 1.
841         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, null);
842         processAllMessages();
843         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2);
844         processAllMessages();
845         assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
846 
847         // Switching data back to primary (subId 1) with customized validation timeout.
848         long timeout = 1234;
849         mContextFixture.getCarrierConfigBundle().putLong(
850                 KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, timeout);
851         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
852                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, null);
853         processAllMessages();
854         verify(mCellularNetworkValidator).validate(eq(1), eq(timeout), eq(false),
855                 eq(mPhoneSwitcherUT.mValidationCallback));
856         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 1);
857         processAllMessages();
858         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
859     }
860 
mockImsRegTech(int phoneId, int regTech)861     private void mockImsRegTech(int phoneId, int regTech) {
862         doReturn(regTech).when(mMockImsRegTechProvider).get(any(), eq(phoneId));
863         mPhoneSwitcherUT.mImsRegTechProvider = mMockImsRegTechProvider;
864     }
865 
mockImsRegisterCallback(int phoneId)866     private void mockImsRegisterCallback(int phoneId) throws ImsException {
867         doNothing().when(mMockImsRegisterCallback).setCallback(any(), eq(phoneId), any(), any());
868         mPhoneSwitcherUT.mImsRegisterCallback = mMockImsRegisterCallback;
869     }
870 
871     @Test
testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds()872     public void testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds() throws Exception {
873         initialize();
874         setAllPhonesInactive();
875 
876         // Phone 0 has sub 1, phone 1 has sub 2.
877         // Sub 1 is default data sub.
878         // Both are active subscriptions are active sub, as they are in both active slots.
879         setSlotIndexToSubId(0, 1);
880         setSlotIndexToSubId(1, 2);
881         setDefaultDataSubId(1);
882         processAllMessages();
883 
884         // Phone 0 should be the default data phoneId.
885         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
886 
887         // Phone2 has active IMS call on LTE. And data of DEFAULT apn is enabled. This should
888         // trigger data switch.
889         doReturn(mImsPhone).when(mPhone2).getImsPhone();
890         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
891         mockImsRegTech(1, REGISTRATION_TECH_LTE);
892         notifyPhoneAsInCall(mImsPhone);
893 
894         // Phone 1 should become the preferred data phone.
895         assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
896     }
897 
898     @Test
testNonDefaultDataPhoneInCall_ImsCallDialingOnLte_shouldSwitchDds()899     public void testNonDefaultDataPhoneInCall_ImsCallDialingOnLte_shouldSwitchDds()
900             throws Exception {
901         initialize();
902         setAllPhonesInactive();
903 
904         // Phone 0 has sub 1, phone 1 has sub 2.
905         // Sub 1 is default data sub.
906         // Both are active subscriptions are active sub, as they are in both active slots.
907         setSlotIndexToSubId(0, 1);
908         setSlotIndexToSubId(1, 2);
909         setDefaultDataSubId(1);
910         processAllMessages();
911 
912         // Phone 0 should be the default data phoneId.
913         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
914 
915         // Dialing shouldn't trigger switch because we give modem time to deal with the dialing call
916         // first. Phone2 has active IMS call on LTE. And data of DEFAULT apn is enabled.
917         doReturn(mImsPhone).when(mPhone2).getImsPhone();
918         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
919         mockImsRegTech(1, REGISTRATION_TECH_LTE);
920         notifyPhoneAsInDial(mImsPhone);
921 
922         // Phone1 should remain as the preferred data phone
923         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
924 
925         // Dialing -> Alert, should trigger phone switch
926         notifyPhoneAsAlerting(mImsPhone);
927 
928         // Phone2 should be preferred data phone
929         assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
930     }
931     @Test
testNonDefaultDataPhoneInCall_ImsCallIncomingOnLte_shouldSwitchDds()932     public void testNonDefaultDataPhoneInCall_ImsCallIncomingOnLte_shouldSwitchDds()
933             throws Exception {
934         initialize();
935         setAllPhonesInactive();
936 
937         // Phone 0 has sub 1, phone 1 has sub 2.
938         // Sub 1 is default data sub.
939         // Both are active subscriptions are active sub, as they are in both active slots.
940         setSlotIndexToSubId(0, 1);
941         setSlotIndexToSubId(1, 2);
942         setDefaultDataSubId(1);
943         processAllMessages();
944 
945         // Phone 0 should be the default data phoneId.
946         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
947 
948         // Phone2 has active IMS call on LTE. And data of DEFAULT apn is enabled. This should
949         // trigger data switch.
950         doReturn(mImsPhone).when(mPhone2).getImsPhone();
951         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
952         mockImsRegTech(1, REGISTRATION_TECH_LTE);
953         notifyPhoneAsInIncomingCall(mImsPhone);
954 
955         // Phone 1 should become the preferred data phone.
956         assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
957     }
958 
959     @Test
testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds()960     public void testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds() throws Exception {
961         initialize();
962         setAllPhonesInactive();
963 
964         // Phone 0 has sub 1, phone 1 has sub 2.
965         // Sub 1 is default data sub.
966         // Both are active subscriptions are active sub, as they are in both active slots.
967         setSlotIndexToSubId(0, 1);
968         setSlotIndexToSubId(1, 2);
969         setDefaultDataSubId(1);
970         processAllMessages();
971 
972         // Phone 0 should be the default data phoneId.
973         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
974 
975         // Phone2 has active call, but data is turned off. So no data switching should happen.
976         doReturn(mImsPhone).when(mPhone2).getImsPhone();
977         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
978         mockImsRegTech(1, REGISTRATION_TECH_IWLAN);
979         notifyPhoneAsInCall(mImsPhone);
980 
981         // Phone 0 should remain the default data phone.
982         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
983     }
984 
985     @Test
testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE()986     public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception {
987         initialize();
988         setAllPhonesInactive();
989 
990         // Phone 0 has sub 1, phone 1 has sub 2.
991         // Sub 1 is default data sub.
992         // Both are active subscriptions are active sub, as they are in both active slots.
993         setSlotIndexToSubId(0, 1);
994         setSlotIndexToSubId(1, 2);
995         setDefaultDataSubId(1);
996         processAllMessages();
997 
998         // Phone 0 should be the default data phoneId.
999         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
1000 
1001         // Phone 1 has active IMS call on CROSS_SIM. And data of DEFAULT apn is enabled. This should
1002         // not trigger data switch.
1003         doReturn(mImsPhone).when(mPhone2).getImsPhone();
1004         doReturn(true).when(mPhone).isUserDataEnabled();
1005         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
1006         mockImsRegTech(1, REGISTRATION_TECH_CROSS_SIM);
1007         notifyPhoneAsInCall(mImsPhone);
1008 
1009         // Phone 0 should remain the default data phone.
1010         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
1011 
1012         // Phone 1 has has handed over the call to LTE. And data of DEFAULT apn is enabled.
1013         // This should trigger data switch.
1014         mockImsRegTech(1, REGISTRATION_TECH_LTE);
1015         notifyImsRegistrationTechChange(mPhone2);
1016 
1017         // Phone 1 should become the default data phone.
1018         assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
1019     }
1020 
1021     @Test
testNonDefaultDataPhoneInCall()1022     public void testNonDefaultDataPhoneInCall() throws Exception {
1023         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1024         initialize();
1025         // Phone 0 has sub 1, phone 1 has sub 2.
1026         // Sub 1 is default data sub.
1027         // Both are active subscriptions are active sub, as they are in both active slots.
1028         setSlotIndexToSubId(0, 1);
1029         setSlotIndexToSubId(1, 2);
1030         setDefaultDataSubId(1);
1031         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1032         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1033                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1034         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1035                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1036         clearInvocations(mMockRadioConfig);
1037         setAllPhonesInactive();
1038         // Initialization done.
1039 
1040         // Phone2 has active call, but data is turned off. So no data switching should happen.
1041         notifyDataEnabled(false);
1042         notifyPhoneAsInCall(mPhone2);
1043         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1044         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1045                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1046         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1047                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1048 
1049         // Phone2 has active call, and data is on. So data switch to it.
1050         doReturn(true).when(mPhone).isUserDataEnabled();
1051         notifyDataEnabled(true);
1052         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1053         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1054                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1055         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1056                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1057         clearInvocations(mMockRadioConfig);
1058 
1059         // Phone2(nDDS) call ended. But Phone1 having cross-SIM call. Don't switch.
1060         mockImsRegTech(0, REGISTRATION_TECH_CROSS_SIM);
1061         notifyPhoneAsInIncomingCall(mPhone);
1062         notifyPhoneAsInactive(mPhone2);
1063         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1064         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1065                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1066         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1067                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1068 
1069         // Phone(DDS) call ended.
1070         // Honor auto data switch's suggestion: if DDS is OOS, auto switch to Phone2(nDDS).
1071         notifyPhoneAsInactive(mPhone);
1072         verify(mAutoDataSwitchController).evaluateAutoDataSwitch(EVALUATION_REASON_VOICE_CALL_END);
1073         mAutoDataSwitchCallback.onRequireValidation(1 /*Phone2*/, true);
1074 
1075         // verify immediately switch back to DDS upon call ends
1076         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1077         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1078                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1079         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1080                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1081 
1082         // verify the attempt to do auto data switch to Phone2(nDDS)
1083         processAllFutureMessages();
1084         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1085                 eq(mPhoneSwitcherUT.mValidationCallback));
1086 
1087         // Phone2 has holding call on VoWifi, no need to switch data
1088         clearInvocations(mMockRadioConfig);
1089         mockImsRegTech(1, REGISTRATION_TECH_IWLAN);
1090         notifyPhoneAsInHoldingCall(mPhone2);
1091         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1092         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1093                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1094         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1095                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1096     }
1097 
1098     @Test
testDataEnabledChangedDuringVoiceCall()1099     public void testDataEnabledChangedDuringVoiceCall() throws Exception {
1100         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1101         initialize();
1102         // Phone 0 has sub 1, phone 1 has sub 2.
1103         // Sub 1 is default data sub.
1104         // Both are active subscriptions are active sub, as they are in both active slots.
1105         setSlotIndexToSubId(0, 1);
1106         setSlotIndexToSubId(1, 2);
1107         setDefaultDataSubId(1);
1108         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1109         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1110                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1111         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1112                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1113         clearInvocations(mMockRadioConfig);
1114         setAllPhonesInactive();
1115         // Initialization done.
1116 
1117         // Phone2 has active call and data is on. So switch to nDDS Phone2
1118         notifyDataEnabled(true);
1119         notifyPhoneAsInCall(mPhone2);
1120         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1121         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1122                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1123         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1124                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1125 
1126         // During the active call, user turns off data, should immediately switch back to DDS
1127         notifyDataEnabled(false);
1128         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1129         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1130                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1131         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1132                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1133     }
1134 
1135     @Test
testRoamingToggle()1136     public void testRoamingToggle() throws Exception {
1137         initialize();
1138         setSlotIndexToSubId(0, 1);
1139 
1140         mDataSettingsManagerCallbacks.get(0).onDataRoamingEnabledChanged(true);
1141         processAllMessages();
1142 
1143         verify(mAutoDataSwitchController).evaluateAutoDataSwitch(AutoDataSwitchController
1144                 .EVALUATION_REASON_DATA_SETTINGS_CHANGED);
1145     }
1146 
1147     @Test
testNetworkRequestOnNonDefaultData()1148     public void testNetworkRequestOnNonDefaultData() throws Exception {
1149         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1150         initialize();
1151         // Phone 0 has sub 1, phone 1 has sub 2.
1152         // Sub 1 is default data sub.
1153         // Both are active subscriptions are active sub, as they are in both active slots.
1154         setSlotIndexToSubId(0, 1);
1155         setSlotIndexToSubId(1, 2);
1156         setDefaultDataSubId(1);
1157         NetworkRequest internetRequest = addInternetNetworkRequest(2, 50);
1158         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1159                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1160         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1161                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1162 
1163         // Restricted network request will should be applied.
1164         internetRequest = addInternetNetworkRequest(2, 50, true);
1165         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1166                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1167         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1168                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1169     }
1170 
1171     @Test
testEmergencyOverrideSuccessBeforeCallStarts()1172     public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
1173         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1174         initialize();
1175         // Phone 0 has sub 1, phone 1 has sub 2.
1176         // Sub 1 is default data sub.
1177         // Both are active subscriptions are active sub, as they are in both active slots.
1178         setMsimDefaultDataSubId(1);
1179         clearInvocations(mMockRadioConfig);
1180 
1181         // override the phone ID in prep for emergency call
1182         mPhoneSwitcherUT.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
1183         sendPreferredDataSuccessResult(1);
1184         processAllMessages();
1185         verify(mFuturePhone).complete(true);
1186 
1187         // Make sure the correct broadcast is sent out for the overridden phone ID
1188         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
1189     }
1190 
1191     @Test
testEmergencyOverrideNoDdsChange()1192     public void testEmergencyOverrideNoDdsChange() throws Exception {
1193         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1194         initialize();
1195         // Phone 0 has sub 1, phone 1 has sub 2.
1196         // Sub 1 is default data sub.
1197         // Both are active subscriptions are active sub, as they are in both active slots.
1198         setMsimDefaultDataSubId(1);
1199         clearInvocations(mMockRadioConfig);
1200 
1201         // override the phone ID in prep for emergency call
1202         mPhoneSwitcherUT.overrideDefaultDataForEmergency(0, 1, mFuturePhone);
1203         processAllMessages();
1204         // The radio command should never be called because the DDS hasn't changed.
1205         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
1206         processAllMessages();
1207         verify(mFuturePhone).complete(true);
1208     }
1209 
1210     @Test
testEmergencyOverrideEndSuccess()1211     public void testEmergencyOverrideEndSuccess() throws Exception {
1212         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
1213         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1214         initialize();
1215         // Phone 0 has sub 1, phone 1 has sub 2.
1216         // Sub 1 is default data sub.
1217         // Both are active subscriptions are active sub, as they are in both active slots.
1218         setMsimDefaultDataSubId(1);
1219         setAllPhonesInactive();
1220         clearInvocations(mMockRadioConfig);
1221         clearInvocations(mTelephonyRegistryManager);
1222 
1223         // override the phone ID in prep for emergency call
1224 
1225         mPhoneSwitcherUT.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
1226         sendPreferredDataSuccessResult(1);
1227         processAllMessages();
1228         verify(mFuturePhone).complete(true);
1229 
1230         // Start and end the emergency call, which will start override timer
1231         notifyPhoneAsInCall(mPhone2);
1232         notifyPhoneAsInactive(mPhone2);
1233 
1234         clearInvocations(mTelephonyRegistryManager);
1235         // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
1236         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
1237         processAllMessages();
1238         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1239         AsyncResult res = new AsyncResult(1, null,  null);
1240         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
1241         processAllMessages();
1242 
1243         // Make sure the correct broadcast is sent out for the phone ID
1244         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
1245     }
1246 
1247     @Test
testEmergencyOverrideEcbmStartEnd()1248     public void testEmergencyOverrideEcbmStartEnd() throws Exception {
1249         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
1250         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1251         initialize();
1252         // Phone 0 has sub 1, phone 1 has sub 2.
1253         // Sub 1 is default data sub.
1254         // Both are active subscriptions are active sub, as they are in both active slots.
1255         setMsimDefaultDataSubId(1);
1256         setAllPhonesInactive();
1257         clearInvocations(mMockRadioConfig);
1258         clearInvocations(mTelephonyRegistryManager);
1259 
1260         // override the phone ID in prep for emergency call
1261         mPhoneSwitcherUT.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
1262         sendPreferredDataSuccessResult(1);
1263         processAllMessages();
1264         verify(mFuturePhone).complete(true);
1265 
1266         // Start and end the emergency call, which will start override timer
1267         notifyPhoneAsInCall(mPhone2);
1268         notifyPhoneAsInactive(mPhone2);
1269         // Start ECBM
1270         Message ecbmMessage = getEcbmRegistration(mPhone2);
1271         notifyEcbmStart(mPhone2, ecbmMessage);
1272 
1273         // DDS should not be switched back until ECBM ends, make sure there is no further
1274         // interaction.
1275         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 2000);
1276         processAllMessages();
1277         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
1278         // Make sure the correct broadcast is sent out for the phone ID
1279         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
1280 
1281         // End ECBM
1282         clearInvocations(mTelephonyRegistryManager);
1283         ecbmMessage = getEcbmRegistration(mPhone2);
1284         notifyEcbmEnd(mPhone2, ecbmMessage);
1285         // Verify that the DDS is successfully switched back after 1 second.
1286         moveTimeForward(1000);
1287         processAllMessages();
1288         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1289         AsyncResult res = new AsyncResult(1, null,  null);
1290         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
1291         processAllMessages();
1292         // Make sure the correct broadcast is sent out for the phone ID
1293         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
1294     }
1295 
1296     @Test
testEmergencyOverrideNoCallStart()1297     public void testEmergencyOverrideNoCallStart() throws Exception {
1298         PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
1299         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1300         initialize();
1301         // Phone 0 has sub 1, phone 1 has sub 2.
1302         // Sub 1 is default data sub.
1303         // Both are active subscriptions are active sub, as they are in both active slots.
1304         setMsimDefaultDataSubId(1);
1305         setAllPhonesInactive();
1306         clearInvocations(mMockRadioConfig);
1307         clearInvocations(mTelephonyRegistryManager);
1308 
1309         // override the phone ID in prep for emergency call
1310         mPhoneSwitcherUT.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
1311         sendPreferredDataSuccessResult(1);
1312         processAllMessages();
1313         verify(mFuturePhone).complete(true);
1314 
1315         // Do not start the call and make sure the override is removed once the timeout expires
1316         moveTimeForward(PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS);
1317         processAllMessages();
1318         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1319         AsyncResult res = new AsyncResult(1, null,  null);
1320         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
1321         processAllMessages();
1322 
1323         // Make sure the correct broadcast is sent out for the phone ID
1324         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
1325     }
1326 
1327     @Test
testEmergencyOverrideMultipleOverrideRequests()1328     public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
1329         PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
1330         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1331         initialize();
1332         // Phone 0 has sub 1, phone 1 has sub 2.
1333         // Sub 1 is default data sub.
1334         // Both are active subscriptions are active sub, as they are in both active slots.
1335         setMsimDefaultDataSubId(1);
1336         setAllPhonesInactive();
1337         clearInvocations(mMockRadioConfig);
1338         clearInvocations(mTelephonyRegistryManager);
1339 
1340         // override the phone ID in prep for emergency call
1341         LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
1342         CompletableFuture<Boolean> futurePhone = new CompletableFuture<>();
1343         futurePhone.whenComplete((r, error) -> queue.offer(r));
1344         mPhoneSwitcherUT.overrideDefaultDataForEmergency(1, 1, futurePhone);
1345         sendPreferredDataSuccessResult(1);
1346         processAllMessages();
1347         Boolean result = queue.poll();
1348         assertNotNull(result);
1349         assertTrue(result);
1350 
1351         // try override the phone ID again while there is an existing override for a different phone
1352         futurePhone = new CompletableFuture<>();
1353         futurePhone.whenComplete((r, error) -> queue.offer(r));
1354         mPhoneSwitcherUT.overrideDefaultDataForEmergency(0, 1, futurePhone);
1355         processAllMessages();
1356         result = queue.poll();
1357         assertNotNull(result);
1358         assertFalse(result);
1359         verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
1360 
1361         // Start and end the emergency call, which will start override timer
1362         notifyPhoneAsInCall(mPhone2);
1363         notifyPhoneAsInactive(mPhone2);
1364 
1365         // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
1366         moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
1367         processAllMessages();
1368         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
1369         AsyncResult res = new AsyncResult(1, null,  null);
1370         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
1371         processAllMessages();
1372 
1373         // Make sure the correct broadcast is sent out for the phone ID
1374         verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
1375     }
1376 
1377     @Test
testSetPreferredDataCallback()1378     public void testSetPreferredDataCallback() throws Exception {
1379         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1380         initialize();
1381 
1382         // Phone 0 has sub 1, phone 1 has sub 2.
1383         // Sub 1 is default data sub.
1384         // Both are active subscriptions are active sub, as they are in both active slots.
1385         setSlotIndexToSubId(0, 1);
1386         setSlotIndexToSubId(1, 2);
1387 
1388         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
1389                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
1390                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
1391 
1392         // Switch to primary before a primary is selected/inactive.
1393         setDefaultDataSubId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1394         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1395                 SubscriptionManager.INVALID_SUBSCRIPTION_ID, false, mSetOpptDataCallback1);
1396         processAllMessages();
1397 
1398         assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
1399                 mPhoneSwitcherUT.getAutoSelectedDataSubId());
1400         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
1401 
1402         // Verify that the switch to default sub is successful
1403         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1404                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, mSetOpptDataCallback1);
1405         processAllMessages();
1406 
1407         assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
1408                 mPhoneSwitcherUT.getAutoSelectedDataSubId());
1409         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1410 
1411         // once the primary is selected, it becomes the active sub.
1412         setDefaultDataSubId(2);
1413         assertEquals(2, mPhoneSwitcherUT.getActiveDataSubId());
1414 
1415         setDefaultDataSubId(1);
1416         // Validating on sub 10 which is inactive.
1417         clearInvocations(mSetOpptDataCallback1);
1418         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(10, true, mSetOpptDataCallback1);
1419         processAllMessages();
1420         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
1421 
1422         // Switch to active subId without validating. Should always succeed.
1423         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1424         processAllMessages();
1425         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
1426         processAllMessages();
1427         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1428 
1429         // Validating on sub 1 and fails.
1430         clearInvocations(mSetOpptDataCallback1);
1431         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(1, true, mSetOpptDataCallback1);
1432         processAllMessages();
1433         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 1);
1434         processAllMessages();
1435         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1436 
1437         // Validating on sub 2 and succeeds.
1438         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
1439         processAllMessages();
1440         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2);
1441         processAllMessages();
1442         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1443 
1444         // Switching data back to primary and validation fails.
1445         clearInvocations(mSetOpptDataCallback2);
1446         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1447                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1448         processAllMessages();
1449         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 1);
1450         processAllMessages();
1451         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1452 
1453         // Switching data back to primary and succeeds.
1454         clearInvocations(mSetOpptDataCallback2);
1455         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1456                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1457         processAllMessages();
1458         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 1);
1459         processAllMessages();
1460         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1461 
1462         // Back to back call on same subId.
1463         clearInvocations(mSetOpptDataCallback1);
1464         clearInvocations(mSetOpptDataCallback2);
1465         clearInvocations(mCellularNetworkValidator);
1466         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
1467         processAllMessages();
1468         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1469                 eq(mPhoneSwitcherUT.mValidationCallback));
1470         doReturn(true).when(mCellularNetworkValidator).isValidating();
1471         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
1472         processAllMessages();
1473         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1474         verify(mSetOpptDataCallback2, never()).onComplete(anyInt());
1475         // Validation succeeds.
1476         doReturn(false).when(mCellularNetworkValidator).isValidating();
1477         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2);
1478         processAllMessages();
1479         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1480 
1481         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1482                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
1483         processAllMessages();
1484         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 1);
1485         processAllMessages();
1486         clearInvocations(mSetOpptDataCallback1);
1487         clearInvocations(mSetOpptDataCallback2);
1488         clearInvocations(mCellularNetworkValidator);
1489         // Back to back call, call 1 to switch to subId 2, call 2 to switch back.
1490         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
1491         processAllMessages();
1492         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1493                 eq(mPhoneSwitcherUT.mValidationCallback));
1494         doReturn(true).when(mCellularNetworkValidator).isValidating();
1495         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
1496                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
1497         processAllMessages();
1498         // Call 1 should be cancelled and failed. Call 2 return success immediately as there's no
1499         // change.
1500         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
1501         verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1502     }
1503 
1504     @Test
testSetPreferredDataCallback_voiceCall()1505     public void testSetPreferredDataCallback_voiceCall() throws Exception {
1506         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1507         initialize();
1508         setAllPhonesInactive();
1509 
1510         // Phone 0 has sub 1, phone 1 has sub 2.
1511         // Sub 1 is default data sub.
1512         // Both are active subscriptions are active sub, as they are in both active slots.
1513         setSlotIndexToSubId(0, 1);
1514         setSlotIndexToSubId(1, 2);
1515         setDefaultDataSubId(1);
1516         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
1517 
1518         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
1519                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
1520                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
1521 
1522         // First temporarily switched to the opportunistic sub 2
1523         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1524         processAllMessages();
1525         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
1526         processAllMessages();
1527         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1528 
1529         // Voice call led back to default sub 1
1530         doReturn(mImsPhone).when(mPhone).getImsPhone();
1531         doReturn(true).when(mPhone).isUserDataEnabled();
1532         doReturn(true).when(mDataSettingsManager).isDataEnabled();
1533         mockImsRegTech(0, REGISTRATION_TECH_LTE);
1534         notifyPhoneAsInCall(mPhone);
1535 
1536         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
1537         assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
1538 
1539         // CBRS set preferred data back to default during the phone call
1540         clearInvocations(mSetOpptDataCallback1);
1541         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(SubscriptionManager
1542                 .DEFAULT_SUBSCRIPTION_ID, false, mSetOpptDataCallback1);
1543         processAllMessages();
1544 
1545         verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
1546         assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
1547         assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
1548                 mPhoneSwitcherUT.getAutoSelectedDataSubId());
1549     }
1550 
1551     @Test
testMultiSimConfigChange()1552     public void testMultiSimConfigChange() throws Exception {
1553         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1554         mActiveModemCount = 1;
1555         initialize();
1556         sendPreferredDataSuccessResult(0);
1557 
1558         // Phone 0 has sub 1, phone 1 has sub 2.
1559         // Sub 1 is default data sub.
1560         // Both are active subscriptions are active sub, as they are in both active slots.
1561         setSlotIndexToSubId(0, 1);
1562         setDefaultDataSubId(1);
1563 
1564         setNumPhones(2, 2);
1565         AsyncResult result = new AsyncResult(null, 2, null);
1566         Message.obtain(mPhoneSwitcherUT, EVENT_MULTI_SIM_CONFIG_CHANGED, result).sendToTarget();
1567         processAllMessages();
1568 
1569         verify(mPhone2).registerForEmergencyCallToggle(any(), anyInt(), any());
1570         verify(mPhone2).registerForPreciseCallStateChanged(any(), anyInt(), any());
1571 
1572         clearInvocations(mMockRadioConfig);
1573         setSlotIndexToSubId(1, 2);
1574         setDefaultDataSubId(2);
1575         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1576     }
1577 
1578     @Test
testValidationOffSwitch_shouldSwitchOnNetworkAvailable()1579     public void testValidationOffSwitch_shouldSwitchOnNetworkAvailable() throws Exception {
1580         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1581         initialize();
1582         // Phone 0 has sub 1, phone 1 has sub 2.
1583         // Sub 1 is default data sub.
1584         // Both are active subscriptions are active sub, as they are in both active slots.
1585         setSlotIndexToSubId(0, 1);
1586         setSlotIndexToSubId(1, 2);
1587         setDefaultDataSubId(1);
1588         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1589         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1590                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1591         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1592                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1593         clearInvocations(mMockRadioConfig);
1594         setAllPhonesInactive();
1595         // Initialization done.
1596 
1597         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
1598                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
1599                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
1600 
1601         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1602         processAllMessages();
1603         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1604                 eq(mPhoneSwitcherUT.mValidationCallback));
1605         doReturn(true).when(mCellularNetworkValidator).isValidating();
1606 
1607         // Network available on different sub. Should do nothing.
1608         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 1);
1609         processAllMessages();
1610         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1611 
1612         // Network available on corresponding sub. Should confirm switch.
1613         mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
1614         processAllMessages();
1615         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1616     }
1617 
1618     @Test
testValidationOffSwitch_shouldSwitchOnTimeOut()1619     public void testValidationOffSwitch_shouldSwitchOnTimeOut() throws Exception {
1620         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1621         initialize();
1622         // Phone 0 has sub 1, phone 1 has sub 2.
1623         // Sub 1 is default data sub.
1624         // Both are active subscriptions are active sub, as they are in both active slots.
1625         setSlotIndexToSubId(0, 1);
1626         setSlotIndexToSubId(1, 2);
1627         setDefaultDataSubId(1);
1628         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1629         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1630                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
1631         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1632                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
1633         clearInvocations(mMockRadioConfig);
1634         setAllPhonesInactive();
1635         // Initialization done.
1636 
1637         doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
1638                 .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
1639                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
1640 
1641         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
1642         processAllMessages();
1643         verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
1644                 eq(mPhoneSwitcherUT.mValidationCallback));
1645         doReturn(true).when(mCellularNetworkValidator).isValidating();
1646 
1647         // Validation failed on different sub. Should do nothing.
1648         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 1);
1649         processAllMessages();
1650         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
1651 
1652         // Network available on corresponding sub. Should confirm switch.
1653         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2);
1654         processAllMessages();
1655         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
1656     }
1657 
1658     @Test
testRetry_DDS_switch_Failure()1659     public void testRetry_DDS_switch_Failure() throws Exception {
1660         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1661         mActiveModemCount = 2;
1662         initialize();
1663         setSlotIndexToSubId(0, 1);
1664         setDefaultDataSubId(1);
1665 
1666         clearInvocations(mMockRadioConfig);
1667         // for exceptions OP_NOT_ALLOWED_DURING_VOICE_CALL and INVALID_SIM_STATE,
1668         // modem retry not invoked.
1669         AsyncResult res1 = new AsyncResult(0, null,
1670                 new CommandException(CommandException.Error.INVALID_SIM_STATE));
1671         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res1).sendToTarget();
1672         processAllMessages();
1673         moveTimeForward(5000);
1674         processAllMessages();
1675         verify(mMockRadioConfig, times(0)).setPreferredDataModem(eq(0), any());
1676 
1677         AsyncResult res2 = new AsyncResult(0, null,
1678                 new CommandException(CommandException.Error.NETWORK_NOT_READY));
1679         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res2).sendToTarget();
1680         processAllMessages();
1681         moveTimeForward(5000);
1682         processAllMessages();
1683 
1684         verify(mMockRadioConfig, times(1)).setPreferredDataModem(eq(0), any());
1685 
1686         clearInvocations(mMockRadioConfig);
1687         doReturn(mSubscriptionInfo).when(mSubscriptionManagerService)
1688                 .getActiveSubscriptionInfoForSimSlotIndex(eq(0), any(), any());
1689         doReturn(true).when(mSubscriptionInfo).areUiccApplicationsEnabled();
1690         doReturn(mIccCard).when(mPhone).getIccCard();
1691         doReturn(true).when(mIccCard).isEmptyProfile();
1692         final Intent intent1 = new Intent(ACTION_SIM_APPLICATION_STATE_CHANGED);
1693         intent1.putExtra(EXTRA_SIM_STATE, SIM_STATE_LOADED);
1694         intent1.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
1695         mContext.sendBroadcast(intent1);
1696         processAllMessages();
1697 
1698         verify(mMockRadioConfig, times(0)).setPreferredDataModem(eq(0), any());
1699 
1700         doReturn(false).when(mIccCard).isEmptyProfile();
1701         final Intent intent2 = new Intent(ACTION_SIM_APPLICATION_STATE_CHANGED);
1702         intent2.putExtra(EXTRA_SIM_STATE, SIM_STATE_LOADED);
1703         intent2.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
1704         mContext.sendBroadcast(intent2);
1705         processAllMessages();
1706 
1707         verify(mMockRadioConfig, times(1)).setPreferredDataModem(eq(0), any());
1708     }
1709 
1710     @Test
testScheduledRetryWhileMultiSimConfigChange()1711     public void testScheduledRetryWhileMultiSimConfigChange() throws Exception {
1712         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
1713         initialize();
1714 
1715         // Phone 0 has sub 1, phone 1 has sub 2.
1716         // Sub 1 is default data sub.
1717         setSlotIndexToSubId(0, 1);
1718         setSlotIndexToSubId(1, 2);
1719 
1720         // for EVENT_MODEM_COMMAND_RETRY
1721         AsyncResult res = new AsyncResult(
1722                 1, null,  new CommandException(CommandException.Error.GENERIC_FAILURE));
1723         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
1724         processAllMessages();
1725 
1726         // reduce count of phone
1727         setNumPhones(1, 1);
1728         AsyncResult result = new AsyncResult(null, 1, null);
1729         Message.obtain(mPhoneSwitcherUT, EVENT_MULTI_SIM_CONFIG_CHANGED, result).sendToTarget();
1730         processAllMessages();
1731 
1732         // fire retries
1733         moveTimeForward(5000);
1734         processAllMessages();
1735 
1736         verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
1737         verify(mCommandsInterface1, never()).setDataAllowed(anyBoolean(), any());
1738     }
1739 
1740     @Test
testRegisterForImsRegistrationCallback()1741     public void testRegisterForImsRegistrationCallback() throws Exception {
1742         initialize();
1743         setAllPhonesInactive();
1744 
1745         // Phone 0 has sub 1, phone 1 has sub 2.
1746         // Sub 1 is default data sub.
1747         // Both are active subscriptions are active sub, as they are in both active slots.
1748         setSlotIndexToSubId(0, 1);
1749         setSlotIndexToSubId(1, 2);
1750         setDefaultDataSubId(1);
1751         processAllMessages();
1752 
1753         // Phone 0 should be the default data phoneId.
1754         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
1755 
1756         doReturn(true).when(mPhone).isUserDataEnabled();
1757         mockImsRegTech(0, REGISTRATION_TECH_LTE);
1758         mockImsRegisterCallback(0);
1759         mockImsRegisterCallback(1);
1760 
1761         notifyImsRegistrationTechChange(mPhone);
1762 
1763         // Verify that the callback is re-registered when the IMS registration callback is called.
1764         verify(mMockImsRegisterCallback, times(2)).setCallback(any(), anyInt(), any(), any());
1765     }
1766 
1767     @Test
testReceivingImsRegistrationTech()1768     public void testReceivingImsRegistrationTech() throws Exception {
1769         doReturn(true).when(mFeatureFlags).changeMethodOfObtainingImsRegistrationRadioTech();
1770 
1771         // Set up input and output for testing
1772         ImsPhone testImsPhone = mock(ImsPhone.class);
1773         doReturn(testImsPhone).when(mPhone).getImsPhone();
1774         doReturn(testImsPhone).when(mPhone2).getImsPhone();
1775         ImsPhoneCall testImsPhoneCall = mock(ImsPhoneCall.class);
1776         doReturn(Call.State.IDLE).when(testImsPhoneCall).getState();
1777         doReturn(true).when(testImsPhoneCall).isIdle();
1778         doReturn(testImsPhoneCall).when(testImsPhone).getForegroundCall();
1779         doReturn(testImsPhoneCall).when(testImsPhone).getBackgroundCall();
1780         doReturn(testImsPhoneCall).when(testImsPhone).getRingingCall();
1781 
1782         doNothing().when(testImsPhone).registerForImsRegistrationChanges(any(), anyInt(), any());
1783 
1784         initialize();
1785         setAllPhonesInactive();
1786 
1787         // Phone 0 has sub 1, phone 1 has sub 2.
1788         // Sub 1 is default data sub.
1789         // Both are active subscriptions are active sub, as they are in both active slots.
1790         setSlotIndexToSubId(0, 1);
1791         setSlotIndexToSubId(1, 2);
1792         setDefaultDataSubId(1);
1793         processAllMessages();
1794 
1795         // Phone 0 should be the default data phoneId.
1796         assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
1797 
1798         doReturn(true).when(mPhone).isUserDataEnabled();
1799         mockImsRegTech(0, REGISTRATION_TECH_NONE);
1800         mockImsRegisterCallback(0);
1801         mockImsRegisterCallback(1);
1802 
1803         AsyncResult ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
1804                 0, REGISTRATION_TECH_LTE, REGISTRATION_STATE_REGISTERED), null);
1805         notifyImsRegistrationTechChangeWithAsyncResult(ar);
1806 
1807         // Verify cached IMS registration tech is LTE
1808         assertTrue(REGISTRATION_TECH_LTE == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
1809 
1810         ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
1811                 0, REGISTRATION_TECH_IWLAN, REGISTRATION_STATE_REGISTERED), null);
1812         notifyImsRegistrationTechChangeWithAsyncResult(ar);
1813 
1814         // Verify cached IMS registration tech is WiFi
1815         assertTrue(REGISTRATION_TECH_IWLAN
1816                 == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
1817 
1818         ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
1819                 0, REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED), null);
1820         notifyImsRegistrationTechChangeWithAsyncResult(ar);
1821 
1822         // Verify cached IMS registration tech is NONE
1823         assertTrue(REGISTRATION_TECH_NONE == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
1824 
1825         // Verify there is no crash
1826         notifyImsRegistrationTechChangeWithAsyncResult(null);
1827 
1828         // Verify that the callback is not re-registered
1829         // when the IMS registration callback is called.
1830         verify(mMockImsRegisterCallback, never()).setCallback(any(), anyInt(), any(), any());
1831     }
1832 
1833     /* Private utility methods start here */
1834 
prepareIdealAutoSwitchCondition()1835     private void prepareIdealAutoSwitchCondition() {
1836         // 1. service state changes
1837         serviceStateChanged(1, NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
1838         serviceStateChanged(0, NetworkRegistrationInfo
1839                 .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
1840 
1841         // 2.1 User data enabled on primary SIM
1842         doReturn(true).when(mPhone).isUserDataEnabled();
1843 
1844         // 2.2 Auto switch feature is enabled
1845         doReturn(true).when(mPhone2).isDataAllowed();
1846         doReturn(true).when(mDataSettingsManager2).isDataEnabled();
1847 
1848         mPhoneSwitcherUT.sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH);
1849     }
1850 
serviceStateChanged(int phoneId, @NetworkRegistrationInfo.RegistrationState int dataRegState)1851     private void serviceStateChanged(int phoneId,
1852             @NetworkRegistrationInfo.RegistrationState int dataRegState) {
1853 
1854         ServiceState ss = new ServiceState();
1855 
1856         ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
1857                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
1858                 .setRegistrationState(dataRegState)
1859                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
1860                 .build());
1861 
1862         ss.setDataRoamingFromRegistration(dataRegState
1863                 == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
1864 
1865         doReturn(ss).when(mPhones[phoneId]).getServiceState();
1866 
1867         Message msg = mPhoneSwitcherUT.obtainMessage(EVENT_SERVICE_STATE_CHANGED);
1868         msg.obj = new AsyncResult(phoneId, null, null);
1869         mPhoneSwitcherUT.sendMessage(msg);
1870     }
1871 
setAllPhonesInactive()1872     private void setAllPhonesInactive() {
1873         doReturn(mInactiveCall).when(mPhone).getForegroundCall();
1874         doReturn(mInactiveCall).when(mPhone).getBackgroundCall();
1875         doReturn(mInactiveCall).when(mPhone).getRingingCall();
1876         doReturn(mInactiveCall).when(mPhone2).getForegroundCall();
1877         doReturn(mInactiveCall).when(mPhone2).getBackgroundCall();
1878         doReturn(mInactiveCall).when(mPhone2).getRingingCall();
1879         doReturn(mInactiveCall).when(mImsPhone).getForegroundCall();
1880         doReturn(mInactiveCall).when(mImsPhone).getBackgroundCall();
1881         doReturn(mInactiveCall).when(mImsPhone).getRingingCall();
1882     }
1883 
notifyPhoneAsInCall(Phone phone)1884     private void notifyPhoneAsInCall(Phone phone) {
1885         doReturn(mActiveCall).when(phone).getForegroundCall();
1886         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1887         processAllMessages();
1888     }
1889 
notifyPhoneAsInDial(Phone phone)1890     private void notifyPhoneAsInDial(Phone phone) {
1891         doReturn(mDialCall).when(phone).getForegroundCall();
1892         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1893         processAllMessages();
1894     }
1895 
notifyPhoneAsAlerting(Phone phone)1896     private void notifyPhoneAsAlerting(Phone phone) {
1897         doReturn(mAlertingCall).when(phone).getForegroundCall();
1898         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1899         processAllMessages();
1900     }
1901 
notifyPhoneAsInIncomingCall(Phone phone)1902     private void notifyPhoneAsInIncomingCall(Phone phone) {
1903         doReturn(mIncomingCall).when(phone).getForegroundCall();
1904         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1905         processAllMessages();
1906     }
1907 
notifyPhoneAsInHoldingCall(Phone phone)1908     private void notifyPhoneAsInHoldingCall(Phone phone) {
1909         doReturn(mHoldingCall).when(phone).getBackgroundCall();
1910         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1911         processAllMessages();
1912     }
1913 
notifyPhoneAsInactive(Phone phone)1914     private void notifyPhoneAsInactive(Phone phone) {
1915         doReturn(mInactiveCall).when(phone).getForegroundCall();
1916         mPhoneSwitcherUT.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
1917         processAllMessages();
1918     }
1919 
notifyDataEnabled(boolean dataEnabled)1920     private void notifyDataEnabled(boolean dataEnabled) {
1921         doReturn(true).when(mPhone).isUserDataEnabled();
1922         doReturn(dataEnabled).when(mDataSettingsManager).isDataEnabled();
1923         doReturn(dataEnabled).when(mDataSettingsManager2).isDataEnabled();
1924         mDataSettingsManagerCallbacks.get(0).onDataEnabledChanged(dataEnabled, 123 , "");
1925         if (mDataSettingsManagerCallbacks.size() > 1) {
1926             mDataSettingsManagerCallbacks.get(1).onDataEnabledChanged(dataEnabled, 123, "");
1927         }
1928         processAllMessages();
1929     }
1930 
notifyImsRegistrationTechChange(Phone phone)1931     private void notifyImsRegistrationTechChange(Phone phone) {
1932         mPhoneSwitcherUT.sendEmptyMessage(EVENT_IMS_RADIO_TECH_CHANGED);
1933         processAllMessages();
1934     }
1935 
notifyImsRegistrationTechChangeWithAsyncResult(AsyncResult ar)1936     private void notifyImsRegistrationTechChangeWithAsyncResult(AsyncResult ar) {
1937         mPhoneSwitcherUT.sendMessage(
1938                 mPhoneSwitcherUT.obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED, ar));
1939         processAllMessages();
1940     }
1941 
getEcbmRegistration(Phone phone)1942     private Message getEcbmRegistration(Phone phone) {
1943         ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1944         ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
1945 
1946         verify(phone).registerForEmergencyCallToggle(handlerCaptor.capture(), intCaptor.capture(),
1947                 any());
1948         assertNotNull(handlerCaptor.getValue());
1949         assertNotNull(intCaptor.getValue());
1950         Message message = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
1951         return message;
1952     }
1953 
notifyEcbmStart(Phone phone, Message ecmMessage)1954     private void notifyEcbmStart(Phone phone, Message ecmMessage) {
1955         doReturn(mInactiveCall).when(phone).getForegroundCall();
1956         doReturn(true).when(phone).isInEcm();
1957         ecmMessage.sendToTarget();
1958         processAllMessages();
1959     }
1960 
notifyEcbmEnd(Phone phone, Message ecmMessage)1961     private void notifyEcbmEnd(Phone phone, Message ecmMessage) {
1962         doReturn(false).when(phone).isInEcm();
1963         ecmMessage.sendToTarget();
1964         processAllMessages();
1965     }
1966 
sendPreferredDataSuccessResult(int phoneId)1967     private void sendPreferredDataSuccessResult(int phoneId) {
1968         // make sure the radio command is called and then send a success result
1969         processAllMessages();
1970         ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
1971         verify(mMockRadioConfig).setPreferredDataModem(eq(phoneId), msgCaptor.capture());
1972         assertNotNull(msgCaptor.getValue());
1973         // Send back successful result
1974         AsyncResult.forMessage(msgCaptor.getValue(), null, null);
1975         msgCaptor.getValue().sendToTarget();
1976         processAllMessages();
1977     }
1978 
setMsimDefaultDataSubId(int defaultDataSub)1979     private void setMsimDefaultDataSubId(int defaultDataSub) throws Exception {
1980         for (int i = 0; i < mActiveModemCount; i++) {
1981             setSlotIndexToSubId(i, i + 1);
1982         }
1983         setDefaultDataSubId(defaultDataSub);
1984         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
1985         for (int i = 0; i < mActiveModemCount; i++) {
1986             if (defaultDataSub == (i + 1)) {
1987                 // sub id is always phoneId+1 for testing
1988                 assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1989                         new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), i));
1990             } else {
1991                 assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
1992                         new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), i));
1993             }
1994         }
1995     }
1996 
initialize()1997     private void initialize() throws Exception {
1998         setNumPhones(mActiveModemCount, mSupportedModemCount);
1999 
2000         initializeSubControllerMock();
2001         initializeCommandInterfacesMock();
2002         initializeTelRegistryMock();
2003         initializeConfigMock();
2004 
2005         mPhoneSwitcherUT = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper(),
2006                 mFeatureFlags);
2007 
2008         Field field = PhoneSwitcher.class.getDeclaredField("mDataSettingsManagerCallbacks");
2009         field.setAccessible(true);
2010         mDataSettingsManagerCallbacks =
2011                 (Map<Integer, DataSettingsManager.DataSettingsManagerCallback>)
2012                         field.get(mPhoneSwitcherUT);
2013 
2014         field = PhoneSwitcher.class.getDeclaredField("mAutoDataSwitchCallback");
2015         field.setAccessible(true);
2016         mAutoDataSwitchCallback = (AutoDataSwitchController.AutoDataSwitchControllerCallback)
2017                 field.get(mPhoneSwitcherUT);
2018 
2019         replaceInstance(PhoneSwitcher.class, "mAutoDataSwitchController", mPhoneSwitcherUT,
2020                 mAutoDataSwitchController);
2021         processAllMessages();
2022 
2023         verify(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
2024 
2025         ArgumentCaptor<SubscriptionManagerServiceCallback> callbackCaptor =
2026                 ArgumentCaptor.forClass(SubscriptionManagerServiceCallback.class);
2027         verify(mSubscriptionManagerService).registerCallback(callbackCaptor.capture());
2028         mSubscriptionManagerServiceCallback = callbackCaptor.getValue();
2029     }
2030 
2031     /**
2032      * Certain variables needs initialized depending on number of phones.
2033      */
setNumPhones(int activeModemCount, int supportedModemCount)2034     private void setNumPhones(int activeModemCount, int supportedModemCount) throws Exception {
2035         mDataAllowed = new boolean[supportedModemCount];
2036         mSlotIndexToSubId = new int[supportedModemCount][];
2037         doReturn(0).when(mPhone).getPhoneId();
2038         doReturn(1).when(mPhone2).getPhoneId();
2039         doReturn(true).when(mPhone2).isUserDataEnabled();
2040         doReturn(mDataSettingsManager2).when(mPhone2).getDataSettingsManager();
2041         doReturn(mSST2).when(mPhone2).getServiceStateTracker();
2042         doReturn(mDisplayInfoController).when(mPhone2).getDisplayInfoController();
2043         doReturn(mSignalStrengthController).when(mPhone2).getSignalStrengthController();
2044         doReturn(mSignalStrength).when(mPhone2).getSignalStrength();
2045         for (int i = 0; i < supportedModemCount; i++) {
2046             mSlotIndexToSubId[i] = new int[1];
2047             mSlotIndexToSubId[i][0] = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2048         }
2049 
2050         doReturn(activeModemCount).when(mTelephonyManager).getPhoneCount();
2051         doReturn(activeModemCount).when(mTelephonyManager).getActiveModemCount();
2052         doReturn(supportedModemCount).when(mTelephonyManager).getSupportedModemCount();
2053 
2054         if (activeModemCount == 1) {
2055             mPhones = new Phone[]{mPhone};
2056         } else if (activeModemCount == 2) {
2057             mPhones = new Phone[]{mPhone, mPhone2};
2058         }
2059 
2060         replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
2061         for (Phone phone : mPhones) {
2062             ServiceState ss = new ServiceState();
2063 
2064             ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
2065                     .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
2066                     .setRegistrationState(
2067                             NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
2068                     .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
2069                     .build());
2070             doReturn(ss).when(phone).getServiceState();
2071         }
2072     }
2073 
initializeCommandInterfacesMock()2074     private void initializeCommandInterfacesMock() {
2075         // Tell PhoneSwitcher that radio is on.
2076         doAnswer(invocation -> {
2077             Handler handler = (Handler) invocation.getArguments()[0];
2078             int message = (int) invocation.getArguments()[1];
2079             Object obj = invocation.getArguments()[2];
2080             handler.obtainMessage(message, obj).sendToTarget();
2081             return null;
2082         }).when(mCommandsInterface0).registerForAvailable(any(), anyInt(), any());
2083 
2084         // Store values of dataAllowed in mDataAllowed[] for easier checking.
2085         doAnswer(invocation -> {
2086             mDataAllowed[0] = (boolean) invocation.getArguments()[0];
2087             return null;
2088         }).when(mCommandsInterface0).setDataAllowed(anyBoolean(), any());
2089 
2090         if (mSupportedModemCount > 1) {
2091             doAnswer(invocation -> {
2092                 mDataAllowed[1] = (boolean) invocation.getArguments()[0];
2093                 return null;
2094             }).when(mCommandsInterface1).setDataAllowed(anyBoolean(), any());
2095         }
2096     }
2097 
2098     /**
2099      * Store subChangedListener of PhoneSwitcher so that testing can notify
2100      * PhoneSwitcher of sub change.
2101      */
initializeTelRegistryMock()2102     private void initializeTelRegistryMock() throws Exception {
2103         doAnswer(invocation -> {
2104             SubscriptionManager.OnSubscriptionsChangedListener subChangedListener =
2105                     (SubscriptionManager.OnSubscriptionsChangedListener) invocation.getArguments()[0];
2106             mSubChangedListener = subChangedListener;
2107             mSubChangedListener.onSubscriptionsChanged();
2108             return null;
2109         }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
2110     }
2111 
2112     /**
2113      * Capture mNetworkProviderMessenger so that testing can request or release
2114      * network requests on PhoneSwitcher.
2115      */
initializeSubControllerMock()2116     private void initializeSubControllerMock() throws Exception {
2117         doReturn(mDefaultDataSub).when(mSubscriptionManagerService).getDefaultDataSubId();
2118         doReturn(mDefaultDataSub).when(mMockedIsub).getDefaultDataSubId();
2119         doReturn(0).when(mSubscriptionManagerService).getPhoneId(1);
2120         doReturn(0).when(mMockedIsub).getPhoneId(1);
2121         doReturn(1).when(mSubscriptionManagerService).getPhoneId(2);
2122         doReturn(1).when(mMockedIsub).getPhoneId(2);
2123 
2124         doAnswer(invocation -> {
2125             int phoneId = (int) invocation.getArguments()[0];
2126             if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
2127                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2128             } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
2129                 return mSlotIndexToSubId[0][0];
2130             } else {
2131                 return mSlotIndexToSubId[phoneId][0];
2132             }
2133         }).when(mMockedIsub).getSubId(anyInt());
2134 
2135         doAnswer(invocation -> {
2136             int phoneId = (int) invocation.getArguments()[0];
2137             if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
2138                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2139             } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
2140                 return mSlotIndexToSubId[0][0];
2141             } else {
2142                 return mSlotIndexToSubId[phoneId][0];
2143             }
2144         }).when(mSubscriptionManagerService).getSubId(anyInt());
2145 
2146         doAnswer(invocation -> {
2147             int subId = (int) invocation.getArguments()[0];
2148 
2149             if (!SubscriptionManager.isUsableSubIdValue(subId)) return null;
2150 
2151             int slotIndex = -1;
2152             for (int i = 0; i < mSlotIndexToSubId.length; i++) {
2153                 if (mSlotIndexToSubId[i][0] == subId) slotIndex = i;
2154             }
2155             return new SubscriptionInfoInternal.Builder()
2156                     .setSimSlotIndex(slotIndex).setId(subId).build();
2157         }).when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
2158 
2159         doReturn(new int[mSlotIndexToSubId.length]).when(mSubscriptionManagerService)
2160                 .getActiveSubIdList(true);
2161     }
2162 
initializeConfigMock()2163     private void initializeConfigMock() {
2164         doReturn(mDataNetworkController).when(mPhone).getDataNetworkController();
2165         doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
2166         doReturn(1000L).when(mDataConfigManager)
2167                 .getAutoDataSwitchAvailabilityStabilityTimeThreshold();
2168         doReturn(7).when(mDataConfigManager).getAutoDataSwitchValidationMaxRetry();
2169         doReturn(true).when(mDataConfigManager).isPingTestBeforeAutoDataSwitchRequired();
2170     }
2171 
setDefaultDataSubId(int defaultDataSub)2172     private void setDefaultDataSubId(int defaultDataSub) {
2173         mDefaultDataSub = defaultDataSub;
2174         doReturn(mDefaultDataSub).when(mSubscriptionManagerService).getDefaultDataSubId();
2175         for (Phone phone : mPhones) {
2176             doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
2177                     .when(phone).isUserDataEnabled();
2178         }
2179         mSubscriptionManagerServiceCallback.onDefaultDataSubscriptionChanged(defaultDataSub);
2180         processAllMessages();
2181     }
2182 
setSlotIndexToSubId(int slotId, int subId)2183     private void setSlotIndexToSubId(int slotId, int subId) {
2184         mSlotIndexToSubId[slotId][0] = subId;
2185         Phone phone = slotId == 0 ? mPhone : mPhone2;
2186         doReturn(subId).when(phone).getSubId();
2187     }
2188 
2189     /**
2190      * Create an internet PDN network request and send it to PhoneSwitcher.
2191      */
addInternetNetworkRequest(Integer subId, int score)2192     private NetworkRequest addInternetNetworkRequest(Integer subId, int score) throws Exception {
2193         return addInternetNetworkRequest(subId, score, false);
2194     }
2195 
addInternetNetworkRequest(Integer subId, int score, boolean restricted)2196     private NetworkRequest addInternetNetworkRequest(Integer subId, int score, boolean restricted)
2197             throws Exception {
2198         NetworkCapabilities netCap = (new NetworkCapabilities())
2199                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
2200                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2201         if (restricted) {
2202             netCap.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
2203         }
2204 
2205         if (subId != null) {
2206             netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
2207                     .setSubscriptionId(subId).build());
2208         }
2209         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
2210                 0, NetworkRequest.Type.REQUEST);
2211 
2212         mPhoneSwitcherUT.onRequestNetwork(networkRequest);
2213         return networkRequest;
2214     }
2215 
2216     /**
2217      * Create a mms PDN network request and send it to PhoneSwitcher.
2218      */
addMmsNetworkRequest(Integer subId)2219     private NetworkRequest addMmsNetworkRequest(Integer subId) throws Exception {
2220         NetworkCapabilities netCap = (new NetworkCapabilities())
2221                 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
2222                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
2223                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2224         if (subId != null) {
2225             netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
2226                     .setSubscriptionId(subId).build());
2227         }
2228         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
2229                 1, NetworkRequest.Type.REQUEST);
2230         mPhoneSwitcherUT.onRequestNetwork(networkRequest);
2231         return networkRequest;
2232     }
2233 
2234     /**
2235      * Tell PhoneSwitcher to release a network request.
2236      */
releaseNetworkRequest(NetworkRequest networkRequest)2237     private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
2238         mPhoneSwitcherUT.onReleaseNetwork(networkRequest);
2239     }
2240 }
2241