1 /*
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 
17 package android.net;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 import static android.net.ConnectivityManager.TYPE_MOBILE;
21 import static android.net.ConnectivityManager.TYPE_WIFI;
22 import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
23 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.SuppressLint;
29 import android.annotation.SystemApi;
30 import android.app.usage.NetworkStatsManager;
31 import android.content.Context;
32 import android.net.wifi.WifiInfo;
33 import android.service.NetworkIdentityProto;
34 import android.telephony.TelephonyManager;
35 import android.util.Log;
36 import android.util.proto.ProtoOutputStream;
37 
38 import com.android.net.module.util.BitUtils;
39 import com.android.net.module.util.CollectionUtils;
40 import com.android.net.module.util.NetworkIdentityUtils;
41 
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 import java.util.ArrayList;
45 import java.util.Objects;
46 
47 /**
48  * Network definition that includes strong identity. Analogous to combining
49  * {@link NetworkCapabilities} and an IMSI.
50  *
51  * @hide
52  */
53 @SystemApi(client = MODULE_LIBRARIES)
54 public class NetworkIdentity {
55     private static final String TAG = "NetworkIdentity";
56 
57     /** @hide */
58     // TODO: Remove this after migrating all callers to use
59     //  {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
60     public static final int SUBTYPE_COMBINED = -1;
61 
62     /** @hide */
63     @Retention(RetentionPolicy.SOURCE)
64     @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
65             NetworkTemplate.OEM_MANAGED_NO,
66             NetworkTemplate.OEM_MANAGED_PAID,
67             NetworkTemplate.OEM_MANAGED_PRIVATE
68     })
69     public @interface OemManaged{}
70 
71     /**
72      * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
73      * @hide
74      */
75     public static final int OEM_NONE = 0x0;
76     /**
77      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
78      * @hide
79      */
80     public static final int OEM_PAID = 1 << 0;
81     /**
82      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
83      * @hide
84      */
85     public static final int OEM_PRIVATE = 1 << 1;
86 
87     private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
88 
89     // Need to be synchronized with ConnectivityManager.
90     // TODO: Use {@code ConnectivityManager#*} when visible.
91     static final int TYPE_TEST = 18;
92     private static final int MAX_NETWORK_TYPE = TYPE_TEST;
93     private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
94 
95     final int mType;
96     final int mRatType;
97     final int mSubId;
98     final String mSubscriberId;
99     final String mWifiNetworkKey;
100     final boolean mRoaming;
101     final boolean mMetered;
102     final boolean mDefaultNetwork;
103     final int mOemManaged;
104 
105     /** @hide */
NetworkIdentity( int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey, boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId)106     public NetworkIdentity(
107             int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
108             boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) {
109         mType = type;
110         mRatType = ratType;
111         mSubscriberId = subscriberId;
112         mWifiNetworkKey = wifiNetworkKey;
113         mRoaming = roaming;
114         mMetered = metered;
115         mDefaultNetwork = defaultNetwork;
116         mOemManaged = oemManaged;
117         mSubId = subId;
118     }
119 
120     @Override
hashCode()121     public int hashCode() {
122         return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
123                 mDefaultNetwork, mOemManaged, mSubId);
124     }
125 
126     @Override
equals(@ullable Object obj)127     public boolean equals(@Nullable Object obj) {
128         if (obj instanceof NetworkIdentity) {
129             final NetworkIdentity ident = (NetworkIdentity) obj;
130             return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
131                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
132                     && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
133                     && mMetered == ident.mMetered
134                     && mDefaultNetwork == ident.mDefaultNetwork
135                     && mOemManaged == ident.mOemManaged
136                     && mSubId == ident.mSubId;
137         }
138         return false;
139     }
140 
141     @Override
toString()142     public String toString() {
143         final StringBuilder builder = new StringBuilder("{");
144         builder.append("type=").append(mType);
145         builder.append(", ratType=");
146         if (mRatType == NETWORK_TYPE_ALL) {
147             builder.append("COMBINED");
148         } else {
149             builder.append(mRatType);
150         }
151         if (mSubscriberId != null) {
152             builder.append(", subscriberId=")
153                     .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
154         }
155         if (mWifiNetworkKey != null) {
156             builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
157         }
158         if (mRoaming) {
159             builder.append(", ROAMING");
160         }
161         builder.append(", metered=").append(mMetered);
162         builder.append(", defaultNetwork=").append(mDefaultNetwork);
163         builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
164         builder.append(", subId=").append(mSubId);
165         return builder.append("}").toString();
166     }
167 
168     /**
169      * Get the human readable representation of a bitfield representing the OEM managed state of a
170      * network.
171      */
getOemManagedNames(int oemManaged)172     static String getOemManagedNames(int oemManaged) {
173         if (oemManaged == OEM_NONE) {
174             return "OEM_NONE";
175         }
176         final int[] bitPositions = BitUtils.unpackBits(oemManaged);
177         final ArrayList<String> oemManagedNames = new ArrayList<String>();
178         for (int position : bitPositions) {
179             oemManagedNames.add(nameOfOemManaged(1 << position));
180         }
181         return String.join(",", oemManagedNames);
182     }
183 
nameOfOemManaged(int oemManagedBit)184     private static String nameOfOemManaged(int oemManagedBit) {
185         switch (oemManagedBit) {
186             case OEM_PAID:
187                 return "OEM_PAID";
188             case OEM_PRIVATE:
189                 return "OEM_PRIVATE";
190             default:
191                 return "Invalid(" + oemManagedBit + ")";
192         }
193     }
194 
195     /** @hide */
dumpDebug(ProtoOutputStream proto, long tag)196     public void dumpDebug(ProtoOutputStream proto, long tag) {
197         final long start = proto.start(tag);
198 
199         proto.write(NetworkIdentityProto.TYPE, mType);
200 
201         // TODO: dump mRatType as well.
202 
203         proto.write(NetworkIdentityProto.ROAMING, mRoaming);
204         proto.write(NetworkIdentityProto.METERED, mMetered);
205         proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
206         proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged);
207 
208         proto.end(start);
209     }
210 
211     /** Get the network type of this instance. */
getType()212     public int getType() {
213         return mType;
214     }
215 
216     /** Get the Radio Access Technology(RAT) type of this instance. */
getRatType()217     public int getRatType() {
218         return mRatType;
219     }
220 
221     /** Get the Subscriber Id of this instance. */
222     @Nullable
getSubscriberId()223     public String getSubscriberId() {
224         return mSubscriberId;
225     }
226 
227     /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
228     @Nullable
getWifiNetworkKey()229     public String getWifiNetworkKey() {
230         return mWifiNetworkKey;
231     }
232 
233     /** @hide */
234     // TODO: Remove this function after all callers are removed.
getRoaming()235     public boolean getRoaming() {
236         return mRoaming;
237     }
238 
239     /** Return whether this network is roaming. */
isRoaming()240     public boolean isRoaming() {
241         return mRoaming;
242     }
243 
244     /** @hide */
245     // TODO: Remove this function after all callers are removed.
getMetered()246     public boolean getMetered() {
247         return mMetered;
248     }
249 
250     /** Return whether this network is metered. */
isMetered()251     public boolean isMetered() {
252         return mMetered;
253     }
254 
255     /** @hide */
256     // TODO: Remove this function after all callers are removed.
getDefaultNetwork()257     public boolean getDefaultNetwork() {
258         return mDefaultNetwork;
259     }
260 
261     /** Return whether this network is the default network. */
isDefaultNetwork()262     public boolean isDefaultNetwork() {
263         return mDefaultNetwork;
264     }
265 
266     /** Get the OEM managed type of this instance. */
getOemManaged()267     public int getOemManaged() {
268         return mOemManaged;
269     }
270 
271     /** Get the SubId of this instance. */
getSubId()272     public int getSubId() {
273         return mSubId;
274     }
275 
276     /**
277      * Assemble a {@link NetworkIdentity} from the passed arguments.
278      *
279      * This methods builds an identity based on the capabilities of the network in the
280      * snapshot and other passed arguments. The identity is used as a key to record data usage.
281      *
282      * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
283      * @param defaultNetwork whether the network is a default network.
284      * @param ratType the Radio Access Technology(RAT) type of the network. Or
285      *                {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
286      *                See {@code TelephonyManager.NETWORK_TYPE_*}.
287      * @hide
288      * @deprecated See {@link NetworkIdentity.Builder}.
289      */
290     // TODO: Remove this after all callers are migrated to use new Api.
291     @Deprecated
292     @NonNull
buildNetworkIdentity(Context context, @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType)293     public static NetworkIdentity buildNetworkIdentity(Context context,
294             @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
295         final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
296                 .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork)
297                 .setSubId(snapshot.getSubId());
298         if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
299             builder.setRatType(ratType);
300         }
301         return builder.build();
302     }
303 
304     /**
305      * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
306      * @hide
307      */
getOemBitfield(@onNull NetworkCapabilities nc)308     public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
309         int oemManaged = OEM_NONE;
310 
311         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
312             oemManaged |= OEM_PAID;
313         }
314         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
315             oemManaged |= OEM_PRIVATE;
316         }
317 
318         return oemManaged;
319     }
320 
321     /** @hide */
compare(@onNull NetworkIdentity left, @NonNull NetworkIdentity right)322     public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
323         Objects.requireNonNull(right);
324         int res = Integer.compare(left.mType, right.mType);
325         if (res == 0) {
326             res = Integer.compare(left.mRatType, right.mRatType);
327         }
328         if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
329             res = left.mSubscriberId.compareTo(right.mSubscriberId);
330         }
331         if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
332             res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
333         }
334         if (res == 0) {
335             res = Boolean.compare(left.mRoaming, right.mRoaming);
336         }
337         if (res == 0) {
338             res = Boolean.compare(left.mMetered, right.mMetered);
339         }
340         if (res == 0) {
341             res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
342         }
343         if (res == 0) {
344             res = Integer.compare(left.mOemManaged, right.mOemManaged);
345         }
346         if (res == 0) {
347             res = Integer.compare(left.mSubId, right.mSubId);
348         }
349         return res;
350     }
351 
352     /**
353      * Builder class for {@link NetworkIdentity}.
354      */
355     public static final class Builder {
356         private int mType;
357         private int mRatType;
358         private String mSubscriberId;
359         private String mWifiNetworkKey;
360         private boolean mRoaming;
361         private boolean mMetered;
362         private boolean mDefaultNetwork;
363         private int mOemManaged;
364         private int mSubId;
365 
366         /**
367          * Creates a new Builder.
368          */
Builder()369         public Builder() {
370             // Initialize with default values. Will be overwritten by setters.
371             mType = ConnectivityManager.TYPE_NONE;
372             mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
373             mSubscriberId = null;
374             mWifiNetworkKey = null;
375             mRoaming = false;
376             mMetered = false;
377             mDefaultNetwork = false;
378             mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
379             mSubId = INVALID_SUBSCRIPTION_ID;
380         }
381 
382         /**
383          * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
384          * This is a useful shorthand that will read from the snapshot and set the
385          * following fields, if they are set in the snapshot :
386          *  - type
387          *  - subscriberId
388          *  - roaming
389          *  - metered
390          *  - oemManaged
391          *  - wifiNetworkKey
392          *
393          * @param snapshot The target {@link NetworkStateSnapshot} object.
394          * @return The builder object.
395          */
396         @SuppressLint("MissingGetterMatchingBuilder")
397         @NonNull
setNetworkStateSnapshot(@onNull NetworkStateSnapshot snapshot)398         public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
399             setType(snapshot.getLegacyType());
400 
401             setSubscriberId(snapshot.getSubscriberId());
402             setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
403                     NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
404             setMetered(!snapshot.getNetworkCapabilities().hasCapability(
405                     NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
406 
407             setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
408 
409             if (mType == TYPE_WIFI) {
410                 final NetworkCapabilities nc = snapshot.getNetworkCapabilities();
411                 final TransportInfo transportInfo = nc.getTransportInfo();
412                 if (transportInfo instanceof WifiInfo) {
413                     final WifiInfo info = (WifiInfo) transportInfo;
414                     // Log.wtf to catch trying to set a null wifiNetworkKey into NetworkIdentity.
415                     // See b/266598304. The problematic data that has null wifi network key is
416                     // thrown out when storing data, which is handled by the service.
417                     if (info.getNetworkKey() == null) {
418                         Log.wtf(TAG, "WifiInfo contains a null wifiNetworkKey and it will"
419                                 + " be set into NetworkIdentity, netId=" + snapshot.getNetwork()
420                                 + "NetworkCapabilities=" + nc);
421                     }
422                     setWifiNetworkKey(info.getNetworkKey());
423                 }
424             } else if (mType == TYPE_TEST) {
425                 final NetworkSpecifier ns = snapshot.getNetworkCapabilities().getNetworkSpecifier();
426                 if (ns instanceof TestNetworkSpecifier) {
427                     // Reuse the wifi network key field to identify individual test networks.
428                     setWifiNetworkKey(((TestNetworkSpecifier) ns).getInterfaceName());
429                 }
430             }
431             return this;
432         }
433 
434         /**
435          * Set the network type of the network.
436          *
437          * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
438          *
439          * @return this builder.
440          */
441         @NonNull
setType(int type)442         public Builder setType(int type) {
443             // Include TYPE_NONE for compatibility, type field might not be filled by some
444             // networks such as test networks.
445             if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
446                     && type != ConnectivityManager.TYPE_NONE) {
447                 throw new IllegalArgumentException("Invalid network type: " + type);
448             }
449             mType = type;
450             return this;
451         }
452 
453         /**
454          * Set the Radio Access Technology(RAT) type of the network.
455          *
456          * No RAT type is specified by default. Call clearRatType to reset.
457          *
458          * @param ratType the Radio Access Technology(RAT) type if applicable. See
459          *                {@code TelephonyManager.NETWORK_TYPE_*}.
460          *
461          * @return this builder.
462          */
463         @NonNull
setRatType(int ratType)464         public Builder setRatType(int ratType) {
465             if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
466                     && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
467                     && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) {
468                 throw new IllegalArgumentException("Invalid ratType " + ratType);
469             }
470             mRatType = ratType;
471             return this;
472         }
473 
474         /**
475          * Clear the Radio Access Technology(RAT) type of the network.
476          *
477          * @return this builder.
478          */
479         @NonNull
clearRatType()480         public Builder clearRatType() {
481             mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
482             return this;
483         }
484 
485         /**
486          * Set the Subscriber Id.
487          *
488          * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
489          * @return this builder.
490          */
491         @NonNull
setSubscriberId(@ullable String subscriberId)492         public Builder setSubscriberId(@Nullable String subscriberId) {
493             mSubscriberId = subscriberId;
494             return this;
495         }
496 
497         /**
498          * Set the Wifi Network Key.
499          *
500          * @param wifiNetworkKey Wifi Network Key of the network,
501          *                        see {@link WifiInfo#getNetworkKey()}.
502          *                        Or null if not applicable.
503          * @return this builder.
504          */
505         @NonNull
setWifiNetworkKey(@ullable String wifiNetworkKey)506         public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
507             mWifiNetworkKey = wifiNetworkKey;
508             return this;
509         }
510 
511         /**
512          * Set whether this network is roaming.
513          *
514          * This field is false by default. Call with false to reset.
515          *
516          * @param roaming the roaming status of the network.
517          * @return this builder.
518          */
519         @NonNull
setRoaming(boolean roaming)520         public Builder setRoaming(boolean roaming) {
521             mRoaming = roaming;
522             return this;
523         }
524 
525         /**
526          * Set whether this network is metered.
527          *
528          * This field is false by default. Call with false to reset.
529          *
530          * @param metered the meteredness of the network.
531          * @return this builder.
532          */
533         @NonNull
setMetered(boolean metered)534         public Builder setMetered(boolean metered) {
535             mMetered = metered;
536             return this;
537         }
538 
539         /**
540          * Set whether this network is the default network.
541          *
542          * This field is false by default. Call with false to reset.
543          *
544          * @param defaultNetwork the default network status of the network.
545          * @return this builder.
546          */
547         @NonNull
setDefaultNetwork(boolean defaultNetwork)548         public Builder setDefaultNetwork(boolean defaultNetwork) {
549             mDefaultNetwork = defaultNetwork;
550             return this;
551         }
552 
553         /**
554          * Set the OEM managed type.
555          *
556          * @param oemManaged Type of OEM managed network or unmanaged networks.
557          *                   See {@code NetworkTemplate#OEM_MANAGED_*}.
558          * @return this builder.
559          */
560         @NonNull
setOemManaged(@emManaged int oemManaged)561         public Builder setOemManaged(@OemManaged int oemManaged) {
562             // Assert input does not contain illegal oemManage bits.
563             if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
564                 throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
565             }
566             mOemManaged = oemManaged;
567             return this;
568         }
569 
570         /**
571          * Set the Subscription Id.
572          *
573          * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not
574          *              applicable.
575          * @return this builder.
576          */
577         @NonNull
setSubId(int subId)578         public Builder setSubId(int subId) {
579             mSubId = subId;
580             return this;
581         }
582 
ensureValidParameters()583         private void ensureValidParameters() {
584             // Assert non-mobile network cannot have a ratType.
585             if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
586                 throw new IllegalArgumentException(
587                         "Invalid ratType " + mRatType + " for type " + mType);
588             }
589 
590             // Assert non-wifi network cannot have a wifi network key.
591             if (mType != TYPE_WIFI && mType != TYPE_TEST && mWifiNetworkKey != null) {
592                 throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
593             }
594         }
595 
596         /**
597          * Builds the instance of the {@link NetworkIdentity}.
598          *
599          * @return the built instance of {@link NetworkIdentity}.
600          */
601         @NonNull
build()602         public NetworkIdentity build() {
603             ensureValidParameters();
604             return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
605                     mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId);
606         }
607     }
608 }
609