am a8fb5803: Merge "Offer to "merge" subscribers for data usage." into lmp-mr1-dev
* commit 'a8fb580379b83b7fc76ee5b99149bbc8a2ce44ab': Offer to "merge" subscribers for data usage.
This commit is contained in:
@@ -68,9 +68,6 @@ interface IConnectivityManager
|
||||
|
||||
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
|
||||
|
||||
/** Policy control over specific {@link NetworkStateTracker}. */
|
||||
void setPolicyDataEnable(int networkType, boolean enabled);
|
||||
|
||||
int tether(String iface);
|
||||
|
||||
int untether(String iface);
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -35,6 +36,8 @@ import java.util.Objects;
|
||||
* @hide
|
||||
*/
|
||||
public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
private static final String TAG = "NetworkIdentity";
|
||||
|
||||
/**
|
||||
* When enabled, combine all {@link #mSubType} together under
|
||||
* {@link #SUBTYPE_COMBINED}.
|
||||
@@ -132,6 +135,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrub given IMSI on production builds.
|
||||
*/
|
||||
public static String[] scrubSubscriberId(String[] subscriberId) {
|
||||
if (subscriberId == null) return null;
|
||||
final String[] res = new String[subscriberId.length];
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link NetworkIdentity} from the given {@link NetworkState},
|
||||
* assuming that any mobile networks are using the current IMSI.
|
||||
@@ -140,23 +155,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
|
||||
final int type = state.networkInfo.getType();
|
||||
final int subType = state.networkInfo.getSubtype();
|
||||
|
||||
// TODO: consider moving subscriberId over to LinkCapabilities, so it
|
||||
// comes from an authoritative source.
|
||||
|
||||
String subscriberId = null;
|
||||
String networkId = null;
|
||||
boolean roaming = false;
|
||||
|
||||
if (isNetworkTypeMobile(type)) {
|
||||
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
|
||||
Context.TELEPHONY_SERVICE);
|
||||
roaming = telephony.isNetworkRoaming();
|
||||
if (state.subscriberId != null) {
|
||||
subscriberId = state.subscriberId;
|
||||
} else {
|
||||
subscriberId = telephony.getSubscriberId();
|
||||
if (state.subscriberId == null) {
|
||||
Slog.w(TAG, "Active mobile network without subscriber!");
|
||||
}
|
||||
|
||||
subscriberId = state.subscriberId;
|
||||
roaming = state.networkInfo.isRoaming();
|
||||
|
||||
} else if (type == TYPE_WIFI) {
|
||||
if (state.networkId != null) {
|
||||
networkId = state.networkId;
|
||||
|
||||
@@ -20,15 +20,18 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A grab-bag of information (metadata, policies, properties, etc) about a {@link Network}.
|
||||
* A grab-bag of information (metadata, policies, properties, etc) about a
|
||||
* {@link Network}. Since this contains PII, it should not be sent outside the
|
||||
* system.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class NetworkMisc implements Parcelable {
|
||||
|
||||
/**
|
||||
* If the {@link Network} is a VPN, whether apps are allowed to bypass the VPN. This is set by
|
||||
* a {@link VpnService} and used by {@link ConnectivityService} when creating a VPN.
|
||||
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
|
||||
* VPN. This is set by a {@link VpnService} and used by
|
||||
* {@link ConnectivityManager} when creating a VPN.
|
||||
*/
|
||||
public boolean allowBypass;
|
||||
|
||||
@@ -41,6 +44,11 @@ public class NetworkMisc implements Parcelable {
|
||||
*/
|
||||
public boolean explicitlySelected;
|
||||
|
||||
/**
|
||||
* For mobile networks, this is the subscriber ID (such as IMSI).
|
||||
*/
|
||||
public String subscriberId;
|
||||
|
||||
public NetworkMisc() {
|
||||
}
|
||||
|
||||
@@ -48,6 +56,7 @@ public class NetworkMisc implements Parcelable {
|
||||
if (nm != null) {
|
||||
allowBypass = nm.allowBypass;
|
||||
explicitlySelected = nm.explicitlySelected;
|
||||
subscriberId = nm.subscriberId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +69,7 @@ public class NetworkMisc implements Parcelable {
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(allowBypass ? 1 : 0);
|
||||
out.writeInt(explicitlySelected ? 1 : 0);
|
||||
out.writeString(subscriberId);
|
||||
}
|
||||
|
||||
public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
|
||||
@@ -68,6 +78,7 @@ public class NetworkMisc implements Parcelable {
|
||||
NetworkMisc networkMisc = new NetworkMisc();
|
||||
networkMisc.allowBypass = in.readInt() != 0;
|
||||
networkMisc.explicitlySelected = in.readInt() != 0;
|
||||
networkMisc.subscriberId = in.readString();
|
||||
return networkMisc;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
|
||||
public static final long LIMIT_DISABLED = -1;
|
||||
public static final long SNOOZE_NEVER = -1;
|
||||
|
||||
public final NetworkTemplate template;
|
||||
public NetworkTemplate template;
|
||||
public int cycleDay;
|
||||
public String cycleTimezone;
|
||||
public long warningBytes;
|
||||
|
||||
@@ -30,15 +30,9 @@ public class NetworkState implements Parcelable {
|
||||
public final LinkProperties linkProperties;
|
||||
public final NetworkCapabilities networkCapabilities;
|
||||
public final Network network;
|
||||
/** Currently only used by testing. */
|
||||
public final String subscriberId;
|
||||
public final String networkId;
|
||||
|
||||
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
|
||||
NetworkCapabilities networkCapabilities, Network network) {
|
||||
this(networkInfo, linkProperties, networkCapabilities, network, null, null);
|
||||
}
|
||||
|
||||
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
|
||||
NetworkCapabilities networkCapabilities, Network network, String subscriberId,
|
||||
String networkId) {
|
||||
@@ -85,5 +79,4 @@ public class NetworkState implements Parcelable {
|
||||
return new NetworkState[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
|
||||
import static android.net.ConnectivityManager.TYPE_WIMAX;
|
||||
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
|
||||
import static android.net.NetworkIdentity.scrubSubscriberId;
|
||||
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
|
||||
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
|
||||
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
|
||||
@@ -36,7 +35,9 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -146,17 +147,35 @@ public class NetworkTemplate implements Parcelable {
|
||||
|
||||
private final int mMatchRule;
|
||||
private final String mSubscriberId;
|
||||
|
||||
/**
|
||||
* Ugh, templates are designed to target a single subscriber, but we might
|
||||
* need to match several "merged" subscribers. These are the subscribers
|
||||
* that should be considered to match this template.
|
||||
* <p>
|
||||
* Since the merge set is dynamic, it should <em>not</em> be persisted or
|
||||
* used for determining equality.
|
||||
*/
|
||||
private final String[] mMatchSubscriberIds;
|
||||
|
||||
private final String mNetworkId;
|
||||
|
||||
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
|
||||
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
|
||||
}
|
||||
|
||||
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
|
||||
String networkId) {
|
||||
mMatchRule = matchRule;
|
||||
mSubscriberId = subscriberId;
|
||||
mMatchSubscriberIds = matchSubscriberIds;
|
||||
mNetworkId = networkId;
|
||||
}
|
||||
|
||||
private NetworkTemplate(Parcel in) {
|
||||
mMatchRule = in.readInt();
|
||||
mSubscriberId = in.readString();
|
||||
mMatchSubscriberIds = in.createStringArray();
|
||||
mNetworkId = in.readString();
|
||||
}
|
||||
|
||||
@@ -164,6 +183,7 @@ public class NetworkTemplate implements Parcelable {
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mMatchRule);
|
||||
dest.writeString(mSubscriberId);
|
||||
dest.writeStringArray(mMatchSubscriberIds);
|
||||
dest.writeString(mNetworkId);
|
||||
}
|
||||
|
||||
@@ -177,7 +197,12 @@ public class NetworkTemplate implements Parcelable {
|
||||
final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
|
||||
builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
|
||||
if (mSubscriberId != null) {
|
||||
builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
|
||||
builder.append(", subscriberId=").append(
|
||||
NetworkIdentity.scrubSubscriberId(mSubscriberId));
|
||||
}
|
||||
if (mMatchSubscriberIds != null) {
|
||||
builder.append(", matchSubscriberIds=").append(
|
||||
Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds)));
|
||||
}
|
||||
if (mNetworkId != null) {
|
||||
builder.append(", networkId=").append(mNetworkId);
|
||||
@@ -201,6 +226,18 @@ public class NetworkTemplate implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isMatchRuleMobile() {
|
||||
switch (mMatchRule) {
|
||||
case MATCH_MOBILE_3G_LOWER:
|
||||
case MATCH_MOBILE_4G:
|
||||
case MATCH_MOBILE_ALL:
|
||||
case MATCH_MOBILE_WILDCARD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMatchRule() {
|
||||
return mMatchRule;
|
||||
}
|
||||
@@ -247,8 +284,9 @@ public class NetworkTemplate implements Parcelable {
|
||||
// TODO: consider matching against WiMAX subscriber identity
|
||||
return true;
|
||||
} else {
|
||||
return ((sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType))
|
||||
&& Objects.equals(mSubscriberId, ident.mSubscriberId));
|
||||
final boolean matchesType = (sForceAllNetworkTypes
|
||||
|| contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
|
||||
return matchesType && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +406,27 @@ public class NetworkTemplate implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the given template and normalize if it refers to a "merged"
|
||||
* mobile subscriber. We pick the "lowest" merged subscriber as the primary
|
||||
* for key purposes, and expand the template to match all other merged
|
||||
* subscribers.
|
||||
* <p>
|
||||
* For example, given an incoming template matching B, and the currently
|
||||
* active merge set [A,B], we'd return a new template that primarily matches
|
||||
* A, but also matches B.
|
||||
*/
|
||||
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
|
||||
if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
|
||||
// Requested template subscriber is part of the merge group; return
|
||||
// a template that matches all merged subscribers.
|
||||
return new NetworkTemplate(template.mMatchRule, merged[0], merged,
|
||||
template.mNetworkId);
|
||||
} else {
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
|
||||
@Override
|
||||
public NetworkTemplate createFromParcel(Parcel in) {
|
||||
|
||||
@@ -127,6 +127,20 @@ public class ArrayUtils
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given array is null or has zero elements.
|
||||
*/
|
||||
public static boolean isEmpty(int[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given array is null or has zero elements.
|
||||
*/
|
||||
public static boolean isEmpty(long[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that value is present as at least one of the elements of the array.
|
||||
* @param array the array to check in
|
||||
@@ -157,6 +171,7 @@ public class ArrayUtils
|
||||
* Test if all {@code check} items are contained in {@code array}.
|
||||
*/
|
||||
public static <T> boolean containsAll(T[] array, T[] check) {
|
||||
if (check == null) return true;
|
||||
for (T checkItem : check) {
|
||||
if (!contains(array, checkItem)) {
|
||||
return false;
|
||||
|
||||
@@ -20,22 +20,8 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
|
||||
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
|
||||
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
|
||||
import static android.net.ConnectivityManager.TYPE_DUMMY;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_CBS;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_IA;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_IMS;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
|
||||
import static android.net.ConnectivityManager.TYPE_NONE;
|
||||
import static android.net.ConnectivityManager.TYPE_PROXY;
|
||||
import static android.net.ConnectivityManager.TYPE_VPN;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.ConnectivityManager.TYPE_WIMAX;
|
||||
import static android.net.ConnectivityManager.getNetworkTypeName;
|
||||
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
@@ -45,11 +31,9 @@ import android.app.AlarmManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -62,7 +46,6 @@ import android.net.INetworkManagementEventObserver;
|
||||
import android.net.INetworkPolicyListener;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.INetworkStatsService;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LinkProperties.CompareResult;
|
||||
import android.net.MobileDataStateTracker;
|
||||
@@ -72,7 +55,6 @@ import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkConfig;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
import android.net.NetworkFactory;
|
||||
import android.net.NetworkMisc;
|
||||
import android.net.NetworkQuotaInfo;
|
||||
import android.net.NetworkRequest;
|
||||
@@ -80,16 +62,12 @@ import android.net.NetworkState;
|
||||
import android.net.NetworkStateTracker;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.Proxy;
|
||||
import android.net.ProxyDataTracker;
|
||||
import android.net.ProxyInfo;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.SamplingDataTracker;
|
||||
import android.net.UidRange;
|
||||
import android.net.Uri;
|
||||
import android.net.wimax.WimaxManagerConstants;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Handler;
|
||||
@@ -103,7 +81,6 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
@@ -126,9 +103,6 @@ import com.android.internal.net.NetworkStatsFactory;
|
||||
import com.android.internal.net.VpnConfig;
|
||||
import com.android.internal.net.VpnProfile;
|
||||
import com.android.internal.telephony.DctConstants;
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.internal.telephony.PhoneConstants;
|
||||
import com.android.internal.telephony.TelephonyIntents;
|
||||
import com.android.internal.util.AsyncChannel;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
@@ -146,8 +120,6 @@ import com.android.server.net.LockdownVpnTracker;
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.android.collect.Sets;
|
||||
|
||||
import dalvik.system.DexClassLoader;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -157,31 +129,20 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -327,12 +288,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
*/
|
||||
private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
|
||||
|
||||
/**
|
||||
* Used internally to
|
||||
* {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
|
||||
*/
|
||||
private static final int EVENT_SET_POLICY_DATA_ENABLE = 12;
|
||||
|
||||
/**
|
||||
* Used internally to disable fail fast of mobile data
|
||||
*/
|
||||
@@ -850,6 +805,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
LinkProperties lp = null;
|
||||
NetworkCapabilities nc = null;
|
||||
Network network = null;
|
||||
String subscriberId = null;
|
||||
|
||||
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
|
||||
NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
|
||||
@@ -859,6 +815,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
lp = new LinkProperties(nai.linkProperties);
|
||||
nc = new NetworkCapabilities(nai.networkCapabilities);
|
||||
network = new Network(nai.network);
|
||||
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
|
||||
}
|
||||
info.setType(networkType);
|
||||
} else {
|
||||
@@ -872,7 +829,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
info = getFilteredNetworkInfo(info, lp, uid);
|
||||
}
|
||||
|
||||
return new NetworkState(info, lp, nc, network);
|
||||
return new NetworkState(info, lp, nc, network, subscriberId, null);
|
||||
}
|
||||
|
||||
private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
|
||||
@@ -889,6 +846,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
LinkProperties lp = null;
|
||||
NetworkCapabilities nc = null;
|
||||
Network network = null;
|
||||
String subscriberId = null;
|
||||
|
||||
NetworkAgentInfo nai = mNetworkForRequestId.get(mDefaultRequest.requestId);
|
||||
|
||||
@@ -920,10 +878,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
lp = new LinkProperties(nai.linkProperties);
|
||||
nc = new NetworkCapabilities(nai.networkCapabilities);
|
||||
network = new Network(nai.network);
|
||||
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
|
||||
}
|
||||
}
|
||||
|
||||
return new NetworkState(info, lp, nc, network);
|
||||
return new NetworkState(info, lp, nc, network, subscriberId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1220,14 +1179,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
@Override
|
||||
public NetworkState[] getAllNetworkState() {
|
||||
enforceAccessPermission();
|
||||
final int uid = Binder.getCallingUid();
|
||||
// Require internal since we're handing out IMSI details
|
||||
enforceConnectivityInternalPermission();
|
||||
|
||||
final ArrayList<NetworkState> result = Lists.newArrayList();
|
||||
for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
|
||||
networkType++) {
|
||||
NetworkState state = getFilteredNetworkState(networkType, uid);
|
||||
if (state.networkInfo != null) {
|
||||
result.add(state);
|
||||
for (Network network : getAllNetworks()) {
|
||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||
if (nai != null) {
|
||||
synchronized (nai) {
|
||||
final String subscriberId = (nai.networkMisc != null)
|
||||
? nai.networkMisc.subscriberId : null;
|
||||
result.add(new NetworkState(nai.networkInfo, nai.linkProperties,
|
||||
nai.networkCapabilities, network, subscriberId, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(new NetworkState[result.size()]);
|
||||
@@ -1452,25 +1416,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void setPolicyDataEnable(int networkType, boolean enabled) {
|
||||
// only someone like NPMS should only be calling us
|
||||
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
|
||||
|
||||
mHandler.sendMessage(mHandler.obtainMessage(
|
||||
EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
|
||||
}
|
||||
|
||||
private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
|
||||
// TODO - handle this passing to factories
|
||||
// if (isNetworkTypeValid(networkType)) {
|
||||
// final NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
// if (tracker != null) {
|
||||
// tracker.setPolicyDataEnable(enabled);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void enforceInternetPermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.INTERNET,
|
||||
@@ -2457,12 +2402,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
sendStickyBroadcast(intent);
|
||||
break;
|
||||
}
|
||||
case EVENT_SET_POLICY_DATA_ENABLE: {
|
||||
final int networkType = msg.arg1;
|
||||
final boolean enabled = msg.arg2 == ENABLED;
|
||||
handleSetPolicyDataEnable(networkType, enabled);
|
||||
break;
|
||||
}
|
||||
case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: {
|
||||
int tag = mEnableFailFastMobileDataTag.get();
|
||||
if (msg.arg1 == tag) {
|
||||
@@ -3858,7 +3797,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mNumDnsEntries = last;
|
||||
}
|
||||
|
||||
|
||||
private void updateCapabilities(NetworkAgentInfo networkAgent,
|
||||
NetworkCapabilities networkCapabilities) {
|
||||
if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {
|
||||
|
||||
@@ -120,7 +120,9 @@ import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.Formatter;
|
||||
import android.text.format.Time;
|
||||
import android.util.ArrayMap;
|
||||
@@ -136,16 +138,17 @@ import android.util.SparseIntArray;
|
||||
import android.util.TrustedTime;
|
||||
import android.util.Xml;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemConfig;
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
@@ -160,7 +163,6 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Service that maintains low-level network policy rules, using
|
||||
@@ -253,38 +255,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
private final boolean mSuppressDefaultPolicy;
|
||||
|
||||
/** Defined network policies. */
|
||||
final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<
|
||||
NetworkTemplate, NetworkPolicy>();
|
||||
final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
|
||||
/** Currently active network rules for ifaces. */
|
||||
private final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<
|
||||
NetworkPolicy, String[]>();
|
||||
final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
|
||||
|
||||
/** Defined UID policies. */
|
||||
final SparseIntArray mUidPolicy = new SparseIntArray();
|
||||
/** Currently derived rules for each UID. */
|
||||
private final SparseIntArray mUidRules = new SparseIntArray();
|
||||
final SparseIntArray mUidRules = new SparseIntArray();
|
||||
|
||||
/** UIDs that have been white-listed to always be able to have network access in
|
||||
* power save mode. */
|
||||
/**
|
||||
* UIDs that have been white-listed to always be able to have network access
|
||||
* in power save mode.
|
||||
*/
|
||||
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
|
||||
|
||||
/** Set of ifaces that are metered. */
|
||||
private ArraySet<String> mMeteredIfaces = new ArraySet<String>();
|
||||
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
|
||||
/** Set of over-limit templates that have been notified. */
|
||||
private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<NetworkTemplate>();
|
||||
private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
|
||||
|
||||
/** Set of currently active {@link Notification} tags. */
|
||||
private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
|
||||
|
||||
/** Foreground at both UID and PID granularity. */
|
||||
private final SparseIntArray mUidState = new SparseIntArray();
|
||||
final SparseArray<SparseIntArray> mUidPidState = new SparseArray<SparseIntArray>();
|
||||
final SparseIntArray mUidState = new SparseIntArray();
|
||||
final SparseArray<SparseIntArray> mUidPidState = new SparseArray<>();
|
||||
|
||||
/** The current maximum process state that we are considering to be foreground. */
|
||||
private int mCurForegroundState = ActivityManager.PROCESS_STATE_TOP;
|
||||
|
||||
private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
|
||||
INetworkPolicyListener>();
|
||||
private final RemoteCallbackList<INetworkPolicyListener>
|
||||
mListeners = new RemoteCallbackList<>();
|
||||
|
||||
final Handler mHandler;
|
||||
|
||||
@@ -740,21 +742,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
* data connection status.
|
||||
*/
|
||||
private boolean isTemplateRelevant(NetworkTemplate template) {
|
||||
final TelephonyManager tele = TelephonyManager.from(mContext);
|
||||
if (template.isMatchRuleMobile()) {
|
||||
final TelephonyManager tele = TelephonyManager.from(mContext);
|
||||
final SubscriptionManager sub = SubscriptionManager.from(mContext);
|
||||
|
||||
switch (template.getMatchRule()) {
|
||||
case MATCH_MOBILE_3G_LOWER:
|
||||
case MATCH_MOBILE_4G:
|
||||
case MATCH_MOBILE_ALL:
|
||||
// mobile templates are relevant when SIM is ready and
|
||||
// subscriberId matches.
|
||||
if (tele.getSimState() == SIM_STATE_READY) {
|
||||
return Objects.equals(tele.getSubscriberId(), template.getSubscriberId());
|
||||
} else {
|
||||
return false;
|
||||
// Mobile template is relevant when any active subscriber matches
|
||||
final int[] subIds = sub.getActiveSubscriptionIdList();
|
||||
for (int subId : subIds) {
|
||||
final String subscriberId = tele.getSubscriberId(subId);
|
||||
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
|
||||
if (template.matches(probeIdent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,6 +966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
maybeRefreshTrustedTime();
|
||||
synchronized (mRulesLock) {
|
||||
ensureActiveMobilePolicyLocked();
|
||||
normalizePoliciesLocked();
|
||||
updateNetworkEnabledLocked();
|
||||
updateNetworkRulesLocked();
|
||||
updateNotificationsLocked();
|
||||
@@ -1001,33 +1007,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
|
||||
* for the given {@link NetworkTemplate}.
|
||||
* Proactively disable networks that match the given
|
||||
* {@link NetworkTemplate}.
|
||||
*/
|
||||
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
|
||||
final TelephonyManager tele = TelephonyManager.from(mContext);
|
||||
|
||||
switch (template.getMatchRule()) {
|
||||
case MATCH_MOBILE_3G_LOWER:
|
||||
case MATCH_MOBILE_4G:
|
||||
case MATCH_MOBILE_ALL:
|
||||
// TODO: offer more granular control over radio states once
|
||||
// 4965893 is available.
|
||||
if (tele.getSimState() == SIM_STATE_READY
|
||||
&& Objects.equals(tele.getSubscriberId(), template.getSubscriberId())) {
|
||||
setPolicyDataEnable(TYPE_MOBILE, enabled);
|
||||
setPolicyDataEnable(TYPE_WIMAX, enabled);
|
||||
}
|
||||
break;
|
||||
case MATCH_WIFI:
|
||||
setPolicyDataEnable(TYPE_WIFI, enabled);
|
||||
break;
|
||||
case MATCH_ETHERNET:
|
||||
setPolicyDataEnable(TYPE_ETHERNET, enabled);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unexpected template");
|
||||
}
|
||||
// TODO: reach into ConnectivityManager to proactively disable bringing
|
||||
// up this network, since we know that traffic will be blocked.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1036,7 +1021,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
* remaining quota based on usage cycle and historical stats.
|
||||
*/
|
||||
void updateNetworkRulesLocked() {
|
||||
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
|
||||
if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
|
||||
|
||||
final NetworkState[] states;
|
||||
try {
|
||||
@@ -1203,42 +1188,47 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
if (mSuppressDefaultPolicy) return;
|
||||
|
||||
final TelephonyManager tele = TelephonyManager.from(mContext);
|
||||
final SubscriptionManager sub = SubscriptionManager.from(mContext);
|
||||
|
||||
// avoid creating policy when SIM isn't ready
|
||||
if (tele.getSimState() != SIM_STATE_READY) return;
|
||||
final int[] subIds = sub.getActiveSubscriptionIdList();
|
||||
for (int subId : subIds) {
|
||||
final String subscriberId = tele.getSubscriberId(subId);
|
||||
ensureActiveMobilePolicyLocked(subscriberId);
|
||||
}
|
||||
}
|
||||
|
||||
final String subscriberId = tele.getSubscriberId();
|
||||
final NetworkIdentity probeIdent = new NetworkIdentity(
|
||||
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
|
||||
|
||||
// examine to see if any policy is defined for active mobile
|
||||
boolean mobileDefined = false;
|
||||
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
|
||||
if (mNetworkPolicy.valueAt(i).template.matches(probeIdent)) {
|
||||
mobileDefined = true;
|
||||
break;
|
||||
private void ensureActiveMobilePolicyLocked(String subscriberId) {
|
||||
// Poke around to see if we already have a policy
|
||||
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
|
||||
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
|
||||
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
|
||||
if (template.matches(probeIdent)) {
|
||||
if (LOGD) {
|
||||
Slog.d(TAG, "Found template " + template + " which matches subscriber "
|
||||
+ NetworkIdentity.scrubSubscriberId(subscriberId));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mobileDefined) {
|
||||
Slog.i(TAG, "no policy for active mobile network; generating default policy");
|
||||
Slog.i(TAG, "No policy for subscriber " + NetworkIdentity.scrubSubscriberId(subscriberId)
|
||||
+ "; generating default policy");
|
||||
|
||||
// build default mobile policy, and assume usage cycle starts today
|
||||
final long warningBytes = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_networkPolicyDefaultWarning)
|
||||
* MB_IN_BYTES;
|
||||
// Build default mobile policy, and assume usage cycle starts today
|
||||
final long warningBytes = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
|
||||
|
||||
final Time time = new Time();
|
||||
time.setToNow();
|
||||
final Time time = new Time();
|
||||
time.setToNow();
|
||||
|
||||
final int cycleDay = time.monthDay;
|
||||
final String cycleTimezone = time.timezone;
|
||||
final int cycleDay = time.monthDay;
|
||||
final String cycleTimezone = time.timezone;
|
||||
|
||||
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
|
||||
final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
|
||||
warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
|
||||
addNetworkPolicyLocked(policy);
|
||||
}
|
||||
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
|
||||
final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
|
||||
warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
|
||||
addNetworkPolicyLocked(policy);
|
||||
}
|
||||
|
||||
private void readPolicyLocked() {
|
||||
@@ -1321,8 +1311,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
inferred = false;
|
||||
}
|
||||
|
||||
final NetworkTemplate template = new NetworkTemplate(
|
||||
networkTemplate, subscriberId, networkId);
|
||||
final NetworkTemplate template = new NetworkTemplate(networkTemplate,
|
||||
subscriberId, networkId);
|
||||
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
|
||||
cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
|
||||
lastLimitSnooze, metered, inferred));
|
||||
@@ -1593,11 +1583,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
maybeRefreshTrustedTime();
|
||||
synchronized (mRulesLock) {
|
||||
mNetworkPolicy.clear();
|
||||
for (NetworkPolicy policy : policies) {
|
||||
mNetworkPolicy.put(policy.template, policy);
|
||||
}
|
||||
|
||||
normalizePoliciesLocked(policies);
|
||||
updateNetworkEnabledLocked();
|
||||
updateNetworkRulesLocked();
|
||||
updateNotificationsLocked();
|
||||
@@ -1606,12 +1592,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
|
||||
void addNetworkPolicyLocked(NetworkPolicy policy) {
|
||||
mNetworkPolicy.put(policy.template, policy);
|
||||
|
||||
updateNetworkEnabledLocked();
|
||||
updateNetworkRulesLocked();
|
||||
updateNotificationsLocked();
|
||||
writePolicyLocked();
|
||||
NetworkPolicy[] policies = getNetworkPolicies();
|
||||
policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
|
||||
setNetworkPolicies(policies);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1620,7 +1603,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
|
||||
|
||||
synchronized (mRulesLock) {
|
||||
return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
|
||||
final int size = mNetworkPolicy.size();
|
||||
final NetworkPolicy[] policies = new NetworkPolicy[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
policies[i] = mNetworkPolicy.valueAt(i);
|
||||
}
|
||||
return policies;
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizePoliciesLocked() {
|
||||
normalizePoliciesLocked(getNetworkPolicies());
|
||||
}
|
||||
|
||||
private void normalizePoliciesLocked(NetworkPolicy[] policies) {
|
||||
final TelephonyManager tele = TelephonyManager.from(mContext);
|
||||
final String[] merged = tele.getMergedSubscriberIds();
|
||||
|
||||
mNetworkPolicy.clear();
|
||||
for (NetworkPolicy policy : policies) {
|
||||
// When two normalized templates conflict, prefer the most
|
||||
// restrictive policy
|
||||
policy.template = NetworkTemplate.normalize(policy.template, merged);
|
||||
final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
|
||||
if (existing == null || existing.compareTo(policy) > 0) {
|
||||
if (existing != null) {
|
||||
Slog.d(TAG, "Normalization replaced " + existing + " with " + policy);
|
||||
}
|
||||
mNetworkPolicy.put(policy.template, policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1657,6 +1668,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
throw new IllegalArgumentException("unexpected type");
|
||||
}
|
||||
|
||||
normalizePoliciesLocked();
|
||||
updateNetworkEnabledLocked();
|
||||
updateNetworkRulesLocked();
|
||||
updateNotificationsLocked();
|
||||
@@ -1784,6 +1796,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
mNetworkPolicy.valueAt(i).clearSnooze();
|
||||
}
|
||||
|
||||
normalizePoliciesLocked();
|
||||
updateNetworkEnabledLocked();
|
||||
updateNetworkRulesLocked();
|
||||
updateNotificationsLocked();
|
||||
@@ -1976,6 +1989,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
// If the set of restricted networks may have changed, re-evaluate those.
|
||||
if (restrictedNetworksChanged) {
|
||||
normalizePoliciesLocked();
|
||||
updateNetworkRulesLocked();
|
||||
}
|
||||
}
|
||||
@@ -2162,17 +2176,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
|
||||
*/
|
||||
private void setPolicyDataEnable(int networkType, boolean enabled) {
|
||||
try {
|
||||
mConnManager.setPolicyDataEnable(networkType, enabled);
|
||||
} catch (RemoteException e) {
|
||||
// ignored; service lives in system_server
|
||||
}
|
||||
}
|
||||
|
||||
private long getTotalBytes(NetworkTemplate template, long start, long end) {
|
||||
try {
|
||||
return mNetworkStats.getNetworkTotalBytes(template, start, end);
|
||||
|
||||
@@ -916,10 +916,8 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
|
||||
}
|
||||
|
||||
private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
|
||||
final FutureAnswer future = new FutureAnswer();
|
||||
mConnManager.setPolicyDataEnable(type, enabled);
|
||||
expectLastCall().andAnswer(future);
|
||||
return future;
|
||||
// TODO: bring back this test
|
||||
return null;
|
||||
}
|
||||
|
||||
private void expectAdvisePersistThreshold() throws Exception {
|
||||
|
||||
@@ -1023,7 +1023,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
|
||||
info.setDetailedState(DetailedState.CONNECTED, null, null);
|
||||
final LinkProperties prop = new LinkProperties();
|
||||
prop.setInterfaceName(iface);
|
||||
return new NetworkState(info, prop, null, null);
|
||||
return new NetworkState(info, prop, null, null, null, null);
|
||||
}
|
||||
|
||||
private NetworkStats buildEmptyStats() {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.telephony;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.content.Context;
|
||||
@@ -1064,7 +1065,7 @@ public class SubscriptionManager {
|
||||
* is never null but the length maybe 0.
|
||||
* @hide
|
||||
*/
|
||||
public int[] getActiveSubscriptionIdList() {
|
||||
public @NonNull int[] getActiveSubscriptionIdList() {
|
||||
int[] subId = null;
|
||||
|
||||
try {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.telephony;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
@@ -40,6 +41,7 @@ import com.android.internal.telephony.TelephonyProperties;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -1878,6 +1880,23 @@ public class TelephonyManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of subscriber IDs that should be considered as "merged
|
||||
* together" for data usage purposes. This is commonly {@code null} to
|
||||
* indicate no merging is required. Any returned subscribers are sorted in a
|
||||
* deterministic order.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public @Nullable String[] getMergedSubscriberIds() {
|
||||
try {
|
||||
return getITelephony().getMergedSubscriberIds();
|
||||
} catch (RemoteException ex) {
|
||||
} catch (NullPointerException ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MSISDN string.
|
||||
* for a GSM phone. Return null if it is unavailable.
|
||||
@@ -3593,5 +3612,3 @@ public class TelephonyManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -772,6 +772,8 @@ interface ITelephony {
|
||||
*/
|
||||
String getLine1AlphaTagForDisplay(int subId);
|
||||
|
||||
String[] getMergedSubscriberIds();
|
||||
|
||||
/**
|
||||
* Override the operator branding for the current ICCID.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user