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.net.ConnectivityManager.TYPE_WIFI;
20 
21 import android.annotation.Nullable;
22 import android.content.Context;
23 import android.net.wifi.WifiInfo;
24 import android.net.wifi.WifiManager;
25 import android.service.NetworkIdentityProto;
26 import android.telephony.Annotation.NetworkType;
27 import android.util.proto.ProtoOutputStream;
28 
29 import com.android.net.module.util.NetworkIdentityUtils;
30 
31 import java.util.Objects;
32 
33 /**
34  * Network definition that includes strong identity. Analogous to combining
35  * {@link NetworkCapabilities} and an IMSI.
36  *
37  * @hide
38  */
39 public class NetworkIdentity implements Comparable<NetworkIdentity> {
40     private static final String TAG = "NetworkIdentity";
41 
42     public static final int SUBTYPE_COMBINED = -1;
43 
44     /**
45      * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
46      * @hide
47      */
48     public static final int OEM_NONE = 0x0;
49     /**
50      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
51      * @hide
52      */
53     public static final int OEM_PAID = 0x1;
54     /**
55      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
56      * @hide
57      */
58     public static final int OEM_PRIVATE = 0x2;
59 
60     final int mType;
61     final int mSubType;
62     final String mSubscriberId;
63     final String mNetworkId;
64     final boolean mRoaming;
65     final boolean mMetered;
66     final boolean mDefaultNetwork;
67     final int mOemManaged;
68 
NetworkIdentity( int type, int subType, String subscriberId, String networkId, boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged)69     public NetworkIdentity(
70             int type, int subType, String subscriberId, String networkId, boolean roaming,
71             boolean metered, boolean defaultNetwork, int oemManaged) {
72         mType = type;
73         mSubType = subType;
74         mSubscriberId = subscriberId;
75         mNetworkId = networkId;
76         mRoaming = roaming;
77         mMetered = metered;
78         mDefaultNetwork = defaultNetwork;
79         mOemManaged = oemManaged;
80     }
81 
82     @Override
hashCode()83     public int hashCode() {
84         return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
85                 mDefaultNetwork, mOemManaged);
86     }
87 
88     @Override
equals(@ullable Object obj)89     public boolean equals(@Nullable Object obj) {
90         if (obj instanceof NetworkIdentity) {
91             final NetworkIdentity ident = (NetworkIdentity) obj;
92             return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
93                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
94                     && Objects.equals(mNetworkId, ident.mNetworkId)
95                     && mMetered == ident.mMetered
96                     && mDefaultNetwork == ident.mDefaultNetwork
97                     && mOemManaged == ident.mOemManaged;
98         }
99         return false;
100     }
101 
102     @Override
toString()103     public String toString() {
104         final StringBuilder builder = new StringBuilder("{");
105         builder.append("type=").append(mType);
106         builder.append(", subType=");
107         if (mSubType == SUBTYPE_COMBINED) {
108             builder.append("COMBINED");
109         } else {
110             builder.append(mSubType);
111         }
112         if (mSubscriberId != null) {
113             builder.append(", subscriberId=")
114                     .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
115         }
116         if (mNetworkId != null) {
117             builder.append(", networkId=").append(mNetworkId);
118         }
119         if (mRoaming) {
120             builder.append(", ROAMING");
121         }
122         builder.append(", metered=").append(mMetered);
123         builder.append(", defaultNetwork=").append(mDefaultNetwork);
124         // TODO(180557699): Print a human readable string for OEM managed state.
125         builder.append(", oemManaged=").append(mOemManaged);
126         return builder.append("}").toString();
127     }
128 
dumpDebug(ProtoOutputStream proto, long tag)129     public void dumpDebug(ProtoOutputStream proto, long tag) {
130         final long start = proto.start(tag);
131 
132         proto.write(NetworkIdentityProto.TYPE, mType);
133 
134         // Not dumping mSubType, subtypes are no longer supported.
135 
136         if (mSubscriberId != null) {
137             proto.write(NetworkIdentityProto.SUBSCRIBER_ID,
138                     NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
139         }
140         proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId);
141         proto.write(NetworkIdentityProto.ROAMING, mRoaming);
142         proto.write(NetworkIdentityProto.METERED, mMetered);
143         proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
144         proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged);
145 
146         proto.end(start);
147     }
148 
getType()149     public int getType() {
150         return mType;
151     }
152 
getSubType()153     public int getSubType() {
154         return mSubType;
155     }
156 
getSubscriberId()157     public String getSubscriberId() {
158         return mSubscriberId;
159     }
160 
getNetworkId()161     public String getNetworkId() {
162         return mNetworkId;
163     }
164 
getRoaming()165     public boolean getRoaming() {
166         return mRoaming;
167     }
168 
getMetered()169     public boolean getMetered() {
170         return mMetered;
171     }
172 
getDefaultNetwork()173     public boolean getDefaultNetwork() {
174         return mDefaultNetwork;
175     }
176 
getOemManaged()177     public int getOemManaged() {
178         return mOemManaged;
179     }
180 
181     /**
182      * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and
183      * {@code subType}, assuming that any mobile networks are using the current IMSI.
184      * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_*
185      * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
186      */
buildNetworkIdentity(Context context, NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType)187     public static NetworkIdentity buildNetworkIdentity(Context context,
188             NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) {
189         final int legacyType = snapshot.getLegacyType();
190 
191         final String subscriberId = snapshot.getSubscriberId();
192         String networkId = null;
193         boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
194                 NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
195         boolean metered = !snapshot.getNetworkCapabilities().hasCapability(
196                 NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
197 
198         final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
199 
200         if (legacyType == TYPE_WIFI) {
201             networkId = snapshot.getNetworkCapabilities().getSsid();
202             if (networkId == null) {
203                 final WifiManager wifi = context.getSystemService(WifiManager.class);
204                 final WifiInfo info = wifi.getConnectionInfo();
205                 networkId = info != null ? info.getSSID() : null;
206             }
207         }
208 
209         return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered,
210                 defaultNetwork, oemManaged);
211     }
212 
213     /**
214      * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
215      * @hide
216      */
getOemBitfield(NetworkCapabilities nc)217     public static int getOemBitfield(NetworkCapabilities nc) {
218         int oemManaged = OEM_NONE;
219 
220         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
221             oemManaged |= OEM_PAID;
222         }
223         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
224             oemManaged |= OEM_PRIVATE;
225         }
226 
227         return oemManaged;
228     }
229 
230     @Override
compareTo(NetworkIdentity another)231     public int compareTo(NetworkIdentity another) {
232         int res = Integer.compare(mType, another.mType);
233         if (res == 0) {
234             res = Integer.compare(mSubType, another.mSubType);
235         }
236         if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
237             res = mSubscriberId.compareTo(another.mSubscriberId);
238         }
239         if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
240             res = mNetworkId.compareTo(another.mNetworkId);
241         }
242         if (res == 0) {
243             res = Boolean.compare(mRoaming, another.mRoaming);
244         }
245         if (res == 0) {
246             res = Boolean.compare(mMetered, another.mMetered);
247         }
248         if (res == 0) {
249             res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
250         }
251         if (res == 0) {
252             res = Integer.compare(mOemManaged, another.mOemManaged);
253         }
254         return res;
255     }
256 }
257