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

Commit 1ef32bad authored by Jack Yu's avatar Jack Yu Committed by Gerrit Code Review
Browse files

Merge "Fixed unmetered network request caused data leak"

parents 9d1d82ae 572ba60b
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -35,13 +35,13 @@ import java.util.Set;
 */
public class DataEvaluation {
    /** The reason for this evaluation */
    private final DataEvaluationReason mDataEvaluationReason;
    private final @NonNull DataEvaluationReason mDataEvaluationReason;

    /** Data disallowed reasons. There could be multiple reasons for not allowing data. */
    private final @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();

    /** Data allowed reason. It is intended to only have one allowed reason. */
    private DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;
    private @NonNull DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;

    private @Nullable DataProfile mCandidateDataProfile = null;

@@ -103,6 +103,13 @@ public class DataEvaluation {
        return new ArrayList<>(mDataDisallowedReasons);
    }

    /**
     * @return The data allowed reason.
     */
    public @NonNull DataAllowedReason getDataAllowedReason() {
        return mDataAllowedReason;
    }

    /**
     * Set the candidate data profile for setup data network.
     *
+46 −7
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason;
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataRetryManager.DataHandoverRetryEntry;
import com.android.internal.telephony.data.DataRetryManager.DataRetryEntry;
@@ -504,6 +505,9 @@ public class DataNetwork extends StateMachine {
     */
    private @TransportType int mTransport;

    /** The reason that why setting up this data network is allowed. */
    private @NonNull DataAllowedReason mDataAllowedReason;

    /**
     * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value
     * is the PCO content.
@@ -677,6 +681,7 @@ public class DataNetwork extends StateMachine {
     * @param dataProfile The data profile for establishing the data network.
     * @param networkRequestList The initial network requests attached to this data network.
     * @param transport The initial transport of the data network.
     * @param dataAllowedReason The reason that why setting up this data network is allowed.
     * @param callback The callback to receives data network state update.
     */
    public DataNetwork(@NonNull Phone phone, @NonNull Looper looper,
@@ -684,6 +689,7 @@ public class DataNetwork extends StateMachine {
            @NonNull DataProfile dataProfile,
            @NonNull NetworkRequestList networkRequestList,
            @TransportType int transport,
            @NonNull DataAllowedReason dataAllowedReason,
            @NonNull DataNetworkCallback callback) {
        super("DataNetwork", looper);
        mPhone = phone;
@@ -704,6 +710,7 @@ public class DataNetwork extends StateMachine {
        mDataNetworkCallback = callback;
        mDataProfile = dataProfile;
        mTransport = transport;
        mDataAllowedReason = dataAllowedReason;
        dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
        mAttachedNetworkRequestList.addAll(networkRequestList);
        mCid.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, INVALID_CID);
@@ -1392,7 +1399,6 @@ public class DataNetwork extends StateMachine {
            }
        }

        // TODO: Support NET_CAPABILITY_NOT_RESTRICTED
        if (!mCongested) {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
        }
@@ -1416,21 +1422,54 @@ public class DataNetwork extends StateMachine {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
        }

        if (NetworkCapabilitiesUtils.inferRestrictedCapability(builder.build())) {
            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        }

        Set<Integer> meteredCapabilities = mDataConfigManager
                .getMeteredNetworkCapabilities(roaming);
                .getMeteredNetworkCapabilities(roaming).stream()
                .filter(cap -> mAccessNetworksManager.getPreferredTransportByNetworkCapability(cap)
                        == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                .collect(Collectors.toSet());
        boolean unmeteredNetwork = meteredCapabilities.stream().noneMatch(
                Arrays.stream(builder.build().getCapabilities()).boxed()
                        .collect(Collectors.toSet())::contains);

        // TODO: Support NET_CAPABILITY_NOT_METERED when non-restricted data is for unmetered use
        if (unmeteredNetwork) {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
        }

        // Always start with not-restricted, and then remove if needed.
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);

        // When data is disabled, or data roaming is disabled and the device is roaming, we need
        // to remove certain capabilities depending on scenarios.
        if (!mDataNetworkController.getDataSettingsManager().isDataEnabled()
                || (mPhone.getServiceState().getDataRoaming()
                && !mDataNetworkController.getDataSettingsManager().isDataRoamingEnabled())) {
            // If data is allowed because the request is a restricted network request, we need
            // to mark the network as restricted when data is disabled or data roaming is disabled
            // and the device is roaming. If we don't do that, non-privileged apps will be able
            // to use this network when data is disabled.
            if (mDataAllowedReason == DataAllowedReason.RESTRICTED_REQUEST) {
                builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
            } else if (mDataAllowedReason == DataAllowedReason.UNMETERED_USAGE
                    || mDataAllowedReason == DataAllowedReason.MMS_REQUEST) {
                // If data is allowed due to unmetered usage, or MMS always-allowed, we need to
                // remove unrelated-but-metered capabilities.
                for (int capability : meteredCapabilities) {
                    // 1. If it's unmetered usage, remove all metered capabilities.
                    // 2. if it's MMS always-allowed, then remove all metered capabilities but MMS.
                    if (capability != NetworkCapabilities.NET_CAPABILITY_MMS
                            || mDataAllowedReason != DataAllowedReason.MMS_REQUEST) {
                        builder.removeCapability(capability);
                    }
                }
            }
        }

        // If one of the capabilities are for special use, for example, IMS, CBS, then this
        // network should be restricted, regardless data is enabled or not.
        if (NetworkCapabilitiesUtils.inferRestrictedCapability(builder.build())) {
            builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        }

        // Set the bandwidth information.
        builder.setLinkDownstreamBandwidthKbps(mNetworkBandwidth.downlinkBandwidthKbps);
        builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);
+23 −14
Original line number Diff line number Diff line
@@ -1060,7 +1060,8 @@ public class DataNetworkController extends Handler {
        if (!evaluation.containsDisallowedReasons()) {
            DataProfile dataProfile = evaluation.getCandidateDataProfile();
            if (dataProfile != null) {
                setupDataNetwork(dataProfile, null);
                setupDataNetwork(dataProfile, null,
                        evaluation.getDataAllowedReason());
            }
        }
    }
@@ -1247,7 +1248,6 @@ public class DataNetworkController extends Handler {
            evaluation.addDataDisallowedReason(DataDisallowedReason.EMERGENCY_CALL);
        }


        if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
                networkRequest.getApnTypeNetworkCapability()))) {
            evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
@@ -1256,13 +1256,16 @@ public class DataNetworkController extends Handler {
        // Check whether to allow data in certain situations if data is disallowed for soft reasons
        if (!evaluation.containsDisallowedReasons()) {
            evaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
        } else if (!evaluation.containsHardDisallowedReasons()) {
            // Check if request is MMS and MMS is always allowed
            if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)

            if (!mDataSettingsManager.isDataEnabled()
                    && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
                    && mDataSettingsManager.isMmsAlwaysAllowed()) {
                // We reach here when data is disabled, but MMS always-allowed is enabled.
                // (Note that isDataEnabled(ApnSetting.TYPE_MMS) returns true in this case, so it
                // would not generate any soft disallowed reason. We need to explicitly handle it.)
                evaluation.addDataAllowedReason(DataAllowedReason.MMS_REQUEST);
            }

        } else if (!evaluation.containsHardDisallowedReasons()) {
            // Check if request is unmetered (WiFi or unmetered APN)
            if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
                evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
@@ -1303,7 +1306,8 @@ public class DataNetworkController extends Handler {
                + TelephonyManager.getNetworkTypeName(getDataNetworkType(transport))
                + ", reg state="
                + NetworkRegistrationInfo.registrationStateToString(
                        getDataRegistrationState(transport)));
                        getDataRegistrationState(transport))
                + ", " + networkRequest);
        return evaluation;
    }

@@ -1349,7 +1353,8 @@ public class DataNetworkController extends Handler {
            if (!evaluation.containsDisallowedReasons()) {
                DataProfile dataProfile = evaluation.getCandidateDataProfile();
                if (dataProfile != null) {
                    setupDataNetwork(dataProfile, null);
                    setupDataNetwork(dataProfile, null,
                            evaluation.getDataAllowedReason());
                }
            }
        }
@@ -1427,8 +1432,7 @@ public class DataNetworkController extends Handler {
        }

        // Check if data roaming is disabled
        if (mPhone.getServiceState().getDataRoaming()
                && !mDataSettingsManager.isDataRoamingEnabled()) {
        if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()) {
            evaluation.addDataDisallowedReason(DataDisallowedReason.ROAMING_DISABLED);
        }

@@ -1869,11 +1873,14 @@ public class DataNetworkController extends Handler {
     * @param dataProfile The data profile to setup the data network.
     * @param dataSetupRetryEntry Data retry entry. {@code null} if this data network setup is not
     * initiated by a data retry.
     * @param allowedReason The reason that why setting up this data network is allowed.
     */
    private void setupDataNetwork(@NonNull DataProfile dataProfile,
            @Nullable DataSetupRetryEntry dataSetupRetryEntry) {
            @Nullable DataSetupRetryEntry dataSetupRetryEntry,
            @NonNull DataAllowedReason allowedReason) {
        log("onSetupDataNetwork: dataProfile=" + dataProfile + ", retryEntry="
                + dataSetupRetryEntry + ", service state=" + mServiceState);
                + dataSetupRetryEntry + ", allowed reason=" + allowedReason + ", service state="
                + mServiceState);
        for (DataNetwork dataNetwork : mDataNetworkList) {
            if (dataNetwork.getDataProfile().equals(dataProfile)) {
                log("onSetupDataNetwork: Found existing data network " + dataNetwork
@@ -1904,7 +1911,8 @@ public class DataNetworkController extends Handler {
                + ", and attaching " + networkRequestList.size() + " network requests to it.");

        mDataNetworkList.add(new DataNetwork(mPhone, getLooper(), mDataServiceManagers,
                dataProfile, networkRequestList, transport, new DataNetworkCallback(this::post) {
                dataProfile, networkRequestList, transport, allowedReason,
                new DataNetworkCallback(this::post) {
                    @Override
                    public void onSetupDataFailed(@NonNull DataNetwork dataNetwork,
                            @NonNull NetworkRequestList requestList, @DataFailureCause int cause,
@@ -2067,7 +2075,8 @@ public class DataNetworkController extends Handler {
                dataProfile = evaluation.getCandidateDataProfile();
            }
            if (dataProfile != null) {
                setupDataNetwork(dataProfile, dataSetupRetryEntry);
                setupDataNetwork(dataProfile, dataSetupRetryEntry,
                        evaluation.getDataAllowedReason());
            } else {
                loge("onDataNetworkSetupRetry: Not able to find a suitable data profile to retry.");
            }
+7 −5
Original line number Diff line number Diff line
@@ -157,7 +157,8 @@ public class TelephonyNetworkRequest {
    /**
     * Data config manager for retrieving data config.
     */
    private final @NonNull DataConfigManager mDataConfigManager;
    // TODO: Make this @NonNull after old data stack removed.
    private final @Nullable DataConfigManager mDataConfigManager;

    /**
     * The attached data network. Note that the data network could be in any state. {@code null}
@@ -387,8 +388,9 @@ public class TelephonyNetworkRequest {
     * @return {@code true} if this network request can result in bringing up a metered network.
     */
    public boolean isMeteredRequest() {
        return mDataConfigManager.isAnyMeteredCapability(getCapabilities(),
                mPhone.getServiceState().getDataRoaming());
        // TODO: Remove null check after old data stack removed.
        return mDataConfigManager != null && mDataConfigManager.isAnyMeteredCapability(
                getCapabilities(), mPhone.getServiceState().getDataRoaming());
    }

    /**
@@ -442,8 +444,8 @@ public class TelephonyNetworkRequest {
        return "[" + mNativeNetworkRequest.toString() + ", mPriority=" + mPriority
                + ", state=" + requestStateToString(mState)
                + ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
                ? mAttachedDataNetwork.name() : null) + ", created time="
                + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
                ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
                + ", created time=" + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
                + ", evaluation result=" + mEvaluation + "]";
    }

+2 −1
Original line number Diff line number Diff line
@@ -64,8 +64,9 @@ public class ExponentialBackoffTest extends ImsTestBase {
    }

    @After
    public void tearDown() {
    public void tearDown() throws Exception {
        mBackoffUnderTest.stop();
        super.tearDown();
    }

    @Test
Loading