Merge "Add PCSCF to LinkProperties." am: 64e495b274
am: 40c9e752ac

Change-Id: I491e99f7225233d5841b61ce383325e7a1c43fa0
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 3a79206..4a466f3 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -55,6 +55,8 @@
     private String mIfaceName;
     private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
     private ArrayList<InetAddress> mDnses = new ArrayList<>();
+    // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
+    private ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
     private ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
     private boolean mUsePrivateDns;
     private String mPrivateDnsServerName;
@@ -179,6 +181,7 @@
             mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
             mUsePrivateDns = source.mUsePrivateDns;
             mPrivateDnsServerName = source.mPrivateDnsServerName;
+            mPcscfs.addAll(source.mPcscfs);
             mDomains = source.mDomains;
             mRoutes.addAll(source.mRoutes);
             mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
@@ -525,6 +528,60 @@
     }
 
     /**
+     * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present.
+     *
+     * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers.
+     * @return true if the PCSCF server was added, false otherwise.
+     * @hide
+     */
+    public boolean addPcscfServer(InetAddress pcscfServer) {
+        if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
+            mPcscfs.add(pcscfServer);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Removes the given {@link InetAddress} from the list of PCSCF servers.
+     *
+     * @param pcscf Server The {@link InetAddress} to remove from the list of PCSCF servers.
+     * @return true if the PCSCF server was removed, false otherwise.
+     * @hide
+     */
+    public boolean removePcscfServer(InetAddress pcscfServer) {
+        if (pcscfServer != null) {
+            return mPcscfs.remove(pcscfServer);
+        }
+        return false;
+    }
+
+    /**
+     * Replaces the PCSCF servers in this {@code LinkProperties} with
+     * the given {@link Collection} of {@link InetAddress} objects.
+     *
+     * @param addresses The {@link Collection} of PCSCF servers to set in this object.
+     * @hide
+     */
+    public void setPcscfServers(Collection<InetAddress> pcscfServers) {
+        mPcscfs.clear();
+        for (InetAddress pcscfServer: pcscfServers) {
+            addPcscfServer(pcscfServer);
+        }
+    }
+
+    /**
+     * Returns all the {@link InetAddress} for PCSCF servers on this link.
+     *
+     * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on
+     *         this link.
+     * @hide
+     */
+    public List<InetAddress> getPcscfServers() {
+        return Collections.unmodifiableList(mPcscfs);
+    }
+
+    /**
      * Sets the DNS domain search path used on this link.
      *
      * @param domains A {@link String} listing in priority order the comma separated
@@ -767,6 +824,7 @@
         mDnses.clear();
         mUsePrivateDns = false;
         mPrivateDnsServerName = null;
+        mPcscfs.clear();
         mDomains = null;
         mRoutes.clear();
         mHttpProxy = null;
@@ -813,6 +871,12 @@
             resultJoiner.add(mPrivateDnsServerName);
         }
 
+        if (!mPcscfs.isEmpty()) {
+            resultJoiner.add("PcscfAddresses: [");
+            resultJoiner.add(TextUtils.join(",", mPcscfs));
+            resultJoiner.add("]");
+        }
+
         if (!mValidatedPrivateDnses.isEmpty()) {
             final StringJoiner validatedPrivateDnsesJoiner =
                     new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]");
@@ -965,6 +1029,36 @@
     }
 
     /**
+     * Returns true if this link has an IPv4 PCSCF server.
+     *
+     * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv4PcscfServer() {
+        for (InetAddress ia : mPcscfs) {
+          if (ia instanceof Inet4Address) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this link has an IPv6 PCSCF server.
+     *
+     * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv6PcscfServer() {
+        for (InetAddress ia : mPcscfs) {
+          if (ia instanceof Inet6Address) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
      * Returns true if this link is provisioned for global IPv4 connectivity.
      * This requires an IP address, default route, and DNS server.
      *
@@ -1117,6 +1211,19 @@
     }
 
     /**
+     * Compares this {@code LinkProperties} PCSCF addresses against the target
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalPcscfs(LinkProperties target) {
+        Collection<InetAddress> targetPcscfs = target.getPcscfServers();
+        return (mPcscfs.size() == targetPcscfs.size()) ?
+                    mPcscfs.containsAll(targetPcscfs) : false;
+    }
+
+    /**
      * Compares this {@code LinkProperties} Routes against the target
      *
      * @param target LinkProperties to compare.
@@ -1218,6 +1325,7 @@
                 && isIdenticalDnses(target)
                 && isIdenticalPrivateDns(target)
                 && isIdenticalValidatedPrivateDnses(target)
+                && isIdenticalPcscfs(target)
                 && isIdenticalRoutes(target)
                 && isIdenticalHttpProxy(target)
                 && isIdenticalStackedLinks(target)
@@ -1334,6 +1442,7 @@
                 + mMtu * 51
                 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
                 + (mUsePrivateDns ? 57 : 0)
+                + mPcscfs.size() * 67
                 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode());
     }
 
@@ -1357,6 +1466,10 @@
         }
         dest.writeBoolean(mUsePrivateDns);
         dest.writeString(mPrivateDnsServerName);
+        dest.writeInt(mPcscfs.size());
+        for (InetAddress d : mPcscfs) {
+            dest.writeByteArray(d.getAddress());
+        }
         dest.writeString(mDomains);
         dest.writeInt(mMtu);
         dest.writeString(mTcpBufferSizes);
@@ -1406,6 +1519,12 @@
                 }
                 netProp.setUsePrivateDns(in.readBoolean());
                 netProp.setPrivateDnsServerName(in.readString());
+                addressCount = in.readInt();
+                for (int i = 0; i < addressCount; i++) {
+                    try {
+                        netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
+                    } catch (UnknownHostException e) { }
+                }
                 netProp.setDomains(in.readString());
                 netProp.setMtu(in.readInt());
                 netProp.setTcpBufferSizes(in.readString());
diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
index 9695e9a..f82b380 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -53,6 +53,8 @@
     private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
     private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
     private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
+    private static InetAddress PCSCFV6 =  NetworkUtils.numericToInetAddress(
+            "2001:0db8:85a3:0000:0000:8a2e:0370:1");
     private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
     private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
     private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
@@ -86,6 +88,9 @@
         assertTrue(source.isIdenticalValidatedPrivateDnses(target));
         assertTrue(target.isIdenticalValidatedPrivateDnses(source));
 
+        assertTrue(source.isIdenticalPcscfs(target));
+        assertTrue(target.isIdenticalPcscfs(source));
+
         assertTrue(source.isIdenticalRoutes(target));
         assertTrue(target.isIdenticalRoutes(source));
 
@@ -128,6 +133,8 @@
         // set 2 dnses
         source.addDnsServer(DNS1);
         source.addDnsServer(DNS2);
+        // set 1 pcscf
+        source.addPcscfServer(PCSCFV6);
         // set 2 gateways
         source.addRoute(new RouteInfo(GATEWAY1));
         source.addRoute(new RouteInfo(GATEWAY2));
@@ -141,6 +148,7 @@
         target.addLinkAddress(LINKADDRV6);
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
+        target.addPcscfServer(PCSCFV6);
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);
@@ -154,6 +162,7 @@
         target.addLinkAddress(LINKADDRV6);
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
+        target.addPcscfServer(PCSCFV6);
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);
@@ -167,6 +176,7 @@
         target.addLinkAddress(LINKADDRV6);
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
+        target.addPcscfServer(PCSCFV6);
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);
@@ -179,6 +189,21 @@
         // change dnses
         target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
         target.addDnsServer(DNS2);
+        target.addPcscfServer(PCSCFV6);
+        target.addRoute(new RouteInfo(GATEWAY1));
+        target.addRoute(new RouteInfo(GATEWAY2));
+        target.setMtu(MTU);
+        assertFalse(source.equals(target));
+
+        target.clear();
+        target.setInterfaceName(NAME);
+        target.addLinkAddress(LINKADDRV4);
+        target.addLinkAddress(LINKADDRV6);
+        target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
+        target.addDnsServer(DNS2);
+        // change pcscf
+        target.addPcscfServer(NetworkUtils.numericToInetAddress(
+            "2001::1"));
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);