blob: eba7ff348328a587e49461d6e4ec7063a30ea7a7 [file] [log] [blame]
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
Jeff Sharkey55a442e2014-11-18 18:22:21 -080019import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
Jeff Sharkey02e21d62011-07-17 15:53:33 -070020import static android.net.ConnectivityManager.TYPE_ETHERNET;
Jack Yu66a6be32016-03-30 11:14:39 -070021import static android.net.ConnectivityManager.TYPE_MOBILE;
Christopher Tate3bf01732017-05-15 16:34:52 -070022import static android.net.ConnectivityManager.TYPE_PROXY;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070023import static android.net.ConnectivityManager.TYPE_WIFI;
Jeff Sharkey3ca74812012-01-24 15:37:07 -080024import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070025import static android.net.ConnectivityManager.TYPE_WIMAX;
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +090026import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
27import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
28import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
29import static android.net.NetworkStats.METERED_ALL;
30import static android.net.NetworkStats.METERED_NO;
31import static android.net.NetworkStats.METERED_YES;
32import static android.net.NetworkStats.ROAMING_ALL;
33import static android.net.NetworkStats.ROAMING_NO;
34import static android.net.NetworkStats.ROAMING_YES;
David Sub4d222a2020-01-27 13:27:50 -080035import static android.net.wifi.WifiInfo.sanitizeSsid;
Ritesh Reddyadca34a2016-02-04 18:33:30 +000036
junyulai317ba5b2020-02-11 14:59:38 +080037import android.annotation.NonNull;
junyulaib1b80c62019-12-20 16:35:34 +080038import android.annotation.Nullable;
Artur Satayev26958002019-12-10 17:47:52 +000039import android.compat.annotation.UnsupportedAppUsage;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070040import android.os.Parcel;
41import android.os.Parcelable;
junyulaib1b80c62019-12-20 16:35:34 +080042import android.telephony.Annotation.NetworkType;
junyulaif2d6fd52019-12-12 19:42:59 +080043import android.telephony.TelephonyManager;
junyulaib1b80c62019-12-20 16:35:34 +080044import android.text.TextUtils;
Ritesh Reddyadca34a2016-02-04 18:33:30 +000045import android.util.BackupUtils;
Christopher Tate3bf01732017-05-15 16:34:52 -070046import android.util.Log;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070047
Varun Anand472b9262019-02-17 23:15:15 -080048import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkey32566012014-12-02 18:30:14 -080049import com.android.internal.util.ArrayUtils;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070050
Ritesh Reddyadca34a2016-02-04 18:33:30 +000051import java.io.ByteArrayOutputStream;
52import java.io.DataInputStream;
53import java.io.DataOutputStream;
54import java.io.IOException;
Jeff Sharkey32566012014-12-02 18:30:14 -080055import java.util.Arrays;
junyulai317ba5b2020-02-11 14:59:38 +080056import java.util.Collection;
57import java.util.HashSet;
Malcolm Chen07fcb5b2019-07-02 22:29:35 -070058import java.util.List;
Jeff Sharkey55a442e2014-11-18 18:22:21 -080059import java.util.Objects;
60
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070061/**
Jeff Sharkeye0c29952018-02-20 17:24:55 -070062 * Predicate used to match {@link NetworkIdentity}, usually when collecting
63 * statistics. (It should probably have been named {@code NetworkPredicate}.)
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070064 *
65 * @hide
66 */
67public class NetworkTemplate implements Parcelable {
Christopher Tate3bf01732017-05-15 16:34:52 -070068 private static final String TAG = "NetworkTemplate";
69
Ritesh Reddyadca34a2016-02-04 18:33:30 +000070 /**
71 * Current Version of the Backup Serializer.
72 */
73 private static final int BACKUP_VERSION = 1;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070074
Jeff Sharkeye0c29952018-02-20 17:24:55 -070075 public static final int MATCH_MOBILE = 1;
Jeff Sharkey4e814c32011-07-14 20:37:37 -070076 public static final int MATCH_WIFI = 4;
Jeff Sharkey4e814c32011-07-14 20:37:37 -070077 public static final int MATCH_ETHERNET = 5;
Jeff Sharkey234766a2012-04-10 19:48:07 -070078 public static final int MATCH_MOBILE_WILDCARD = 6;
79 public static final int MATCH_WIFI_WILDCARD = 7;
Jeff Sharkey55a442e2014-11-18 18:22:21 -080080 public static final int MATCH_BLUETOOTH = 8;
Sharvil Nanavati7f8d6502016-03-21 14:19:37 -070081 public static final int MATCH_PROXY = 9;
Jeff Sharkey4e814c32011-07-14 20:37:37 -070082
junyulaib1b80c62019-12-20 16:35:34 +080083 /**
84 * Include all network types when filtering. This is meant to merge in with the
85 * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
86 *
87 * @hide
88 */
89 public static final int NETWORK_TYPE_ALL = -1;
90
Christopher Tate3bf01732017-05-15 16:34:52 -070091 private static boolean isKnownMatchRule(final int rule) {
92 switch (rule) {
Jeff Sharkeye0c29952018-02-20 17:24:55 -070093 case MATCH_MOBILE:
Christopher Tate3bf01732017-05-15 16:34:52 -070094 case MATCH_WIFI:
95 case MATCH_ETHERNET:
96 case MATCH_MOBILE_WILDCARD:
97 case MATCH_WIFI_WILDCARD:
98 case MATCH_BLUETOOTH:
99 case MATCH_PROXY:
100 return true;
101
102 default:
103 return false;
104 }
105 }
106
Jeff Sharkey70c70532012-05-16 14:51:19 -0700107 private static boolean sForceAllNetworkTypes = false;
108
Varun Anand472b9262019-02-17 23:15:15 -0800109 /**
110 * Results in matching against all mobile network types.
111 *
112 * <p>See {@link #matchesMobile} and {@link matchesMobileWildcard}.
113 */
114 @VisibleForTesting
Jeff Sharkey70c70532012-05-16 14:51:19 -0700115 public static void forceAllNetworkTypes() {
116 sForceAllNetworkTypes = true;
117 }
118
Varun Anand472b9262019-02-17 23:15:15 -0800119 /** Resets the affect of {@link #forceAllNetworkTypes}. */
120 @VisibleForTesting
121 public static void resetForceAllNetworkTypes() {
122 sForceAllNetworkTypes = false;
123 }
124
Jeff Sharkey630a1712011-09-26 10:47:10 -0700125 /**
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700126 * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
127 * the given IMSI.
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700128 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100129 @UnsupportedAppUsage
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700130 public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
Jeff Sharkeye0c29952018-02-20 17:24:55 -0700131 return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700132 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700133
134 /**
junyulaib1b80c62019-12-20 16:35:34 +0800135 * Template to match cellular networks with the given IMSI and {@code ratType}.
136 * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
137 * See {@code TelephonyManager.NETWORK_TYPE_*}.
138 */
139 public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
140 @NetworkType int ratType) {
141 if (TextUtils.isEmpty(subscriberId)) {
142 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
143 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
144 }
145 return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
146 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
147 }
148
149 /**
150 * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
Jeff Sharkey234766a2012-04-10 19:48:07 -0700151 * regardless of IMSI.
152 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100153 @UnsupportedAppUsage
Jeff Sharkey234766a2012-04-10 19:48:07 -0700154 public static NetworkTemplate buildTemplateMobileWildcard() {
155 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
156 }
157
158 /**
junyulaib1b80c62019-12-20 16:35:34 +0800159 * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700160 * regardless of SSID.
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700161 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100162 @UnsupportedAppUsage
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700163 public static NetworkTemplate buildTemplateWifiWildcard() {
Jeff Sharkey234766a2012-04-10 19:48:07 -0700164 return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700165 }
166
167 @Deprecated
Mathew Inwood53f089f2018-08-08 14:44:44 +0100168 @UnsupportedAppUsage
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700169 public static NetworkTemplate buildTemplateWifi() {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700170 return buildTemplateWifiWildcard();
171 }
172
173 /**
174 * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
175 * given SSID.
176 */
177 public static NetworkTemplate buildTemplateWifi(String networkId) {
178 return new NetworkTemplate(MATCH_WIFI, null, networkId);
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700179 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700180
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700181 /**
182 * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
183 * networks together.
184 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100185 @UnsupportedAppUsage
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700186 public static NetworkTemplate buildTemplateEthernet() {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700187 return new NetworkTemplate(MATCH_ETHERNET, null, null);
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700188 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700189
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800190 /**
191 * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
192 * networks together.
193 */
194 public static NetworkTemplate buildTemplateBluetooth() {
195 return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
196 }
197
Sharvil Nanavati7f8d6502016-03-21 14:19:37 -0700198 /**
199 * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
200 * networks together.
201 */
202 public static NetworkTemplate buildTemplateProxy() {
203 return new NetworkTemplate(MATCH_PROXY, null, null);
204 }
205
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700206 private final int mMatchRule;
207 private final String mSubscriberId;
Jeff Sharkey32566012014-12-02 18:30:14 -0800208
209 /**
210 * Ugh, templates are designed to target a single subscriber, but we might
211 * need to match several "merged" subscribers. These are the subscribers
212 * that should be considered to match this template.
213 * <p>
214 * Since the merge set is dynamic, it should <em>not</em> be persisted or
215 * used for determining equality.
216 */
217 private final String[] mMatchSubscriberIds;
218
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700219 private final String mNetworkId;
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700220
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900221 // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
222 private final int mMetered;
223 private final int mRoaming;
224 private final int mDefaultNetwork;
junyulaib1b80c62019-12-20 16:35:34 +0800225 private final int mSubType;
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900226
Mathew Inwood53f089f2018-08-08 14:44:44 +0100227 @UnsupportedAppUsage
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700228 public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
Jeff Sharkey32566012014-12-02 18:30:14 -0800229 this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
230 }
231
232 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
233 String networkId) {
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900234 this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
junyulaib1b80c62019-12-20 16:35:34 +0800235 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL);
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900236 }
237
238 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
junyulaib1b80c62019-12-20 16:35:34 +0800239 String networkId, int metered, int roaming, int defaultNetwork, int subType) {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700240 mMatchRule = matchRule;
241 mSubscriberId = subscriberId;
Jeff Sharkey32566012014-12-02 18:30:14 -0800242 mMatchSubscriberIds = matchSubscriberIds;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700243 mNetworkId = networkId;
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900244 mMetered = metered;
245 mRoaming = roaming;
246 mDefaultNetwork = defaultNetwork;
junyulaib1b80c62019-12-20 16:35:34 +0800247 mSubType = subType;
Christopher Tate3bf01732017-05-15 16:34:52 -0700248
249 if (!isKnownMatchRule(matchRule)) {
250 Log.e(TAG, "Unknown network template rule " + matchRule
251 + " will not match any identity.");
252 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700253 }
254
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700255 private NetworkTemplate(Parcel in) {
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700256 mMatchRule = in.readInt();
257 mSubscriberId = in.readString();
Jeff Sharkey32566012014-12-02 18:30:14 -0800258 mMatchSubscriberIds = in.createStringArray();
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700259 mNetworkId = in.readString();
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900260 mMetered = in.readInt();
261 mRoaming = in.readInt();
262 mDefaultNetwork = in.readInt();
junyulaib1b80c62019-12-20 16:35:34 +0800263 mSubType = in.readInt();
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700264 }
265
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700266 @Override
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700267 public void writeToParcel(Parcel dest, int flags) {
268 dest.writeInt(mMatchRule);
269 dest.writeString(mSubscriberId);
Jeff Sharkey32566012014-12-02 18:30:14 -0800270 dest.writeStringArray(mMatchSubscriberIds);
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700271 dest.writeString(mNetworkId);
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900272 dest.writeInt(mMetered);
273 dest.writeInt(mRoaming);
274 dest.writeInt(mDefaultNetwork);
junyulaib1b80c62019-12-20 16:35:34 +0800275 dest.writeInt(mSubType);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700276 }
277
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700278 @Override
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700279 public int describeContents() {
280 return 0;
281 }
282
283 @Override
284 public String toString() {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700285 final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
286 builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
287 if (mSubscriberId != null) {
Jeff Sharkey32566012014-12-02 18:30:14 -0800288 builder.append(", subscriberId=").append(
289 NetworkIdentity.scrubSubscriberId(mSubscriberId));
290 }
291 if (mMatchSubscriberIds != null) {
292 builder.append(", matchSubscriberIds=").append(
293 Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds)));
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700294 }
295 if (mNetworkId != null) {
296 builder.append(", networkId=").append(mNetworkId);
297 }
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900298 if (mMetered != METERED_ALL) {
299 builder.append(", metered=").append(NetworkStats.meteredToString(mMetered));
300 }
301 if (mRoaming != ROAMING_ALL) {
302 builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming));
303 }
304 if (mDefaultNetwork != DEFAULT_NETWORK_ALL) {
305 builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
306 mDefaultNetwork));
307 }
junyulaib1b80c62019-12-20 16:35:34 +0800308 if (mSubType != NETWORK_TYPE_ALL) {
309 builder.append(", subType=").append(mSubType);
310 }
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700311 return builder.toString();
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700312 }
313
314 @Override
315 public int hashCode() {
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900316 return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
junyulaib1b80c62019-12-20 16:35:34 +0800317 mDefaultNetwork, mSubType);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700318 }
319
320 @Override
321 public boolean equals(Object obj) {
322 if (obj instanceof NetworkTemplate) {
323 final NetworkTemplate other = (NetworkTemplate) obj;
324 return mMatchRule == other.mMatchRule
Kenny Roote6585b32013-12-13 12:00:26 -0800325 && Objects.equals(mSubscriberId, other.mSubscriberId)
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900326 && Objects.equals(mNetworkId, other.mNetworkId)
327 && mMetered == other.mMetered
328 && mRoaming == other.mRoaming
junyulaib1b80c62019-12-20 16:35:34 +0800329 && mDefaultNetwork == other.mDefaultNetwork
330 && mSubType == other.mSubType;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700331 }
332 return false;
333 }
334
Jeff Sharkey32566012014-12-02 18:30:14 -0800335 public boolean isMatchRuleMobile() {
336 switch (mMatchRule) {
Jeff Sharkeye0c29952018-02-20 17:24:55 -0700337 case MATCH_MOBILE:
Jeff Sharkey32566012014-12-02 18:30:14 -0800338 case MATCH_MOBILE_WILDCARD:
339 return true;
340 default:
341 return false;
342 }
343 }
344
Jeff Sharkey7474fe7b2016-03-21 13:12:59 -0600345 public boolean isPersistable() {
346 switch (mMatchRule) {
347 case MATCH_MOBILE_WILDCARD:
348 case MATCH_WIFI_WILDCARD:
349 return false;
350 default:
351 return true;
352 }
353 }
354
Mathew Inwood53f089f2018-08-08 14:44:44 +0100355 @UnsupportedAppUsage
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700356 public int getMatchRule() {
357 return mMatchRule;
358 }
359
Mathew Inwood53f089f2018-08-08 14:44:44 +0100360 @UnsupportedAppUsage
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700361 public String getSubscriberId() {
362 return mSubscriberId;
363 }
364
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700365 public String getNetworkId() {
366 return mNetworkId;
367 }
368
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700369 /**
Jeff Sharkey630a1712011-09-26 10:47:10 -0700370 * Test if given {@link NetworkIdentity} matches this template.
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700371 */
372 public boolean matches(NetworkIdentity ident) {
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900373 if (!matchesMetered(ident)) return false;
374 if (!matchesRoaming(ident)) return false;
375 if (!matchesDefaultNetwork(ident)) return false;
376
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700377 switch (mMatchRule) {
Jeff Sharkeye0c29952018-02-20 17:24:55 -0700378 case MATCH_MOBILE:
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700379 return matchesMobile(ident);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700380 case MATCH_WIFI:
381 return matchesWifi(ident);
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700382 case MATCH_ETHERNET:
383 return matchesEthernet(ident);
Jeff Sharkey234766a2012-04-10 19:48:07 -0700384 case MATCH_MOBILE_WILDCARD:
385 return matchesMobileWildcard(ident);
386 case MATCH_WIFI_WILDCARD:
387 return matchesWifiWildcard(ident);
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800388 case MATCH_BLUETOOTH:
389 return matchesBluetooth(ident);
Sharvil Nanavati7f8d6502016-03-21 14:19:37 -0700390 case MATCH_PROXY:
391 return matchesProxy(ident);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700392 default:
Christopher Tate3bf01732017-05-15 16:34:52 -0700393 // We have no idea what kind of network template we are, so we
394 // just claim not to match anything.
395 return false;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700396 }
397 }
398
Lorenzo Colitti53ba2f02018-01-22 11:54:46 +0900399 private boolean matchesMetered(NetworkIdentity ident) {
400 return (mMetered == METERED_ALL)
401 || (mMetered == METERED_YES && ident.mMetered)
402 || (mMetered == METERED_NO && !ident.mMetered);
403 }
404
405 private boolean matchesRoaming(NetworkIdentity ident) {
406 return (mRoaming == ROAMING_ALL)
407 || (mRoaming == ROAMING_YES && ident.mRoaming)
408 || (mRoaming == ROAMING_NO && !ident.mRoaming);
409 }
410
411 private boolean matchesDefaultNetwork(NetworkIdentity ident) {
412 return (mDefaultNetwork == DEFAULT_NETWORK_ALL)
413 || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork)
414 || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
415 }
416
junyulaib1b80c62019-12-20 16:35:34 +0800417 private boolean matchesCollapsedRatType(NetworkIdentity ident) {
418 return mSubType == NETWORK_TYPE_ALL
419 || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
420 }
421
Jeff Sharkeyf4de2942017-08-29 15:32:13 -0600422 public boolean matchesSubscriberId(String subscriberId) {
423 return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
424 }
425
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700426 /**
Jeff Sharkey630a1712011-09-26 10:47:10 -0700427 * Check if mobile network with matching IMSI.
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700428 */
429 private boolean matchesMobile(NetworkIdentity ident) {
Jeff Sharkey630a1712011-09-26 10:47:10 -0700430 if (ident.mType == TYPE_WIMAX) {
431 // TODO: consider matching against WiMAX subscriber identity
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700432 return true;
Jeff Sharkey630a1712011-09-26 10:47:10 -0700433 } else {
junyulaib1b80c62019-12-20 16:35:34 +0800434 // Only metered mobile network would be matched regardless of metered filter.
435 // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
436 // TODO: Respect metered filter and remove mMetered condition.
Jack Yu66a6be32016-03-30 11:14:39 -0700437 return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
438 && !ArrayUtils.isEmpty(mMatchSubscriberIds)
junyulaib1b80c62019-12-20 16:35:34 +0800439 && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
440 && matchesCollapsedRatType(ident);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700441 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700442 }
443
444 /**
junyulaif2d6fd52019-12-12 19:42:59 +0800445 * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
446 * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
447 *
448 * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
449 */
450 // TODO: 1. Consider move this to TelephonyManager if used by other modules.
451 // 2. Consider make this configurable.
452 // 3. Use TelephonyManager APIs when available.
453 public static int getCollapsedRatType(int ratType) {
454 switch (ratType) {
455 case TelephonyManager.NETWORK_TYPE_GPRS:
456 case TelephonyManager.NETWORK_TYPE_GSM:
457 case TelephonyManager.NETWORK_TYPE_EDGE:
458 case TelephonyManager.NETWORK_TYPE_IDEN:
459 case TelephonyManager.NETWORK_TYPE_CDMA:
460 case TelephonyManager.NETWORK_TYPE_1xRTT:
461 return TelephonyManager.NETWORK_TYPE_GSM;
462 case TelephonyManager.NETWORK_TYPE_EVDO_0:
463 case TelephonyManager.NETWORK_TYPE_EVDO_A:
464 case TelephonyManager.NETWORK_TYPE_EVDO_B:
465 case TelephonyManager.NETWORK_TYPE_EHRPD:
466 case TelephonyManager.NETWORK_TYPE_UMTS:
467 case TelephonyManager.NETWORK_TYPE_HSDPA:
468 case TelephonyManager.NETWORK_TYPE_HSUPA:
469 case TelephonyManager.NETWORK_TYPE_HSPA:
470 case TelephonyManager.NETWORK_TYPE_HSPAP:
471 case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
472 return TelephonyManager.NETWORK_TYPE_UMTS;
473 case TelephonyManager.NETWORK_TYPE_LTE:
474 case TelephonyManager.NETWORK_TYPE_IWLAN:
475 return TelephonyManager.NETWORK_TYPE_LTE;
476 case TelephonyManager.NETWORK_TYPE_NR:
477 return TelephonyManager.NETWORK_TYPE_NR;
478 default:
479 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
480 }
481 }
482
483 /**
junyulai317ba5b2020-02-11 14:59:38 +0800484 * Return all supported collapsed RAT types that could be returned by
485 * {@link #getCollapsedRatType(int)}.
486 */
487 @NonNull
488 public static final int[] getAllCollapsedRatTypes() {
489 final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
490 final HashSet<Integer> collapsedRatTypes = new HashSet<>();
491 for (final int ratType : ratTypes) {
492 collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
493 }
494 // Ensure that unknown type is returned.
495 collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
496 return toIntArray(collapsedRatTypes);
497 }
498
499 @NonNull
500 private static int[] toIntArray(@NonNull Collection<Integer> list) {
501 final int[] array = new int[list.size()];
502 int i = 0;
503 for (final Integer item : list) {
504 array[i++] = item;
505 }
506 return array;
507 }
508
509 /**
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700510 * Check if matches Wi-Fi network template.
511 */
512 private boolean matchesWifi(NetworkIdentity ident) {
Jeff Sharkey3ca74812012-01-24 15:37:07 -0800513 switch (ident.mType) {
514 case TYPE_WIFI:
Kenny Roote6585b32013-12-13 12:00:26 -0800515 return Objects.equals(
David Sub4d222a2020-01-27 13:27:50 -0800516 sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId));
Jeff Sharkey3ca74812012-01-24 15:37:07 -0800517 default:
518 return false;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700519 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700520 }
521
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700522 /**
523 * Check if matches Ethernet network template.
524 */
525 private boolean matchesEthernet(NetworkIdentity ident) {
526 if (ident.mType == TYPE_ETHERNET) {
527 return true;
528 }
529 return false;
530 }
531
Jeff Sharkey234766a2012-04-10 19:48:07 -0700532 private boolean matchesMobileWildcard(NetworkIdentity ident) {
533 if (ident.mType == TYPE_WIMAX) {
534 return true;
535 } else {
junyulaib1b80c62019-12-20 16:35:34 +0800536 return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
537 && matchesCollapsedRatType(ident);
Jeff Sharkey234766a2012-04-10 19:48:07 -0700538 }
539 }
540
541 private boolean matchesWifiWildcard(NetworkIdentity ident) {
542 switch (ident.mType) {
543 case TYPE_WIFI:
544 case TYPE_WIFI_P2P:
545 return true;
546 default:
547 return false;
548 }
549 }
550
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800551 /**
552 * Check if matches Bluetooth network template.
553 */
554 private boolean matchesBluetooth(NetworkIdentity ident) {
555 if (ident.mType == TYPE_BLUETOOTH) {
556 return true;
557 }
558 return false;
559 }
560
Sharvil Nanavati7f8d6502016-03-21 14:19:37 -0700561 /**
562 * Check if matches Proxy network template.
563 */
564 private boolean matchesProxy(NetworkIdentity ident) {
565 return ident.mType == TYPE_PROXY;
566 }
567
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700568 private static String getMatchRuleName(int matchRule) {
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700569 switch (matchRule) {
Jeff Sharkeye0c29952018-02-20 17:24:55 -0700570 case MATCH_MOBILE:
571 return "MOBILE";
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700572 case MATCH_WIFI:
573 return "WIFI";
Jeff Sharkey4e814c32011-07-14 20:37:37 -0700574 case MATCH_ETHERNET:
575 return "ETHERNET";
Jeff Sharkey234766a2012-04-10 19:48:07 -0700576 case MATCH_MOBILE_WILDCARD:
577 return "MOBILE_WILDCARD";
578 case MATCH_WIFI_WILDCARD:
579 return "WIFI_WILDCARD";
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800580 case MATCH_BLUETOOTH:
581 return "BLUETOOTH";
Sharvil Nanavati7f8d6502016-03-21 14:19:37 -0700582 case MATCH_PROXY:
583 return "PROXY";
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700584 default:
Christopher Tate3bf01732017-05-15 16:34:52 -0700585 return "UNKNOWN(" + matchRule + ")";
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700586 }
587 }
588
Jeff Sharkey32566012014-12-02 18:30:14 -0800589 /**
590 * Examine the given template and normalize if it refers to a "merged"
591 * mobile subscriber. We pick the "lowest" merged subscriber as the primary
592 * for key purposes, and expand the template to match all other merged
593 * subscribers.
594 * <p>
595 * For example, given an incoming template matching B, and the currently
596 * active merge set [A,B], we'd return a new template that primarily matches
597 * A, but also matches B.
Malcolm Chen07fcb5b2019-07-02 22:29:35 -0700598 * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
Jeff Sharkey32566012014-12-02 18:30:14 -0800599 */
Mathew Inwood53f089f2018-08-08 14:44:44 +0100600 @UnsupportedAppUsage
Jeff Sharkey32566012014-12-02 18:30:14 -0800601 public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
Malcolm Chen07fcb5b2019-07-02 22:29:35 -0700602 return normalize(template, Arrays.<String[]>asList(merged));
603 }
604
605 /**
606 * Examine the given template and normalize if it refers to a "merged"
607 * mobile subscriber. We pick the "lowest" merged subscriber as the primary
608 * for key purposes, and expand the template to match all other merged
609 * subscribers.
610 *
611 * There can be multiple merged subscriberIds for multi-SIM devices.
612 *
613 * <p>
614 * For example, given an incoming template matching B, and the currently
615 * active merge set [A,B], we'd return a new template that primarily matches
616 * A, but also matches B.
617 */
618 public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
619 if (!template.isMatchRuleMobile()) return template;
620
621 for (String[] merged : mergedList) {
622 if (ArrayUtils.contains(merged, template.mSubscriberId)) {
623 // Requested template subscriber is part of the merge group; return
624 // a template that matches all merged subscribers.
625 return new NetworkTemplate(template.mMatchRule, merged[0], merged,
626 template.mNetworkId);
627 }
Jeff Sharkey32566012014-12-02 18:30:14 -0800628 }
Malcolm Chen07fcb5b2019-07-02 22:29:35 -0700629
630 return template;
Jeff Sharkey32566012014-12-02 18:30:14 -0800631 }
632
Mathew Inwood53f089f2018-08-08 14:44:44 +0100633 @UnsupportedAppUsage
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700634 public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700635 @Override
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700636 public NetworkTemplate createFromParcel(Parcel in) {
637 return new NetworkTemplate(in);
638 }
639
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700640 @Override
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700641 public NetworkTemplate[] newArray(int size) {
642 return new NetworkTemplate[size];
643 }
644 };
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000645
646 public byte[] getBytesForBackup() throws IOException {
647 ByteArrayOutputStream baos = new ByteArrayOutputStream();
648 DataOutputStream out = new DataOutputStream(baos);
649
650 out.writeInt(BACKUP_VERSION);
651
652 out.writeInt(mMatchRule);
653 BackupUtils.writeString(out, mSubscriberId);
654 BackupUtils.writeString(out, mNetworkId);
655
656 return baos.toByteArray();
657 }
658
659 public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
660 throws IOException, BackupUtils.BadVersionException {
661 int version = in.readInt();
662 if (version < 1 || version > BACKUP_VERSION) {
663 throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
664 }
665
666 int matchRule = in.readInt();
667 String subscriberId = BackupUtils.readString(in);
668 String networkId = BackupUtils.readString(in);
669
Christopher Tate3bf01732017-05-15 16:34:52 -0700670 if (!isKnownMatchRule(matchRule)) {
671 throw new BackupUtils.BadVersionException(
672 "Restored network template contains unknown match rule " + matchRule);
673 }
674
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000675 return new NetworkTemplate(matchRule, subscriberId, networkId);
676 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700677}