/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;

import static com.android.internal.telephony.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_MULTI_SIM_CONFIG_CHANGED;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import com.android.internal.telephony.dataconnection.DataEnabledSettings;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class PhoneSwitcherTest extends TelephonyTest {
    private static final int ACTIVE_PHONE_SWITCH = 1;

    @Mock
    private CommandsInterface mCommandsInterface0;
    @Mock
    private CommandsInterface mCommandsInterface1;
    @Mock
    private Phone mPhone2; // mPhone as phone 1 is already defined in TelephonyTest.
    @Mock
    private DataEnabledSettings mDataEnabledSettings2;
    @Mock
    private Handler mActivePhoneSwitchHandler;
    @Mock
    private GsmCdmaCall mActiveCall;
    @Mock
    private GsmCdmaCall mHoldingCall;
    @Mock
    private GsmCdmaCall mInactiveCall;
    @Mock
    private ISetOpportunisticDataCallback mSetOpptDataCallback1;
    @Mock
    private ISetOpportunisticDataCallback mSetOpptDataCallback2;
    @Mock
    CompletableFuture<Boolean> mFuturePhone;

    private PhoneSwitcher mPhoneSwitcher;
    private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
    private ConnectivityManager mConnectivityManager;
    // The messenger of PhoneSwitcher used to receive network requests.
    private Messenger mNetworkProviderMessenger = null;
    private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private int[][] mSlotIndexToSubId;
    private boolean[] mDataAllowed;
    private int mActiveModemCount = 2;
    private int mSupportedModemCount = 2;
    private int mMaxDataAttachModemCount = 1;

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());

        PhoneCapability phoneCapability = new PhoneCapability(1, 1, 0, null, false);
        doReturn(phoneCapability).when(mPhoneConfigurationManager).getCurrentPhoneCapability();

        doReturn(Call.State.ACTIVE).when(mActiveCall).getState();
        doReturn(Call.State.IDLE).when(mInactiveCall).getState();
        doReturn(Call.State.HOLDING).when(mHoldingCall).getState();

        replaceInstance(Phone.class, "mCi", mPhone, mCommandsInterface0);
        replaceInstance(Phone.class, "mCi", mPhone2, mCommandsInterface1);
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    /**
     * Test that a single phone case results in our phone being active and the RIL called
     */
    @Test
    @SmallTest
    public void testRegister() throws Exception {
        initialize();

        // verify nothing has been done while there are no inputs
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("data allowed initially", mDataAllowed[1]);

        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);

        assertFalse("phone active after request", mPhoneSwitcher
                .shouldApplyNetworkRequest(internetNetworkRequest, 0));

        // not registered yet - shouldn't inc
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());

        mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);

        setDefaultDataSubId(0);

        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());

        setSlotIndexToSubId(0, 0);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertTrue("data not allowed", mDataAllowed[0]);

        // now try various things that should cause the active phone to switch:
        // 1 lose default via default sub change
        // 2 gain default via default sub change
        // 3 lose default via sub->phone change
        // 4 gain default via sub->phone change
        // 5 lose default network request
        // 6 gain subscription-specific request
        // 7 lose via sub->phone change
        // 8 gain via sub->phone change
        // 9 lose subscription-specific request
        // 10 don't switch phones when in emergency mode

        // 1 lose default via default sub change
        setDefaultDataSubId(1);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);

        setSlotIndexToSubId(1, 1);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);
        assertTrue("data not allowed", mDataAllowed[1]);

        // 2 gain default via default sub change
        setDefaultDataSubId(0);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[1]);
        assertTrue("data not allowed", mDataAllowed[0]);

        // 3 lose default via sub->phone change
        setSlotIndexToSubId(0, 2);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 4 gain default via sub->phone change
        setSlotIndexToSubId(0, 0);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 5 lose default network request
        releaseNetworkRequest(internetNetworkRequest);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 6 gain subscription-specific request
        NetworkRequest specificInternetRequest = addInternetNetworkRequest(0, 50);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 7 lose via sub->phone change
        setSlotIndexToSubId(0, 1);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 8 gain via sub->phone change
        setSlotIndexToSubId(0, 0);
        mSubChangedListener.onSubscriptionsChanged();
        processAllMessages();

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 9 lose subscription-specific request
        releaseNetworkRequest(specificInternetRequest);

        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mActivePhoneSwitchHandler);
        assertFalse("data allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // 10 don't switch phones when in emergency mode
        // not ready yet - Phone turns out to be hard to stub out
//        phones[0].setInEmergencyCall(true);
//        connectivityServiceMock.addDefaultRequest();
//        processAllMessages();
//        if (testHandler.getActivePhoneSwitchCount() != 11) {
//            fail("after release of request, ActivePhoneSwitchCount not 11!");
//        }
//        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
//        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
//
//        phones[0].setInEmergencyCall(false);
//        connectivityServiceMock.addDefaultRequest();
//        processAllMessages();
//        if (testHandler.getActivePhoneSwitchCount() != 12) {
//            fail("after release of request, ActivePhoneSwitchCount not 11!");
//        }
//        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
//        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
    }

    /**
     * Test a multi-sim case with limited active phones:
     * - lose default via default sub change
     * - lose default via sub->phone change
     * - gain default via sub->phone change
     * - gain default via default sub change
     * - lose default network request
     * - gain subscription-specific request
     * - lose via sub->phone change
     * - gain via sub->phone change
     * - lose subscription-specific request
     * - tear down low priority phone when new request comes in
     * - tear down low priority phone when sub change causes split
     * - bring up low priority phone when sub change causes join
     * - don't switch phones when in emergency mode
     */
    @Test
    @SmallTest
    public void testPrioritization() throws Exception {
        initialize();

        addInternetNetworkRequest(null, 50);
        setSlotIndexToSubId(0, 0);
        setSlotIndexToSubId(1, 1);
        setDefaultDataSubId(0);
        mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);
        processAllMessages();
        // verify initial conditions
        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());

        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        // now start a higher priority connection on the other sub
        addMmsNetworkRequest(1);

        // After gain of network request, mActivePhoneSwitchHandler should be notified 2 times.
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertFalse("data allowed", mDataAllowed[0]);
        assertTrue("data not allowed", mDataAllowed[1]);
    }

    /**
     * Verify we don't send spurious DATA_ALLOWED calls when another NetworkProvider
     * wins (ie, switch to wifi).
     */
    @Test
    @SmallTest
    public void testHigherPriorityDefault() throws Exception {
        initialize();

        addInternetNetworkRequest(null, 50);

        setSlotIndexToSubId(0, 0);
        setSlotIndexToSubId(1, 1);
        setDefaultDataSubId(0);

        // Phone 0 should be active
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        addInternetNetworkRequest(null, 100);

        // should be no change
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);

        addInternetNetworkRequest(null, 0);
        // should be no change
        assertTrue("data not allowed", mDataAllowed[0]);
        assertFalse("data allowed", mDataAllowed[1]);
    }

    /**
     * Verify testSetPreferredData.
     * When preferredData is set, it overwrites defaultData sub to be active sub in single
     * active phone mode. If it's unset (to DEFAULT_SUBSCRIPTION_ID), defaultData sub becomes
     * active one.
     */
    @Test
    @SmallTest
    public void testSetPreferredData() throws Exception {
        initialize();

        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);

        doReturn(true).when(mSubscriptionController).isOpportunistic(2);

        // Notify phoneSwitcher about default data sub and default network request.
        addInternetNetworkRequest(null, 50);
        // Phone 0 (sub 1) should be activated as it has default data sub.
        assertTrue(mDataAllowed[0]);

        // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
        processAllMessages();
        assertFalse(mDataAllowed[0]);
        assertTrue(mDataAllowed[1]);

        // Unset preferred sub should make default data sub (phone 0 / sub 1) activated again.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
        processAllMessages();
        assertTrue(mDataAllowed[0]);
        assertFalse(mDataAllowed[1]);
    }

    @Test
    @SmallTest
    public void testSetPreferredDataModemCommand() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);
        mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);

        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        // Phone 0 (sub 1) should be preferred data phone as it has default data sub.
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());

        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);

        // Notify phoneSwitcher about default data sub and default network request.
        // It shouldn't change anything.
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        NetworkRequest mmsRequest = addMmsNetworkRequest(2);
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));

        // Set sub 2 as preferred sub should make phone 1 preferredDataModem
        doReturn(true).when(mSubscriptionController).isOpportunistic(2);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));

        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);

        // Unset preferred sub should make phone0 preferredDataModem again.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
        processAllMessages();

        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));

        // SetDataAllowed should never be triggered.
        verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
        verify(mCommandsInterface1, never()).setDataAllowed(anyBoolean(), any());
    }

    @Test
    @SmallTest
    public void testSetPreferredDataWithValidation() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();

        // Mark sub 2 as opportunistic.
        doReturn(true).when(mSubscriptionController).isOpportunistic(2);
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);

        // Phone 0 (sub 1) should be activated as it has default data sub.
        assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());

        // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, null);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        // Validation failed. Preferred data sub should remain 1, data phone should remain 0.
        mPhoneSwitcher.mValidationCallback.onValidationDone(false, 2);
        processAllMessages();
        assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());

        // Validation succeeds. Preferred data sub changes to 2, data phone changes to 1.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
        processAllMessages();
        assertEquals(1, mPhoneSwitcher.getPreferredDataPhoneId());

        // Switching data back to primary (subId 1) with customized validation timeout.
        long timeout = 1234;
        mContextFixture.getCarrierConfigBundle().putLong(
                KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, timeout);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, null);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(1), eq(timeout), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        mPhoneSwitcher.mValidationCallback.onValidationDone(true, 1);
        processAllMessages();
        assertEquals(0, mPhoneSwitcher.getPreferredDataPhoneId());
    }

    @Test
    @SmallTest
    public void testNonDefaultDataPhoneInCall() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        clearInvocations(mMockRadioConfig);
        setAllPhonesInactive();
        // Initialization done.

        // Phone2 has active call, but data is turned off. So no data switching should happen.
        notifyDataEnabled(false);
        notifyPhoneAsInCall(mPhone2);
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));

        // Phone2 has active call. So data switch to it.
        notifyDataEnabled(true);
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        clearInvocations(mMockRadioConfig);

        // Phone2 call ended. So data switch back to default data sub.
        notifyPhoneAsInactive(mPhone2);
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        clearInvocations(mMockRadioConfig);

        // Phone2 has holding call, but data is turned off. So no data switching should happen.
        notifyPhoneAsInHoldingCall(mPhone2);
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
    }


    @Test
    @SmallTest
    public void testNetworkRequestOnNonDefaultData() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        NetworkRequest internetRequest = addInternetNetworkRequest(2, 50);
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));

        // Restricted network request will should be applied.
        internetRequest = addInternetNetworkRequest(2, 50, true);
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        clearInvocations(mMockRadioConfig);

        // override the phone ID in prep for emergency call
        mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
        sendPreferredDataSuccessResult(1);
        processAllMessages();
        verify(mFuturePhone).complete(true);
        // Make sure the correct broadcast is sent out for the overridden phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideNoDdsChange() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        clearInvocations(mMockRadioConfig);

        // override the phone ID in prep for emergency call
        mPhoneSwitcher.overrideDefaultDataForEmergency(0, 1, mFuturePhone);
        processAllMessages();
        // The radio command should never be called because the DDS hasn't changed.
        verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
        processAllMessages();
        verify(mFuturePhone).complete(true);
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideEndSuccess() throws Exception {
        PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        setAllPhonesInactive();
        clearInvocations(mMockRadioConfig);
        clearInvocations(mTelephonyRegistryManager);

        // override the phone ID in prep for emergency call

        mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
        sendPreferredDataSuccessResult(1);
        processAllMessages();
        verify(mFuturePhone).complete(true);

        // Start and end the emergency call, which will start override timer
        notifyPhoneAsInCall(mPhone2);
        notifyPhoneAsInactive(mPhone2);

        clearInvocations(mTelephonyRegistryManager);
        // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
        moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        // Make sure the correct broadcast is sent out for the phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideEcbmStartEnd() throws Exception {
        PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        setAllPhonesInactive();
        clearInvocations(mMockRadioConfig);
        clearInvocations(mTelephonyRegistryManager);

        // override the phone ID in prep for emergency call
        mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
        sendPreferredDataSuccessResult(1);
        processAllMessages();
        verify(mFuturePhone).complete(true);

        // Start and end the emergency call, which will start override timer
        notifyPhoneAsInCall(mPhone2);
        notifyPhoneAsInactive(mPhone2);
        // Start ECBM
        Message ecbmMessage = getEcbmRegistration(mPhone2);
        notifyEcbmStart(mPhone2, ecbmMessage);

        // DDS should not be switched back until ECBM ends, make sure there is no further
        // interaction.
        moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 2000);
        processAllMessages();
        verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
        // Make sure the correct broadcast is sent out for the phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));

        // End ECBM
        clearInvocations(mTelephonyRegistryManager);
        ecbmMessage = getEcbmRegistration(mPhone2);
        notifyEcbmEnd(mPhone2, ecbmMessage);
        // Verify that the DDS is successfully switched back after 1 second.
        moveTimeForward(1000);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        // Make sure the correct broadcast is sent out for the phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideNoCallStart() throws Exception {
        PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        setAllPhonesInactive();
        clearInvocations(mMockRadioConfig);
        clearInvocations(mTelephonyRegistryManager);

        // override the phone ID in prep for emergency call
        mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
        sendPreferredDataSuccessResult(1);
        processAllMessages();
        verify(mFuturePhone).complete(true);

        // Do not start the call and make sure the override is removed once the timeout expires
        moveTimeForward(PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        // Make sure the correct broadcast is sent out for the phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
    }

    @Test
    @SmallTest
    public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
        PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setMsimDefaultDataSubId(1);
        setAllPhonesInactive();
        clearInvocations(mMockRadioConfig);
        clearInvocations(mTelephonyRegistryManager);

        // override the phone ID in prep for emergency call
        LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
        CompletableFuture<Boolean> futurePhone = new CompletableFuture<>();
        futurePhone.whenComplete((r, error) -> queue.offer(r));
        mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, futurePhone);
        sendPreferredDataSuccessResult(1);
        processAllMessages();
        Boolean result = queue.poll();
        assertNotNull(result);
        assertTrue(result);

        // try override the phone ID again while there is an existing override for a different phone
        futurePhone = new CompletableFuture<>();
        futurePhone.whenComplete((r, error) -> queue.offer(r));
        mPhoneSwitcher.overrideDefaultDataForEmergency(0, 1, futurePhone);
        processAllMessages();
        result = queue.poll();
        assertNotNull(result);
        assertFalse(result);
        verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());

        // Start and end the emergency call, which will start override timer
        notifyPhoneAsInCall(mPhone2);
        notifyPhoneAsInactive(mPhone2);

        // Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
        moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        // Make sure the correct broadcast is sent out for the phone ID
        verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
    }

    @Test
    @SmallTest
    public void testSetPreferredDataCallback() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();

        // Mark sub 2 as opportunistic.
        doReturn(true).when(mSubscriptionController).isOpportunistic(2);
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);

        // Validating on sub 10 which is inactive.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(10, true, mSetOpptDataCallback1);
        processAllMessages();
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);

        // Switch to active subId without validating. Should always succeed.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
        processAllMessages();
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);

        // Validating on sub 1 and fails.
        clearInvocations(mSetOpptDataCallback1);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(1, true, mSetOpptDataCallback1);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
        processAllMessages();
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);

        // Validating on sub 2 and succeeds.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
        processAllMessages();
        verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);

        // Switching data back to primary and validation fails.
        clearInvocations(mSetOpptDataCallback2);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
        processAllMessages();
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);

        // Switching data back to primary and succeeds.
        clearInvocations(mSetOpptDataCallback2);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onValidationDone(true, 1);
        processAllMessages();
        verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);

        // Back to back call on same subId.
        clearInvocations(mSetOpptDataCallback1);
        clearInvocations(mSetOpptDataCallback2);
        clearInvocations(mCellularNetworkValidator);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        doReturn(true).when(mCellularNetworkValidator).isValidating();
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
        processAllMessages();
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
        verify(mSetOpptDataCallback2, never()).onComplete(anyInt());
        // Validation succeeds.
        doReturn(false).when(mCellularNetworkValidator).isValidating();
        mPhoneSwitcher.mValidationCallback.onValidationDone(true, 2);
        processAllMessages();
        verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);

        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
        processAllMessages();
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
        processAllMessages();
        clearInvocations(mSetOpptDataCallback1);
        clearInvocations(mSetOpptDataCallback2);
        clearInvocations(mCellularNetworkValidator);
        // Back to back call, call 1 to switch to subId 2, call 2 to switch back.
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        doReturn(true).when(mCellularNetworkValidator).isValidating();
        mPhoneSwitcher.trySetOpportunisticDataSubscription(
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, mSetOpptDataCallback2);
        processAllMessages();
        // Call 1 should be cancelled and failed. Call 2 return success immediately as there's no
        // change.
        verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
        verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
    }

    @Test
    @SmallTest
    public void testMultiSimConfigChange() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        mActiveModemCount = 1;
        initialize();
        sendPreferredDataSuccessResult(0);

        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setDefaultDataSubId(1);

        setNumPhones(2, 2);
        AsyncResult result = new AsyncResult(null, 2, null);
        Message.obtain(mPhoneSwitcher, EVENT_MULTI_SIM_CONFIG_CHANGED, result).sendToTarget();
        processAllMessages();

        verify(mPhone2).registerForEmergencyCallToggle(any(), anyInt(), any());
        verify(mPhone2).registerForPreciseCallStateChanged(any(), anyInt(), any());
        verify(mDataEnabledSettings2).registerForDataEnabledChanged(any(), anyInt(), any());

        clearInvocations(mMockRadioConfig);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(2);
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
    }

    @Test
    @SmallTest
    public void testValidationOffSwitch_shouldSwitchOnNetworkAvailable() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        clearInvocations(mMockRadioConfig);
        setAllPhonesInactive();
        // Initialization done.

        doReturn(true).when(mSubscriptionController).isOpportunistic(2);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        doReturn(true).when(mCellularNetworkValidator).isValidating();

        // Network available on different sub. Should do nothing.
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 1);
        processAllMessages();
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());

        // Network available on corresponding sub. Should confirm switch.
        mPhoneSwitcher.mValidationCallback.onNetworkAvailable(null, 2);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
    }

    @Test
    @SmallTest
    public void testValidationOffSwitch_shouldSwitchOnTimeOut() throws Exception {
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize();
        // Phone 0 has sub 1, phone 1 has sub 2.
        // Sub 1 is default data sub.
        // Both are active subscriptions are active sub, as they are in both active slots.
        setSlotIndexToSubId(0, 1);
        setSlotIndexToSubId(1, 2);
        setDefaultDataSubId(1);
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        clearInvocations(mMockRadioConfig);
        setAllPhonesInactive();
        // Initialization done.

        doReturn(true).when(mSubscriptionController).isOpportunistic(2);
        mPhoneSwitcher.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
        processAllMessages();
        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
                eq(mPhoneSwitcher.mValidationCallback));
        doReturn(true).when(mCellularNetworkValidator).isValidating();

        // Validation failed on different sub. Should do nothing.
        mPhoneSwitcher.mValidationCallback.onValidationDone(false, 1);
        processAllMessages();
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());

        // Network available on corresponding sub. Should confirm switch.
        mPhoneSwitcher.mValidationCallback.onValidationDone(false, 2);
        processAllMessages();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
    }

    /* Private utility methods start here */

    private void setAllPhonesInactive() {
        doReturn(mInactiveCall).when(mPhone).getForegroundCall();
        doReturn(mInactiveCall).when(mPhone).getBackgroundCall();
        doReturn(mInactiveCall).when(mPhone).getRingingCall();
        doReturn(mInactiveCall).when(mPhone2).getForegroundCall();
        doReturn(mInactiveCall).when(mPhone2).getBackgroundCall();
        doReturn(mInactiveCall).when(mPhone2).getRingingCall();
    }

    private void notifyPhoneAsInCall(Phone phone) {
        doReturn(mActiveCall).when(phone).getForegroundCall();
        mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
        processAllMessages();
    }

    private void notifyPhoneAsInHoldingCall(Phone phone) {
        doReturn(mHoldingCall).when(phone).getBackgroundCall();
        mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
        processAllMessages();
    }

    private void notifyPhoneAsInactive(Phone phone) {
        doReturn(mInactiveCall).when(phone).getForegroundCall();
        mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
        processAllMessages();
    }

    private void notifyDataEnabled(boolean dataEnabled) {
        doReturn(dataEnabled).when(mDataEnabledSettings).isDataEnabled(anyInt());
        doReturn(dataEnabled).when(mDataEnabledSettings2).isDataEnabled(anyInt());
        mPhoneSwitcher.sendEmptyMessage(EVENT_DATA_ENABLED_CHANGED);
        processAllMessages();
    }

    private Message getEcbmRegistration(Phone phone) {
        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
        ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);

        verify(phone).registerForEmergencyCallToggle(handlerCaptor.capture(), intCaptor.capture(),
                any());
        assertNotNull(handlerCaptor.getValue());
        assertNotNull(intCaptor.getValue());
        Message message = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
        return message;
    }

    private void notifyEcbmStart(Phone phone, Message ecmMessage) {
        doReturn(mInactiveCall).when(phone).getForegroundCall();
        doReturn(true).when(phone).isInEcm();
        ecmMessage.sendToTarget();
        processAllMessages();
    }

    private void notifyEcbmEnd(Phone phone, Message ecmMessage) {
        doReturn(false).when(phone).isInEcm();
        ecmMessage.sendToTarget();
        processAllMessages();
    }

    private void sendPreferredDataSuccessResult(int phoneId) {
        // make sure the radio command is called and then send a success result
        processAllMessages();
        ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockRadioConfig).setPreferredDataModem(eq(phoneId), msgCaptor.capture());
        assertNotNull(msgCaptor.getValue());
        // Send back successful result
        AsyncResult.forMessage(msgCaptor.getValue(), null, null);
        msgCaptor.getValue().sendToTarget();
        processAllMessages();
    }

    private void setMsimDefaultDataSubId(int defaultDataSub) throws Exception {
        for (int i = 0; i < mActiveModemCount; i++) {
            setSlotIndexToSubId(i, i + 1);
        }
        setDefaultDataSubId(defaultDataSub);
        NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
        for (int i = 0; i < mActiveModemCount; i++) {
            if (defaultDataSub == (i + 1)) {
                // sub id is always phoneId+1 for testing
                assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, i));
            } else {
                assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, i));
            }
        }
    }

    private void sendDefaultDataSubChanged() {
        final Intent intent = new Intent(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
        mContext.sendBroadcast(intent);
        processAllMessages();
    }

    private void initialize() throws Exception {
        setNumPhones(mActiveModemCount, mSupportedModemCount);

        initializeSubControllerMock();
        initializeCommandInterfacesMock();
        initializeTelRegistryMock();
        initializeConnManagerMock();

        mPhoneSwitcher = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper());
        processAllMessages();

        verify(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
    }

    /**
     * Certain variables needs initialized depending on number of phones.
     */
    private void setNumPhones(int activeModemCount, int supportedModemCount) throws Exception {
        mDataAllowed = new boolean[supportedModemCount];
        mSlotIndexToSubId = new int[supportedModemCount][];
        doReturn(0).when(mPhone).getPhoneId();
        doReturn(1).when(mPhone2).getPhoneId();
        doReturn(true).when(mPhone2).isUserDataEnabled();
        doReturn(mDataEnabledSettings2).when(mPhone2).getDataEnabledSettings();
        for (int i = 0; i < supportedModemCount; i++) {
            mSlotIndexToSubId[i] = new int[1];
            mSlotIndexToSubId[i][0] = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }

        doReturn(activeModemCount).when(mTelephonyManager).getPhoneCount();
        doReturn(activeModemCount).when(mTelephonyManager).getActiveModemCount();
        doReturn(supportedModemCount).when(mTelephonyManager).getSupportedModemCount();

        if (activeModemCount == 1) {
            mPhones = new Phone[]{mPhone};
        } else if (activeModemCount == 2) {
            mPhones = new Phone[]{mPhone, mPhone2};
        }

        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
    }

    private void initializeCommandInterfacesMock() {
        // Tell PhoneSwitcher that radio is on.
        doAnswer(invocation -> {
            Handler handler = (Handler) invocation.getArguments()[0];
            int message = (int) invocation.getArguments()[1];
            Object obj = invocation.getArguments()[2];
            handler.obtainMessage(message, obj).sendToTarget();
            return null;
        }).when(mCommandsInterface0).registerForAvailable(any(), anyInt(), any());

        // Store values of dataAllowed in mDataAllowed[] for easier checking.
        doAnswer(invocation -> {
            mDataAllowed[0] = (boolean) invocation.getArguments()[0];
            return null;
        }).when(mCommandsInterface0).setDataAllowed(anyBoolean(), any());

        if (mSupportedModemCount > 1) {
            doAnswer(invocation -> {
                mDataAllowed[1] = (boolean) invocation.getArguments()[0];
                return null;
            }).when(mCommandsInterface1).setDataAllowed(anyBoolean(), any());
        }
    }

    /**
     * Store subChangedListener of PhoneSwitcher so that testing can notify
     * PhoneSwitcher of sub change.
     */
    private void initializeTelRegistryMock() throws Exception {
        doAnswer(invocation -> {
            SubscriptionManager.OnSubscriptionsChangedListener subChangedListener =
                    (SubscriptionManager.OnSubscriptionsChangedListener) invocation.getArguments()[0];
            mSubChangedListener = subChangedListener;
            mSubChangedListener.onSubscriptionsChanged();
            return null;
        }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
    }

    /**
     * Capture mNetworkProviderMessenger so that testing can request or release
     * network requests on PhoneSwitcher.
     */
    private void initializeConnManagerMock() {
        mConnectivityManager = (ConnectivityManager)
                mContext.getSystemService(Context.CONNECTIVITY_SERVICE);

        doAnswer(invocation -> {
            mNetworkProviderMessenger =
                    ((NetworkProvider) invocation.getArgument(0)).getMessenger();
            return null;
        }).when(mConnectivityManager).registerNetworkProvider(any());
    }

    /**
     * Capture mNetworkProviderMessenger so that testing can request or release
     * network requests on PhoneSwitcher.
     */
    private void initializeSubControllerMock() {
        doReturn(mDefaultDataSub).when(mSubscriptionController).getDefaultDataSubId();
        doAnswer(invocation -> {
            int phoneId = (int) invocation.getArguments()[0];
            if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
            } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
                return mSlotIndexToSubId[0][0];
            } else {
                return mSlotIndexToSubId[phoneId][0];
            }
        }).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());

        doAnswer(invocation -> {
            int subId = (int) invocation.getArguments()[0];

            if (!SubscriptionManager.isUsableSubIdValue(subId)) return false;

            for (int i = 0; i < mSlotIndexToSubId.length; i++) {
                if (mSlotIndexToSubId[i][0] == subId) return true;
            }
            return false;
        }).when(mSubscriptionController).isActiveSubId(anyInt());
    }

    private void setDefaultDataSubId(int defaultDataSub) {
        mDefaultDataSub = defaultDataSub;
        doReturn(mDefaultDataSub).when(mSubscriptionController).getDefaultDataSubId();
        sendDefaultDataSubChanged();
    }

    private void setSlotIndexToSubId(int slotId, int subId) {
        mSlotIndexToSubId[slotId][0] = subId;
    }

    /**
     * Create an internet PDN network request and send it to PhoneSwitcher.
     */
    private NetworkRequest addInternetNetworkRequest(Integer subId, int score) throws Exception {
        return addInternetNetworkRequest(subId, score, false);
    }

    private NetworkRequest addInternetNetworkRequest(Integer subId, int score, boolean restricted)
            throws Exception {
        NetworkCapabilities netCap = (new NetworkCapabilities())
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        if (restricted) {
            netCap.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        }

        if (subId != null) {
            netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
                    .setSubscriptionId(subId).build());
        }
        NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
                0, NetworkRequest.Type.REQUEST);

        Message message = Message.obtain();
        message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
        message.arg1 = score;
        message.obj = networkRequest;
        mNetworkProviderMessenger.send(message);
        processAllMessages();

        return networkRequest;
    }

    /**
     * Create a mms PDN network request and send it to PhoneSwitcher.
     */
    private NetworkRequest addMmsNetworkRequest(Integer subId) throws Exception {
        NetworkCapabilities netCap = (new NetworkCapabilities())
                .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        if (subId != null) {
            netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
                    .setSubscriptionId(subId).build());
        }
        NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
                1, NetworkRequest.Type.REQUEST);

        Message message = Message.obtain();
        message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
        message.arg1 = 50; // Score
        message.obj = networkRequest;
        mNetworkProviderMessenger.send(message);
        processAllMessages();

        return networkRequest;
    }

    /**
     * Tell PhoneSwitcher to release a network request.
     */
    private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
        Message message = Message.obtain();
        message.what = android.net.NetworkProvider.CMD_CANCEL_REQUEST;
        message.obj = networkRequest;
        mNetworkProviderMessenger.send(message);
        processAllMessages();
    }
}
