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

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

Merge "Added IWLAN handover policy support"

parents 1609028c ebe97bde
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -656,16 +656,16 @@ public class AccessNetworksManager extends Handler {
        for (QualifiedNetworks networks : networksList) {
            if (networks.qualifiedNetworks.length > 0) {
                int transport = getTransportFromAccessNetwork(networks.qualifiedNetworks[0]);
                if (getCurrentTransport(networks.apnType) != transport) {
                if (getPreferredTransport(networks.apnType) != transport) {
                    mAccessNetworksManagerCallbacks.forEach(callback ->
                            callback.invokeFromExecutor(() ->
                                    callback.onPreferredTransportChanged(DataUtils
                                            .apnTypeToNetworkCapability(networks.apnType))));
                }
                    mPreferredTransports.put(networks.apnType, transport);
                    logl("setPreferredTransports: apnType="
                        + ApnSetting.getApnTypeString(networks.apnType)
                        + ", transport=" + AccessNetworkConstants.transportTypeToString(transport));
                            + ApnSetting.getApnTypeString(networks.apnType) + ", transport="
                            + AccessNetworkConstants.transportTypeToString(transport));
                }
            }
        }
    }
+22 −8
Original line number Diff line number Diff line
@@ -21,14 +21,17 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.telephony.data.DataProfile;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The class to describe a data evaluation for whether allowing or disallowing
 * establishing a data network.
 * The class to describe a data evaluation for whether allowing or disallowing certain operations
 * like setup a data network, sustaining existing data networks, or handover between IWLAN and
 * cellular.
 */
public class DataEvaluation {
    /** The reason for this evaluation */
@@ -107,7 +110,7 @@ public class DataEvaluation {
    }

    /**
     * @return {@code true} if data is allowed.
     * @return {@code true} if the operation is allowed.
     */
    public boolean isDataAllowed() {
        return mDataDisallowedReasons.size() == 0;
@@ -155,8 +158,11 @@ public class DataEvaluation {
        return false;
    }

    /** The reason for evaluating unsatisfied network requests. */
    enum DataEvaluationReason {
    /**
     * The reason for evaluating unsatisfied network requests, existing data networks, and handover.
     */
    @VisibleForTesting
    public enum DataEvaluationReason {
        /** New request from the apps. */
        NEW_REQUEST,
        /** Data config changed. */
@@ -185,9 +191,13 @@ public class DataEvaluation {
        RETRY_AFTER_DISCONNECTED,
        /** Data setup retry. */
        DATA_RETRY,
        /** Handover between IWLAN and cellular. */
        DATA_HANDOVER,
        /** Preferred transport changed. */
        PREFERRED_TRANSPORT_CHANGED,
    }

    /** Disallowed reasons. There could be multiple reasons if data connection is not allowed. */
    /** Disallowed reasons. There could be multiple reasons if it is not allowed. */
    public enum DataDisallowedReason {
        // Soft failure reasons. A soft reason means that in certain conditions, data is still
        // allowed. Normally those reasons are due to users settings.
@@ -222,14 +232,18 @@ public class DataEvaluation {
        DATA_NETWORK_TYPE_NOT_ALLOWED(true),
        /** Device is currently in an emergency call. */
        EMERGENCY_CALL(true),
        /** There is already a retry setup scheduled for this data profile. */
        /** There is already a retry setup/handover scheduled. */
        RETRY_SCHEDULED(true),
        /** Network has explicitly request to throttle setup attempt. */
        DATA_THROTTLED(true),
        /** Data profile becomes invalid. (could be removed by the user, or SIM refresh, etc..) */
        DATA_PROFILE_INVALID(true),
        /** Data profile not preferred (i.e. users switch preferred profile in APN editor.) */
        DATA_PROFILE_NOT_PREFERRED(true);
        DATA_PROFILE_NOT_PREFERRED(true),
        /** Handover is not allowed by policy. */
        NOT_ALLOWED_BY_POLICY(true),
        /** Data network is not in the right state. */
        ILLEGAL_STATE(true);

        private final boolean mIsHardReason;

+6 −0
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ public class DataNetwork extends StateMachine {
                    TEAR_DOWN_REASON_POWER_OFF_BY_CARRIER,
                    TEAR_DOWN_REASON_DATA_STALL,
                    TEAR_DOWN_REASON_HANDOVER_FAILED,
                    TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED,
            })
    public @interface TearDownReason {}

@@ -254,6 +255,9 @@ public class DataNetwork extends StateMachine {
    /** Data network tear down due to handover failed. */
    public static final int TEAR_DOWN_REASON_HANDOVER_FAILED = 13;

    /** Data network tear down due to handover not allowed. */
    public static final int TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED = 14;

    @IntDef(prefix = {"BANDWIDTH_SOURCE_"},
            value = {
                    BANDWIDTH_SOURCE_UNKNOWN,
@@ -2192,6 +2196,8 @@ public class DataNetwork extends StateMachine {
                return "TEAR_DOWN_REASON_DATA_STALL";
            case TEAR_DOWN_REASON_HANDOVER_FAILED:
                return "TEAR_DOWN_REASON_HANDOVER_FAILED";
            case TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED:
                return "TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED";
            default:
                return "UNKNOWN(" + reason + ")";
        }
+93 −29
Original line number Diff line number Diff line
@@ -176,8 +176,8 @@ public class DataNetworkController extends Handler {
    /** Event for emergency call started or ended. */
    private static final int EVENT_EMERGENCY_CALL_CHANGED = 20;

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

    /** Event for subscription plans changed. */
    private static final int EVENT_SUBSCRIPTION_PLANS_CHANGED = 22;
@@ -551,7 +551,7 @@ public class DataNetworkController extends Handler {
        private static final String RULE_TAG_ROAMING = "roaming";

        /** Handover rule type. */
        public final @HandoverRuleType int ruleType;
        public final @HandoverRuleType int type;

        /** The applicable source access networks for handover. */
        public final @NonNull @RadioAccessNetworkType Set<Integer> sourceAccessNetworks;
@@ -560,7 +560,7 @@ public class DataNetworkController extends Handler {
        public final @NonNull @RadioAccessNetworkType Set<Integer> targetAccessNetworks;

        /** {@code true} indicates this policy is only applicable when the device is roaming. */
        public final boolean isRoaming;
        public final boolean isOnlyForRoaming;

        /**
         * Constructor
@@ -652,17 +652,17 @@ public class DataNetworkController extends Handler {

            sourceAccessNetworks = source;
            targetAccessNetworks = target;
            ruleType = type;
            isRoaming = roaming;
            this.type = type;
            isOnlyForRoaming = roaming;
        }

        @Override
        public String toString() {
            return "[HandoverRule: type=" + (ruleType == RULE_TYPE_ALLOWED ? "allowed"
            return "[HandoverRule: type=" + (type == RULE_TYPE_ALLOWED ? "allowed"
                    : "disallowed") + ", source=" + sourceAccessNetworks.stream()
                    .map(AccessNetworkType::toString).collect(Collectors.joining("|"))
                    + ", target=" + targetAccessNetworks.stream().map(AccessNetworkType::toString)
                    .collect(Collectors.joining("|")) + ", isRoaming=" + isRoaming + "]";
                    .collect(Collectors.joining("|")) + ", isRoaming=" + isOnlyForRoaming + "]";
        }
    }

@@ -783,7 +783,9 @@ public class DataNetworkController extends Handler {
        mAccessNetworksManager.registerCallback(new AccessNetworksManagerCallback(this::post) {
            @Override
            public void onPreferredTransportChanged(@NetCapability int capability) {
                DataNetworkController.this.onReevaluatePreferredTransport(capability);
                DataNetworkController.this.onPreferredTransportChanged(capability);
                sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
                        DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED));
            }
        });

@@ -919,8 +921,8 @@ public class DataNetworkController extends Handler {
                            DataEvaluationReason.EMERGENCY_CALL_CHANGED));
                }
                break;
            case EVENT_REEVALUATE_PREFERRED_TRANSPORT:
                onReevaluatePreferredTransport(msg.arg1);
            case EVENT_PREFERRED_TRANSPORT_CHANGED:
                onPreferredTransportChanged(msg.arg1);
                break;
            case EVENT_SUBSCRIPTION_PLANS_CHANGED:
                SubscriptionPlan[] plans = (SubscriptionPlan[]) msg.obj;
@@ -1424,6 +1426,67 @@ public class DataNetworkController extends Handler {
        }
    }

    /**
     * Evaluate if it is allowed to handover the data network between IWLAN and cellular. Some
     * carriers do not allow handover in certain conditions.
     *
     * @param dataNetwork The data network to be handover.
     * @return The evaluation result.
     *
     * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY
     */
    private @NonNull DataEvaluation evaluateDataNetworkHandover(@NonNull DataNetwork dataNetwork) {
        DataEvaluation dataEvaluation = new DataEvaluation(DataEvaluationReason.DATA_HANDOVER);
        if (!dataNetwork.isConnecting() && !dataNetwork.isConnected()) {
            log("evaluateDataNetworkHandover:" + dataNetwork
                    + " it not in the right state.");
            dataEvaluation.addDataDisallowedReason(DataDisallowedReason.ILLEGAL_STATE);
            return dataEvaluation;
        }

        if (mDataRetryManager.isAnyHandoverRetryScheduled(dataNetwork)) {
            log("evaluateDataNetworkHandover: Found handover retry entry for "
                    + dataNetwork);
            dataEvaluation.addDataDisallowedReason(DataDisallowedReason.RETRY_SCHEDULED);
            return dataEvaluation;
        }

        List<HandoverRule> handoverRules = mDataConfigManager.getHandoverRules();

        int sourceAccessNetwork = DataUtils.networkTypeToAccessNetworkType(
                getDataNetworkType(dataNetwork.getTransport()));
        int targetAccessNetwork = DataUtils.networkTypeToAccessNetworkType(
                getDataNetworkType(DataUtils.getTargetTransport(dataNetwork.getTransport())));
        log("evaluateDataNetworkHandover: "
                + "source=" + AccessNetworkType.toString(sourceAccessNetwork)
                + ", target=" + AccessNetworkType.toString(targetAccessNetwork)
                + ", ServiceState=" + mServiceState);

        // Matching the rules by the configured order. Bail out if find first matching rule.
        for (HandoverRule rule : handoverRules) {
            // Check if the rule is only for roaming and we are not roaming.
            if (rule.isOnlyForRoaming && !mServiceState.getDataRoaming()) continue;

            if (rule.sourceAccessNetworks.contains(sourceAccessNetwork)
                    && rule.targetAccessNetworks.contains(targetAccessNetwork)) {
                log("evaluateDataNetworkHandover: Matched " + rule);
                if (rule.type == HandoverRule.RULE_TYPE_DISALLOWED) {
                    dataEvaluation.addDataDisallowedReason(
                            DataDisallowedReason.NOT_ALLOWED_BY_POLICY);
                } else {
                    dataEvaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
                }
                log("evaluateDataNetworkHandover: " + dataEvaluation);
                return dataEvaluation;
            }
        }

        log("evaluateDataNetworkHandover: Did not find matching rule. " + dataEvaluation);
        // Allow handover anyway if no rule is found.
        dataEvaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
        return dataEvaluation;
    }

    /**
     * Get tear down reason from the evaluation result.
     *
@@ -1688,7 +1751,7 @@ public class DataNetworkController extends Handler {
    private void setupDataNetwork(@NonNull DataProfile dataProfile,
            @Nullable DataSetupRetryEntry dataSetupRetryEntry) {
        log("onSetupDataNetwork: dataProfile=" + dataProfile + ", retryEntry="
                + dataSetupRetryEntry);
                + dataSetupRetryEntry + ", service state=" + mServiceState);
        for (DataNetwork dataNetwork : mDataNetworkList) {
            if (dataNetwork.getDataProfile().equals(dataProfile)) {
                log("onSetupDataNetwork: Found existing data network " + dataNetwork
@@ -2047,7 +2110,7 @@ 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_REEVALUATE_PREFERRED_TRANSPORT,
            sendMessageDelayed(obtainMessage(EVENT_PREFERRED_TRANSPORT_CHANGED,
                    dataNetwork.getHighestPriorityNetworkCapability(), 0),
                    REEVALUATE_PREFERRED_TRANSPORT_DELAY_MILLIS);
        } else if (handoverFailureMode == DataCallResponse
@@ -2143,14 +2206,15 @@ public class DataNetworkController extends Handler {
    }

    /**
     * Called when needed to re-evaluate preferred transport for certain capability.
     * Called when preferred transport changed for certain capability.
     *
     * @param capability The network capability that has preferred transport changed.
     */
    private void onReevaluatePreferredTransport(@NetCapability int capability) {
    private void onPreferredTransportChanged(@NetCapability int capability) {
        int preferredTransport = mAccessNetworksManager
                .getPreferredTransportByNetworkCapability(capability);
        logl(DataUtils.networkCapabilityToString(capability) + " preferred on "
        logl("onPreferredTransportChanged: " + DataUtils.networkCapabilityToString(capability)
                + " preferred on "
                + AccessNetworkConstants.transportTypeToString(preferredTransport));
        for (DataNetwork dataNetwork : mDataNetworkList) {
            if (dataNetwork.getHighestPriorityNetworkCapability() == capability) {
@@ -2162,20 +2226,20 @@ public class DataNetworkController extends Handler {
                    continue;
                }

                if (!dataNetwork.isConnecting() && !dataNetwork.isConnected()) {
                    log("onReevaluatePreferredTransport:" + dataNetwork
                            + " it not in the right state.");
                    continue;
                }

                if (mDataRetryManager.isAnyHandoverRetryScheduled(dataNetwork)) {
                    log("onReevaluatePreferredTransport: Found handover retry entry for "
                            + dataNetwork);
                    continue;
                }
                DataEvaluation dataEvaluation = evaluateDataNetworkHandover(dataNetwork);
                if (dataEvaluation.isDataAllowed()) {
                    logl("Start handover " + dataNetwork + " to "
                            + AccessNetworkConstants.transportTypeToString(preferredTransport));
                    dataNetwork.startHandover(preferredTransport, null);
                } else if (dataEvaluation.containsOnly(
                        DataDisallowedReason.NOT_ALLOWED_BY_POLICY)) {
                    logl("onPreferredTransportChanged: Handover not allowed by policy. Tear "
                            + "down the network so a new network can be setup on "
                            + AccessNetworkConstants.transportTypeToString(preferredTransport)
                            + ".");
                    tearDownGracefully(dataNetwork,
                            DataNetwork.TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED);
                }
            }
        }
    }
+124 −16

File changed.

Preview size limit exceeded, changes collapsed.