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

Commit 818cf71d authored by Rambo Wang's avatar Rambo Wang
Browse files

Replace StringNetworkSpecifier & subId with TelephonyNetworkSpecifer

StringNetworkSpecifier is widely used to specify subscription id for
the NetworkRequest. The raw string field introduce ambiguity and leave
large space for bugs. With TelephonyNetworkSpecifer, we are able to
settle down the type and value of the fields (although currently only
one) and introduce validation to detect the bug in the beginning.

Bug: 145993724
Test: atest FrameworksNetTests FrameworksTelephonyTests &
      make offline-sdk-docs
Change-Id: Iefbad9b1deb3de2c0b262d9ce5ae0704a50d08a6
parent 6408fa47
Loading
Loading
Loading
Loading
+14 −1
Original line number Original line Diff line number Diff line
@@ -29167,7 +29167,7 @@ package android.net {
    method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
    method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
    method public android.net.NetworkRequest.Builder removeCapability(int);
    method public android.net.NetworkRequest.Builder removeCapability(int);
    method public android.net.NetworkRequest.Builder removeTransportType(int);
    method public android.net.NetworkRequest.Builder removeTransportType(int);
    method public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
    method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
  }
  }
@@ -29266,6 +29266,19 @@ package android.net {
    method public void onStopped();
    method public void onStopped();
  }
  }
  public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
    method public int describeContents();
    method public int getSubscriptionId();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.net.TelephonyNetworkSpecifier> CREATOR;
  }
  public static final class TelephonyNetworkSpecifier.Builder {
    ctor public TelephonyNetworkSpecifier.Builder();
    method @NonNull public android.net.TelephonyNetworkSpecifier build();
    method @NonNull public android.net.TelephonyNetworkSpecifier.Builder setSubscriptionId(int);
  }
  public class TrafficStats {
  public class TrafficStats {
    ctor public TrafficStats();
    ctor public TrafficStats();
    method public static void clearThreadStatsTag();
    method public static void clearThreadStatsTag();
+4 −0
Original line number Original line Diff line number Diff line
@@ -4638,6 +4638,10 @@ package android.net {
    field @NonNull public final String specifier;
    field @NonNull public final String specifier;
  }
  }
  public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
    method public boolean satisfiedBy(android.net.NetworkSpecifier);
  }
  public class TrafficStats {
  public class TrafficStats {
    method public static void setThreadStatsTagApp();
    method public static void setThreadStatsTagApp();
    method public static void setThreadStatsTagBackup();
    method public static void setThreadStatsTagBackup();
+25 −13
Original line number Original line Diff line number Diff line
@@ -300,23 +300,35 @@ public class NetworkRequest implements Parcelable {
         * this without a single transport set will generate an exception, as will
         * this without a single transport set will generate an exception, as will
         * subsequently adding or removing transports after this is set.
         * subsequently adding or removing transports after this is set.
         * </p>
         * </p>
         * The interpretation of this {@code String} is bearer specific and bearers that use
         * If the {@code networkSpecifier} is provided, it shall be interpreted as follows:
         * it should document their particulars.  For example, Bluetooth may use some sort of
         * <ul>
         * device id while WiFi could used ssid and/or bssid.  Cellular may use carrier spn.
         * <li>If the specifier can be parsed as an integer, it will be treated as a
         *
         * {@link android.net TelephonyNetworkSpecifier}, and the provided integer will be
         * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
         * interpreted as a SubscriptionId.
         *                         specific network specifier where the bearer has a choice of
         * <li>If the value is an ethernet interface name, it will be treated as such.
         *                         networks.
         * <li>For all other cases, the behavior is undefined.
         */
         * </ul>
         *
         * @param networkSpecifier A {@code String} of either a SubscriptionId in cellular
         *                         network request or an ethernet interface name in ethernet
         *                         network request.
         *
         * @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead.
         */
        @Deprecated
        public Builder setNetworkSpecifier(String networkSpecifier) {
        public Builder setNetworkSpecifier(String networkSpecifier) {
            /*
            try {
             * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
                int subId = Integer.parseInt(networkSpecifier);
             * specifiers were strings a null string and an empty string were considered equivalent.
                return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
             * Hence no meaning is attached to a null or empty ("") string.
                        .setSubscriptionId(subId).build());
             */
            } catch (NumberFormatException nfe) {
                // A StringNetworkSpecifier does not accept null or empty ("") strings. When network
                // specifiers were strings a null string and an empty string were considered
                // equivalent. Hence no meaning is attached to a null or empty ("") string.
                return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
                return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
                        : new StringNetworkSpecifier(networkSpecifier));
                        : new StringNetworkSpecifier(networkSpecifier));
            }
            }
        }


        /**
        /**
         * Sets the optional bearer specific network specifier.
         * Sets the optional bearer specific network specifier.
+146 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * NetworkSpecifier object for cellular network request. Apps should use the
 * {@link TelephonyNetworkSpecifier.Builder} class to create an instance.
 */
public final class TelephonyNetworkSpecifier extends NetworkSpecifier implements Parcelable {

    private final int mSubId;

    /**
     * Return the subscription Id of current TelephonyNetworkSpecifier object.
     *
     * @return The subscription id.
     */
    public int getSubscriptionId() {
        return mSubId;
    }

    /**
     * @hide
     */
    public TelephonyNetworkSpecifier(int subId) {
        this.mSubId = subId;
    }

    public static final @NonNull Creator<TelephonyNetworkSpecifier> CREATOR =
            new Creator<TelephonyNetworkSpecifier>() {
                @Override
                public TelephonyNetworkSpecifier createFromParcel(Parcel in) {
                    int subId = in.readInt();
                    return new TelephonyNetworkSpecifier(subId);
                }

                @Override
                public TelephonyNetworkSpecifier[] newArray(int size) {
                    return new TelephonyNetworkSpecifier[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mSubId);
    }

    @Override
    public int hashCode() {
        return mSubId;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof TelephonyNetworkSpecifier)) {
            return false;
        }

        TelephonyNetworkSpecifier lhs = (TelephonyNetworkSpecifier) obj;
        return mSubId == lhs.mSubId;
    }

    @Override
    public String toString() {
        return new StringBuilder()
                .append("TelephonyNetworkSpecifier [")
                .append("mSubId = ").append(mSubId)
                .append("]")
                .toString();
    }

    /** @hide */
    @Override
    public boolean satisfiedBy(NetworkSpecifier other) {
        // Any generic requests should be satisfied by a specific telephony network.
        // For simplicity, we treat null same as MatchAllNetworkSpecifier
        return equals(other) || other == null || other instanceof MatchAllNetworkSpecifier;
    }


    /**
     * Builder to create {@link TelephonyNetworkSpecifier} object.
     */
    public static final class Builder {
        // Integer.MIN_VALUE which is not a valid subId, services as the sentinel to check if
        // subId was set
        private static final int SENTINEL_SUB_ID = Integer.MIN_VALUE;

        private int mSubId;

        public Builder() {
            mSubId = SENTINEL_SUB_ID;
        }

        /**
         * Set the subscription id.
         *
         * @param subId The subscription Id.
         * @return Instance of {@link Builder} to enable the chaining of the builder method.
         */
        public @NonNull Builder setSubscriptionId(int subId) {
            mSubId = subId;
            return this;
        }

        /**
         * Create a NetworkSpecifier for the cellular network request.
         *
         * @return TelephonyNetworkSpecifier object.
         * @throws IllegalArgumentException when subscription Id is not provided through
         *         {@link #setSubscriptionId(int)}.
         */
        public @NonNull TelephonyNetworkSpecifier build() {
            if (mSubId == SENTINEL_SUB_ID) {
                throw new IllegalArgumentException("Subscription Id is not provided.");
            }
            return new TelephonyNetworkSpecifier(mSubId);
        }
    }
}
+11 −12
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;


import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
@@ -46,19 +47,18 @@ import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStats;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.net.NetworkTemplate;
import android.net.StringNetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.os.BestClock;
import android.os.BestClock;
import android.os.Handler;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemClock;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager;
import android.util.DataUnit;
import android.util.DebugUtils;
import android.util.DebugUtils;
import android.util.Pair;
import android.util.Range;
import android.util.Range;
import android.util.Slog;
import android.util.Slog;


@@ -74,7 +74,6 @@ import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;


@@ -185,7 +184,6 @@ public class MultipathPolicyTracker {
    // Track information on mobile networks as they come and go.
    // Track information on mobile networks as they come and go.
    class MultipathTracker {
    class MultipathTracker {
        final Network network;
        final Network network;
        final int subId;
        final String subscriberId;
        final String subscriberId;


        private long mQuota;
        private long mQuota;
@@ -198,13 +196,14 @@ public class MultipathPolicyTracker {
        public MultipathTracker(Network network, NetworkCapabilities nc) {
        public MultipathTracker(Network network, NetworkCapabilities nc) {
            this.network = network;
            this.network = network;
            this.mNetworkCapabilities = new NetworkCapabilities(nc);
            this.mNetworkCapabilities = new NetworkCapabilities(nc);
            try {
            NetworkSpecifier specifier = nc.getNetworkSpecifier();
                subId = Integer.parseInt(
            int subId = INVALID_SUBSCRIPTION_ID;
                        ((StringNetworkSpecifier) nc.getNetworkSpecifier()).toString());
            if (specifier instanceof TelephonyNetworkSpecifier) {
            } catch (ClassCastException | NullPointerException | NumberFormatException e) {
                subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
            } else {
                throw new IllegalStateException(String.format(
                throw new IllegalStateException(String.format(
                        "Can't get subId from mobile network %s (%s): %s",
                        "Can't get subId from mobile network %s (%s)",
                        network, nc, e.getMessage()));
                        network, nc));
            }
            }


            TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
            TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
Loading