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

Commit 946245de authored by Jack Yu's avatar Jack Yu
Browse files

Fixed allocate/deallocate PDU session id

1. For data connection originated on IWLAN, Android frameworks
   is responsible for allocating a PDU session id from the modem.
   If later on this data connection handover to cellular, and then ends,
   modem will be responsible for releasing the PDU session id. Android
   frameworks will NOT call "release PDU session id" in this case.
2. For data connection originated on cellular, Android frameworks passes
   -1 in setup data call request, which means modem should allocate the
   PDU session id for this data connection. When handover is about to
   happen, Android frameworks calls startHandover(psi), meaning this PDU
   session id should be preserved for the handover connection on IWLAN.
   Later on if this data connection ends on IWLAN, Android frameworks
   will be responsible for calling "release pdu session id", even though
   Android frameworks did not call "allocate pdu session id" for this
   data connection at the beginning.

Fix: 198516169
Test: atest DataConnectionTest

Change-Id: I95146e150bec0cf34fa86ca4f78a67e933957ca0
parent 81f65cc7
Loading
Loading
Loading
Loading
+13 −25
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ public class DataConnection extends StateMachine {
    private DcTesterFailBringUpAll mDcTesterFailBringUpAll;

    // Whether or not the data connection should allocate its own pdu session id
    private final boolean mDoAllocatePduSessionId;
    private boolean mDoAllocatePduSessionId;

    private static AtomicInteger mInstanceNumber = new AtomicInteger(0);
    private AsyncChannel mAc;
@@ -466,15 +466,14 @@ public class DataConnection extends StateMachine {
    public static DataConnection makeDataConnection(Phone phone, int id, DcTracker dct,
                                                    DataServiceManager dataServiceManager,
                                                    DcTesterFailBringUpAll failBringUpAll,
                                                    DcController dcc,
                                                    boolean doAllocatePduSessionId) {
                                                    DcController dcc) {
        String transportType = (dataServiceManager.getTransportType()
                == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                ? "C"   // Cellular
                : "I";  // IWLAN
        DataConnection dc = new DataConnection(phone, transportType + "-"
                + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll,
                dcc, doAllocatePduSessionId);
                dcc);
        dc.start();
        if (DBG) dc.log("Made " + dc.getName());
        return dc;
@@ -759,8 +758,7 @@ public class DataConnection extends StateMachine {
    //***** Constructor (NOTE: uses dcc.getHandler() as its Handler)
    private DataConnection(Phone phone, String tagSuffix, int id,
                           DcTracker dct, DataServiceManager dataServiceManager,
                           DcTesterFailBringUpAll failBringUpAll, DcController dcc,
                           boolean doAllocatePduSessionId) {
                           DcTesterFailBringUpAll failBringUpAll, DcController dcc) {
        super("DC-" + tagSuffix, dcc);
        mTagSuffix = tagSuffix;
        setLogRecSize(300);
@@ -779,7 +777,7 @@ public class DataConnection extends StateMachine {
        mDataRegState = mPhone.getServiceState().getDataRegistrationState();
        mIsSuspended = false;
        mDataCallSessionStats = new DataCallSessionStats(mPhone);
        mDoAllocatePduSessionId = doAllocatePduSessionId;
        mDoAllocatePduSessionId = false;

        int networkType = getNetworkType();
        mRilRat = ServiceState.networkTypeToRilRadioTechnology(networkType);
@@ -971,6 +969,7 @@ public class DataConnection extends StateMachine {
        }

        // setup data call for REQUEST_TYPE_NORMAL
        mDoAllocatePduSessionId = mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
        allocatePduSessionId(psi -> {
            this.setPduSessionId(psi);
            mDataServiceManager.setupDataCall(
@@ -992,7 +991,7 @@ public class DataConnection extends StateMachine {
    }

    private void allocatePduSessionId(Consumer<Integer> allocateCallback) {
        if (getDoAllocatePduSessionId()) {
        if (mDoAllocatePduSessionId) {
            Message msg = this.obtainMessage(EVENT_ALLOCATE_PDU_SESSION_ID);
            msg.obj = allocateCallback;
            mPhone.mCi.allocatePduSessionId(msg);
@@ -1182,8 +1181,10 @@ public class DataConnection extends StateMachine {
    }

    private void releasePduSessionId(Runnable releaseCallback) {
        // If we are not in the middle of a handover and have a real pdu session id, then we release
        if (mHandoverState != HANDOVER_STATE_BEING_TRANSFERRED
        // If the transport is IWLAN, and there is a valid PDU session id, also the data connection
        // is not being handovered, we should release the pdu session id.
        if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
                && mHandoverState == HANDOVER_STATE_IDLE
                && this.getPduSessionId() != PDU_SESSION_ID_NOT_SET) {
            Message msg = this.obtainMessage(EVENT_RELEASE_PDU_SESSION_ID);
            msg.obj = releaseCallback;
@@ -1353,6 +1354,7 @@ public class DataConnection extends StateMachine {
        mHandoverFailureMode = DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN;
        mSliceInfo = null;
        mDefaultQos = null;
        mDoAllocatePduSessionId = false;
        mQosBearerSessions.clear();
        mTrafficDescriptors.clear();
    }
@@ -1407,17 +1409,7 @@ public class DataConnection extends StateMachine {
        } else {
            if (DBG) log("onSetupConnectionCompleted received successful DataCallResponse");
            mCid = response.getId();

            if (response.getPduSessionId() != getPduSessionId()) {
                if (getDoAllocatePduSessionId()) {
                    loge("The pdu session id on DataCallResponse is different than the one "
                            + "allocated.  response psi=" + response.getPduSessionId()
                            + ", allocated psi=" + getPduSessionId());
                } else {
            setPduSessionId(response.getPduSessionId());
                }
            }

            updatePcscfAddr(response);
            updateResponseFields(response);
            result = updateLinkProperty(response).setupResult;
@@ -2158,10 +2150,6 @@ public class DataConnection extends StateMachine {
        return result;
    }

    private boolean getDoAllocatePduSessionId() {
        return mDoAllocatePduSessionId;
    }

    /**
     * Initialize connection, this will fail if the
     * apnSettings are not compatible.
+1 −3
Original line number Diff line number Diff line
@@ -3607,10 +3607,8 @@ public class DcTracker extends Handler {
        if (DBG) log("createDataConnection E");

        int id = mUniqueIdGenerator.getAndIncrement();
        boolean doAllocatePduSessionId =
                mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
        DataConnection dataConnection = DataConnection.makeDataConnection(mPhone, id, this,
                mDataServiceManager, mDcTesterFailBringUpAll, mDcc, doAllocatePduSessionId);
                mDataServiceManager, mDcTesterFailBringUpAll, mDcc);
        mDataConnections.put(id, dataConnection);
        if (DBG) log("createDataConnection() X id=" + id + " dc=" + dataConnection);
        return dataConnection;
+81 −2
Original line number Diff line number Diff line
@@ -297,7 +297,7 @@ public class DataConnectionTest extends TelephonyTest {
            Handler h = new Handler();
            mDcc = DcController.makeDcc(mPhone, mDcTracker, mDataServiceManager, h.getLooper(), "");
            mDc = DataConnection.makeDataConnection(mPhone, 0, mDcTracker, mDataServiceManager,
                    mDcTesterFailBringUpAll, mDcc, true);
                    mDcTesterFailBringUpAll, mDcc);
        }
    }

@@ -482,6 +482,63 @@ public class DataConnectionTest extends TelephonyTest {
                eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                anyInt(), any(), tdCaptor.capture(), anyBoolean(), any(Message.class));

        verify(mSimulatedCommandsVerifier, times(0))
                .allocatePduSessionId(any());

        assertEquals("spmode.ne.jp", dpCaptor.getValue().getApn());
        if (tdCaptor.getValue() != null) {
            if (mApnContext.getApnTypeBitmask() == ApnSetting.TYPE_ENTERPRISE) {
                assertEquals(null, tdCaptor.getValue().getDataNetworkName());
                assertTrue(Arrays.equals(DataConnection.getEnterpriseOsAppId(),
                        tdCaptor.getValue().getOsAppId()));
            } else {
                assertEquals("spmode.ne.jp", tdCaptor.getValue().getDataNetworkName());
                assertEquals(null, tdCaptor.getValue().getOsAppId());
            }
        }
        assertTrue(mDc.isActive());

        assertEquals(1, mDc.getPduSessionId());
        assertEquals(3, mDc.getPcscfAddresses().length);
        assertTrue(Arrays.stream(mDc.getPcscfAddresses()).anyMatch("fd00:976a:c305:1d::8"::equals));
        assertTrue(Arrays.stream(mDc.getPcscfAddresses()).anyMatch("fd00:976a:c202:1d::7"::equals));
        assertTrue(Arrays.stream(mDc.getPcscfAddresses()).anyMatch("fd00:976a:c305:1d::5"::equals));
    }

    @Test
    @SmallTest
    public void testConnectOnIwlan() throws Exception {
        assertTrue(mDc.isInactive());
        Field field = DataConnection.class.getDeclaredField("mTransportType");
        field.setAccessible(true);
        field.setInt(mDc, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
        connectEvent(true);

        verify(mCT, times(1)).registerForVoiceCallStarted(any(Handler.class),
                eq(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED), eq(null));
        verify(mCT, times(1)).registerForVoiceCallEnded(any(Handler.class),
                eq(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED), eq(null));
        verify(mSimulatedCommandsVerifier, times(0))
                .registerForNattKeepaliveStatus(any(Handler.class),
                        eq(DataConnection.EVENT_KEEPALIVE_STATUS), eq(null));
        verify(mSimulatedCommandsVerifier, times(0))
                .registerForLceInfo(any(Handler.class),
                        eq(DataConnection.EVENT_LINK_CAPACITY_CHANGED), eq(null));
        verify(mVcnManager, atLeastOnce())
                .applyVcnNetworkPolicy(
                        argThat(caps ->
                                caps.hasCapability(
                                        NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)),
                        any());

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        ArgumentCaptor<TrafficDescriptor> tdCaptor =
                ArgumentCaptor.forClass(TrafficDescriptor.class);
        verify(mDataServiceManager, times(1)).setupDataCall(
                eq(AccessNetworkType.UTRAN), dpCaptor.capture(), eq(false),
                eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                anyInt(), any(), tdCaptor.capture(), anyBoolean(), any(Message.class));

        verify(mSimulatedCommandsVerifier, times(1))
                .allocatePduSessionId(any());

@@ -498,7 +555,7 @@ public class DataConnectionTest extends TelephonyTest {
        }
        assertTrue(mDc.isActive());

        assertEquals(mDc.getPduSessionId(), 1);
        assertEquals(1, mDc.getPduSessionId());
        assertEquals(3, mDc.getPcscfAddresses().length);
        assertTrue(Arrays.stream(mDc.getPcscfAddresses()).anyMatch("fd00:976a:c305:1d::8"::equals));
        assertTrue(Arrays.stream(mDc.getPcscfAddresses()).anyMatch("fd00:976a:c202:1d::7"::equals));
@@ -575,6 +632,28 @@ public class DataConnectionTest extends TelephonyTest {
                .unregisterForNattKeepaliveStatus(any(Handler.class));
        verify(mDataServiceManager, times(1)).deactivateDataCall(eq(DEFAULT_DC_CID),
                eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
        verify(mSimulatedCommandsVerifier, times(0))
                .releasePduSessionId(any(), eq(5));

        assertTrue(mDc.isInactive());
    }

    @Test
    @SmallTest
    public void testDisconnectOnIwlan() throws Exception {
        testConnectEvent();

        Field field = DataConnection.class.getDeclaredField("mTransportType");
        field.setAccessible(true);
        field.setInt(mDc, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
        mDc.setPduSessionId(5);
        disconnectEvent();

        verify(mSimulatedCommandsVerifier, times(0)).unregisterForLceInfo(any(Handler.class));
        verify(mSimulatedCommandsVerifier, times(0))
                .unregisterForNattKeepaliveStatus(any(Handler.class));
        verify(mDataServiceManager, times(1)).deactivateDataCall(eq(DEFAULT_DC_CID),
                eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
        verify(mSimulatedCommandsVerifier, times(1))
                .releasePduSessionId(any(), eq(5));