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

Commit 098b9ead authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "IWLAN handover optimization" into tm-dev

parents 8cfa9878 7d0db95d
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -1982,10 +1982,11 @@ public class RIL extends BaseCommands implements CommandsInterface {

            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
                        + ",reason=" + RILUtils.setupDataReasonToString(reason)
                        + ",accessNetworkType=" + AccessNetworkType.toString(accessNetworkType)
                        + ",dataProfile=" + dataProfile + ",isRoaming=" + isRoaming
                        + ",allowRoaming=" + allowRoaming + ",reason" + reason
                        + ",linkProerties=" + linkProperties + ",pduSessionId=" + pduSessionId
                        + ",allowRoaming=" + allowRoaming
                        + ",linkProperties=" + linkProperties + ",pduSessionId=" + pduSessionId
                        + ",sliceInfo=" + sliceInfo + ",trafficDescriptor=" + trafficDescriptor
                        + ",matchAllRuleAllowed=" + matchAllRuleAllowed);
            }
@@ -2249,7 +2250,8 @@ public class RIL extends BaseCommands implements CommandsInterface {

            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
                        + " cid = " + cid + " reason = " + reason);
                        + " cid = " + cid + " reason = "
                        + RILUtils.deactivateDataReasonToString(reason));
            }

            try {
+43 −0
Original line number Diff line number Diff line
@@ -313,6 +313,9 @@ import android.telephony.UiccSlotMapping;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataService.DeactivateDataReason;
import android.telephony.data.DataService.SetupDataReason;
import android.telephony.data.EpsQos;
import android.telephony.data.NetworkSliceInfo;
import android.telephony.data.NetworkSlicingConfig;
@@ -4626,6 +4629,46 @@ public class RILUtils {
        return string != null ? string : "";
    }

    /**
     * Convert setup data reason to string.
     *
     * @param reason The reason for setup data call.
     * @return The reason in string format.
     */
    public static String setupDataReasonToString(@SetupDataReason int reason) {
        switch (reason) {
            case DataService.REQUEST_REASON_NORMAL:
                return "NORMAL";
            case DataService.REQUEST_REASON_HANDOVER:
                return "HANDOVER";
            case DataService.REQUEST_REASON_UNKNOWN:
                return "UNKNOWN";
            default:
                return "UNKNOWN(" + reason + ")";
        }
    }

    /**
     * Convert deactivate data reason to string.
     *
     * @param reason The reason for deactivate data call.
     * @return The reason in string format.
     */
    public static String deactivateDataReasonToString(@DeactivateDataReason int reason) {
        switch (reason) {
            case DataService.REQUEST_REASON_NORMAL:
                return "NORMAL";
            case DataService.REQUEST_REASON_HANDOVER:
                return "HANDOVER";
            case DataService.REQUEST_REASON_SHUTDOWN:
                return "SHUTDOWN";
            case DataService.REQUEST_REASON_UNKNOWN:
                return "UNKNOWN";
            default:
                return "UNKNOWN(" + reason + ")";
        }
    }

    /**
     * RIL request to String
     * @param request request
+15 −23
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -973,14 +974,18 @@ public class DataNetwork extends StateMachine {
                    mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length);
                    break;
                }
                case EVENT_START_HANDOVER:
                case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED:
                case EVENT_BANDWIDTH_ESTIMATE_FROM_BANDWIDTH_ESTIMATOR_CHANGED:
                case EVENT_TEAR_DOWN_NETWORK:
                case EVENT_PCO_DATA_RECEIVED:
                case EVENT_STUCK_IN_TRANSIENT_STATE:
                case EVENT_DISPLAY_INFO_CHANGED:
                    // Ignore the events when not in the correct state.
                    break;
                case EVENT_START_HANDOVER:
                    log("Ignore the handover to " + AccessNetworkConstants
                            .transportTypeToString(msg.arg1) + " request.");
                    break;
                default:
                    loge("Unhandled event " + eventToString(msg.what));
                    break;
@@ -1206,7 +1211,6 @@ public class DataNetwork extends StateMachine {
                        deferMessage(msg);
                    }
                    break;
                case EVENT_START_HANDOVER:
                case EVENT_TEAR_DOWN_NETWORK:
                    // Defer the request until handover succeeds or fails.
                    deferMessage(msg);
@@ -2440,28 +2444,16 @@ public class DataNetwork extends StateMachine {
    }

    /**
     * Get the highest priority network capability from the network request. This is used to get
     * the representative APN-type capability for different purposes. It will never return a
     * non-APN-type capability.
     * Get the APN type network capability. If there are more than one capabilities that are
     * APN-types, then return the highest priority one.
     *
     * @return The highest priority network capability from this network.
     * @return The APN type network capability from this network.
     */
    public @NetCapability int getHighestPriorityNetworkCapability() {
        int highestPriority = 0;
        int highestPriorityCapability = -1;
        for (int capability : getNetworkCapabilities().getCapabilities()) {
            // Convert the capability to APN type. For non-APN-type capabilities, TYPE_NONE is
            // returned.
            int apnType = DataUtils.networkCapabilityToApnType(capability);
            if (apnType != ApnSetting.TYPE_NONE) {
                int priority = mDataConfigManager.getNetworkCapabilityPriority(capability);
                if (priority > highestPriority) {
                    highestPriority = priority;
                    highestPriorityCapability = capability;
                }
            }
        }
        return highestPriorityCapability;
    public @NetCapability int getApnTypeNetworkCapability() {
        return Arrays.stream(getNetworkCapabilities().getCapabilities()).boxed()
                .filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
                .max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
                .orElse(-1);
    }

    /**
+38 −20
Original line number Diff line number Diff line
@@ -178,8 +178,8 @@ public class DataNetworkController extends Handler {
    /** Event for emergency call started or ended. */
    private static final int EVENT_EMERGENCY_CALL_CHANGED = 20;

    /** Event for preferred transport changed. */
    private static final int EVENT_PREFERRED_TRANSPORT_CHANGED = 21;
    /** Event for evaluating preferred transport. */
    private static final int EVENT_EVALUATE_PREFERRED_TRANSPORT = 21;

    /** Event for subscription plans changed. */
    private static final int EVENT_SUBSCRIPTION_PLANS_CHANGED = 22;
@@ -821,7 +821,12 @@ public class DataNetworkController extends Handler {
        mAccessNetworksManager.registerCallback(new AccessNetworksManagerCallback(this::post) {
            @Override
            public void onPreferredTransportChanged(@NetCapability int capability) {
                DataNetworkController.this.onPreferredTransportChanged(capability);
                int preferredTransport = mAccessNetworksManager
                        .getPreferredTransportByNetworkCapability(capability);
                logl("onPreferredTransportChanged: "
                        + DataUtils.networkCapabilityToString(capability) + " preferred on "
                        + AccessNetworkConstants.transportTypeToString(preferredTransport));
                DataNetworkController.this.onEvaluatePreferredTransport(capability);
                sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
                        DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED));
            }
@@ -963,8 +968,8 @@ public class DataNetworkController extends Handler {
                            DataEvaluationReason.EMERGENCY_CALL_CHANGED));
                }
                break;
            case EVENT_PREFERRED_TRANSPORT_CHANGED:
                onPreferredTransportChanged(msg.arg1);
            case EVENT_EVALUATE_PREFERRED_TRANSPORT:
                onEvaluatePreferredTransport(msg.arg1);
                break;
            case EVENT_SUBSCRIPTION_PLANS_CHANGED:
                SubscriptionPlan[] plans = (SubscriptionPlan[]) msg.obj;
@@ -2182,7 +2187,7 @@ public class DataNetworkController extends Handler {
        }

        int preferredTransport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
                dataNetwork.getHighestPriorityNetworkCapability());
                dataNetwork.getApnTypeNetworkCapability());
        if (dataNetwork.getTransport() == preferredTransport) {
            log("onDataNetworkHandoverRetry: " + dataNetwork + " is already on the preferred "
                    + "transport " + AccessNetworkConstants.transportTypeToString(
@@ -2295,8 +2300,13 @@ public class DataNetworkController extends Handler {
     * @param dataNetwork The data network.
     */
    private void onDataNetworkHandoverSucceeded(@NonNull DataNetwork dataNetwork) {
        logl("Successfully handover " + dataNetwork + " to "
                + AccessNetworkConstants.transportTypeToString(dataNetwork.getTransport()));
        logl("Handover successfully. " + dataNetwork + " to " + AccessNetworkConstants
                .transportTypeToString(dataNetwork.getTransport()));
        // The preferred transport might be changed when handover was in progress. We need to
        // evaluate again to make sure we are not out-of-sync with the input from access network
        // manager.
        sendMessage(obtainMessage(EVENT_EVALUATE_PREFERRED_TRANSPORT,
                dataNetwork.getApnTypeNetworkCapability(), 0));
    }

    /**
@@ -2314,9 +2324,9 @@ public class DataNetworkController extends Handler {
    private void onDataNetworkHandoverFailed(@NonNull DataNetwork dataNetwork,
            @DataFailureCause int cause, long retryDelayMillis,
            @HandoverFailureMode int handoverFailureMode) {
        logl("onDataNetworkHandoverFailed: " + dataNetwork + ", cause="
                + DataFailCause.toString(cause) + "(0x" + Integer.toHexString(cause)
                + "), retryDelayMillis=" + retryDelayMillis + "ms, handoverFailureMode="
        logl("Handover failed. " + dataNetwork + ", cause=" + DataFailCause.toString(cause)
                + "(0x" + Integer.toHexString(cause) + "), retryDelayMillis=" + retryDelayMillis
                + "ms, handoverFailureMode="
                + DataCallResponse.failureModeToString(handoverFailureMode));
        if (handoverFailureMode == DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK
                || (handoverFailureMode == DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY
@@ -2325,8 +2335,8 @@ public class DataNetworkController extends Handler {
            // to the original one, but we should re-evaluate the preferred transport again to
            // make sure QNS does change it back, if not, we still need to perform handover at that
            // time.
            sendMessageDelayed(obtainMessage(EVENT_PREFERRED_TRANSPORT_CHANGED,
                    dataNetwork.getHighestPriorityNetworkCapability(), 0),
            sendMessageDelayed(obtainMessage(EVENT_EVALUATE_PREFERRED_TRANSPORT,
                    dataNetwork.getApnTypeNetworkCapability(), 0),
                    REEVALUATE_PREFERRED_TRANSPORT_DELAY_MILLIS);
        } else if (handoverFailureMode == DataCallResponse
                .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL || handoverFailureMode
@@ -2422,26 +2432,34 @@ public class DataNetworkController extends Handler {
    }

    /**
     * Called when preferred transport changed for certain capability.
     * Called when needed to evaluate the preferred transport for certain capability.
     *
     * @param capability The network capability that has preferred transport changed.
     * @param capability The network capability to evaluate.
     */
    private void onPreferredTransportChanged(@NetCapability int capability) {
    private void onEvaluatePreferredTransport(@NetCapability int capability) {
        int preferredTransport = mAccessNetworksManager
                .getPreferredTransportByNetworkCapability(capability);
        logl("onPreferredTransportChanged: " + DataUtils.networkCapabilityToString(capability)
        log("evaluatePreferredTransport: " + DataUtils.networkCapabilityToString(capability)
                + " preferred on "
                + AccessNetworkConstants.transportTypeToString(preferredTransport));
        for (DataNetwork dataNetwork : mDataNetworkList) {
            if (dataNetwork.getHighestPriorityNetworkCapability() == capability) {
            if (dataNetwork.getApnTypeNetworkCapability() == capability) {
                // Check if the data network's current transport is different than from the
                // preferred transport. If it's different, then handover is needed.
                if (dataNetwork.getTransport() == preferredTransport) {
                    log("onPreferredTransportChanged:" + dataNetwork + " already on "
                    log("evaluatePreferredTransport:" + dataNetwork + " already on "
                            + AccessNetworkConstants.transportTypeToString(preferredTransport));
                    continue;
                }

                // If handover is ongoing, ignore the preference change for now. After handover
                // succeeds or fails, preferred transport will be re-evaluate again. Handover will
                // be performed at that time if needed.
                if (dataNetwork.isHandoverInProgress()) {
                    log("evaluatePreferredTransport: " + dataNetwork + " handover in progress.");
                    continue;
                }

                DataEvaluation dataEvaluation = evaluateDataNetworkHandover(dataNetwork);
                if (!dataEvaluation.containsDisallowedReasons()) {
                    logl("Start handover " + dataNetwork + " to "
@@ -2449,7 +2467,7 @@ public class DataNetworkController extends Handler {
                    dataNetwork.startHandover(preferredTransport, null);
                } else if (dataEvaluation.containsOnly(
                        DataDisallowedReason.NOT_ALLOWED_BY_POLICY)) {
                    logl("onPreferredTransportChanged: Handover not allowed by policy. Tear "
                    logl("evaluatePreferredTransport: Handover not allowed by policy. Tear "
                            + "down the network so a new network can be setup on "
                            + AccessNetworkConstants.transportTypeToString(preferredTransport)
                            + ".");
+61 −5
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ import com.android.internal.telephony.ISub;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataNetworkController.HandoverRule;
import com.android.internal.telephony.data.DataRetryManager.DataRetryManagerCallback;

@@ -126,6 +127,8 @@ public class DataNetworkControllerTest extends TelephonyTest {
    private DataNetworkController mDataNetworkControllerUT;
    private PersistableBundle mCarrierConfig;

    private AccessNetworksManagerCallback mAccessNetworksManagerCallback;

    private final DataProfile mGeneralPurposeDataProfile = new DataProfile.Builder()
            .setApnSetting(new ApnSetting.Builder()
                    .setId(2163)
@@ -501,6 +504,11 @@ public class DataNetworkControllerTest extends TelephonyTest {
        replaceInstance(DataNetworkController.class, "mAccessNetworksManager",
                mDataNetworkControllerUT, mAccessNetworksManager);

        ArgumentCaptor<AccessNetworksManagerCallback> callbackCaptor =
                ArgumentCaptor.forClass(AccessNetworksManagerCallback.class);
        verify(mAccessNetworksManager).registerCallback(callbackCaptor.capture());
        mAccessNetworksManagerCallback = callbackCaptor.getValue();

        doAnswer(invocation -> {
            TelephonyNetworkRequest networkRequest =
                    (TelephonyNetworkRequest) invocation.getArguments()[0];
@@ -1027,7 +1035,7 @@ public class DataNetworkControllerTest extends TelephonyTest {
                .getPreferredTransportByNetworkCapability(
                        eq(NetworkCapabilities.NET_CAPABILITY_INTERNET));
        // Data remain disabled, but trigger the preference evaluation.
        mDataNetworkControllerUT.obtainMessage(21 /*EVENT_PREFERRED_TRANSPORT_CHANGED*/,
        mDataNetworkControllerUT.obtainMessage(21 /*EVENT_EVALUATE_PREFERRED_TRANSPORT*/,
                NetworkCapabilities.NET_CAPABILITY_INTERNET, 0).sendToTarget();
        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
@@ -1295,8 +1303,8 @@ public class DataNetworkControllerTest extends TelephonyTest {

        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        mDataNetworkControllerUT.obtainMessage(21/*EVENT_EVALUATE_PREFERRED_TRANSPORT*/,
                NetworkCapabilities.NET_CAPABILITY_IMS, 0).sendToTarget();
        mAccessNetworksManagerCallback.onPreferredTransportChanged(
                NetworkCapabilities.NET_CAPABILITY_IMS);
        processAllMessages();

        DataNetwork dataNetwork = getDataNetworks().get(0);
@@ -1305,6 +1313,54 @@ public class DataNetworkControllerTest extends TelephonyTest {
                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
    }

    @Test
    public void testHandoverDataNetworkBackToBackPreferenceChanged() throws Exception {
        testSetupImsDataNetwork();

        Mockito.reset(mMockedWlanDataServiceManager);
        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        mAccessNetworksManagerCallback.onPreferredTransportChanged(
                NetworkCapabilities.NET_CAPABILITY_IMS);

        processAllMessages();

        // Capture the message for setup data call response. We want to delay it.
        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
        verify(mMockedWlanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class),
                anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(),
                messageCaptor.capture());

        // Before setup data call response, change the preference back to cellular.
        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        mAccessNetworksManagerCallback.onPreferredTransportChanged(
                NetworkCapabilities.NET_CAPABILITY_IMS);
        processAllMessages();

        // Before setup data call response, change the preference back to IWLAN.
        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        mAccessNetworksManagerCallback.onPreferredTransportChanged(
                NetworkCapabilities.NET_CAPABILITY_IMS);
        processAllMessages();

        // Finally handover is completed.
        Message msg = messageCaptor.getValue();
        DataCallResponse response = new DataCallResponse.Builder()
                .setCause(DataFailCause.NONE)
                .build();
        msg.getData().putParcelable("data_call_response", response);
        msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
        msg.sendToTarget();
        processAllMessages();

        // Make sure handover request is only sent once.
        verify(mMockedWlanDataServiceManager, times(1)).setupDataCall(anyInt(),
                any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
                any(), any(), anyBoolean(), messageCaptor.capture());
    }

    @Test
    public void testHandoverDataNetworkNotAllowedByPolicy() throws Exception {
        mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
@@ -1318,8 +1374,8 @@ public class DataNetworkControllerTest extends TelephonyTest {

        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
                .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        mDataNetworkControllerUT.obtainMessage(21/*EVENT_PREFERRED_TRANSPORT_CHANGED*/,
                NetworkCapabilities.NET_CAPABILITY_IMS, 0).sendToTarget();
        mAccessNetworksManagerCallback.onPreferredTransportChanged(
                NetworkCapabilities.NET_CAPABILITY_IMS);
        // After this, IMS data network should be disconnected, and DNC should attempt to
        // establish a new one on IWLAN
        processAllMessages();