Merge "Include KReclaimable meminfo field into getMemInfo results"
diff --git a/api/current.txt b/api/current.txt
index f3f1cb9..5d15646 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44199,7 +44199,9 @@
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
-    field public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+    field public static final String KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING = "config_ims_mmtel_package_override_string";
+    field @Deprecated public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+    field public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING = "config_ims_rcs_package_override_string";
     field public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
     field public static final String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
     field public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index e539e6c..6656c07 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8992,6 +8992,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
     field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
+    field public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 8e18341..f4ead4a 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -74,6 +74,8 @@
     private static final int MIN_MTU_V6 = 1280;
     private static final int MAX_MTU    = 10000;
 
+    private static final int INET6_ADDR_LENGTH = 16;
+
     // Stores the properties of links that are "stacked" above this link.
     // Indexed by interface name to allow modification and to prevent duplicates being added.
     private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
@@ -1626,20 +1628,11 @@
             dest.writeParcelable(linkAddress, flags);
         }
 
-        dest.writeInt(mDnses.size());
-        for (InetAddress d : mDnses) {
-            dest.writeByteArray(d.getAddress());
-        }
-        dest.writeInt(mValidatedPrivateDnses.size());
-        for (InetAddress d : mValidatedPrivateDnses) {
-            dest.writeByteArray(d.getAddress());
-        }
+        writeAddresses(dest, mDnses);
+        writeAddresses(dest, mValidatedPrivateDnses);
         dest.writeBoolean(mUsePrivateDns);
         dest.writeString(mPrivateDnsServerName);
-        dest.writeInt(mPcscfs.size());
-        for (InetAddress d : mPcscfs) {
-            dest.writeByteArray(d.getAddress());
-        }
+        writeAddresses(dest, mPcscfs);
         dest.writeString(mDomains);
         dest.writeInt(mMtu);
         dest.writeString(mTcpBufferSizes);
@@ -1662,6 +1655,35 @@
         dest.writeBoolean(mWakeOnLanSupported);
     }
 
+    private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
+        dest.writeInt(list.size());
+        for (InetAddress d : list) {
+            writeAddress(dest, d);
+        }
+    }
+
+    private static void writeAddress(@NonNull Parcel dest, @NonNull InetAddress addr) {
+        dest.writeByteArray(addr.getAddress());
+        if (addr instanceof Inet6Address) {
+            final Inet6Address v6Addr = (Inet6Address) addr;
+            final boolean hasScopeId = v6Addr.getScopeId() != 0;
+            dest.writeBoolean(hasScopeId);
+            if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
+        }
+    }
+
+    @NonNull
+    private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
+        final byte[] addr = p.createByteArray();
+        if (addr.length == INET6_ADDR_LENGTH) {
+            final boolean hasScopeId = p.readBoolean();
+            final int scopeId = hasScopeId ? p.readInt() : 0;
+            return Inet6Address.getByAddress(null /* host */, addr, scopeId);
+        }
+
+        return InetAddress.getByAddress(addr);
+    }
+
     /**
      * Implement the Parcelable interface.
      */
@@ -1681,14 +1703,13 @@
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addDnsServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addValidatedPrivateDnsServer(
-                                InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addValidatedPrivateDnsServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 netProp.setUsePrivateDns(in.readBoolean());
@@ -1696,7 +1717,7 @@
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addPcscfServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 netProp.setDomains(in.readString());
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 082424f..9ce29e3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -635,7 +635,7 @@
 
     <!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
          removed. -->
-    <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIME" />
+    <protected-broadcast android:name="android.telephony.action.NETWORK_SET_TIME" />
 
     <!-- For tether entitlement recheck-->
     <protected-broadcast
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4b5840e..b516c41 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3020,10 +3020,6 @@
     <!-- Whether to use voip audio mode for ims call -->
     <bool name="config_use_voip_mode_for_ims">false</bool>
 
-    <!-- ImsService package name to bind to by default. If none is specified in an overlay, an
-         empty string is passed in -->
-    <string name="config_ims_package"/>
-
     <!-- String array containing numbers that shouldn't be logged. Country-specific. -->
     <string-array name="unloggable_phone_numbers" />
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 04b86a8..5cd5c8c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -295,7 +295,6 @@
   <java-symbol type="bool" name="config_enableBurnInProtection" />
   <java-symbol type="bool" name="config_hotswapCapable" />
   <java-symbol type="bool" name="config_mms_content_disposition_support" />
-  <java-symbol type="string" name="config_ims_package" />
   <java-symbol type="string" name="config_wwan_network_service_package" />
   <java-symbol type="string" name="config_wlan_network_service_package" />
   <java-symbol type="string" name="config_wwan_network_service_class" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0ff6c1b..6543a2e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -340,6 +340,8 @@
         <permission name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
         <!-- Permission required for Telecom car mode CTS tests. -->
         <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+        <!-- Permission required for Tethering CTS tests. -->
+        <permission name="android.permission.TETHER_PRIVILEGED"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fb5c553..efd31ca 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -213,6 +213,9 @@
       <!-- Permission required for CTS test - CarModeInCallServiceTest -->
     <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
 
+    <!-- Permission required for CTS test - TetheringManagerTest -->
+    <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
index b0b45f4..39be311 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
@@ -35,11 +35,11 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.TimeUtils;
 
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
@@ -137,7 +137,7 @@
 
     private void registerForTelephonyIntents() {
         IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+        intentFilter.addAction(TelephonyManager.ACTION_NETWORK_SET_TIME);
         mContext.registerReceiver(mNitzReceiver, intentFilter);
     }
 
@@ -247,7 +247,7 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (DBG) Log.d(TAG, "Received " + action);
-            if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
+            if (TelephonyManager.ACTION_NETWORK_SET_TIME.equals(action)) {
                 mNitzTimeSetTime = SystemClock.elapsedRealtime();
             }
         }
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 1b1ac6d..d99e03b 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -23,6 +23,7 @@
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.Intent;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.LocalLog;
 import android.util.Slog;
@@ -30,7 +31,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.PrintWriter;
@@ -512,12 +512,12 @@
             mLastAutoSystemClockTimeSet = null;
         }
 
-        // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
+        // Historically, Android has sent a TelephonyManager.ACTION_NETWORK_SET_TIME broadcast only
         // when setting the time using NITZ.
         if (origin == ORIGIN_PHONE) {
             // Send a broadcast that telephony code used to send after setting the clock.
             // TODO Remove this broadcast as soon as there are no remaining listeners.
-            Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+            Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_SET_TIME);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
             intent.putExtra("time", newSystemClockMillis);
             mCallback.sendStickyBroadcast(intent);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2a81de5..264044e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -419,12 +419,33 @@
             KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
 
     /**
-     * Override the device's configuration for the ImsService to use for this SIM card.
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support both IMS MMTEL and RCS feature functionality instead of the device default
+     * ImsService for this subscription.
+     * @deprecated Use {@link #KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING} and
+     * {@link #KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING} instead to configure these values
+     * separately. If any of those values are not empty, they will override this value.
      */
     public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING =
             "config_ims_package_override_string";
 
     /**
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support IMS MMTEL feature functionality instead of the device default ImsService for this
+     * subscription.
+     */
+    public static final String KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING =
+            "config_ims_mmtel_package_override_string";
+
+    /**
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support IMS RCS feature functionality instead of the device default ImsService for this
+     * subscription.
+     */
+    public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING =
+            "config_ims_rcs_package_override_string";
+
+    /**
      * Override the package that will manage {@link SubscriptionPlan}
      * information instead of the {@link CarrierService} that defines this
      * value.
@@ -3503,6 +3524,8 @@
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putString(KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
+        sDefaults.putString(KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING, null);
+        sDefaults.putString(KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING, null);
         sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_DIAL_STRING_REPLACE_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c190486..c67ebfe 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1462,6 +1462,26 @@
      */
     public static final String EXTRA_SIM_COMBINATION_NAMES =
             "android.telephony.extra.SIM_COMBINATION_NAMES";
+
+    /**
+     * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
+     * This is a sticky broadcast.
+     * The intent will have the following extra values:</p>
+     * <ul>
+     *   <li><em>time</em> - The time as a long in UTC milliseconds.</li>
+     * </ul>
+     *
+     * <p class="note">
+     * Requires the READ_PHONE_STATE permission.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
+
     //
     //
     // Device Info
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3264c751..feb1368 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -858,12 +858,13 @@
     /**
     *  @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
     */
-    boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
+    boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
+            in int[] featureTypes, in String packageName);
 
     /**
     * @return the package name of the carrier/device ImsService associated with this slot.
     */
-    String getImsService(int slotId, boolean isCarrierImsService);
+    String getBoundImsServicePackage(int slotIndex, boolean isCarrierImsService, int featureType);
 
     /**
      * Get the MmTelFeature state attached to this subscription id.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index b2c3fc7..8e1a78c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -225,22 +225,6 @@
     public static final String EXTRA_REBROADCAST_ON_UNLOCK= "rebroadcastOnUnlock";
 
     /**
-     * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
-     * This is a sticky broadcast.
-     * The intent will have the following extra values:</p>
-     * <ul>
-     *   <li><em>time</em> - The time as a long in UTC milliseconds.</li>
-     * </ul>
-     *
-     * <p class="note">
-     * Requires the READ_PHONE_STATE permission.
-     *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
-     */
-    public static final String ACTION_NETWORK_SET_TIME = "android.intent.action.NETWORK_SET_TIME";
-
-    /**
      * <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
      * <p class="note">.
      * This is to pop up a notice to show user that the phone is in emergency callback mode
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index ae8285b..a7eef05 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -16,7 +16,9 @@
 
 package android.net;
 
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
 import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
+import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -47,25 +49,22 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class LinkPropertiesTest {
-    private static final InetAddress ADDRV4 = InetAddresses.parseNumericAddress("75.208.6.1");
-    private static final InetAddress ADDRV6 = InetAddresses.parseNumericAddress(
-            "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
-    private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("75.208.7.1");
-    private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("69.78.7.1");
-    private static final InetAddress DNS6 = InetAddresses.parseNumericAddress(
-            "2001:4860:4860::8888");
-    private static final InetAddress PRIVDNS1 = InetAddresses.parseNumericAddress("1.1.1.1");
-    private static final InetAddress PRIVDNS2 = InetAddresses.parseNumericAddress("1.0.0.1");
-    private static final InetAddress PRIVDNS6 = InetAddresses.parseNumericAddress(
-            "2606:4700:4700::1111");
-    private static final InetAddress PCSCFV4 = InetAddresses.parseNumericAddress("10.77.25.37");
-    private static final InetAddress PCSCFV6 = InetAddresses.parseNumericAddress(
-            "2001:0db8:85a3:0000:0000:8a2e:0370:1");
-    private static final InetAddress GATEWAY1 = InetAddresses.parseNumericAddress("75.208.8.1");
-    private static final InetAddress GATEWAY2 = InetAddresses.parseNumericAddress("69.78.8.1");
-    private static final InetAddress GATEWAY61 = InetAddresses.parseNumericAddress(
-            "fe80::6:0000:613");
-    private static final InetAddress GATEWAY62 = InetAddresses.parseNumericAddress("fe80::6:2222");
+    private static final InetAddress ADDRV4 = address("75.208.6.1");
+    private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+    private static final InetAddress DNS1 = address("75.208.7.1");
+    private static final InetAddress DNS2 = address("69.78.7.1");
+    private static final InetAddress DNS6 = address("2001:4860:4860::8888");
+    private static final InetAddress PRIVDNS1 = address("1.1.1.1");
+    private static final InetAddress PRIVDNS2 = address("1.0.0.1");
+    private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111");
+    private static final InetAddress PCSCFV4 = address("10.77.25.37");
+    private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1");
+    private static final InetAddress GATEWAY1 = address("75.208.8.1");
+    private static final InetAddress GATEWAY2 = address("69.78.8.1");
+    private static final InetAddress GATEWAY61 = address("fe80::6:0000:613");
+    private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
+    private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
+    private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
     private static final String NAME = "qmi0";
     private static final String DOMAINS = "google.com";
     private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
@@ -75,8 +74,7 @@
     private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
     private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
 
-    // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
-    private InetAddress Address(String addrString) {
+    private static InetAddress address(String addrString) {
         return InetAddresses.parseNumericAddress(addrString);
     }
 
@@ -228,7 +226,7 @@
         target.clear();
         target.setInterfaceName(NAME);
         // change link addresses
-        target.addLinkAddress(new LinkAddress(Address("75.208.6.2"), 32));
+        target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32));
         target.addLinkAddress(LINKADDRV6);
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
@@ -243,7 +241,7 @@
         target.addLinkAddress(LINKADDRV4);
         target.addLinkAddress(LINKADDRV6);
         // change dnses
-        target.addDnsServer(Address("75.208.7.2"));
+        target.addDnsServer(address("75.208.7.2"));
         target.addDnsServer(DNS2);
         target.addPcscfServer(PCSCFV6);
         target.addRoute(new RouteInfo(GATEWAY1));
@@ -255,10 +253,10 @@
         target.setInterfaceName(NAME);
         target.addLinkAddress(LINKADDRV4);
         target.addLinkAddress(LINKADDRV6);
-        target.addDnsServer(Address("75.208.7.2"));
+        target.addDnsServer(address("75.208.7.2"));
         target.addDnsServer(DNS2);
         // change pcscf
-        target.addPcscfServer(Address("2001::1"));
+        target.addPcscfServer(address("2001::1"));
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);
@@ -271,9 +269,9 @@
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
         // change gateway
-        target.addRoute(new RouteInfo(Address("75.208.8.2")));
-        target.addRoute(new RouteInfo(GATEWAY2));
+        target.addRoute(new RouteInfo(address("75.208.8.2")));
         target.setMtu(MTU);
+        target.addRoute(new RouteInfo(GATEWAY2));
         assertFalse(source.equals(target));
 
         target.clear();
@@ -349,7 +347,7 @@
 
     @Test
     public void testRouteInterfaces() {
-        LinkAddress prefix = new LinkAddress(Address("2001:db8::"), 32);
+        LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32);
         InetAddress address = ADDRV6;
 
         // Add a route with no interface to a LinkProperties with no interface. No errors.
@@ -739,8 +737,7 @@
 
         // Add an on-link route, making the on-link DNS server reachable,
         // but there is still no IPv4 address.
-        assertTrue(v4lp.addRoute(new RouteInfo(
-                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
+        assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16))));
         assertFalse(v4lp.isReachable(DNS1));
         assertFalse(v4lp.isReachable(DNS2));
 
@@ -756,9 +753,9 @@
         assertTrue(v4lp.isReachable(DNS2));
 
         final LinkProperties v6lp = new LinkProperties();
-        final InetAddress kLinkLocalDns = Address("fe80::6:1");
-        final InetAddress kLinkLocalDnsWithScope = Address("fe80::6:2%43");
-        final InetAddress kOnLinkDns = Address("2001:db8:85a3::53");
+        final InetAddress kLinkLocalDns = address("fe80::6:1");
+        final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43");
+        final InetAddress kOnLinkDns = address("2001:db8:85a3::53");
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -767,7 +764,7 @@
         // Add a link-local route, making the link-local DNS servers reachable. Because
         // we assume the presence of an IPv6 link-local address, link-local DNS servers
         // are considered reachable, but only those with a non-zero scope identifier.
-        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("fe80::"), 64))));
+        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64))));
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -783,7 +780,7 @@
         // Add a global route on link, but no global address yet. DNS servers reachable
         // via a route that doesn't require a gateway: give them the benefit of the
         // doubt and hope the link-local source address suffices for communication.
-        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("2001:db8:85a3::"), 64))));
+        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64))));
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertTrue(v6lp.isReachable(kOnLinkDns));
@@ -812,7 +809,7 @@
         stacked.setInterfaceName("v4-test0");
         v6lp.addStackedLink(stacked);
 
-        InetAddress stackedAddress = Address("192.0.0.4");
+        InetAddress stackedAddress = address("192.0.0.4");
         LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
         assertFalse(v6lp.isReachable(stackedAddress));
         stacked.addLinkAddress(stackedLinkAddress);
@@ -845,7 +842,7 @@
         LinkProperties rmnet1 = new LinkProperties();
         rmnet1.setInterfaceName("rmnet1");
         rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
-        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, Address("10.0.0.1"),
+        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"),
                 rmnet1.getInterfaceName());
         RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
                 rmnet1.getInterfaceName());
@@ -864,7 +861,7 @@
         rmnet2.setInterfaceName("rmnet2");
         rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
         rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
-        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, Address("2001:db8::1"),
+        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"),
                 rmnet2.getInterfaceName());
         RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
                 rmnet2.getInterfaceName());
@@ -930,24 +927,54 @@
     public void testLinkPropertiesParcelable() throws Exception {
         LinkProperties source = new LinkProperties();
         source.setInterfaceName(NAME);
-        // set 2 link addresses
+
         source.addLinkAddress(LINKADDRV4);
         source.addLinkAddress(LINKADDRV6);
-        // set 2 dnses
+
         source.addDnsServer(DNS1);
         source.addDnsServer(DNS2);
-        // set 2 gateways
+        source.addDnsServer(GATEWAY62);
+
+        source.addPcscfServer(TESTIPV4ADDR);
+        source.addPcscfServer(TESTIPV6ADDR);
+
+        source.setUsePrivateDns(true);
+        source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
+
+        source.setDomains(DOMAINS);
+
         source.addRoute(new RouteInfo(GATEWAY1));
         source.addRoute(new RouteInfo(GATEWAY2));
-        // set 2 validated private dnses
+
         source.addValidatedPrivateDnsServer(DNS6);
         source.addValidatedPrivateDnsServer(GATEWAY61);
+        source.addValidatedPrivateDnsServer(TESTIPV6ADDR);
+
+        source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
 
         source.setMtu(MTU);
 
+        source.setTcpBufferSizes(TCP_BUFFER_SIZES);
+
         source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
 
-        assertParcelingIsLossless(source);
+        source.setWakeOnLanSupported(true);
+
+        final LinkProperties stacked = new LinkProperties();
+        stacked.setInterfaceName("test-stacked");
+        source.addStackedLink(stacked);
+
+        assertParcelSane(source, 15 /* fieldCount */);
+    }
+
+    @Test
+    public void testLinkLocalDnsServerParceling() throws Exception {
+        final String strAddress = "fe80::1%lo";
+        final LinkProperties lp = new LinkProperties();
+        lp.addDnsServer(address(strAddress));
+        final LinkProperties unparceled = parcelingRoundTrip(lp);
+        // Inet6Address#equals does not test for the scope id
+        assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress());
     }
 
     @Test