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

Commit 4a89a800 authored by Jack Yu's avatar Jack Yu Committed by Automerger Merge Worker
Browse files

Merge "Fixed unmetered network request caused data leak" am: 1ef32bad

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

Change-Id: Ifc79240fd24f2ffb03bc8b13d3ea91933ebd8b1d
parents 0f82e355 1ef32bad
Loading
Loading
Loading
Loading
+9 −2
Original line number Original line Diff line number Diff line
@@ -35,13 +35,13 @@ import java.util.Set;
 */
 */
public class DataEvaluation {
public class DataEvaluation {
    /** The reason for this evaluation */
    /** 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. */
    /** Data disallowed reasons. There could be multiple reasons for not allowing data. */
    private final @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();
    private final @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();


    /** Data allowed reason. It is intended to only have one allowed reason. */
    /** 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;
    private @Nullable DataProfile mCandidateDataProfile = null;


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


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

    /**
    /**
     * Set the candidate data profile for setup data network.
     * Set the candidate data profile for setup data network.
     *
     *
+46 −7
Original line number Original line 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.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
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.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataRetryManager.DataHandoverRetryEntry;
import com.android.internal.telephony.data.DataRetryManager.DataHandoverRetryEntry;
import com.android.internal.telephony.data.DataRetryManager.DataRetryEntry;
import com.android.internal.telephony.data.DataRetryManager.DataRetryEntry;
@@ -504,6 +505,9 @@ public class DataNetwork extends StateMachine {
     */
     */
    private @TransportType int mTransport;
    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
     * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value
     * is the PCO content.
     * is the PCO content.
@@ -677,6 +681,7 @@ public class DataNetwork extends StateMachine {
     * @param dataProfile The data profile for establishing the data network.
     * @param dataProfile The data profile for establishing the data network.
     * @param networkRequestList The initial network requests attached to this data network.
     * @param networkRequestList The initial network requests attached to this data network.
     * @param transport The initial transport of the 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.
     * @param callback The callback to receives data network state update.
     */
     */
    public DataNetwork(@NonNull Phone phone, @NonNull Looper looper,
    public DataNetwork(@NonNull Phone phone, @NonNull Looper looper,
@@ -684,6 +689,7 @@ public class DataNetwork extends StateMachine {
            @NonNull DataProfile dataProfile,
            @NonNull DataProfile dataProfile,
            @NonNull NetworkRequestList networkRequestList,
            @NonNull NetworkRequestList networkRequestList,
            @TransportType int transport,
            @TransportType int transport,
            @NonNull DataAllowedReason dataAllowedReason,
            @NonNull DataNetworkCallback callback) {
            @NonNull DataNetworkCallback callback) {
        super("DataNetwork", looper);
        super("DataNetwork", looper);
        mPhone = phone;
        mPhone = phone;
@@ -704,6 +710,7 @@ public class DataNetwork extends StateMachine {
        mDataNetworkCallback = callback;
        mDataNetworkCallback = callback;
        mDataProfile = dataProfile;
        mDataProfile = dataProfile;
        mTransport = transport;
        mTransport = transport;
        mDataAllowedReason = dataAllowedReason;
        dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
        dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
        mAttachedNetworkRequestList.addAll(networkRequestList);
        mAttachedNetworkRequestList.addAll(networkRequestList);
        mCid.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, INVALID_CID);
        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) {
        if (!mCongested) {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
        }
        }
@@ -1416,21 +1422,54 @@ public class DataNetwork extends StateMachine {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
        }
        }


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

        Set<Integer> meteredCapabilities = mDataConfigManager
        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(
        boolean unmeteredNetwork = meteredCapabilities.stream().noneMatch(
                Arrays.stream(builder.build().getCapabilities()).boxed()
                Arrays.stream(builder.build().getCapabilities()).boxed()
                        .collect(Collectors.toSet())::contains);
                        .collect(Collectors.toSet())::contains);


        // TODO: Support NET_CAPABILITY_NOT_METERED when non-restricted data is for unmetered use
        if (unmeteredNetwork) {
        if (unmeteredNetwork) {
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
            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.
        // Set the bandwidth information.
        builder.setLinkDownstreamBandwidthKbps(mNetworkBandwidth.downlinkBandwidthKbps);
        builder.setLinkDownstreamBandwidthKbps(mNetworkBandwidth.downlinkBandwidthKbps);
        builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);
        builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);
+23 −14
Original line number Original line Diff line number Diff line
@@ -1060,7 +1060,8 @@ public class DataNetworkController extends Handler {
        if (!evaluation.containsDisallowedReasons()) {
        if (!evaluation.containsDisallowedReasons()) {
            DataProfile dataProfile = evaluation.getCandidateDataProfile();
            DataProfile dataProfile = evaluation.getCandidateDataProfile();
            if (dataProfile != null) {
            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);
            evaluation.addDataDisallowedReason(DataDisallowedReason.EMERGENCY_CALL);
        }
        }



        if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
        if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
                networkRequest.getApnTypeNetworkCapability()))) {
                networkRequest.getApnTypeNetworkCapability()))) {
            evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
            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
        // Check whether to allow data in certain situations if data is disallowed for soft reasons
        if (!evaluation.containsDisallowedReasons()) {
        if (!evaluation.containsDisallowedReasons()) {
            evaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
            evaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
        } else if (!evaluation.containsHardDisallowedReasons()) {

            // Check if request is MMS and MMS is always allowed
            if (!mDataSettingsManager.isDataEnabled()
            if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
                    && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
                    && mDataSettingsManager.isMmsAlwaysAllowed()) {
                    && 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);
                evaluation.addDataAllowedReason(DataAllowedReason.MMS_REQUEST);
            }
            }

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


@@ -1349,7 +1353,8 @@ public class DataNetworkController extends Handler {
            if (!evaluation.containsDisallowedReasons()) {
            if (!evaluation.containsDisallowedReasons()) {
                DataProfile dataProfile = evaluation.getCandidateDataProfile();
                DataProfile dataProfile = evaluation.getCandidateDataProfile();
                if (dataProfile != null) {
                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
        // Check if data roaming is disabled
        if (mPhone.getServiceState().getDataRoaming()
        if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()) {
                && !mDataSettingsManager.isDataRoamingEnabled()) {
            evaluation.addDataDisallowedReason(DataDisallowedReason.ROAMING_DISABLED);
            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 dataProfile The data profile to setup the data network.
     * @param dataSetupRetryEntry Data retry entry. {@code null} if this data network setup is not
     * @param dataSetupRetryEntry Data retry entry. {@code null} if this data network setup is not
     * initiated by a data retry.
     * initiated by a data retry.
     * @param allowedReason The reason that why setting up this data network is allowed.
     */
     */
    private void setupDataNetwork(@NonNull DataProfile dataProfile,
    private void setupDataNetwork(@NonNull DataProfile dataProfile,
            @Nullable DataSetupRetryEntry dataSetupRetryEntry) {
            @Nullable DataSetupRetryEntry dataSetupRetryEntry,
            @NonNull DataAllowedReason allowedReason) {
        log("onSetupDataNetwork: dataProfile=" + dataProfile + ", retryEntry="
        log("onSetupDataNetwork: dataProfile=" + dataProfile + ", retryEntry="
                + dataSetupRetryEntry + ", service state=" + mServiceState);
                + dataSetupRetryEntry + ", allowed reason=" + allowedReason + ", service state="
                + mServiceState);
        for (DataNetwork dataNetwork : mDataNetworkList) {
        for (DataNetwork dataNetwork : mDataNetworkList) {
            if (dataNetwork.getDataProfile().equals(dataProfile)) {
            if (dataNetwork.getDataProfile().equals(dataProfile)) {
                log("onSetupDataNetwork: Found existing data network " + dataNetwork
                log("onSetupDataNetwork: Found existing data network " + dataNetwork
@@ -1904,7 +1911,8 @@ public class DataNetworkController extends Handler {
                + ", and attaching " + networkRequestList.size() + " network requests to it.");
                + ", and attaching " + networkRequestList.size() + " network requests to it.");


        mDataNetworkList.add(new DataNetwork(mPhone, getLooper(), mDataServiceManagers,
        mDataNetworkList.add(new DataNetwork(mPhone, getLooper(), mDataServiceManagers,
                dataProfile, networkRequestList, transport, new DataNetworkCallback(this::post) {
                dataProfile, networkRequestList, transport, allowedReason,
                new DataNetworkCallback(this::post) {
                    @Override
                    @Override
                    public void onSetupDataFailed(@NonNull DataNetwork dataNetwork,
                    public void onSetupDataFailed(@NonNull DataNetwork dataNetwork,
                            @NonNull NetworkRequestList requestList, @DataFailureCause int cause,
                            @NonNull NetworkRequestList requestList, @DataFailureCause int cause,
@@ -2067,7 +2075,8 @@ public class DataNetworkController extends Handler {
                dataProfile = evaluation.getCandidateDataProfile();
                dataProfile = evaluation.getCandidateDataProfile();
            }
            }
            if (dataProfile != null) {
            if (dataProfile != null) {
                setupDataNetwork(dataProfile, dataSetupRetryEntry);
                setupDataNetwork(dataProfile, dataSetupRetryEntry,
                        evaluation.getDataAllowedReason());
            } else {
            } else {
                loge("onDataNetworkSetupRetry: Not able to find a suitable data profile to retry.");
                loge("onDataNetworkSetupRetry: Not able to find a suitable data profile to retry.");
            }
            }
+7 −5
Original line number Original line Diff line number Diff line
@@ -157,7 +157,8 @@ public class TelephonyNetworkRequest {
    /**
    /**
     * Data config manager for retrieving data config.
     * 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}
     * 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.
     * @return {@code true} if this network request can result in bringing up a metered network.
     */
     */
    public boolean isMeteredRequest() {
    public boolean isMeteredRequest() {
        return mDataConfigManager.isAnyMeteredCapability(getCapabilities(),
        // TODO: Remove null check after old data stack removed.
                mPhone.getServiceState().getDataRoaming());
        return mDataConfigManager != null && mDataConfigManager.isAnyMeteredCapability(
                getCapabilities(), mPhone.getServiceState().getDataRoaming());
    }
    }


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


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


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


    @Test
    @Test
Loading