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

Commit 5b561176 authored by Robert Greenwalt's avatar Robert Greenwalt Committed by Android (Google) Code Review
Browse files

Merge "Support requesting restricted default" into nyc-mr1-dev

parents ad6a054e 692640f4
Loading
Loading
Loading
Loading
+50 −22
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

@@ -388,8 +389,9 @@ public class ApnContext {
        }
    }

    private final ArrayList<LocalLog> mLocalLogs = new ArrayList<LocalLog>();
    private final ArrayDeque<LocalLog> mHistoryLogs = new ArrayDeque<LocalLog>();
    private final ArrayList<LocalLog> mLocalLogs = new ArrayList<>();
    private final ArrayList<NetworkRequest> mNetworkRequests = new ArrayList<>();
    private final ArrayDeque<LocalLog> mHistoryLogs = new ArrayDeque<>();
    private final static int MAX_HISTORY_LOG_COUNT = 4;

    public void requestLog(String str) {
@@ -400,41 +402,59 @@ public class ApnContext {
        }
    }

    public void incRefCount(LocalLog log) {
    public void requestNetwork(NetworkRequest networkRequest, LocalLog log) {
        synchronized (mRefCountLock) {
            if (mLocalLogs.contains(log)) {
                log.log("ApnContext.incRefCount has duplicate add - " + mRefCount);
            if (mLocalLogs.contains(log) || mNetworkRequests.contains(networkRequest)) {
                log.log("ApnContext.requestNetwork has duplicate add - " + mNetworkRequests.size());
            } else {
                mLocalLogs.add(log);
                log.log("ApnContext.incRefCount - " + mRefCount);
            }
            if (mRefCount++ == 0) {
                mNetworkRequests.add(networkRequest);
                if (mNetworkRequests.size() == 1) {
                    mDcTracker.setEnabled(apnIdForApnName(mApnType), true);
                }
            }
        }
    }

    public void decRefCount(LocalLog log) {
    public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) {
        synchronized (mRefCountLock) {
            if (mLocalLogs.remove(log)) {
                log.log("ApnContext.decRefCount - " + mRefCount);
                mHistoryLogs.addFirst(log);
                while (mHistoryLogs.size() > MAX_HISTORY_LOG_COUNT) {
                    mHistoryLogs.removeLast();
                }
            if (mLocalLogs.contains(log) == false) {
                log.log("ApnContext.releaseNetwork can't find this log");
            } else {
                log.log("ApnContext.decRefCount didn't find log - " + mRefCount);
                mLocalLogs.remove(log);
            }
            if (mRefCount-- == 1) {
            if (mNetworkRequests.contains(networkRequest) == false) {
                log.log("ApnContext.releaseNetwork can't find this request ("
                        + networkRequest + ")");
            } else {
                mNetworkRequests.remove(networkRequest);
                log.log("ApnContext.releaseNetwork left with " + mNetworkRequests.size() +
                        " requests.");
                if (mNetworkRequests.size() == 0) {
                    mDcTracker.setEnabled(apnIdForApnName(mApnType), false);
                }
            if (mRefCount < 0) {
                log.log("ApnContext.decRefCount went to " + mRefCount);
                mRefCount = 0;
            }
        }
    }

    public List<NetworkRequest> getNetworkRequests() {
        synchronized (mRefCountLock) {
            return new ArrayList<NetworkRequest>(mNetworkRequests);
        }
    }

    public boolean hasNoRestrictedRequests() {
        synchronized (mRefCountLock) {
            for (NetworkRequest nr : mNetworkRequests) {
                if (nr.networkCapabilities.hasCapability(
                        NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) == false) {
                    return false;
                }
            }
        }
        return true;
    }

    private final SparseIntArray mRetriesLeftPerErrorCode = new SparseIntArray();

    public void resetErrorCodeRetries() {
@@ -677,6 +697,14 @@ public class ApnContext {
        final IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
        synchronized (mRefCountLock) {
            pw.println(toString());
            if (mNetworkRequests.size() > 0) {
                pw.println("NetworkRequests:");
                pw.increaseIndent();
                for (NetworkRequest nr : mNetworkRequests) {
                    pw.println(nr);
                }
                pw.decreaseIndent();
            }
            pw.increaseIndent();
            for (LocalLog l : mLocalLogs) {
                l.dump(fd, pw, args);
+55 −0
Original line number Diff line number Diff line
@@ -826,6 +826,56 @@ public class DataConnection extends StateMachine {
        mLinkProperties.setTcpBufferSizes(sizes);
    }

    /**
     * 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
     * experiement 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
     * of having both restricted requests and unrestricted requests for the same apn:
     * 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.
     */
    private boolean mRestrictedNetworkOverride = 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()) {
            noRestrictedRequests &= apnContext.hasNoRestrictedRequests();
        }
        if (noRestrictedRequests) {
            return;
        }

        // Do we need a restricted network to satisfy the request?
        // Is this network metered?  If not, then don't add restricted
        if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(),
                mPhone.getServiceState().getDataRoaming())) {
            return;
        }

        // Is user data disabled?
        mRestrictedNetworkOverride = (mDct.isDataEnabled(true) == false);
    }

    private NetworkCapabilities makeNetworkCapabilities() {
        NetworkCapabilities result = new NetworkCapabilities();
        result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
@@ -895,6 +945,10 @@ public class DataConnection extends StateMachine {

            result.maybeMarkCapabilitiesRestricted();
        }
        if (mRestrictedNetworkOverride) {
            result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        }

        int up = 14;
        int down = 14;
        switch (mRilRat) {
@@ -1522,6 +1576,7 @@ public class DataConnection extends StateMachine {
            misc.subscriberId = mPhone.getSubscriberId();

            if (createNetworkAgent) {
                setNetworkRestriction();
                mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
                        "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,
                        50, misc);
+10 −6
Original line number Diff line number Diff line
@@ -927,14 +927,14 @@ public class DcTracker extends Handler {
        final int apnId = ApnContext.apnIdForNetworkRequest(networkRequest);
        final ApnContext apnContext = mApnContextsById.get(apnId);
        log.log("DcTracker.requestNetwork for " + networkRequest + " found " + apnContext);
        if (apnContext != null) apnContext.incRefCount(log);
        if (apnContext != null) apnContext.requestNetwork(networkRequest, log);
    }

    public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) {
        final int apnId = ApnContext.apnIdForNetworkRequest(networkRequest);
        final ApnContext apnContext = mApnContextsById.get(apnId);
        log.log("DcTracker.releaseNetwork for " + networkRequest + " found " + apnContext);
        if (apnContext != null) apnContext.decRefCount(log);
        if (apnContext != null) apnContext.releaseNetwork(networkRequest, log);
    }

    public boolean isApnSupported(String name) {
@@ -1274,7 +1274,7 @@ public class DcTracker extends Handler {
        return false;
    }

    private boolean isDataEnabled(boolean checkUserDataEnabled) {
    boolean isDataEnabled(boolean checkUserDataEnabled) {
        synchronized (mDataEnabledLock) {
            if (!(mInternalDataEnabled && (!checkUserDataEnabled || mUserDataEnabled)
                    && (!checkUserDataEnabled || sPolicyDataEnabled)
@@ -1512,10 +1512,14 @@ public class DcTracker extends Handler {
        boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY);
        final ServiceStateTracker sst = mPhone.getServiceStateTracker();

        // set to false if apn type is non-metered.
        // set to false if apn type is non-metered or if we have a restricted (priveleged)
        // request for the network.
        // TODO - may want restricted requests to only apply to carrier-limited data access
        //        rather than applying to user limited as well.
        boolean checkUserDataEnabled =
                (ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(),
                        mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()));
                ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(),
                        mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()) &&
                apnContext.hasNoRestrictedRequests();

        DataAllowFailReason failureReason = new DataAllowFailReason();

+10 −6
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.internal.telephony.dataconnection;

import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
import android.net.NetworkRequest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.LocalLog;

@@ -136,16 +138,18 @@ public class ApnContextTest extends TelephonyTest {

    @Test
    @SmallTest
    public void testRefCount() throws Exception {
    public void testNetworkRequest() throws Exception {
        LocalLog log = new LocalLog(3);
        mApnContext.incRefCount(log);
        NetworkCapabilities nc = new NetworkCapabilities();
        NetworkRequest nr = new NetworkRequest(nc, 0, 0);
        mApnContext.requestNetwork(nr, log);
        verify(mDcTracker, times(1)).setEnabled(eq(DctConstants.APN_DEFAULT_ID), eq(true));
        mApnContext.incRefCount(log);
        mApnContext.requestNetwork(nr, log);
        verify(mDcTracker, times(1)).setEnabled(eq(DctConstants.APN_DEFAULT_ID), eq(true));

        mApnContext.decRefCount(log);
        verify(mDcTracker, never()).setEnabled(eq(DctConstants.APN_DEFAULT_ID), eq(false));
        mApnContext.decRefCount(log);
        mApnContext.releaseNetwork(nr, log);
        verify(mDcTracker, times(1)).setEnabled(eq(DctConstants.APN_DEFAULT_ID), eq(false));
        mApnContext.releaseNetwork(nr, log);
        verify(mDcTracker, times(1)).setEnabled(eq(DctConstants.APN_DEFAULT_ID), eq(false));
    }