2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.net.ProxyProperties;
20 import android.os.Parcelable;
21 import android.os.Parcel;
22 import android.text.TextUtils;
24 import java.net.InetAddress;
25 import java.net.UnknownHostException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
31 * Describes the properties of a network link.
33 * A link represents a connection to a network.
34 * It may have multiple addresses and multiple gateways,
35 * multiple dns servers but only one http proxy.
37 * Because it's a single network, the dns's
38 * are interchangeable and don't need associating with
39 * particular addresses. The gateways similarly don't
40 * need associating with particular addresses.
42 * A dual stack interface works fine in this model:
43 * each address has it's own prefix length to describe
44 * the local network. The dns servers all return
45 * both v4 addresses and v6 addresses regardless of the
46 * address family of the server itself (rfc4213) and we
47 * don't care which is used. The gateways will be
48 * selected based on the destination address and the
49 * source address has no relavence.
52 public class LinkProperties implements Parcelable {
55 private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
56 private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
57 private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
58 private ProxyProperties mHttpProxy;
60 public static class CompareAddressesResult {
61 public ArrayList<LinkAddress> removed = new ArrayList<LinkAddress>();
62 public ArrayList<LinkAddress> added = new ArrayList<LinkAddress>();
65 public String toString() {
66 String retVal = "removedAddresses=[";
67 for (LinkAddress addr : removed) retVal += addr.toString() + ",";
68 retVal += "] addedAddresses=[";
69 for (LinkAddress addr : added) retVal += addr.toString() + ",";
75 public LinkProperties() {
79 // copy constructor instead of clone
80 public LinkProperties(LinkProperties source) {
82 mIfaceName = source.getInterfaceName();
83 mLinkAddresses = source.getLinkAddresses();
84 mDnses = source.getDnses();
85 mRoutes = source.getRoutes();
86 mHttpProxy = (source.getHttpProxy() == null) ?
87 null : new ProxyProperties(source.getHttpProxy());
91 public void setInterfaceName(String iface) {
95 public String getInterfaceName() {
99 public Collection<InetAddress> getAddresses() {
100 Collection<InetAddress> addresses = new ArrayList<InetAddress>();
101 for (LinkAddress linkAddress : mLinkAddresses) {
102 addresses.add(linkAddress.getAddress());
104 return Collections.unmodifiableCollection(addresses);
107 public void addLinkAddress(LinkAddress address) {
108 if (address != null) mLinkAddresses.add(address);
111 public Collection<LinkAddress> getLinkAddresses() {
112 return Collections.unmodifiableCollection(mLinkAddresses);
115 public void addDns(InetAddress dns) {
116 if (dns != null) mDnses.add(dns);
119 public Collection<InetAddress> getDnses() {
120 return Collections.unmodifiableCollection(mDnses);
123 public void addRoute(RouteInfo route) {
124 if (route != null) mRoutes.add(route);
126 public Collection<RouteInfo> getRoutes() {
127 return Collections.unmodifiableCollection(mRoutes);
130 public void setHttpProxy(ProxyProperties proxy) {
133 public ProxyProperties getHttpProxy() {
137 public void clear() {
139 mLinkAddresses.clear();
146 * Implement the Parcelable interface
149 public int describeContents() {
154 public String toString() {
155 String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
157 String linkAddresses = "LinkAddresses: [";
158 for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
159 linkAddresses += "] ";
161 String dns = "DnsAddresses: [";
162 for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
165 String routes = "Routes: [";
166 for (RouteInfo route : mRoutes) routes += route.toString() + ",";
168 String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
170 return ifaceName + linkAddresses + routes + dns + proxy;
174 * Compares this {@code LinkProperties} interface name against the target
176 * @param target LinkProperties to compare.
177 * @return {@code true} if both are identical, {@code false} otherwise.
179 public boolean isIdenticalInterfaceName(LinkProperties target) {
180 return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
184 * Compares this {@code LinkProperties} interface name against the target
186 * @param target LinkProperties to compare.
187 * @return {@code true} if both are identical, {@code false} otherwise.
189 public boolean isIdenticalAddresses(LinkProperties target) {
190 Collection<InetAddress> targetAddresses = target.getAddresses();
191 Collection<InetAddress> sourceAddresses = getAddresses();
192 return (sourceAddresses.size() == targetAddresses.size()) ?
193 sourceAddresses.containsAll(targetAddresses) : false;
197 * Compares this {@code LinkProperties} DNS addresses against the target
199 * @param target LinkProperties to compare.
200 * @return {@code true} if both are identical, {@code false} otherwise.
202 public boolean isIdenticalDnses(LinkProperties target) {
203 Collection<InetAddress> targetDnses = target.getDnses();
204 return (mDnses.size() == targetDnses.size()) ?
205 mDnses.containsAll(targetDnses) : false;
209 * Compares this {@code LinkProperties} Routes against the target
211 * @param target LinkProperties to compare.
212 * @return {@code true} if both are identical, {@code false} otherwise.
214 public boolean isIdenticalRoutes(LinkProperties target) {
215 Collection<RouteInfo> targetRoutes = target.getRoutes();
216 return (mRoutes.size() == targetRoutes.size()) ?
217 mRoutes.containsAll(targetRoutes) : false;
221 * Compares this {@code LinkProperties} HttpProxy against the target
223 * @param target LinkProperties to compare.
224 * @return {@code true} if both are identical, {@code false} otherwise.
226 public boolean isIdenticalHttpProxy(LinkProperties target) {
227 return getHttpProxy() == null ? target.getHttpProxy() == null :
228 getHttpProxy().equals(target.getHttpProxy());
233 * Compares this {@code LinkProperties} instance against the target
234 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
235 * all their fields are equal in values.
237 * For collection fields, such as mDnses, containsAll() is used to check
238 * if two collections contains the same elements, independent of order.
239 * There are two thoughts regarding containsAll()
240 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
241 * 2. Worst case performance is O(n^2).
243 * @param obj the object to be tested for equality.
244 * @return {@code true} if both objects are equal, {@code false} otherwise.
246 public boolean equals(Object obj) {
247 if (this == obj) return true;
249 if (!(obj instanceof LinkProperties)) return false;
251 LinkProperties target = (LinkProperties) obj;
253 return isIdenticalInterfaceName(target) &&
254 isIdenticalAddresses(target) &&
255 isIdenticalDnses(target) &&
256 isIdenticalRoutes(target) &&
257 isIdenticalHttpProxy(target);
261 * Return two lists, a list of addresses that would be removed from
262 * mLinkAddresses and a list of addresses that would be added to
263 * mLinkAddress which would then result in target and mLinkAddresses
264 * being the same list.
266 * @param target is a new list of addresses
267 * @return the removed and added lists.
269 public CompareAddressesResult compareAddresses(LinkProperties target) {
271 * Duplicate the LinkAddresses into removed, we will be removing
272 * address which are common between mLinkAddresses and target
273 * leaving the addresses that are different. And address which
274 * are in target but not in mLinkAddresses are placed in the
277 CompareAddressesResult result = new CompareAddressesResult();
278 result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
279 result.added.clear();
280 for (LinkAddress newAddress : target.getLinkAddresses()) {
281 if (! result.removed.remove(newAddress)) {
282 result.added.add(newAddress);
290 * generate hashcode based on significant fields
291 * Equal objects must produce the same hash code, while unequal objects
292 * may have the same hash codes.
294 public int hashCode() {
295 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
296 + mLinkAddresses.size() * 31
298 + mRoutes.size() * 41
299 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
303 * Implement the Parcelable interface.
306 public void writeToParcel(Parcel dest, int flags) {
307 dest.writeString(getInterfaceName());
308 dest.writeInt(mLinkAddresses.size());
309 for(LinkAddress linkAddress : mLinkAddresses) {
310 dest.writeParcelable(linkAddress, flags);
313 dest.writeInt(mDnses.size());
314 for(InetAddress d : mDnses) {
315 dest.writeByteArray(d.getAddress());
318 dest.writeInt(mRoutes.size());
319 for(RouteInfo route : mRoutes) {
320 dest.writeParcelable(route, flags);
323 if (mHttpProxy != null) {
324 dest.writeByte((byte)1);
325 dest.writeParcelable(mHttpProxy, flags);
327 dest.writeByte((byte)0);
332 * Implement the Parcelable interface.
335 public static final Creator<LinkProperties> CREATOR =
336 new Creator<LinkProperties>() {
337 public LinkProperties createFromParcel(Parcel in) {
338 LinkProperties netProp = new LinkProperties();
339 String iface = in.readString();
342 netProp.setInterfaceName(iface);
343 } catch (Exception e) {
347 int addressCount = in.readInt();
348 for (int i=0; i<addressCount; i++) {
349 netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
351 addressCount = in.readInt();
352 for (int i=0; i<addressCount; i++) {
354 netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
355 } catch (UnknownHostException e) { }
357 addressCount = in.readInt();
358 for (int i=0; i<addressCount; i++) {
359 netProp.addRoute((RouteInfo)in.readParcelable(null));
361 if (in.readByte() == 1) {
362 netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
367 public LinkProperties[] newArray(int size) {
368 return new LinkProperties[size];