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

Commit 8f663184 authored by Jack Yu's avatar Jack Yu Committed by Automerger Merge Worker
Browse files

Disallow data when QNS switched the preference am: dbeef141

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/1763675

Change-Id: Iadfe145534a58e818f9944452ddd6cdcaa0c365e
parents 2af2fa48 dbeef141
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -477,7 +477,7 @@ public class AccessNetworksManager extends Handler {
            pw.println("APN type "
                    + ApnSetting.getApnTypeStringInternal(mAvailableNetworks.keyAt(i))
                    + ": [" + Arrays.stream(mAvailableNetworks.valueAt(i))
                    .mapToObj(type -> AccessNetworkType.toString(type))
                    .mapToObj(AccessNetworkType::toString)
                    .collect(Collectors.joining(",")) + "]");
        }
        pw.decreaseIndent();
+27 −15
Original line number Diff line number Diff line
@@ -50,12 +50,12 @@ public class DataConnectionReasons {
    public String toString() {
        StringBuilder reasonStr = new StringBuilder();
        if (mDataDisallowedReasonSet.size() > 0) {
            reasonStr.append("Data disallowed, reasons:");
            reasonStr.append("Data disallowed reasons:");
            for (DataDisallowedReasonType reason : mDataDisallowedReasonSet) {
                reasonStr.append(" ").append(reason);
            }
        } else {
            reasonStr.append("Data allowed, reason:");
            reasonStr.append("Data allowed reason:");
            reasonStr.append(" ").append(mDataAllowedReason);
        }
        return reasonStr.toString();
@@ -100,9 +100,13 @@ public class DataConnectionReasons {
    // Disallowed reasons. There could be multiple reasons if data connection is not allowed.
    public enum DataDisallowedReasonType {
        // Soft failure reasons. Normally the reasons from users or policy settings.
        DATA_DISABLED(false),               // Data is disabled by the user or policy.
        ROAMING_DISABLED(false),            // Data roaming is disabled by the user.
        DEFAULT_DATA_UNSELECTED(false),     // Default data not selected.

        // Data is disabled by the user or policy.
        DATA_DISABLED(false),
        // Data roaming is disabled by the user.
        ROAMING_DISABLED(false),
        // Default data not selected.
        DEFAULT_DATA_UNSELECTED(false),

        // Belows are all hard failure reasons.
        NOT_ATTACHED(true),
@@ -113,19 +117,27 @@ public class DataConnectionReasons {
        UNDESIRED_POWER_STATE(true),
        INTERNAL_DATA_DISABLED(true),
        RADIO_DISABLED_BY_CARRIER(true),
        APN_NOT_CONNECTABLE(true),  // Not in the right state for data call setup.
        DATA_IS_CONNECTING(true),   // Data is in connecting state. No need to send another setup
                                    // request.
        DATA_IS_DISCONNECTING(true),    // Data is being disconnected. Telephony will retry after
                                        // disconnected.
        DATA_ALREADY_CONNECTED(true),   // Data is already connected. No need to setup data again.
        // Not in the right state for data call setup.
        APN_NOT_CONNECTABLE(true),
        // Data is in connecting state. No need to send another setup request.
        DATA_IS_CONNECTING(true),
        // Data is being disconnected. Telephony will retry after disconnected.
        DATA_IS_DISCONNECTING(true),
        // Data is already connected. No need to setup data again.
        DATA_ALREADY_CONNECTED(true),
        // certain APNs are not allowed on IWLAN in legacy mode.
        ON_IWLAN(true),
        // certain APNs are only allowed when the device is camped on NR.
        NOT_ON_NR(true),
        // Data is not allowed while device is in emergency callback mode.
        IN_ECBM(true),
        ON_OTHER_TRANSPORT(true),   // When data retry occurs, the given APN type's preferred
                                    // transport might be already changed. In this case we
                                    // should disallow data retry.
        DATA_SERVICE_NOT_READY(true);   // Underlying data service is not bound.
        // The given APN type's preferred transport has switched.
        ON_OTHER_TRANSPORT(true),
        // Underlying data service is not bound.
        DATA_SERVICE_NOT_READY(true),
        // Qualified networks service does not allow certain types of APN brought up on either
        // cellular or IWLAN.
        DISABLED_BY_QNS(true);

        private boolean mIsHardReason;

+22 −0
Original line number Diff line number Diff line
@@ -1437,6 +1437,19 @@ public class DcTracker extends Handler {
        }

        if (apnContext != null) {
            if (mPhone.getTransportManager().getPreferredTransport(
                    apnContext.getApnTypeBitmask())
                    == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
                // If QNS explicitly specified this APN type is not allowed on either cellular or
                // IWLAN, we should not allow data setup.
                reasons.add(DataDisallowedReasonType.DISABLED_BY_QNS);
            } else if (mTransportType != mPhone.getTransportManager().getPreferredTransport(
                    apnContext.getApnTypeBitmask())) {
                // If the latest preference has already switched to other transport, we should not
                // allow data setup.
                reasons.add(DataDisallowedReasonType.ON_OTHER_TRANSPORT);
            }

            // If the transport has been already switched to the other transport, we should not
            // allow the data setup. The only exception is the handover case, where we setup
            // handover data connection before switching the transport.
@@ -1578,6 +1591,15 @@ public class DcTracker extends Handler {
        String logStr = "trySetupData for APN type " + apnContext.getApnType() + ", reason: "
                + apnContext.getReason() + ", requestType=" + requestTypeToString(requestType)
                + ". " + dataConnectionReasons.toString();
        if (dataConnectionReasons.contains(DataDisallowedReasonType.DISABLED_BY_QNS)
                || dataConnectionReasons.contains(DataDisallowedReasonType.ON_OTHER_TRANSPORT)) {
            logStr += ", current transport=" + AccessNetworkConstants.transportTypeToString(
                    mPhone.getTransportManager().getCurrentTransport(
                            apnContext.getApnTypeBitmask()));
            logStr += ", preferred transport=" + AccessNetworkConstants.transportTypeToString(
                    mPhone.getTransportManager().getPreferredTransport(
                            apnContext.getApnTypeBitmask()));
        }
        if (DBG) log(logStr);
        apnContext.requestLog(logStr);
        if (!isDataAllowed) {
+74 −12
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.RegistrantList;
import android.os.SystemProperties;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.ApnType;
import android.telephony.CarrierConfigManager;
import android.telephony.data.ApnSetting;
@@ -45,9 +46,10 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -168,7 +170,7 @@ public class TransportManager extends Handler {
    /**
     * The queued available networks list.
     */
    private final LinkedList<List<QualifiedNetworks>> mAvailableNetworksList;
    private final ArrayDeque<List<QualifiedNetworks>> mQueuedNetworksList;

    /**
     * The current transport of the APN type. The key is the APN type, and the value is the
@@ -225,7 +227,7 @@ public class TransportManager extends Handler {
        mCurrentTransports = new ConcurrentHashMap<>();
        mPendingHandoverApns = new SparseIntArray();
        mHandoverNeededEventRegistrants = new RegistrantList();
        mAvailableNetworksList = new LinkedList<>();
        mQueuedNetworksList = new ArrayDeque<>();
        mLogTag = TransportManager.class.getSimpleName() + "-" + mPhone.getPhoneId();

        if (isInLegacyMode()) {
@@ -249,7 +251,7 @@ public class TransportManager extends Handler {
            case EVENT_QUALIFIED_NETWORKS_CHANGED:
                AsyncResult ar = (AsyncResult) msg.obj;
                List<QualifiedNetworks> networks = (List<QualifiedNetworks>) ar.result;
                mAvailableNetworksList.add(networks);
                mQueuedNetworksList.add(networks);
                sendEmptyMessage(EVENT_UPDATE_AVAILABLE_NETWORKS);
                break;
            case EVENT_UPDATE_AVAILABLE_NETWORKS:
@@ -333,12 +335,12 @@ public class TransportManager extends Handler {
            return;
        }

        if (mAvailableNetworksList.size() == 0) {
        if (mQueuedNetworksList.size() == 0) {
            log("Nothing in the available network list queue.");
            return;
        }

        List<QualifiedNetworks> networksList = mAvailableNetworksList.remove();
        List<QualifiedNetworks> networksList = mQueuedNetworksList.remove();
        logl("updateAvailableNetworks: " + networksList);
        for (QualifiedNetworks networks : networksList) {
            if (areNetworksValid(networks)) {
@@ -379,7 +381,7 @@ public class TransportManager extends Handler {

                                        // If there are still pending available network changes, we
                                        // need to process the rest.
                                        if (mAvailableNetworksList.size() > 0) {
                                        if (mQueuedNetworksList.size() > 0) {
                                            sendEmptyMessage(EVENT_UPDATE_AVAILABLE_NETWORKS);
                                        }
                                    }));
@@ -391,7 +393,7 @@ public class TransportManager extends Handler {
        }

        // If there are still pending available network changes, we need to process the rest.
        if (mAvailableNetworksList.size() > 0) {
        if (mQueuedNetworksList.size() > 0) {
            sendEmptyMessage(EVENT_UPDATE_AVAILABLE_NETWORKS);
        }
    }
@@ -486,6 +488,51 @@ public class TransportManager extends Handler {
        }
    }

    /**
     * Get the latest preferred transport. Note that the current transport only changed after
     * handover is completed, and there might be queued update network requests not processed yet.
     * This method is used to get the latest preference sent from qualified networks service.
     *
     * @param apnType APN type
     * @return The preferred transport. {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID} if
     * unknown, unavailable, or QNS explicitly specifies data connection of the APN type should not
     * be brought up on either cellular or IWLAN.
     */
    public @TransportType int getPreferredTransport(@ApnType int apnType) {
        // Since the latest updates from QNS is stored at the end of the queue, so if we want to
        // check what's the latest, we should iterate the queue reversely.
        Iterator<List<QualifiedNetworks>> it = mQueuedNetworksList.descendingIterator();
        while (it.hasNext()) {
            List<QualifiedNetworks> networksList = it.next();
            for (QualifiedNetworks networks : networksList) {
                if (networks.apnType == apnType) {
                    if (networks.qualifiedNetworks.length > 0) {
                        return ACCESS_NETWORK_TRANSPORT_TYPE_MAP.get(networks.qualifiedNetworks[0]);
                    }
                    // This is the case that QNS explicitly specifies no data allowed on neither
                    // cellular nor IWLAN.
                    return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
                }
            }
        }

        // if not found in the queue, see if it's in the current available networks.
        int[] currentNetworkList = mCurrentAvailableNetworks.get(apnType);
        if (currentNetworkList != null) {
            if (currentNetworkList.length > 0) {
                return ACCESS_NETWORK_TRANSPORT_TYPE_MAP.get(currentNetworkList[0]);
            }
            // This is the case that QNS explicitly specifies no data allowed on neither
            // cellular nor IWLAN.
            return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
        }

        // If no input from QNS, for example in legacy mode, the default preferred transport should
        // be cellular.
        return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
    }


    /**
     * Dump the state of transport manager
     *
@@ -498,12 +545,27 @@ public class TransportManager extends Handler {
        pw.println(mLogTag);
        pw.increaseIndent();
        pw.println("mAvailableTransports=[" + Arrays.stream(mAvailableTransports)
                .mapToObj(type -> AccessNetworkConstants.transportTypeToString(type))
                .mapToObj(AccessNetworkConstants::transportTypeToString)
                .collect(Collectors.joining(",")) + "]");
        pw.println("mCurrentAvailableNetworks=" + mCurrentAvailableNetworks);
        pw.println("mAvailableNetworksList=" + mAvailableNetworksList);
        pw.println("mCurrentAvailableNetworks=");
        pw.increaseIndent();
        for (int i = 0; i < mCurrentAvailableNetworks.size(); i++) {
            pw.println("APN type "
                    + ApnSetting.getApnTypeStringInternal(mCurrentAvailableNetworks.keyAt(i))
                    + ": [" + Arrays.stream(mCurrentAvailableNetworks.valueAt(i))
                    .mapToObj(AccessNetworkType::toString)
                    .collect(Collectors.joining(",")) + "]");
        }
        pw.decreaseIndent();
        pw.println("mQueuedNetworksList=" + mQueuedNetworksList);
        pw.println("mPendingHandoverApns=" + mPendingHandoverApns);
        pw.println("mCurrentTransports=" + mCurrentTransports);
        pw.println("mCurrentTransports=");
        pw.increaseIndent();
        for (Map.Entry<Integer, Integer> entry : mCurrentTransports.entrySet()) {
            pw.println("APN type " + ApnSetting.getApnTypeStringInternal(entry.getKey())
                    + ": " + AccessNetworkConstants.transportTypeToString(entry.getValue()));
        }
        pw.decreaseIndent();
        pw.println("isInLegacy=" + isInLegacyMode());
        pw.println("IWLAN operation mode="
                + SystemProperties.get(SYSTEM_PROPERTIES_IWLAN_OPERATION_MODE));
+2 −0
Original line number Diff line number Diff line
@@ -684,6 +684,8 @@ public class DcTrackerTest extends TelephonyTest {
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);

        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mTransportManager)
                .getPreferredTransport(anyInt());
        doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
        doReturn(true).when(mSST).getDesiredPowerState();
        doReturn(true).when(mSST).getPowerStateFromCarrier();
Loading