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

Commit 1ff4b6ff authored by Nathan Harold's avatar Nathan Harold
Browse files

Allow EIMS Requests When No SIM is Active

-When there is no SIM, change the preferred
 data subscription to use phoneId=0 and to allow
 the EIMS / emergency NetworkRequest/APN type to
 go down to DcTracker.

-Always add the Emergency APN to the list of valid
 APNs:
--If no APN is found in the APNs DB construct one.
--After locating the emergency APN, immediately add
  it to the APNs list even if there is no SIM change,
  which occurs if the phone boots without a SIM.

Bug: 130663120
Test: atest PhoneSwitcherTest;
      atest TelephonyNetworkFactoryTest;
      manual verification by cp'ing: aosp/949940,
          aosp/946764, aosp/946998
Change-Id: I5b28527d96c3d7d3ee178cb54ffbe0027d10a2cd
parent 01b06c77
Loading
Loading
Loading
Loading
+46 −4
Original line number Diff line number Diff line
@@ -85,6 +85,10 @@ public class PhoneSwitcher extends Handler {
    private static final int DEFAULT_NETWORK_CHANGE_TIMEOUT_MS = 5000;
    private static final int MODEM_COMMAND_RETRY_PERIOD_MS     = 5000;

    // If there are no subscriptions in a device, then the phone to be used for emergency should
    // always be the "first" phone.
    private static final int DEFAULT_EMERGENCY_PHONE_ID = 0;

    private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
    private final RegistrantList mActivePhoneRegistrants;
    private final SubscriptionController mSubscriptionController;
@@ -578,9 +582,15 @@ public class PhoneSwitcher extends Handler {
            mPrimaryDataSubId = primaryDataSubId;
        }

        // Check to see if there is any active subscription on any phone
        boolean hasAnyActiveSubscription = false;

        // Check if phoneId to subId mapping is changed.
        for (int i = 0; i < mNumPhones; i++) {
            int sub = mSubscriptionController.getSubIdUsingPhoneId(i);

            if (SubscriptionManager.isValidSubscriptionId(sub)) hasAnyActiveSubscription = true;

            if (sub != mPhoneSubscriptions[i]) {
                sb.append(" phone[").append(i).append("] ").append(mPhoneSubscriptions[i]);
                sb.append("->").append(sub);
@@ -589,9 +599,22 @@ public class PhoneSwitcher extends Handler {
            }
        }

        if (!hasAnyActiveSubscription) {
            transitionToEmergencyPhone();
        } else {
            if (VDBG) log("Found an active subscription");
        }

        // Check if phoneId for preferred data is changed.
        int oldPreferredDataPhoneId = mPreferredDataPhoneId;
        updatePreferredDataPhoneId();

        // When there are no subscriptions, the preferred data phone ID is invalid, but we want
        // to keep a valid phoneId for Emergency, so skip logic that updates for preferred data
        // phone ID. Ideally there should be a single set of checks that evaluate the correct
        // phoneId on a service-by-service basis (EIMS being one), but for now... just bypass
        // this logic in the no-SIM case.
        if (hasAnyActiveSubscription) updatePreferredDataPhoneId();

        if (oldPreferredDataPhoneId != mPreferredDataPhoneId) {
            sb.append(" preferred phoneId ").append(oldPreferredDataPhoneId)
                    .append("->").append(mPreferredDataPhoneId);
@@ -738,8 +761,7 @@ public class PhoneSwitcher extends Handler {
        // if Internet PDN is established on the non-preferred phone, it will interrupt
        // Internet connection on the preferred phone. So we only accept Internet request with
        // preferred data subscription or no specified subscription.
        if (netRequest.networkCapabilities.hasCapability(
                NetworkCapabilities.NET_CAPABILITY_INTERNET)
        if (netRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                && subId != preferredDataSubId && subId != mValidator.getSubIdInValidation()) {
            // Returning INVALID_PHONE_INDEX will result in netRequest not being handled.
            return INVALID_PHONE_INDEX;
@@ -816,6 +838,18 @@ public class PhoneSwitcher extends Handler {
        mPreferredDataSubId = mSubscriptionController.getSubIdUsingPhoneId(mPreferredDataPhoneId);
    }

    private void transitionToEmergencyPhone() {
        if (mPreferredDataPhoneId != DEFAULT_EMERGENCY_PHONE_ID) {
            log("No active subscriptions: resetting preferred phone to 0 for emergency");
            mPreferredDataPhoneId = DEFAULT_EMERGENCY_PHONE_ID;
        }

        if (mPreferredDataSubId != INVALID_SUBSCRIPTION_ID) {
            mPreferredDataSubId = INVALID_SUBSCRIPTION_ID;
            notifyPreferredDataSubIdChanged();
        }
    }

    private Phone findPhoneById(final int phoneId) {
        if (phoneId < 0 || phoneId >= mNumPhones) {
            return null;
@@ -827,13 +861,21 @@ public class PhoneSwitcher extends Handler {
        validatePhoneId(phoneId);

        // In any case, if phone state is inactive, don't apply the network request.
        if (!isPhoneActive(phoneId)) return false;
        if (!isPhoneActive(phoneId) || (
                mSubscriptionController.getSubIdUsingPhoneId(phoneId) == INVALID_SUBSCRIPTION_ID
                && !isEmergencyNetworkRequest(networkRequest))) {
            return false;
        }

        int phoneIdToHandle = phoneIdForRequest(networkRequest);

        return phoneId == phoneIdToHandle;
    }

    boolean isEmergencyNetworkRequest(NetworkRequest networkRequest) {
        return networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
    }

    @VisibleForTesting
    protected boolean isPhoneActive(int phoneId) {
        return mPhoneStates[phoneId].active;
+10 −2
Original line number Diff line number Diff line
@@ -3574,7 +3574,15 @@ public class SubscriptionController extends ISub.Stub {
    }

    private @ApnSetting.ApnType int getWhiteListedApnDataTypes(int subId, String callingPackage) {
        return Integer.valueOf(getSubscriptionProperty(subId,
                SubscriptionManager.WHITE_LISTED_APN_DATA, callingPackage));
        String whiteListedApnData = getSubscriptionProperty(subId,
                SubscriptionManager.WHITE_LISTED_APN_DATA, callingPackage);

        try {
            return Integer.valueOf(whiteListedApnData);
        } catch (NumberFormatException e) {
            loge("[getWhiteListedApnDataTypes] couldn't parse apn data:" + whiteListedApnData);
        }

        return ApnSetting.TYPE_NONE;
    }
}
+13 −1
Original line number Diff line number Diff line
@@ -739,6 +739,7 @@ public class DcTracker extends Handler {
        }

        initEmergencyApnSetting();
        addEmergencyApnSetting();

        mProvisionActionName = "com.android.internal.telephony.PROVISION" + phone.getPhoneId();

@@ -3965,6 +3966,7 @@ public class DcTracker extends Handler {
        pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum);
        pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag);
        pw.println(" mDataStallNoRxEnabled=" + mDataStallNoRxEnabled);
        pw.println(" mEmergencyApn=" + mEmergencyApn);
        pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv);
        pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
        pw.println(" mResolver=" + mResolver);
@@ -4088,7 +4090,7 @@ public class DcTracker extends Handler {

    /**
     * Read APN configuration from Telephony.db for Emergency APN
     * All opertors recognize the connection request for EPDN based on APN type
     * All operators recognize the connection request for EPDN based on APN type
     * PLMN name,APN name are not mandatory parameters
     */
    private void initEmergencyApnSetting() {
@@ -4109,6 +4111,15 @@ public class DcTracker extends Handler {
            }
            cursor.close();
        }
        if (mEmergencyApn != null) return;

        // If no emergency APN setting has been found, make one using reasonable defaults
        mEmergencyApn = new ApnSetting.Builder()
                .setEntryName("Emergency")
                .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
                .setApnName("sos")
                .setApnTypeBitmask(ApnSetting.TYPE_EMERGENCY)
                .build();
    }

    /**
@@ -4128,6 +4139,7 @@ public class DcTracker extends Handler {
            if (!mAllApnSettings.contains(mEmergencyApn)) {
                mAllApnSettings.add(mEmergencyApn);
                log("Adding emergency APN : " + mEmergencyApn);
                return;
            }
        }
    }
+1 −2
Original line number Diff line number Diff line
@@ -116,7 +116,6 @@ public class PhoneSwitcherTest extends TelephonyTest {
        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
        waitABit();

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

@@ -132,7 +131,6 @@ public class PhoneSwitcherTest extends TelephonyTest {
        setDefaultDataSubId(0);

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

        setSlotIndexToSubId(0, 0);
        mSubChangedListener.onSubscriptionsChanged();
@@ -413,6 +411,7 @@ public class PhoneSwitcherTest extends TelephonyTest {
        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.
+2 −4
Original line number Diff line number Diff line
@@ -152,13 +152,11 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
        mContextFixture.setSystemService(Context.CONNECTIVITY_SERVICE,
                new ConnectivityManager(mContext, mIConnectivityManager));
        mTelephonyRegistryMock = new TelephonyRegistryMock();
        mPhoneSwitcherMock = new PhoneSwitcherMock(numberOfPhones, mLooper);
        mSubscriptionControllerMock = new SubscriptionControllerMock(mContext,
                mTelephonyRegistryMock, numberOfPhones);
        mSubscriptionMonitorMock = new SubscriptionMonitorMock(numberOfPhones);
        mPhoneSwitcherMock = new PhoneSwitcherMock(numberOfPhones, mLooper);
        mSubscriptionControllerMock = new SubscriptionControllerMock(mContext,
                mTelephonyRegistryMock, numberOfPhones);
        mPhoneSwitcherMock = new PhoneSwitcherMock(
                numberOfPhones, mLooper, mSubscriptionControllerMock);
        mSubscriptionMonitorMock = new SubscriptionMonitorMock(numberOfPhones);

        replaceInstance(SubscriptionController.class, "sInstance", null,
Loading