Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e19c38b authored by Thomas Stuart's avatar Thomas Stuart Committed by Android (Google) Code Review
Browse files

Merge "fix No Call Preference bug afer switch to DSDS mode" into tm-dev

parents 938da806 fd0b1d2c
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -397,6 +397,24 @@ public class PhoneConfigurationManager {
                registerForRadioState(phone);
                phone.mCi.onSlotActiveStatusChange(SubscriptionManager.isValidPhoneId(phoneId));
            }

            // When the user enables DSDS mode, the default VOICE and SMS subId should be switched
            // to "No Preference".  Doing so will sync the network/sim settings and telephony.
            // (see b/198123192)
            if (numOfActiveModems > oldNumOfActiveModems && numOfActiveModems == 2) {
                Log.i(LOG_TAG, " onMultiSimConfigChanged: DSDS mode enabled; "
                        + "setting VOICE & SMS subId to -1 (No Preference)");

                //Set the default VOICE subId to -1 ("No Preference")
                SubscriptionController.getInstance().setDefaultVoiceSubId(
                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);

                //TODO:: Set the default SMS sub to "No Preference". Tracking this bug (b/227386042)
            } else {
                Log.i(LOG_TAG,
                        "onMultiSimConfigChanged: DSDS mode NOT detected.  NOT setting the "
                                + "default VOICE and SMS subId to -1 (No Preference)");
            }
        }
    }

+101 −45
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -37,6 +38,7 @@ import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -46,6 +48,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -148,29 +151,27 @@ public class PhoneConfigurationManagerTest extends TelephonyTest {
    @SmallTest
    public void testSwitchMultiSimConfig_dsdsCapable_noRebootRequired() throws Exception {
        init(1);
        testSwitchFromSingleToDualSimModeNoReboot();
    }

    @Test
    @SmallTest
    public void testSwitchMultiSimConfig_multiSimToSingleSim() throws Exception {
        mPhones = new Phone[]{mPhone, mPhone1};
        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
        init(2);
        verify(mMockCi0, times(1)).registerForAvailable(any(), anyInt(), any());
        verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any());

        // Register for multi SIM config change.
        mPcm.registerForMultiSimConfigChange(mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
        verify(mHandler, never()).sendMessageAtTime(any(), anyLong());

        // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
        mPcm.switchMultiSimConfig(2);
        verify(mMockRadioConfig, never()).setNumOfLiveModems(anyInt(), any());

        // Send static capability back to indicate DSDS is supported.
        clearInvocations(mMockRadioConfig);
        testGetDsdsCapability();
        // testGetDsdsCapability leads to another call to registerForAvailable()
        verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any());

        // Try to switch to DSDS.
        // Switch to single sim.
        setRebootRequiredForConfigSwitch(false);
        mPhones = new Phone[]{mPhone, mPhone1};
        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
        mPcm.switchMultiSimConfig(2);
        mPcm.switchMultiSimConfig(1);
        ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
        verify(mMockRadioConfig).setNumOfLiveModems(eq(2), captor.capture());
        verify(mMockRadioConfig).setNumOfLiveModems(eq(1), captor.capture());

        // Send message back to indicate switch success.
        Message message = captor.getValue();
@@ -179,50 +180,107 @@ public class PhoneConfigurationManagerTest extends TelephonyTest {
        processAllMessages();

        // Verify set system property being called.
        verify(mMi).setMultiSimProperties(2);
        verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(2));
        verify(mMi).setMultiSimProperties(1);
        verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(1));

        // Capture and verify registration notification.
        verify(mHandler).sendMessageAtTime(captor.capture(), anyLong());
        message = captor.getValue();
        assertEquals(EVENT_MULTI_SIM_CONFIG_CHANGED, message.what);
        assertEquals(2, ((AsyncResult) message.obj).result);
        assertEquals(1, ((AsyncResult) message.obj).result);

        // Capture and verify broadcast.
        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcast(intentCaptor.capture());
        Intent intent = intentCaptor.getValue();
        assertEquals(ACTION_MULTI_SIM_CONFIG_CHANGED, intent.getAction());
        assertEquals(2, intent.getIntExtra(
        assertEquals(1, intent.getIntExtra(
                EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 0));

        // Verify registerForAvailable() and onSlotActiveStatusChange() are called for the second
        // phone, and not for the first phone (registerForAvailable() was already called twice
        // earlier so verify that the count is still at 2)
        verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any());
        // Verify clearSubInfoRecord() and onSlotActiveStatusChange() are called for second phone,
        // and not for the first one
        verify(mSubscriptionController).clearSubInfoRecord(1);
        verify(mMockCi1).onSlotActiveStatusChange(anyBoolean());
        verify(mSubscriptionController, never()).clearSubInfoRecord(0);
        verify(mMockCi0, never()).onSlotActiveStatusChange(anyBoolean());
        verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any());
        verify(mMockCi1, times(1)).onSlotActiveStatusChange(anyBoolean());

        // Verify onPhoneRemoved() gets called on MultiSimSettingController phone
        verify(mMultiSimSettingController).onPhoneRemoved();
    }

    @Test
    @SmallTest
    public void testSwitchMultiSimConfig_multiSimToSingleSim() throws Exception {
        mPhones = new Phone[]{mPhone, mPhone1};
        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
        init(2);
    public void testNoCallPreferenceIsSetAfterSwitchToDsdsMode() throws Exception {
        final int startingDefaultSubscriptionId = 2; // arbitrary value (can't be -1 which
        // represents the "No Call Preference" value)

        /*
            TL;DR:  the following mockito code block dynamically changes the last call to the getter

            doAnswer(invocation -> {
                Integer value = (Integer) invocation.getArguments()[0];
                Mockito.when(object.getter()).thenReturn(value);
                return null;
            }).when(object).setter(anyInt());

            read the code block as, whenever we call the setter, change the Mock call
            of the getter to whatever argument value we last passed to the setter.

            ex.)    object.set( 2 )   --> next call to object.get() will return 2
         */

        // setup mocks for  VOICE mSubscriptionController. getter/setter
        doAnswer(invocation -> {
            Integer value = (Integer) invocation.getArguments()[0];
            Mockito.when(mSubscriptionController.getDefaultVoiceSubId()).thenReturn(value);
            return null;
        }).when(mSubscriptionController).setDefaultVoiceSubId(anyInt());

        // start off the phone stat with 1 active sim. reset values for new test.
        init(1);

        mSubscriptionController.setDefaultVoiceSubId(startingDefaultSubscriptionId);

        // assert the mSubscriptionController registers the change
        assertEquals(startingDefaultSubscriptionId, mSubscriptionController.getDefaultVoiceSubId());

        // Perform the switch to DSDS mode and ensure all existing checks are not altered
        testSwitchFromSingleToDualSimModeNoReboot();

        // VOICE check
        assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID /* No CALL Preference value */,
                mSubscriptionController.getDefaultVoiceSubId()); //  Now, when the user goes to
        // place a CALL, they will be prompted on which sim to use.
    }

    /**
     * must call init(1) from the parent test before calling this helper test
     * @throws Exception
     */
    public void testSwitchFromSingleToDualSimModeNoReboot() throws Exception {
        verify(mMockCi0, times(1)).registerForAvailable(any(), anyInt(), any());
        verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any());

        // Register for multi SIM config change.
        mPcm.registerForMultiSimConfigChange(mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
        verify(mHandler, never()).sendMessageAtTime(any(), anyLong());

        // Switch to single sim.
        // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
        mPcm.switchMultiSimConfig(2);
        verify(mMockRadioConfig, never()).setNumOfLiveModems(anyInt(), any());

        // Send static capability back to indicate DSDS is supported.
        clearInvocations(mMockRadioConfig);
        testGetDsdsCapability();
        // testGetDsdsCapability leads to another call to registerForAvailable()
        verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any());

        // Try to switch to DSDS.
        setRebootRequiredForConfigSwitch(false);
        mPcm.switchMultiSimConfig(1);
        mPhones = new Phone[]{mPhone, mPhone1};
        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
        mPcm.switchMultiSimConfig(2);
        ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
        verify(mMockRadioConfig).setNumOfLiveModems(eq(1), captor.capture());
        verify(mMockRadioConfig).setNumOfLiveModems(eq(2), captor.capture());

        // Send message back to indicate switch success.
        Message message = captor.getValue();
@@ -231,31 +289,29 @@ public class PhoneConfigurationManagerTest extends TelephonyTest {
        processAllMessages();

        // Verify set system property being called.
        verify(mMi).setMultiSimProperties(1);
        verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(1));
        verify(mMi).setMultiSimProperties(2);
        verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(2));

        // Capture and verify registration notification.
        verify(mHandler).sendMessageAtTime(captor.capture(), anyLong());
        message = captor.getValue();
        assertEquals(EVENT_MULTI_SIM_CONFIG_CHANGED, message.what);
        assertEquals(1, ((AsyncResult) message.obj).result);
        assertEquals(2, ((AsyncResult) message.obj).result);

        // Capture and verify broadcast.
        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcast(intentCaptor.capture());
        Intent intent = intentCaptor.getValue();
        assertEquals(ACTION_MULTI_SIM_CONFIG_CHANGED, intent.getAction());
        assertEquals(1, intent.getIntExtra(
        assertEquals(2, intent.getIntExtra(
                EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 0));

        // Verify clearSubInfoRecord() and onSlotActiveStatusChange() are called for second phone,
        // and not for the first one
        verify(mSubscriptionController).clearSubInfoRecord(1);
        verify(mMockCi1).onSlotActiveStatusChange(anyBoolean());
        verify(mSubscriptionController, never()).clearSubInfoRecord(0);
        // Verify registerForAvailable() and onSlotActiveStatusChange() are called for the second
        // phone, and not for the first phone (registerForAvailable() was already called twice
        // earlier so verify that the count is still at 2)
        verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any());
        verify(mMockCi0, never()).onSlotActiveStatusChange(anyBoolean());

        // Verify onPhoneRemoved() gets called on MultiSimSettingController phone
        verify(mMultiSimSettingController).onPhoneRemoved();
        verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any());
        verify(mMockCi1, times(1)).onSlotActiveStatusChange(anyBoolean());
    }
}