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

Commit 2e8149bb authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Revert "Support restricted data connection when roaming""

parents ff449699 ed31eef3
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -460,11 +460,7 @@ public class ApnContext {
        }
    }

    /**
     * @param excludeDun True if excluding requests that have DUN capability
     * @return True if the attached network requests contain restricted capability.
     */
    public boolean hasRestrictedRequests(boolean excludeDun) {
    public boolean hasNoRestrictedRequests(boolean excludeDun) {
        synchronized (mRefCountLock) {
            for (NetworkRequest nr : mNetworkRequests) {
                if (excludeDun &&
@@ -472,13 +468,13 @@ public class ApnContext {
                        NetworkCapabilities.NET_CAPABILITY_DUN)) {
                    continue;
                }
                if (!nr.networkCapabilities.hasCapability(
                        NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
                    return true;
                if (nr.networkCapabilities.hasCapability(
                        NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) == false) {
                    return false;
                }
            }
        }
        return false;
        return true;
    }

    private final SparseIntArray mRetriesLeftPerErrorCode = new SparseIntArray();
+51 −134
Original line number Diff line number Diff line
@@ -123,14 +123,17 @@ public class DataConnection extends StateMachine {
        ApnContext mApnContext;
        int mProfileId;
        int mRilRat;
        final boolean mUnmeteredUseOnly;
        Message mOnCompletedMsg;
        final int mConnectionGeneration;

        ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology,
                         Message onCompletedMsg, int connectionGeneration) {
                         boolean unmeteredUseOnly,  Message onCompletedMsg,
                         int connectionGeneration) {
            mApnContext = apnContext;
            mProfileId = profileId;
            mRilRat = rilRadioTechnology;
            mUnmeteredUseOnly = unmeteredUseOnly;
            mOnCompletedMsg = onCompletedMsg;
            mConnectionGeneration = connectionGeneration;
        }
@@ -140,6 +143,7 @@ public class DataConnection extends StateMachine {
            return "{mTag=" + mTag + " mApnContext=" + mApnContext
                    + " mProfileId=" + mProfileId
                    + " mRat=" + mRilRat
                    + " mUnmeteredUseOnly=" + mUnmeteredUseOnly
                    + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
        }
    }
@@ -218,9 +222,8 @@ public class DataConnection extends StateMachine {
    static final int EVENT_KEEPALIVE_STOP_REQUEST = BASE + 22;
    static final int EVENT_LINK_CAPACITY_CHANGED = BASE + 23;
    static final int EVENT_RESET = BASE + 24;
    static final int EVENT_REEVALUATE_RESTRICTED_STATE = BASE + 25;

    private static final int CMD_TO_STRING_COUNT = EVENT_REEVALUATE_RESTRICTED_STATE - BASE + 1;
    private static final int CMD_TO_STRING_COUNT = EVENT_RESET - BASE + 1;

    private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
    static {
@@ -252,8 +255,6 @@ public class DataConnection extends StateMachine {
        sCmdToString[EVENT_KEEPALIVE_STOP_REQUEST - BASE] = "EVENT_KEEPALIVE_STOP_REQUEST";
        sCmdToString[EVENT_LINK_CAPACITY_CHANGED - BASE] = "EVENT_LINK_CAPACITY_CHANGED";
        sCmdToString[EVENT_RESET - BASE] = "EVENT_RESET";
        sCmdToString[EVENT_REEVALUATE_RESTRICTED_STATE - BASE] =
                "EVENT_REEVALUATE_RESTRICTED_STATE";
    }
    // Convert cmd to string or null if unknown
    static String cmdToString(int cmd) {
@@ -884,19 +885,14 @@ public class DataConnection extends StateMachine {
        mLinkProperties.setTcpBufferSizes(sizes);
    }

    /**
     * Indicates if this data connection was established for unmetered use only. Note that this
     * flag should be populated when data becomes active. And if it is set to true, it can be set to
     * false later when we are reevaluating the data connection. But if it is set to false, it
     * can never become true later because setting it to true will cause this data connection
     * losing some immutable network capabilities, which can cause issues in connectivity service.
     */
    private boolean mUnmeteredUseOnly = false;

    /**
     * Indicates if when this connection was established we had a restricted/privileged
     * NetworkRequest and needed it to overcome data-enabled limitations.
     *
     * This gets set once per connection setup and is based on conditions at that time.
     * We could theoretically have dynamic capabilities but now is not a good time to
     * experiment with that.
     *
     * This flag overrides the APN-based restriction capability, restricting the network
     * based on both having a NetworkRequest with restricted AND needing a restricted
     * bit to overcome user-disabled status.  This allows us to handle the common case
@@ -904,78 +900,38 @@ public class DataConnection extends StateMachine {
     * if conditions require a restricted network to overcome user-disabled then it must
     * be restricted, otherwise it is unrestricted (or restricted based on APN type).
     *
     * Because we're not supporting dynamic capabilities, if conditions change and we go from
     * data-enabled to not or vice-versa we will need to tear down networks to deal with it
     * at connection setup time with the new state.
     *
     * This supports a privileged app bringing up a network without general apps having access
     * to it when the network is otherwise unavailable (hipri).  The first use case is
     * pre-paid SIM reprovisioning over internet, where the carrier insists on no traffic
     * other than from the privileged carrier-app.
     *
     * Note that the data connection cannot go from unrestricted to restricted because the
     * connectivity service does not support dynamically closing TCP connections at this point.
     */
    private boolean mRestrictedNetworkOverride = false;

    /**
     * Check if this data connection should be restricted. We should call this when data connection
     * becomes active, or when we want to re-evaluate the conditions to decide if we need to
     * unstrict the data connection.
     *
     * @return True if this data connection needs to be restricted.
     */

    private boolean shouldRestrictNetwork() {
        // first, check if there is any network request that containing restricted capability
        // (i.e. Do not have NET_CAPABILITY_NOT_RESTRICTED in the request)
        boolean isAnyRestrictedRequest = false;
    // Should be called once when the call goes active to examine the state of things and
    // declare the restriction override for the life of the connection
    private void setNetworkRestriction() {
        mRestrictedNetworkOverride = false;
        // first, if we have no restricted requests, this override can stay FALSE:
        boolean noRestrictedRequests = true;
        for (ApnContext apnContext : mApnContexts.keySet()) {
            if (apnContext.hasRestrictedRequests(true /* exclude DUN */)) {
                isAnyRestrictedRequest = true;
                break;
            noRestrictedRequests &= apnContext.hasNoRestrictedRequests(true /* exclude DUN */);
        }
        if (noRestrictedRequests) {
            return;
        }

        // If all of the network requests are non-restricted, then we don't need to restrict
        // the network.
        if (!isAnyRestrictedRequest) {
            return false;
        }

        // If the network is unmetered, then we don't need to restrict the network because users
        // won't be charged anyway.
        // Do we need a restricted network to satisfy the request?
        // Is this network metered?  If not, then don't add restricted
        if (!ApnSettingUtils.isMetered(mApnSetting, mPhone)) {
            return false;
        }

        // If the data is disabled, then we need to restrict the network so only privileged apps can
        // use the restricted network while data is disabled.
        if (!mDct.isDataEnabled()) {
            return true;
            return;
        }

        // If the device is roaming, and the user does not turn on data roaming, then we need to
        // restrict the network so only privileged apps can use it.
        if (!mDct.getDataRoamingEnabled() && mPhone.getServiceState().getDataRoaming()) {
            return true;
        }

        // Otherwise we should not restrict the network so anyone who requests can use it.
        return false;
    }

    /**
     * @return True if this data connection should only be used for unmetered purposes.
     */
    private boolean isUnmeteredUseOnly() {
        // The data connection can only be unmetered used only if all requests' reasons are
        // unmetered.
        for (ApnContext apnContext : mApnContexts.keySet()) {
            DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
            boolean isDataAllowed = mDct.isDataAllowed(apnContext, dataConnectionReasons);
            if (!isDataAllowed || !dataConnectionReasons.contains(
                    DataConnectionReasons.DataAllowedReasonType.UNMETERED_APN)) {
                return false;
            }
        }
        return true;
        // Is data disabled?
        mRestrictedNetworkOverride = !mDct.isDataEnabled();
    }

    NetworkCapabilities getNetworkCapabilities() {
@@ -986,7 +942,8 @@ public class DataConnection extends StateMachine {
            final String[] types = ApnSetting.getApnTypesStringFromBitmask(
                mApnSetting.getApnTypeBitmask()).split(",");
            for (String type : types) {
                if (!mRestrictedNetworkOverride && mUnmeteredUseOnly
                if (!mRestrictedNetworkOverride
                        && (mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
                        && ApnSettingUtils.isMeteredApnType(type, mPhone)) {
                    log("Dropped the metered " + type + " for the unmetered data call.");
                    continue;
@@ -1046,7 +1003,8 @@ public class DataConnection extends StateMachine {
            // Mark NOT_METERED in the following cases,
            // 1. All APNs in APN settings are unmetered.
            // 2. The non-restricted data and is intended for unmetered use only.
            if ((mUnmeteredUseOnly && !mRestrictedNetworkOverride)
            if (((mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
                    && !mRestrictedNetworkOverride)
                    || !ApnSettingUtils.isMetered(mApnSetting, mPhone)) {
                result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
            } else {
@@ -1055,7 +1013,6 @@ public class DataConnection extends StateMachine {

            result.maybeMarkCapabilitiesRestricted();
        }

        if (mRestrictedNetworkOverride) {
            result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
            // don't use dun on restriction-overriden networks.
@@ -1313,11 +1270,17 @@ public class DataConnection extends StateMachine {
                    break;

                case EVENT_DISCONNECT:
                    if (DBG) {
                        log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount="
                                + mApnContexts.size());
                    }
                    deferMessage(msg);
                    break;

                case EVENT_DISCONNECT_ALL:
                case EVENT_REEVALUATE_RESTRICTED_STATE:
                    if (DBG) {
                        log("DcDefaultState deferring msg.what=" + getWhatToString(msg.what)
                                + " RefCount=" + mApnContexts.size());
                        log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount="
                                + mApnContexts.size());
                    }
                    deferMessage(msg);
                    break;
@@ -1494,10 +1457,8 @@ public class DataConnection extends StateMachine {

            switch (msg.what) {
                case EVENT_RESET:
                case EVENT_REEVALUATE_RESTRICTED_STATE:
                    if (DBG) {
                        log("DcInactiveState: msg.what=" + getWhatToString(msg.what)
                                + ", ignore we're already done");
                        log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset");
                    }
                    retVal = HANDLED;
                    break;
@@ -1698,13 +1659,8 @@ public class DataConnection extends StateMachine {
            }
            misc.subscriberId = mPhone.getSubscriberId();

            mRestrictedNetworkOverride = shouldRestrictNetwork();
            mUnmeteredUseOnly = isUnmeteredUseOnly();

            if (DBG) {
                log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride
                        + ", mUnmeteredUseOnly = " + mUnmeteredUseOnly);
            }
            setNetworkRestriction();
            if (DBG) log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride);
            mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
                    "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties,
                    50, misc);
@@ -1968,37 +1924,6 @@ public class DataConnection extends StateMachine {
                    retVal = HANDLED;
                    break;
                }
                case EVENT_REEVALUATE_RESTRICTED_STATE: {
                    // If the network was restricted, and now it does not need to be restricted
                    // anymore, we should add the NET_CAPABILITY_NOT_RESTRICTED capability.
                    if (mRestrictedNetworkOverride && !shouldRestrictNetwork()) {
                        if (DBG) {
                            log("Data connection becomes not-restricted. dc=" + this);
                        }
                        // Note we only do this when network becomes non-restricted. When a
                        // non-restricted becomes restricted (e.g. users disable data, or turn off
                        // data roaming), DCT will explicitly tear down the networks (because
                        // connectivity service does not support force-close TCP connections today).
                        // Also note that NET_CAPABILITY_NOT_RESTRICTED is an immutable capability
                        // (see {@link NetworkCapabilities}) once we add it to the network, we can't
                        // remove it through the entire life cycle of the connection.
                        mRestrictedNetworkOverride = false;
                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
                    }

                    // If the data does need to be unmetered use only (e.g. users turn on data, or
                    // device is not roaming anymore assuming data roaming is off), then we can
                    // dynamically add those metered APN type capabilities back. (But not the
                    // other way around because most of the APN-type capabilities are immutable
                    // capabilities.)
                    if (mUnmeteredUseOnly && !isUnmeteredUseOnly()) {
                        mUnmeteredUseOnly = false;
                        mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
                    }

                    retVal = HANDLED;
                    break;
                }
                default:
                    if (VDBG) {
                        log("DcActiveState not handled msg.what=" + getWhatToString(msg.what));
@@ -2334,6 +2259,7 @@ public class DataConnection extends StateMachine {
     * @param apnContext is the Access Point Name to bring up a connection to
     * @param profileId for the connection
     * @param rilRadioTechnology Radio technology for the data connection
     * @param unmeteredUseOnly Indicates the data connection can only used for unmetered purposes
     * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
     *                       With AsyncResult.userObj set to the original msg.obj,
     *                       AsyncResult.result = FailCause and AsyncResult.exception = Exception().
@@ -2341,13 +2267,15 @@ public class DataConnection extends StateMachine {
     *                             ignored if obsolete.
     */
    public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology,
                        Message onCompletedMsg, int connectionGeneration) {
                        boolean unmeteredUseOnly, Message onCompletedMsg,
                        int connectionGeneration) {
        if (DBG) {
            log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg);
            log("bringUp: apnContext=" + apnContext + "unmeteredUseOnly=" + unmeteredUseOnly
                    + " onCompletedMsg=" + onCompletedMsg);
        }
        sendMessage(DataConnection.EVENT_CONNECT,
                new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg,
                        connectionGeneration));
                new ConnectionParams(apnContext, profileId, rilRadioTechnology, unmeteredUseOnly,
                        onCompletedMsg, connectionGeneration));
    }

    /**
@@ -2396,15 +2324,6 @@ public class DataConnection extends StateMachine {
        if (DBG) log("reset");
    }

    /**
     * Re-evaluate the restricted state. If the restricted data connection does not need to be
     * restricted anymore, we need to dynamically change the network's capability.
     */
    void reevaluateRestrictedState() {
        sendMessage(EVENT_REEVALUATE_RESTRICTED_STATE);
        if (DBG) log("reevaluate restricted state");
    }

    /**
     * @return The parameters used for initiating a data connection.
     */
@@ -2638,8 +2557,6 @@ public class DataConnection extends StateMachine {
        pw.println("mLastFailCause=" + mLastFailCause);
        pw.println("mUserData=" + mUserData);
        pw.println("mSubscriptionOverride=" + Integer.toHexString(mSubscriptionOverride));
        pw.println("mRestrictedNetworkOverride=" + mRestrictedNetworkOverride);
        pw.println("mUnmeteredUseOnly=" + mUnmeteredUseOnly);
        pw.println("mInstanceNumber=" + mInstanceNumber);
        pw.println("mAc=" + mAc);
        pw.println("Network capabilities changed history:");
+46 −22
Original line number Diff line number Diff line
@@ -818,16 +818,47 @@ public class DcTracker extends Handler {
     *
     * For example, handle reverting restricted networks back to unrestricted. If we're changing
     * user data to enabled and this makes data truly enabled (not disabled by other factors) we
     * need to reevaluate and possibly add NET_CAPABILITY_NOT_RESTRICTED capability to the data
     * connection. This allows non-privilege apps to use the network.
     * need to tear down any metered apn type that was enabled anyway by a privileged request.
     * This allows us to reconnect to it in an unrestricted way.
     *
     * Or when we brought up a unmetered data connection while data is off, we only limit this
     * data connection for unmetered use only. When data is turned back on, we need to tear that
     * down so a full capable data connection can be re-established.
     */
    private void reevaluateDataConnections() {
        for (DataConnection dataConnection : mDataConnections.values()) {
            dataConnection.reevaluateRestrictedState();
        if (mDataEnabledSettings.isDataEnabled()) {
            for (ApnContext apnContext : mApnContexts.values()) {
                if (apnContext.isConnectedOrConnecting()) {
                    final DataConnection dataConnection = apnContext.getDataConnection();
                    if (dataConnection != null) {
                        final NetworkCapabilities netCaps = dataConnection.getNetworkCapabilities();
                        if (netCaps != null && !netCaps.hasCapability(NetworkCapabilities
                                .NET_CAPABILITY_NOT_RESTRICTED) && !netCaps.hasCapability(
                                NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
                            if (DBG) {
                                log("Tearing down restricted metered net:" + apnContext);
                            }
                            // Tearing down the restricted metered data call when
                            // conditions change. This will allow reestablishing a new unrestricted
                            // data connection.
                            apnContext.setReason(Phone.REASON_DATA_ENABLED);
                            cleanUpConnection(true, apnContext);
                        } else if (ApnSettingUtils.isMetered(apnContext.getApnSetting(), mPhone)
                                && (netCaps != null && netCaps.hasCapability(
                                        NetworkCapabilities.NET_CAPABILITY_NOT_METERED))) {
                            if (DBG) {
                                log("Tearing down unmetered net:" + apnContext);
                            }
                            // The APN settings is metered, but the data was still marked as
                            // unmetered data, must be the unmetered data connection brought up when
                            // data is off. We need to tear that down when data is enabled again.
                            // This will allow reestablishing a new full capability data connection.
                            apnContext.setReason(Phone.REASON_DATA_ENABLED);
                            cleanUpConnection(true, apnContext);
                        }
                    }
                }
            }
        }
    }

@@ -1213,8 +1244,7 @@ public class DcTracker extends Handler {
     *                              provided.
     * @return True if data connection is allowed, otherwise false.
     */
    public boolean isDataAllowed(ApnContext apnContext,
                                 DataConnectionReasons dataConnectionReasons) {
    boolean isDataAllowed(ApnContext apnContext, DataConnectionReasons dataConnectionReasons) {
        // Step 1: Get all environment conditions.
        // Step 2: Special handling for emergency APN.
        // Step 3. Build disallowed reasons.
@@ -1337,11 +1367,11 @@ public class DcTracker extends Handler {
            reasons.add(DataAllowedReasonType.UNMETERED_APN);
        }

        // If the request is restricted and there are only soft disallowed reasons (e.g. data
        // disabled, data roaming disabled) existing, we should allow the data.
        // If the request is restricted and there are only disallowed reasons due to data
        // disabled, we should allow the data.
        if (apnContext != null
                && apnContext.hasRestrictedRequests(true)
                && !reasons.allowed()) {
                && !apnContext.hasNoRestrictedRequests(true)
                && reasons.contains(DataDisallowedReasonType.DATA_DISABLED)) {
            reasons.add(DataAllowedReasonType.RESTRICTED_REQUEST);
        }

@@ -1461,7 +1491,8 @@ public class DcTracker extends Handler {
                }
            }

            boolean retValue = setupData(apnContext, radioTech);
            boolean retValue = setupData(apnContext, radioTech, dataConnectionReasons.contains(
                    DataAllowedReasonType.UNMETERED_APN));
            notifyOffApnsOfAvailability(apnContext.getReason());

            if (DBG) log("trySetupData: X retValue=" + retValue);
@@ -1870,9 +1901,11 @@ public class DcTracker extends Handler {
     *
     * @param apnContext APN context
     * @param radioTech RAT of the data connection
     * @param unmeteredUseOnly True if this data connection should be only used for unmetered
     *                         purposes only.
     * @return True if successful, otherwise false.
     */
    private boolean setupData(ApnContext apnContext, int radioTech) {
    private boolean setupData(ApnContext apnContext, int radioTech, boolean unmeteredUseOnly) {
        if (DBG) log("setupData: apnContext=" + apnContext);
        apnContext.requestLog("setupData");
        ApnSetting apnSetting;
@@ -1962,7 +1995,7 @@ public class DcTracker extends Handler {
        Message msg = obtainMessage();
        msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
        msg.obj = new Pair<ApnContext, Integer>(apnContext, generation);
        dataConnection.bringUp(apnContext, profileId, radioTech, msg, generation);
        dataConnection.bringUp(apnContext, profileId, radioTech, unmeteredUseOnly, msg, generation);

        if (DBG) log("setupData: initing!");
        return true;
@@ -2615,8 +2648,6 @@ public class DcTracker extends Handler {
    private void onDataRoamingOff() {
        if (DBG) log("onDataRoamingOff");

        reevaluateDataConnections();

        if (!getDataRoamingEnabled()) {
            // TODO: Remove this once all old vendor RILs are gone. We don't need to set initial apn
            // attach and send the data profile again as the modem should have both roaming and
@@ -2652,13 +2683,6 @@ public class DcTracker extends Handler {
        checkDataRoamingStatus(settingChanged);

        if (getDataRoamingEnabled()) {
            // If the restricted data was brought up when data roaming is disabled, and now users
            // enable data roaming, we need to re-evaluate the conditions and possibly change the
            // network's capability.
            if (settingChanged) {
                reevaluateDataConnections();
            }

            if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming");

            setupDataOnConnectableApns(Phone.REASON_ROAMING_ON);
+5 −4

File changed.

Preview size limit exceeded, changes collapsed.