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

Commit 0c3275e8 authored by Jack Yu's avatar Jack Yu Committed by android-build-merger
Browse files

Merge "Revert "Support restricted data connection when roaming"" am: 2e8149bb am: 24f83e64

am: 183d4803

Change-Id: Ib2d21b3415fe05a1f17638056739550d735ea114
parents e6dde7ad 183d4803
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.