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

Commit ae41f95b authored by Xiangyu/Malcolm Chen's avatar Xiangyu/Malcolm Chen Committed by Android (Google) Code Review
Browse files

Merge changes from topic "80268699"

* changes:
  Add unittest for RIL_SET_PREFERRED_DATA command is supported.
  Support of RIL_REQUEST_SET_PREFERRED_DATA_MODEM in PhoneSwitcher.
parents 23bd135d 2e04c998
Loading
Loading
Loading
Loading
+109 −60
Original line number Diff line number Diff line
@@ -99,8 +99,19 @@ public class PhoneSwitcher extends Handler {
    private static final int EVENT_REQUEST_NETWORK                = 103;
    private static final int EVENT_RELEASE_NETWORK                = 104;
    private static final int EVENT_EMERGENCY_TOGGLE               = 105;
    private static final int EVENT_RESEND_DATA_ALLOWED            = 106;
    private static final int EVENT_RADIO_CAPABILITY_CHANGED       = 106;
    private static final int EVENT_PREFERRED_SUBSCRIPTION_CHANGED = 107;
    private static final int EVENT_RADIO_AVAILABLE                = 108;

    // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's
    // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse
    // will be either HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_UNKNOWN.
    private static final int HAL_COMMAND_UNKNOWN        = 0;
    private static final int HAL_COMMAND_ALLOW_DATA     = 1;
    private static final int HAL_COMMAND_PREFERRED_DATA = 2;
    private int mHalCommandToUse = HAL_COMMAND_UNKNOWN;

    private RadioConfig mRadioConfig;

    private final static int MAX_LOCAL_LOG_LINES = 30;

@@ -138,6 +149,7 @@ public class PhoneSwitcher extends Handler {
        mLocalLog = null;
        mActivePhoneRegistrants = null;
        mNumPhones = 0;
        mRadioConfig = RadioConfig.getInstance(mContext);
        mPhoneStateListener = new PhoneStateListener(looper) {
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
                onPhoneCapabilityChangedInternal(capability);
@@ -158,6 +170,7 @@ public class PhoneSwitcher extends Handler {
        mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES);

        mSubscriptionController = subscriptionController;
        mRadioConfig = RadioConfig.getInstance(mContext);

        mPhoneStateListener = new PhoneStateListener(looper) {
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
@@ -181,6 +194,7 @@ public class PhoneSwitcher extends Handler {

        mCommandsInterfaces = cis;

        mCommandsInterfaces[0].registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
        try {
            tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
                    mSubscriptionsChangedListener);
@@ -255,14 +269,19 @@ public class PhoneSwitcher extends Handler {
                onEvaluate(REQUESTS_CHANGED, "emergencyToggle");
                break;
            }
            case EVENT_RESEND_DATA_ALLOWED: {
                onResendDataAllowed(msg);
            case EVENT_RADIO_CAPABILITY_CHANGED: {
                resendRilCommands(msg);
                break;
            }
            case EVENT_PREFERRED_SUBSCRIPTION_CHANGED: {
                onEvaluate(REQUESTS_UNCHANGED, "preferredDataSubIdChanged");
                break;
            }
            case EVENT_RADIO_AVAILABLE: {
                updateHalCommandToUse();
                onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE");
                break;
            }
        }
    }

@@ -334,8 +353,8 @@ public class PhoneSwitcher extends Handler {
            return;
        }

        // Check if preferred slotId is changed.
        boolean diffDetected = requestsChanged;
        // If we use HAL_COMMAND_PREFERRED_DATA,
        boolean diffDetected = mHalCommandToUse != HAL_COMMAND_PREFERRED_DATA && requestsChanged;

        // Check if user setting of default data sub is changed.
        final int dataSub = mSubscriptionController.getDefaultDataSubId();
@@ -366,7 +385,15 @@ public class PhoneSwitcher extends Handler {

        if (diffDetected) {
            log("evaluating due to " + sb.toString());

            if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) {
                if (SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) {
                    mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
                    // Notify all registrants.
                    for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
                        mActivePhoneRegistrants[phoneId].notifyRegistrants();
                    }
                }
            } else {
                List<Integer> newActivePhones = new ArrayList<Integer>();

                for (DcRequest dcRequest : mPrioritizedDcRequests) {
@@ -388,7 +415,7 @@ public class PhoneSwitcher extends Handler {
                }

                for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
                if (newActivePhones.contains(phoneId) == false) {
                    if (!newActivePhones.contains(phoneId)) {
                        deactivate(phoneId);
                    }
                }
@@ -399,53 +426,58 @@ public class PhoneSwitcher extends Handler {
                }
            }
        }
    }

    private static class PhoneState {
        public volatile boolean active = false;
        public long lastRequested = 0;
    }

    private void deactivate(int phoneId) {
        PhoneState state = mPhoneStates[phoneId];
        if (state.active == false) return;
        state.active = false;
        log("deactivate " + phoneId);
        state.lastRequested = System.currentTimeMillis();
        // Skip ALLOW_DATA for single SIM device
        if (mNumPhones > 1) {
            mCommandsInterfaces[phoneId].setDataAllowed(false, null);
    private void activate(int phoneId) {
        switchPhone(phoneId, true);
    }
        mActivePhoneRegistrants[phoneId].notifyRegistrants();

    private void deactivate(int phoneId) {
        switchPhone(phoneId, false);
    }

    private void activate(int phoneId) {
    private void switchPhone(int phoneId, boolean active) {
        PhoneState state = mPhoneStates[phoneId];
        if (state.active == true) return;
        state.active = true;
        log("activate " + phoneId);
        if (state.active == active) return;
        state.active = active;
        log(active ? "activate " : "deactivate " + phoneId);
        state.lastRequested = System.currentTimeMillis();
        if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
            // Skip ALLOW_DATA for single SIM device
            if (mNumPhones > 1) {
            mCommandsInterfaces[phoneId].setDataAllowed(true, null);
                mCommandsInterfaces[phoneId].setDataAllowed(active, null);
            }
        }
        mActivePhoneRegistrants[phoneId].notifyRegistrants();

    }

    // used when the modem may have been rebooted and we want to resend
    // setDataAllowed
    public void resendDataAllowed(int phoneId) {
    /**
     * Used when the modem may have been rebooted and we
     * want to resend setDataAllowed or setPreferredData
     */
    public void onRadioCapChanged(int phoneId) {
        validatePhoneId(phoneId);
        Message msg = obtainMessage(EVENT_RESEND_DATA_ALLOWED);
        Message msg = obtainMessage(EVENT_RADIO_CAPABILITY_CHANGED);
        msg.arg1 = phoneId;
        msg.sendToTarget();
    }

    private void onResendDataAllowed(Message msg) {
    private void resendRilCommands(Message msg) {
        final int phoneId = msg.arg1;
        if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
            // Skip ALLOW_DATA for single SIM device
            if (mNumPhones > 1) {
                mCommandsInterfaces[phoneId].setDataAllowed(mPhoneStates[phoneId].active, null);
            }
        } else {
            mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, null);
        }
    }

    private void onPhoneCapabilityChangedInternal(PhoneCapability capability) {
@@ -517,15 +549,27 @@ public class PhoneSwitcher extends Handler {
    }

    /**
     * Returns whether phone should handle default network requests.
     * Returns whether phone should handle network requests
     * that don't specify a subId.
     */
    public boolean isActiveForDefaultRequests(int phoneId) {
        return isPhoneActive(phoneId) && phoneId == mPreferredDataPhoneId;
    public boolean shouldApplyUnspecifiedRequests(int phoneId) {
        validatePhoneId(phoneId);
        if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) {
            return phoneId == mPreferredDataPhoneId;
        } else {
            return mPhoneStates[phoneId].active && phoneId == mPreferredDataPhoneId;
        }
    }

    public boolean isPhoneActive(int phoneId) {
    /**
     * Returns whether phone should handle network requests
     * that specify a subId.
     */
    public boolean shouldApplySpecifiedRequests(int phoneId) {
        validatePhoneId(phoneId);
        return mPhoneStates[phoneId].active;
        // If we use SET_PREFERRED_DATA, always apply specified network requests. Otherwise,
        // only apply network requests if the phone is active (dataAllowed).
        return mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA || mPhoneStates[phoneId].active;
    }

    public void registerForActivePhoneSwitch(int phoneId, Handler h, int what, Object o) {
@@ -559,6 +603,11 @@ public class PhoneSwitcher extends Handler {
        }
    }

    private void updateHalCommandToUse() {
        mHalCommandToUse = mRadioConfig.isSetPreferredDataCommandSupported()
                ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
    }

    private void log(String l) {
        Rlog.d(LOG_TAG, l);
        mLocalLog.log(l);
+1 −1
Original line number Diff line number Diff line
@@ -454,7 +454,7 @@ public class ProxyController {
                logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=SUCCESS");
                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS;
                // The modems may have been restarted and forgotten this
                mPhoneSwitcher.resendDataAllowed(id);
                mPhoneSwitcher.onRadioCapChanged(id);
                mPhones[id].radioCapabilityUpdated(rc);
            }

+29 −2
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.internal.telephony;

import static com.android.internal.telephony.RILConstants.RADIO_NOT_AVAILABLE;
import static com.android.internal.telephony.RILConstants.REQUEST_NOT_SUPPORTED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SLOT_STATUS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING;
import static com.android.internal.telephony.RILConstants
        .RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING;

import android.content.Context;
import android.hardware.radio.V1_0.RadioResponseInfo;
@@ -258,7 +260,32 @@ public class RadioConfig extends Handler {
    }

    /**
     * Wrapper function for IRadioConfig.getSimSlotsStatus().
     * Wrapper function for IRadioConfig.setPreferredDataModem(int modemId).
     */
    public void setPreferredDataModem(int modemId, Message result) {
        if (!isSetPreferredDataCommandSupported()) {
            if (result != null) {
                AsyncResult.forMessage(result, null,
                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
                result.sendToTarget();
            }
        }
        // TODO: call radioConfigProxy.setPreferredDataModem when it's ready.
    }

    /**
     * @return whether current radio config version supports SET_PREFERRED_DATA_MODEM command.
     * If yes, we'll use RIL_REQUEST_SET_PREFERRED_DATA_MODEM to indicate which modem is preferred.
     * If not, we shall use RIL_REQUEST_ALLOW_DATA for on-demand PS attach / detach.
     * See PhoneSwitcher for more details.
     */
    public boolean isSetPreferredDataCommandSupported() {
        // TODO: call radioConfigProxy.isSetPreferredDataCommandSupported when it's ready.
        return false;
    }

    /**
     * Wrapper function for IRadioConfig.setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap).
     */
    public void setSimSlotsMapping(int[] physicalSlots, Message result) {
        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
+3 −2
Original line number Diff line number Diff line
@@ -183,8 +183,9 @@ public class TelephonyNetworkFactory extends NetworkFactory {

    // apply or revoke requests if our active-ness changes
    private void onActivePhoneSwitch() {
        final boolean newIsActive = mPhoneSwitcher.isPhoneActive(mPhoneId);
        final boolean newIsActiveForDefault = mPhoneSwitcher.isActiveForDefaultRequests(mPhoneId);
        final boolean newIsActive = mPhoneSwitcher.shouldApplySpecifiedRequests(mPhoneId);
        final boolean newIsActiveForDefault =
                mPhoneSwitcher.shouldApplyUnspecifiedRequests(mPhoneId);

        String logString = "onActivePhoneSwitch(newIsActive " + newIsActive + ", "
                + "newIsActive " + newIsActiveForDefault + ")";
+89 −8
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ 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;
@@ -103,13 +104,13 @@ public class PhoneSwitcherTest extends TelephonyTest {
        // verify nothing has been done while there are no inputs
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("data allowed initially", mDataAllowed[0]);
        assertFalse("phone active initially", mPhoneSwitcher.isPhoneActive(0));
        assertFalse("phone active initially", mPhoneSwitcher.shouldApplySpecifiedRequests(0));

        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
        waitABit();

        assertFalse("data allowed after request", mDataAllowed[0]);
        assertFalse("phone active after request", mPhoneSwitcher.isPhoneActive(0));
        assertFalse("phone active after request", mPhoneSwitcher.shouldApplySpecifiedRequests(0));

        // not registered yet - shouldn't inc
        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
@@ -388,6 +389,81 @@ public class PhoneSwitcherTest extends TelephonyTest {
        mHandlerThread.quit();
    }

    @Test
    @SmallTest
    public void testSetPreferredDataModemCommand() throws Exception {
        final int numPhones = 2;
        final int maxActivePhones = 1;
        doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
        initialize(numPhones, maxActivePhones);
        mPhoneSwitcher.registerForActivePhoneSwitch(1, mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);
        mPhoneSwitcher.registerForActivePhoneSwitch(0, mActivePhoneSwitchHandler,
                ACTIVE_PHONE_SWITCH, null);
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        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);
        waitABit();
        // Phone 0 (sub 1) should preferredDataModem it has default data sub.
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));

        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);

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

        // Set sub 2 as preferred sub should make phone 1 preferredDataModem
        mPhoneSwitcher.setPreferredData(2);
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));

        clearInvocations(mMockRadioConfig);
        clearInvocations(mActivePhoneSwitchHandler);

        // Unset preferred sub should make phone0 preferredDataModem again.
        mPhoneSwitcher.setPreferredData(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
        waitABit();
        verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(0));
        assertTrue(mPhoneSwitcher.shouldApplySpecifiedRequests(1));
        assertTrue(mPhoneSwitcher.shouldApplyUnspecifiedRequests(0));
        assertFalse(mPhoneSwitcher.shouldApplyUnspecifiedRequests(1));

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

        mHandlerThread.quit();

    }

    /* Private utility methods start here */

    private void sendDefaultDataSubChanged() {
@@ -396,9 +472,6 @@ public class PhoneSwitcherTest extends TelephonyTest {
    }

    private void initialize(int numPhones, int maxActivePhones) throws Exception {
        mHandlerThread = new HandlerThread("PhoneSwitcherTestThread");
        mHandlerThread.start();

        mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
                sNetworkAttributes);

@@ -409,9 +482,17 @@ public class PhoneSwitcherTest extends TelephonyTest {
        initializeTelRegistryMock();
        initializeConnManagerMock();

        mHandlerThread = new HandlerThread("PhoneSwitcherTestThread") {
            @Override
            public void onLooperPrepared() {
                mPhoneSwitcher = new PhoneSwitcher(maxActivePhones, numPhones,
                mContext, mSubscriptionController, mHandlerThread.getLooper(),
                        mContext, mSubscriptionController, this.getLooper(),
                        mTelRegistryMock, mCommandsInterfaces, mPhones);
            }
        };

        mHandlerThread.start();
        waitABit();

        verify(mTelRegistryMock).addOnSubscriptionsChangedListener(
                eq(mContext.getOpPackageName()), any());
Loading