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

Commit 8d249387 authored by Jack Yu's avatar Jack Yu
Browse files

Fixed delay data switching issue

When allow data on voice call's feature is turned on,
it took a long time for new data to establish on
the voice sub. That's because we didn't tear down
the original network on default data sub.

When temp switching happens, we should tear down the
data network on the original data sub to let new
network setup on the voice sub.

Also when switching happens, we should dynamically update
the network score, so connectivity service will let
the new network created instead of treating the new one
as identical one and then tearing it down.

Fix: 229353836
Test: atest DataNetworkTest + Basic testing + voice call
data temp switching

Change-Id: I026a4d71a737f9a74a588ba236c0fa490054b030
parent 2260c01c
Loading
Loading
Loading
Loading
+56 −8
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.telephony.NetworkRegistrationInfo;
import android.telephony.PcoData;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
@@ -281,6 +282,7 @@ public class DataNetwork extends StateMachine {
                    TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY,
                    TEAR_DOWN_REASON_ILLEGAL_STATE,
                    TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK,
                    TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED,
            })
    public @interface TearDownReason {}

@@ -371,6 +373,9 @@ public class DataNetwork extends StateMachine {
    /** Data network tear down due to only allowed single network. */
    public static final int TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK = 29;

    /** Data network tear down due to preferred data switched to another phone. */
    public static final int TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED = 30;

    @IntDef(prefix = {"BANDWIDTH_SOURCE_"},
            value = {
                    BANDWIDTH_SOURCE_UNKNOWN,
@@ -469,6 +474,9 @@ public class DataNetwork extends StateMachine {
     */
    private final int mSubId;

    /** The network score of this network. */
    private int mNetworkScore;

    /**
     * Indicates that
     * {@link DataService.DataServiceProvider#deactivateDataCall(int, int, DataServiceCallback)}
@@ -957,8 +965,10 @@ public class DataNetwork extends StateMachine {
                mPhone.getPhoneId());
        final NetworkProvider provider = (null == factory) ? null : factory.getProvider();

        mNetworkScore = getNetworkScore();
        return new TelephonyNetworkAgent(mPhone, getHandler().getLooper(), this,
                getNetworkScore(), configBuilder.build(), provider,
                new NetworkScore.Builder().setLegacyInt(mNetworkScore).build(),
                configBuilder.build(), provider,
                new TelephonyNetworkAgentCallback(getHandler()::post) {
                    @Override
                    public void onValidationStatus(@ValidationStatus int status,
@@ -1049,13 +1059,12 @@ public class DataNetwork extends StateMachine {
                }
                case EVENT_ATTACH_NETWORK_REQUEST: {
                    onAttachNetworkRequests((NetworkRequestList) msg.obj);
                    updateNetworkScore();
                    break;
                }
                case EVENT_DETACH_NETWORK_REQUEST: {
                    TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) msg.obj;
                    mAttachedNetworkRequestList.remove(networkRequest);
                    networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
                    networkRequest.setAttachedNetwork(null);
                    onDetachNetworkRequest((TelephonyNetworkRequest) msg.obj);
                    updateNetworkScore();
                    break;
                }
                case EVENT_DETACH_ALL_NETWORK_REQUESTS: {
@@ -1620,6 +1629,31 @@ public class DataNetwork extends StateMachine {
        }
    }

    /**
     * Called when detaching the network request from this data network.
     *
     * @param networkRequest Network request to detach.
     */
    private void onDetachNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
        mAttachedNetworkRequestList.remove(networkRequest);
        networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
        networkRequest.setAttachedNetwork(null);

        if (mAttachedNetworkRequestList.isEmpty()) {
            log("All network requests are detached.");

            // If there is no network request attached, and we are not preferred data phone, then
            // this detach is likely due to temp DDS switch. We should tear down the network when
            // all requests are detached so the other network on preferred data sub can be
            // established properly.
            int preferredDataPhoneId = PhoneSwitcher.getInstance().getPreferredDataPhoneId();
            if (preferredDataPhoneId != SubscriptionManager.INVALID_PHONE_INDEX
                    && preferredDataPhoneId != mPhone.getPhoneId()) {
                tearDown(TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED);
            }
        }
    }

    /**
     * Detach the network request from this data network. Note that this will not tear down the
     * network.
@@ -2759,17 +2793,28 @@ public class DataNetwork extends StateMachine {
        return mLinkStatus;
    }

    /**
     * Update the network score and report to connectivity service if necessary.
     */
    private void updateNetworkScore() {
        int networkScore = getNetworkScore();
        if (networkScore != mNetworkScore) {
            logl("Updating score from " + mNetworkScore + " to " + networkScore);
            mNetworkScore = networkScore;
            mNetworkAgent.sendNetworkScore(mNetworkScore);
        }
    }

    /**
     * @return The network score. The higher score of the network has higher chance to be
     * selected by the connectivity service as active network.
     */
    private @NonNull NetworkScore getNetworkScore() {
    private int getNetworkScore() {
        // If it's serving a network request that asks NET_CAPABILITY_INTERNET and doesn't have
        // specify a sub id, this data network is considered to be default internet data
        // connection. In this case we assign a slightly higher score of 50. The intention is
        // it will not be replaced by other data networks accidentally in DSDS use case.
        int score = OTHER_NETWORK_SCORE;
        // TODO: Should update the score when attached list changed.
        for (TelephonyNetworkRequest networkRequest : mAttachedNetworkRequestList) {
            if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    && networkRequest.getNetworkSpecifier() == null) {
@@ -2777,7 +2822,7 @@ public class DataNetwork extends StateMachine {
            }
        }

        return new NetworkScore.Builder().setLegacyInt(score).build();
        return score;
    }

    /**
@@ -3210,6 +3255,8 @@ public class DataNetwork extends StateMachine {
                return "TEAR_DOWN_REASON_ILLEGAL_STATE";
            case TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK:
                return "TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK";
            case TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED:
                return "TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED";
            default:
                return "UNKNOWN(" + reason + ")";
        }
@@ -3354,6 +3401,7 @@ public class DataNetwork extends StateMachine {
        pw.println("mTransport=" + AccessNetworkConstants.transportTypeToString(mTransport));
        pw.println("WWAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
        pw.println("WLAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
        pw.println("mNetworkScore=" + mNetworkScore);
        pw.println("mDataAllowedReason=" + mDataAllowedReason);
        pw.println("mPduSessionId=" + mPduSessionId);
        pw.println("mDataProfile=" + mDataProfile);
+18 −0
Original line number Diff line number Diff line
@@ -2970,4 +2970,22 @@ public class DataNetworkControllerTest extends TelephonyTest {
        assertThat(dataNetworkList.get(0).getAttachedNetworkRequestList()).isEmpty();
        assertThat(dataNetworkList.get(0).isConnected()).isTrue();
    }

    @Test
    public void testTempDdsSwitchTearDown() throws Exception {
        TelephonyNetworkRequest request = createNetworkRequest(
                NetworkCapabilities.NET_CAPABILITY_INTERNET);
        mDataNetworkControllerUT.addNetworkRequest(request);
        processAllMessages();

        // Now DDS temporarily switched to phone 1
        doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();

        // Simulate telephony network factory remove request due to switch.
        mDataNetworkControllerUT.removeNetworkRequest(request);
        processAllMessages();

        // Data should be torn down on this non-preferred sub.
        verifyAllDataDisconnected();
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ public class DataNetworkTest extends TelephonyTest {
    // Mocked classes
    private DataNetworkCallback mDataNetworkCallback;
    private DataCallSessionStats mDataCallSessionStats;
    private PhoneSwitcher mMockedPhoneSwitcher;

    private final NetworkRegistrationInfo mIwlanNetworkRegistrationInfo =
            new NetworkRegistrationInfo.Builder()
@@ -300,6 +301,8 @@ public class DataNetworkTest extends TelephonyTest {

        mDataNetworkCallback = Mockito.mock(DataNetworkCallback.class);
        mDataCallSessionStats = Mockito.mock(DataCallSessionStats.class);
        mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
        replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
        doAnswer(invocation -> {
            ((Runnable) invocation.getArguments()[0]).run();
            return null;