Loading core/java/android/net/LinkProperties.java +22 −1 Original line number Diff line number Diff line Loading @@ -92,6 +92,11 @@ public class LinkProperties implements Parcelable { public void setInterfaceName(String iface) { mIfaceName = iface; ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size()); for (RouteInfo route : mRoutes) { newRoutes.add(routeWithInterface(route)); } mRoutes = newRoutes; } public String getInterfaceName() { Loading Loading @@ -130,9 +135,25 @@ public class LinkProperties implements Parcelable { mDomains = domains; } private RouteInfo routeWithInterface(RouteInfo route) { return new RouteInfo( route.getDestination(), route.getGateway(), mIfaceName); } public void addRoute(RouteInfo route) { if (route != null) mRoutes.add(route); if (route != null) { String routeIface = route.getInterface(); if (routeIface != null && !routeIface.equals(mIfaceName)) { throw new IllegalStateException( "Route added with non-matching interface: " + routeIface + " vs. mIfaceName"); } mRoutes.add(routeWithInterface(route)); } } public Collection<RouteInfo> getRoutes() { return Collections.unmodifiableCollection(mRoutes); } Loading core/java/android/net/RouteInfo.java +59 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,17 @@ import java.util.Collection; /** * A simple container for route information. * * In order to be used, a route must have a destination prefix and: * * - A gateway address (next-hop, for gatewayed routes), or * - An interface (for directly-connected routes), or * - Both a gateway and an interface. * * This class does not enforce these constraints because there is code that * uses RouteInfo objects to store directly-connected routes without interfaces. * Such objects cannot be used directly, but can be put into a LinkProperties * object which then specifies the interface. * * @hide */ public class RouteInfo implements Parcelable { Loading @@ -42,10 +53,30 @@ public class RouteInfo implements Parcelable { */ private final InetAddress mGateway; /** * The interface for this route. */ private final String mInterface; private final boolean mIsDefault; private final boolean mIsHost; public RouteInfo(LinkAddress destination, InetAddress gateway) { /** * Constructs a RouteInfo object. * * If @destination is null, then @gateway must be specified and the * constructed route is either the IPv4 default route <code>0.0.0.0</code> * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default * route <code>::/0</code> if @gateway is an instance of * {@link Inet6Address}. * * @destination and @gateway may not both be null. * * @param destination the destination prefix * @param gateway the IP address to route packets through * @param iface the interface name to send packets on */ public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) { if (destination == null) { if (gateway != null) { if (gateway instanceof Inet4Address) { Loading @@ -55,7 +86,8 @@ public class RouteInfo implements Parcelable { } } else { // no destination, no gateway. invalid. throw new RuntimeException("Invalid arguments passed in."); throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + destination); } } if (gateway == null) { Loading @@ -68,16 +100,21 @@ public class RouteInfo implements Parcelable { mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(), destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength()); mGateway = gateway; mInterface = iface; mIsDefault = isDefault(); mIsHost = isHost(); } public RouteInfo(LinkAddress destination, InetAddress gateway) { this(destination, gateway, null); } public RouteInfo(InetAddress gateway) { this(null, gateway); this(null, gateway, null); } public RouteInfo(LinkAddress host) { this(host, null); this(host, null, null); } public static RouteInfo makeHostRoute(InetAddress host) { Loading Loading @@ -119,6 +156,10 @@ public class RouteInfo implements Parcelable { return mGateway; } public String getInterface() { return mInterface; } public boolean isDefaultRoute() { return mIsDefault; } Loading Loading @@ -153,6 +194,8 @@ public class RouteInfo implements Parcelable { dest.writeByte((byte) 1); dest.writeByteArray(mGateway.getAddress()); } dest.writeString(mInterface); } @Override Loading @@ -171,14 +214,19 @@ public class RouteInfo implements Parcelable { target.getGateway() == null : mGateway.equals(target.getGateway()); return sameDestination && sameAddress boolean sameInterface = (mInterface == null) ? target.getInterface() == null : mInterface.equals(target.getInterface()); return sameDestination && sameAddress && sameInterface && mIsDefault == target.mIsDefault; } @Override public int hashCode() { return (mDestination == null ? 0 : mDestination.hashCode()) + (mGateway == null ? 0 :mGateway.hashCode()) return (mDestination == null ? 0 : mDestination.hashCode() * 41) + (mGateway == null ? 0 :mGateway.hashCode() * 47) + (mInterface == null ? 0 :mInterface.hashCode() * 67) + (mIsDefault ? 3 : 7); } Loading Loading @@ -206,13 +254,15 @@ public class RouteInfo implements Parcelable { } catch (UnknownHostException e) {} } String iface = in.readString(); LinkAddress dest = null; if (destAddr != null) { dest = new LinkAddress(destAddr, prefix); } return new RouteInfo(dest, gateway); return new RouteInfo(dest, gateway, iface); } public RouteInfo[] newArray(int size) { Loading @@ -220,13 +270,9 @@ public class RouteInfo implements Parcelable { } }; private boolean matches(InetAddress destination) { protected boolean matches(InetAddress destination) { if (destination == null) return false; // if the destination is present and the route is default. // return true if (isDefault()) return true; // match the route destination and destination with prefix length InetAddress dstNet = NetworkUtils.getNetworkPart(destination, mDestination.getNetworkPrefixLength()); Loading core/tests/coretests/src/android/net/RouteInfoTest.java 0 → 100644 +180 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import java.lang.reflect.Method; import java.net.InetAddress; import android.net.LinkAddress; import android.net.RouteInfo; import android.os.Parcel; import junit.framework.TestCase; import android.test.suitebuilder.annotation.SmallTest; public class RouteInfoTest extends TestCase { private InetAddress Address(String addr) { return InetAddress.parseNumericAddress(addr); } private LinkAddress Prefix(String prefix) { String[] parts = prefix.split("/"); return new LinkAddress(Address(parts[0]), Integer.parseInt(parts[1])); } @SmallTest public void testConstructor() { RouteInfo r; // Invalid input. try { r = new RouteInfo(null, null, "rmnet0"); fail("Expected RuntimeException: destination and gateway null"); } catch(RuntimeException e) {} // Null destination is default route. r = new RouteInfo(null, Address("2001:db8::1"), null); assertEquals(Prefix("::/0"), r.getDestination()); assertEquals(Address("2001:db8::1"), r.getGateway()); assertNull(r.getInterface()); r = new RouteInfo(null, Address("192.0.2.1"), "wlan0"); assertEquals(Prefix("0.0.0.0/0"), r.getDestination()); assertEquals(Address("192.0.2.1"), r.getGateway()); assertEquals("wlan0", r.getInterface()); // Null gateway sets gateway to unspecified address (why?). r = new RouteInfo(Prefix("2001:db8:beef:cafe::/48"), null, "lo"); assertEquals(Prefix("2001:db8:beef::/48"), r.getDestination()); assertEquals(Address("::"), r.getGateway()); assertEquals("lo", r.getInterface()); r = new RouteInfo(Prefix("192.0.2.5/24"), null); assertEquals(Prefix("192.0.2.0/24"), r.getDestination()); assertEquals(Address("0.0.0.0"), r.getGateway()); assertNull(r.getInterface()); } public void testMatches() { class PatchedRouteInfo extends RouteInfo { public PatchedRouteInfo(LinkAddress destination, InetAddress gateway, String iface) { super(destination, gateway, iface); } public boolean matches(InetAddress destination) { return super.matches(destination); } } RouteInfo r; r = new PatchedRouteInfo(Prefix("2001:db8:f00::ace:d00d/127"), null, "rmnet0"); assertTrue(r.matches(Address("2001:db8:f00::ace:d00c"))); assertTrue(r.matches(Address("2001:db8:f00::ace:d00d"))); assertFalse(r.matches(Address("2001:db8:f00::ace:d00e"))); assertFalse(r.matches(Address("2001:db8:f00::bad:d00d"))); assertFalse(r.matches(Address("2001:4868:4860::8888"))); r = new PatchedRouteInfo(Prefix("192.0.2.0/23"), null, "wlan0"); assertTrue(r.matches(Address("192.0.2.43"))); assertTrue(r.matches(Address("192.0.3.21"))); assertFalse(r.matches(Address("192.0.0.21"))); assertFalse(r.matches(Address("8.8.8.8"))); RouteInfo ipv6Default = new PatchedRouteInfo(Prefix("::/0"), null, "rmnet0"); assertTrue(ipv6Default.matches(Address("2001:db8::f00"))); assertFalse(ipv6Default.matches(Address("192.0.2.1"))); RouteInfo ipv4Default = new PatchedRouteInfo(Prefix("0.0.0.0/0"), null, "rmnet0"); assertTrue(ipv4Default.matches(Address("255.255.255.255"))); assertTrue(ipv4Default.matches(Address("192.0.2.1"))); assertFalse(ipv4Default.matches(Address("2001:db8::f00"))); } private void assertAreEqual(Object o1, Object o2) { assertTrue(o1.equals(o2)); assertTrue(o2.equals(o1)); } private void assertAreNotEqual(Object o1, Object o2) { assertFalse(o1.equals(o2)); assertFalse(o2.equals(o1)); } public void testEquals() { // IPv4 RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); RouteInfo r2 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); assertAreEqual(r1, r2); RouteInfo r3 = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "wlan0"); RouteInfo r4 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::2"), "wlan0"); RouteInfo r5 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "rmnet0"); assertAreNotEqual(r1, r3); assertAreNotEqual(r1, r4); assertAreNotEqual(r1, r5); // IPv6 r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); assertAreEqual(r1, r2); r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); r4 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.2"), "wlan0"); r5 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "rmnet0"); assertAreNotEqual(r1, r3); assertAreNotEqual(r1, r4); assertAreNotEqual(r1, r5); // Interfaces (but not destinations or gateways) can be null. r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); assertAreEqual(r1, r2); assertAreNotEqual(r1, r3); } public RouteInfo passThroughParcel(RouteInfo r) { Parcel p = Parcel.obtain(); RouteInfo r2 = null; try { r.writeToParcel(p, 0); p.setDataPosition(0); r2 = RouteInfo.CREATOR.createFromParcel(p); } finally { p.recycle(); } assertNotNull(r2); return r2; } public void assertParcelingIsLossless(RouteInfo r) { RouteInfo r2 = passThroughParcel(r); assertEquals(r, r2); } public void testParceling() { RouteInfo r; r = new RouteInfo(Prefix("::/0"), Address("2001:db8::"), null); assertParcelingIsLossless(r); r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); assertParcelingIsLossless(r); } } Loading
core/java/android/net/LinkProperties.java +22 −1 Original line number Diff line number Diff line Loading @@ -92,6 +92,11 @@ public class LinkProperties implements Parcelable { public void setInterfaceName(String iface) { mIfaceName = iface; ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size()); for (RouteInfo route : mRoutes) { newRoutes.add(routeWithInterface(route)); } mRoutes = newRoutes; } public String getInterfaceName() { Loading Loading @@ -130,9 +135,25 @@ public class LinkProperties implements Parcelable { mDomains = domains; } private RouteInfo routeWithInterface(RouteInfo route) { return new RouteInfo( route.getDestination(), route.getGateway(), mIfaceName); } public void addRoute(RouteInfo route) { if (route != null) mRoutes.add(route); if (route != null) { String routeIface = route.getInterface(); if (routeIface != null && !routeIface.equals(mIfaceName)) { throw new IllegalStateException( "Route added with non-matching interface: " + routeIface + " vs. mIfaceName"); } mRoutes.add(routeWithInterface(route)); } } public Collection<RouteInfo> getRoutes() { return Collections.unmodifiableCollection(mRoutes); } Loading
core/java/android/net/RouteInfo.java +59 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,17 @@ import java.util.Collection; /** * A simple container for route information. * * In order to be used, a route must have a destination prefix and: * * - A gateway address (next-hop, for gatewayed routes), or * - An interface (for directly-connected routes), or * - Both a gateway and an interface. * * This class does not enforce these constraints because there is code that * uses RouteInfo objects to store directly-connected routes without interfaces. * Such objects cannot be used directly, but can be put into a LinkProperties * object which then specifies the interface. * * @hide */ public class RouteInfo implements Parcelable { Loading @@ -42,10 +53,30 @@ public class RouteInfo implements Parcelable { */ private final InetAddress mGateway; /** * The interface for this route. */ private final String mInterface; private final boolean mIsDefault; private final boolean mIsHost; public RouteInfo(LinkAddress destination, InetAddress gateway) { /** * Constructs a RouteInfo object. * * If @destination is null, then @gateway must be specified and the * constructed route is either the IPv4 default route <code>0.0.0.0</code> * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default * route <code>::/0</code> if @gateway is an instance of * {@link Inet6Address}. * * @destination and @gateway may not both be null. * * @param destination the destination prefix * @param gateway the IP address to route packets through * @param iface the interface name to send packets on */ public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) { if (destination == null) { if (gateway != null) { if (gateway instanceof Inet4Address) { Loading @@ -55,7 +86,8 @@ public class RouteInfo implements Parcelable { } } else { // no destination, no gateway. invalid. throw new RuntimeException("Invalid arguments passed in."); throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + destination); } } if (gateway == null) { Loading @@ -68,16 +100,21 @@ public class RouteInfo implements Parcelable { mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(), destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength()); mGateway = gateway; mInterface = iface; mIsDefault = isDefault(); mIsHost = isHost(); } public RouteInfo(LinkAddress destination, InetAddress gateway) { this(destination, gateway, null); } public RouteInfo(InetAddress gateway) { this(null, gateway); this(null, gateway, null); } public RouteInfo(LinkAddress host) { this(host, null); this(host, null, null); } public static RouteInfo makeHostRoute(InetAddress host) { Loading Loading @@ -119,6 +156,10 @@ public class RouteInfo implements Parcelable { return mGateway; } public String getInterface() { return mInterface; } public boolean isDefaultRoute() { return mIsDefault; } Loading Loading @@ -153,6 +194,8 @@ public class RouteInfo implements Parcelable { dest.writeByte((byte) 1); dest.writeByteArray(mGateway.getAddress()); } dest.writeString(mInterface); } @Override Loading @@ -171,14 +214,19 @@ public class RouteInfo implements Parcelable { target.getGateway() == null : mGateway.equals(target.getGateway()); return sameDestination && sameAddress boolean sameInterface = (mInterface == null) ? target.getInterface() == null : mInterface.equals(target.getInterface()); return sameDestination && sameAddress && sameInterface && mIsDefault == target.mIsDefault; } @Override public int hashCode() { return (mDestination == null ? 0 : mDestination.hashCode()) + (mGateway == null ? 0 :mGateway.hashCode()) return (mDestination == null ? 0 : mDestination.hashCode() * 41) + (mGateway == null ? 0 :mGateway.hashCode() * 47) + (mInterface == null ? 0 :mInterface.hashCode() * 67) + (mIsDefault ? 3 : 7); } Loading Loading @@ -206,13 +254,15 @@ public class RouteInfo implements Parcelable { } catch (UnknownHostException e) {} } String iface = in.readString(); LinkAddress dest = null; if (destAddr != null) { dest = new LinkAddress(destAddr, prefix); } return new RouteInfo(dest, gateway); return new RouteInfo(dest, gateway, iface); } public RouteInfo[] newArray(int size) { Loading @@ -220,13 +270,9 @@ public class RouteInfo implements Parcelable { } }; private boolean matches(InetAddress destination) { protected boolean matches(InetAddress destination) { if (destination == null) return false; // if the destination is present and the route is default. // return true if (isDefault()) return true; // match the route destination and destination with prefix length InetAddress dstNet = NetworkUtils.getNetworkPart(destination, mDestination.getNetworkPrefixLength()); Loading
core/tests/coretests/src/android/net/RouteInfoTest.java 0 → 100644 +180 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net; import java.lang.reflect.Method; import java.net.InetAddress; import android.net.LinkAddress; import android.net.RouteInfo; import android.os.Parcel; import junit.framework.TestCase; import android.test.suitebuilder.annotation.SmallTest; public class RouteInfoTest extends TestCase { private InetAddress Address(String addr) { return InetAddress.parseNumericAddress(addr); } private LinkAddress Prefix(String prefix) { String[] parts = prefix.split("/"); return new LinkAddress(Address(parts[0]), Integer.parseInt(parts[1])); } @SmallTest public void testConstructor() { RouteInfo r; // Invalid input. try { r = new RouteInfo(null, null, "rmnet0"); fail("Expected RuntimeException: destination and gateway null"); } catch(RuntimeException e) {} // Null destination is default route. r = new RouteInfo(null, Address("2001:db8::1"), null); assertEquals(Prefix("::/0"), r.getDestination()); assertEquals(Address("2001:db8::1"), r.getGateway()); assertNull(r.getInterface()); r = new RouteInfo(null, Address("192.0.2.1"), "wlan0"); assertEquals(Prefix("0.0.0.0/0"), r.getDestination()); assertEquals(Address("192.0.2.1"), r.getGateway()); assertEquals("wlan0", r.getInterface()); // Null gateway sets gateway to unspecified address (why?). r = new RouteInfo(Prefix("2001:db8:beef:cafe::/48"), null, "lo"); assertEquals(Prefix("2001:db8:beef::/48"), r.getDestination()); assertEquals(Address("::"), r.getGateway()); assertEquals("lo", r.getInterface()); r = new RouteInfo(Prefix("192.0.2.5/24"), null); assertEquals(Prefix("192.0.2.0/24"), r.getDestination()); assertEquals(Address("0.0.0.0"), r.getGateway()); assertNull(r.getInterface()); } public void testMatches() { class PatchedRouteInfo extends RouteInfo { public PatchedRouteInfo(LinkAddress destination, InetAddress gateway, String iface) { super(destination, gateway, iface); } public boolean matches(InetAddress destination) { return super.matches(destination); } } RouteInfo r; r = new PatchedRouteInfo(Prefix("2001:db8:f00::ace:d00d/127"), null, "rmnet0"); assertTrue(r.matches(Address("2001:db8:f00::ace:d00c"))); assertTrue(r.matches(Address("2001:db8:f00::ace:d00d"))); assertFalse(r.matches(Address("2001:db8:f00::ace:d00e"))); assertFalse(r.matches(Address("2001:db8:f00::bad:d00d"))); assertFalse(r.matches(Address("2001:4868:4860::8888"))); r = new PatchedRouteInfo(Prefix("192.0.2.0/23"), null, "wlan0"); assertTrue(r.matches(Address("192.0.2.43"))); assertTrue(r.matches(Address("192.0.3.21"))); assertFalse(r.matches(Address("192.0.0.21"))); assertFalse(r.matches(Address("8.8.8.8"))); RouteInfo ipv6Default = new PatchedRouteInfo(Prefix("::/0"), null, "rmnet0"); assertTrue(ipv6Default.matches(Address("2001:db8::f00"))); assertFalse(ipv6Default.matches(Address("192.0.2.1"))); RouteInfo ipv4Default = new PatchedRouteInfo(Prefix("0.0.0.0/0"), null, "rmnet0"); assertTrue(ipv4Default.matches(Address("255.255.255.255"))); assertTrue(ipv4Default.matches(Address("192.0.2.1"))); assertFalse(ipv4Default.matches(Address("2001:db8::f00"))); } private void assertAreEqual(Object o1, Object o2) { assertTrue(o1.equals(o2)); assertTrue(o2.equals(o1)); } private void assertAreNotEqual(Object o1, Object o2) { assertFalse(o1.equals(o2)); assertFalse(o2.equals(o1)); } public void testEquals() { // IPv4 RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); RouteInfo r2 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); assertAreEqual(r1, r2); RouteInfo r3 = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "wlan0"); RouteInfo r4 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::2"), "wlan0"); RouteInfo r5 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "rmnet0"); assertAreNotEqual(r1, r3); assertAreNotEqual(r1, r4); assertAreNotEqual(r1, r5); // IPv6 r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0"); assertAreEqual(r1, r2); r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); r4 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.2"), "wlan0"); r5 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "rmnet0"); assertAreNotEqual(r1, r3); assertAreNotEqual(r1, r4); assertAreNotEqual(r1, r5); // Interfaces (but not destinations or gateways) can be null. r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null); r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0"); assertAreEqual(r1, r2); assertAreNotEqual(r1, r3); } public RouteInfo passThroughParcel(RouteInfo r) { Parcel p = Parcel.obtain(); RouteInfo r2 = null; try { r.writeToParcel(p, 0); p.setDataPosition(0); r2 = RouteInfo.CREATOR.createFromParcel(p); } finally { p.recycle(); } assertNotNull(r2); return r2; } public void assertParcelingIsLossless(RouteInfo r) { RouteInfo r2 = passThroughParcel(r); assertEquals(r, r2); } public void testParceling() { RouteInfo r; r = new RouteInfo(Prefix("::/0"), Address("2001:db8::"), null); assertParcelingIsLossless(r); r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); assertParcelingIsLossless(r); } }