blob: f7a7c49730cf07b0c0ed3750a63fdaacb9425db8 [file] [log] [blame]
Jeff Sharkeyd2a45872011-05-28 20:56:34 -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 com.android.server.net;
18
19import static android.net.ConnectivityManager.TYPE_WIFI;
20import static android.net.ConnectivityManager.TYPE_WIMAX;
21import static android.net.ConnectivityManager.isNetworkTypeMobile;
22import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
23import static android.net.TrafficStats.TEMPLATE_MOBILE_4G;
24import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
25import static android.net.TrafficStats.TEMPLATE_WIFI;
26import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
27import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
28import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
29import static android.telephony.TelephonyManager.getNetworkClass;
30
31import android.content.Context;
32import android.net.ConnectivityManager;
33import android.net.NetworkInfo;
34import android.net.NetworkState;
35import android.telephony.TelephonyManager;
36
37import com.android.internal.util.Objects;
38
39import java.io.DataInputStream;
40import java.io.DataOutputStream;
41import java.io.IOException;
42import java.net.ProtocolException;
43
44/**
45 * Identity of a {@link NetworkInfo}, defined by network type and billing
46 * relationship (such as IMSI).
47 *
48 * @hide
49 */
50public class NetworkIdentity {
51 private static final int VERSION_CURRENT = 1;
52
53 public final int type;
54 public final int subType;
55 public final String subscriberId;
56
57 public NetworkIdentity(int type, int subType, String subscriberId) {
58 this.type = type;
59 this.subType = subType;
60 this.subscriberId = subscriberId;
61 }
62
63 public NetworkIdentity(DataInputStream in) throws IOException {
64 final int version = in.readInt();
65 switch (version) {
66 case VERSION_CURRENT: {
67 type = in.readInt();
68 subType = in.readInt();
Jeff Sharkey3f391352011-06-05 17:42:53 -070069 subscriberId = readOptionalString(in);
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070070 break;
71 }
72 default: {
73 throw new ProtocolException("unexpected version: " + version);
74 }
75 }
76 }
77
78 public void writeToStream(DataOutputStream out) throws IOException {
79 out.writeInt(VERSION_CURRENT);
80 out.writeInt(type);
81 out.writeInt(subType);
Jeff Sharkey3f391352011-06-05 17:42:53 -070082 writeOptionalString(out, subscriberId);
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070083 }
84
85 @Override
86 public int hashCode() {
87 return Objects.hashCode(type, subType, subscriberId);
88 }
89
90 @Override
91 public boolean equals(Object obj) {
92 if (obj instanceof NetworkIdentity) {
93 final NetworkIdentity ident = (NetworkIdentity) obj;
94 return type == ident.type && subType == ident.subType
95 && Objects.equal(subscriberId, ident.subscriberId);
96 }
97 return false;
98 }
99
100 @Override
101 public String toString() {
102 final String typeName = ConnectivityManager.getNetworkTypeName(type);
103 final String subTypeName;
104 if (ConnectivityManager.isNetworkTypeMobile(type)) {
105 subTypeName = TelephonyManager.getNetworkTypeName(subType);
106 } else {
107 subTypeName = Integer.toString(subType);
108 }
109
110 return "[type=" + typeName + ", subType=" + subTypeName + ", subId=" + subscriberId + "]";
111 }
112
113 /**
114 * Test if this network matches the given template and IMEI.
115 */
116 public boolean matchesTemplate(int networkTemplate, String subscriberId) {
117 switch (networkTemplate) {
118 case TEMPLATE_MOBILE_ALL:
119 return matchesMobile(subscriberId);
120 case TEMPLATE_MOBILE_3G_LOWER:
121 return matchesMobile3gLower(subscriberId);
122 case TEMPLATE_MOBILE_4G:
123 return matchesMobile4g(subscriberId);
124 case TEMPLATE_WIFI:
125 return matchesWifi();
126 default:
127 throw new IllegalArgumentException("unknown network template");
128 }
129 }
130
131 /**
132 * Check if mobile network with matching IMEI. Also matches
133 * {@link #TYPE_WIMAX}.
134 */
135 private boolean matchesMobile(String subscriberId) {
136 if (isNetworkTypeMobile(type) && Objects.equal(this.subscriberId, subscriberId)) {
137 return true;
138 } else if (type == TYPE_WIMAX) {
139 return true;
140 }
141 return false;
142 }
143
144 /**
145 * Check if mobile network classified 3G or lower with matching IMEI.
146 */
147 private boolean matchesMobile3gLower(String subscriberId) {
148 if (isNetworkTypeMobile(type)
149 && Objects.equal(this.subscriberId, subscriberId)) {
150 switch (getNetworkClass(subType)) {
151 case NETWORK_CLASS_2_G:
152 case NETWORK_CLASS_3_G:
153 return true;
154 }
155 }
156 return false;
157 }
158
159 /**
160 * Check if mobile network classified 4G with matching IMEI. Also matches
161 * {@link #TYPE_WIMAX}.
162 */
163 private boolean matchesMobile4g(String subscriberId) {
164 if (isNetworkTypeMobile(type)
165 && Objects.equal(this.subscriberId, subscriberId)) {
166 switch (getNetworkClass(subType)) {
167 case NETWORK_CLASS_4_G:
168 return true;
169 }
170 } else if (type == TYPE_WIMAX) {
171 return true;
172 }
173 return false;
174 }
175
176 /**
177 * Check if matches Wi-Fi network template.
178 */
179 private boolean matchesWifi() {
180 if (type == TYPE_WIFI) {
181 return true;
182 }
183 return false;
184 }
185
186 /**
187 * Build a {@link NetworkIdentity} from the given {@link NetworkState},
188 * assuming that any mobile networks are using the current IMSI.
189 */
190 public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
191 final int type = state.networkInfo.getType();
192 final int subType = state.networkInfo.getSubtype();
193
194 // TODO: consider moving subscriberId over to LinkCapabilities, so it
195 // comes from an authoritative source.
196
197 final String subscriberId;
198 if (isNetworkTypeMobile(type)) {
199 final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
200 Context.TELEPHONY_SERVICE);
201 subscriberId = telephony.getSubscriberId();
202 } else {
203 subscriberId = null;
204 }
205 return new NetworkIdentity(type, subType, subscriberId);
206 }
207
Jeff Sharkey3f391352011-06-05 17:42:53 -0700208 private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
209 if (value != null) {
210 out.writeByte(1);
211 out.writeUTF(value);
212 } else {
213 out.writeByte(0);
214 }
215 }
216
217 private static String readOptionalString(DataInputStream in) throws IOException {
218 if (in.readByte() != 0) {
219 return in.readUTF();
220 } else {
221 return null;
222 }
223 }
224
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700225}