Merge "Revert "Make the network stack a persistent process.""
diff --git a/api/system-current.txt b/api/system-current.txt
index 3b4a868..ce379f5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4609,17 +4609,6 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, @Nullable String, boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
     field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
-    field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
-    field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
-    field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
-    field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
-    field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
-    field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
-    field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
-    field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
-    field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
     field public static final String CARRIER_APP_NAMES = "carrier_app_names";
     field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
     field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
diff --git a/api/test-current.txt b/api/test-current.txt
index cb9ff493..21d761f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1201,17 +1201,6 @@
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
-    field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
-    field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
-    field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
-    field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
-    field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
-    field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
-    field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
-    field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
-    field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
     field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
     field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final String LOW_POWER_MODE = "low_power";
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
deleted file mode 100644
index 01c7587..0000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-
-#define DEBUG false  // STOPSHIP if true
-#include "Log.h"
-
-#include <sstream>
-#include "MemoryLeakTrackUtil.h"
-
-/*
- * The code here originally resided in MediaPlayerService.cpp
- */
-
-// Figure out the abi based on defined macros.
-#if defined(__arm__)
-#define ABI_STRING "arm"
-#elif defined(__aarch64__)
-#define ABI_STRING "arm64"
-#elif defined(__mips__) && !defined(__LP64__)
-#define ABI_STRING "mips"
-#elif defined(__mips__) && defined(__LP64__)
-#define ABI_STRING "mips64"
-#elif defined(__i386__)
-#define ABI_STRING "x86"
-#elif defined(__x86_64__)
-#define ABI_STRING "x86_64"
-#else
-#error "Unsupported ABI"
-#endif
-
-extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count);
-
-namespace android {
-namespace os {
-namespace statsd {
-
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, size_t* infoSize,
-                                     size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
-std::string dumpMemInfo(size_t limit) {
-    uint8_t* info;
-    size_t overallSize;
-    size_t infoSize;
-    size_t totalMemory;
-    size_t backtraceSize;
-    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
-
-    size_t count;
-    if (info == nullptr || overallSize == 0 || infoSize == 0 ||
-        (count = overallSize / infoSize) == 0) {
-        VLOG("no malloc info, libc.debug.malloc.program property should be set");
-        return std::string();
-    }
-
-    std::ostringstream oss;
-    oss << totalMemory << " bytes in " << count << " allocations\n";
-    oss << "  ABI: '" ABI_STRING "'"
-        << "\n\n";
-    if (count > limit) count = limit;
-
-    // The memory is sorted based on total size which is useful for finding
-    // worst memory offenders. For diffs, sometimes it is preferable to sort
-    // based on the backtrace.
-    for (size_t i = 0; i < count; i++) {
-        struct AllocEntry {
-            size_t size;  // bit 31 is set if this is zygote allocated memory
-            size_t allocations;
-            uintptr_t backtrace[];
-        };
-
-        const AllocEntry* const e = (AllocEntry*)(info + i * infoSize);
-
-        oss << (e->size * e->allocations) << " bytes ( " << e->size << " bytes * " << e->allocations
-            << " allocations )\n";
-        oss << backtrace_string(e->backtrace, backtraceSize) << "\n";
-    }
-    oss << "\n";
-    free_malloc_leak_info(info);
-    return oss.str();
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
deleted file mode 100644
index 444ed92..0000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-#pragma once
-
-#include <iostream>
-
-namespace android {
-namespace os {
-namespace statsd {
-/*
- * Dump the heap memory of the calling process, sorted by total size
- * (allocation size * number of allocations).
- *
- *    limit is the number of unique allocations to return.
- */
-extern std::string dumpMemInfo(size_t limit);
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
\ No newline at end of file
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 70fa5fa..f6b7eef 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -555,7 +555,7 @@
                 new CachedServiceFetcher<RcsManager>() {
                     @Override
                     public RcsManager createService(ContextImpl ctx) {
-                        return new RcsManager();
+                        return new RcsManager(ctx.getOuterContext());
                     }
                 });
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d710d57..ca43d40 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -80,7 +80,6 @@
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Base64;
-import android.util.ByteStringUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.PackageUtils;
@@ -99,6 +98,7 @@
 
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -5999,7 +5999,8 @@
             }
 
             // first see if the hash represents a single-signer in our signing history
-            byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
+            byte[] sha256Bytes = sha256String == null
+                    ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */);
             if (hasSha256Certificate(sha256Bytes, flags)) {
                 return true;
             }
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index a33f3fc..65bc75b 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -64,6 +64,8 @@
     @UnsupportedAppUsage
     public int mtu;
 
+    public String serverHostName;
+
     public DhcpResults() {
         super();
     }
@@ -97,6 +99,7 @@
             vendorInfo = source.vendorInfo;
             leaseDuration = source.leaseDuration;
             mtu = source.mtu;
+            serverHostName = source.serverHostName;
         }
     }
 
@@ -129,6 +132,7 @@
         vendorInfo = null;
         leaseDuration = 0;
         mtu = 0;
+        serverHostName = null;
     }
 
     @Override
@@ -139,6 +143,7 @@
         str.append(" Vendor info ").append(vendorInfo);
         str.append(" lease ").append(leaseDuration).append(" seconds");
         if (mtu != 0) str.append(" MTU ").append(mtu);
+        str.append(" Servername ").append(serverHostName);
 
         return str.toString();
     }
@@ -154,6 +159,7 @@
         return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
                 && Objects.equals(serverAddress, target.serverAddress)
                 && Objects.equals(vendorInfo, target.vendorInfo)
+                && Objects.equals(serverHostName, target.serverHostName)
                 && leaseDuration == target.leaseDuration
                 && mtu == target.mtu;
     }
@@ -179,6 +185,7 @@
         dest.writeInt(mtu);
         InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
         dest.writeString(vendorInfo);
+        dest.writeString(serverHostName);
     }
 
     @Override
@@ -193,6 +200,7 @@
         dhcpResults.mtu = in.readInt();
         dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
         dhcpResults.vendorInfo = in.readString();
+        dhcpResults.serverHostName = in.readString();
         return dhcpResults;
     }
 
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 03e8c15..7f60b9c 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -363,18 +363,6 @@
     boolean isNetworkActive();
 
     /**
-     * Setup a new physical network.
-     * @param permission PERMISSION_NONE if no permissions required to access this network.
-     *                   PERMISSION_NETWORK or PERMISSION_SYSTEM to set respective permission.
-     */
-    void createPhysicalNetwork(int netId, int permission);
-
-    /**
-     * Setup a new VPN.
-     */
-    void createVirtualNetwork(int netId, boolean secure);
-
-    /**
      * Add an interface to a network.
      */
     void addInterfaceToNetwork(String iface, int netId);
@@ -396,9 +384,6 @@
      */
     void setNetworkPermission(int netId, int permission);
 
-    void setPermission(String permission, in int[] uids);
-    void clearPermission(in int[] uids);
-
     /**
      * Allow UID to call protect().
      */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f98641d..e94d3a7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10336,8 +10336,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
 
         /**
@@ -10346,8 +10344,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
 
         /**
@@ -10356,8 +10352,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
 
         /**
@@ -10367,8 +10361,6 @@
          * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
 
         /**
@@ -10397,8 +10389,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
 
         /**
@@ -10407,8 +10397,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
 
         /**
@@ -10417,8 +10405,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
 
         /**
@@ -10427,8 +10413,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
                 "captive_portal_other_fallback_urls";
 
@@ -10438,8 +10422,6 @@
          * by "@@,@@".
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
                 "captive_portal_fallback_probe_specs";
 
@@ -10450,8 +10432,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
 
         /**
@@ -10460,8 +10440,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
 
         /**
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index e22f581..076e99d 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -22,6 +22,9 @@
 #include <jni.h>
 #include "core_jni_helpers.h"
 
+#include <android-base/logging.h>
+#include <bionic_malloc.h>
+
 #include <utils/Log.h>
 #include <utils/String8.h>
 
@@ -30,11 +33,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
-                                     size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
 #define DDMS_HEADER_SIGNATURE 0x812345dd
 #define DDMS_VERSION 2
 
@@ -78,9 +76,16 @@
     ReadFile("/proc/self/maps", maps);
     header.mapSize = maps.size();
 
-    uint8_t* allocBytes;
-    get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
-                         &header.totalMemory, &header.backtraceSize);
+    android_mallopt_leak_info_t leak_info;
+    if (!android_mallopt(M_GET_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info))) {
+      PLOG(ERROR) << "*** Failed to get malloc leak info";
+      return nullptr;
+    }
+
+    header.allocSize = leak_info.overall_size;
+    header.allocInfoSize = leak_info.info_size;
+    header.totalMemory = leak_info.total_memory;
+    header.backtraceSize = leak_info.backtrace_size;
 
     ALOGD("*** mapSize: %zu allocSize: %zu allocInfoSize: %zu totalMemory: %zu",
           header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
@@ -98,10 +103,10 @@
         env->SetByteArrayRegion(array, sizeof(header),
                                 maps.size(), reinterpret_cast<const jbyte*>(maps.string()));
         env->SetByteArrayRegion(array, sizeof(header) + maps.size(),
-                                header.allocSize, reinterpret_cast<jbyte*>(allocBytes));
+                                header.allocSize, reinterpret_cast<jbyte*>(leak_info.buffer));
     }
 
-    free_malloc_leak_info(allocBytes);
+    android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info));
     return array;
 }
 
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 8be617f..62c4d76 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -33,8 +33,10 @@
 #include <iomanip>
 #include <string>
 
+#include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <bionic_malloc.h>
 #include <debuggerd/client.h>
 #include <log/log.h>
 #include <utils/misc.h>
@@ -960,9 +962,6 @@
     return true;
 }
 
-/* pulled out of bionic */
-extern "C" void write_malloc_leak_info(FILE* fp);
-
 /*
  * Dump the native heap, writing human-readable output to the specified
  * file descriptor.
@@ -978,8 +977,11 @@
     ALOGD("Native heap dump starting...\n");
     // Formatting of the native heap dump is handled by malloc debug itself.
     // See https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md#backtrace-heap-dump-format
-    write_malloc_leak_info(fp.get());
-    ALOGD("Native heap dump complete.\n");
+    if (android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp.get(), sizeof(FILE*))) {
+      ALOGD("Native heap dump complete.\n");
+    } else {
+      PLOG(ERROR) << "Failed to write native heap dump to file";
+    }
 }
 
 /*
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 28099a1..c17f076 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,12 +33,18 @@
         <permission name="android.permission.CRYPT_KEEPER"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.captiveportallogin">
+        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+        <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.cellbroadcastreceiver">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
+        <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.defcontainer">
@@ -203,6 +209,7 @@
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
         <permission name="android.permission.MANAGE_USB"/>
+        <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
         <permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
         <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
         <permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
index 4af6274..63a670c 100644
--- a/libs/usb/tests/AccessoryChat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -1 +1,25 @@
 subdirs = ["accessorychat"]
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "AccessoryChat",
+
+    srcs: ["**/*.java"],
+
+    platform_apis: true,
+
+}
diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk
deleted file mode 100644
index cfe2da1..0000000
--- a/libs/usb/tests/AccessoryChat/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessoryChat
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/nfc-extras/tests/Android.bp b/nfc-extras/tests/Android.bp
new file mode 100644
index 0000000..fc52006
--- /dev/null
+++ b/nfc-extras/tests/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2011, 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.
+
+android_test {
+    name: "NfcExtrasTests",
+
+    // We only want this apk build for tests.
+
+    libs: [
+        "android.test.runner.stubs",
+        "com.android.nfc_extras.stubs",
+        "android.test.base.stubs",
+    ],
+
+    static_libs: ["junit"],
+
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "current",
+
+}
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
deleted file mode 100644
index 8bba3ba..0000000
--- a/nfc-extras/tests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2011, 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner.stubs \
-    com.android.nfc_extras.stubs \
-    android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NfcExtrasTests
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 44e0a65..ffd4d9d 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -26,6 +26,7 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
     <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
 
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
index d7ff98b1..a15d423 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
@@ -195,6 +195,18 @@
     public static final String VENDOR_INFO_ANDROID_METERED = "ANDROID_METERED";
 
     /**
+     * DHCP Optional Type: Option overload option
+     */
+    protected static final byte DHCP_OPTION_OVERLOAD = 52;
+
+    /**
+     * Possible values of the option overload option.
+     */
+    private static final byte OPTION_OVERLOAD_FILE = 1;
+    private static final byte OPTION_OVERLOAD_SNAME = 2;
+    private static final byte OPTION_OVERLOAD_BOTH = 3;
+
+    /**
      * DHCP Optional Type: DHCP Requested IP Address
      */
     protected static final byte DHCP_REQUESTED_IP = 50;
@@ -309,6 +321,11 @@
     protected final byte[] mClientMac;
 
     /**
+     * The server host name from server.
+     */
+    protected String mServerHostName;
+
+    /**
      * Asks the packet object to create a ByteBuffer serialization of
      * the packet for transmission.
      */
@@ -848,6 +865,8 @@
         Inet4Address ipDst = null;
         Inet4Address bcAddr = null;
         Inet4Address requestedIp = null;
+        String serverHostName;
+        byte optionOverload = 0;
 
         // The following are all unsigned integers. Internally we store them as signed integers of
         // the same length because that way we're guaranteed that they can't be out of the range of
@@ -989,9 +1008,9 @@
         packet.get(clientMac);
 
         // skip over address padding (16 octets allocated)
-        packet.position(packet.position() + (16 - addrLen)
-                        + 64    // skip server host name (64 chars)
-                        + 128); // skip boot file name (128 chars)
+        packet.position(packet.position() + (16 - addrLen));
+        serverHostName = readAsciiString(packet, 64, false);
+        packet.position(packet.position() + 128);
 
         // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
         if (packet.remaining() < 4) {
@@ -1102,6 +1121,11 @@
                             // Embedded nulls are safe as this does not get passed to netd.
                             vendorInfo = readAsciiString(packet, optionLen, true);
                             break;
+                        case DHCP_OPTION_OVERLOAD:
+                            expectedLen = 1;
+                            optionOverload = packet.get();
+                            optionOverload &= OPTION_OVERLOAD_BOTH;
+                            break;
                         default:
                             // ignore any other parameters
                             for (int i = 0; i < optionLen; i++) {
@@ -1192,6 +1216,11 @@
         newPacket.mT2 = T2;
         newPacket.mVendorId = vendorId;
         newPacket.mVendorInfo = vendorInfo;
+        if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
+            newPacket.mServerHostName = serverHostName;
+        } else {
+            newPacket.mServerHostName = "";
+        }
         return newPacket;
     }
 
@@ -1251,6 +1280,7 @@
         results.vendorInfo = mVendorInfo;
         results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
         results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
+        results.serverHostName = mServerHostName;
 
         return results;
     }
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index fb03c54..abfed3e 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -62,6 +62,49 @@
      */
     public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
 
+    /**
+     * The URL used for HTTPS captive portal detection upon a new connection.
+     * A 204 response code from the server is used for validation.
+     */
+    public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
+
+    /**
+     * The URL used for HTTP captive portal detection upon a new connection.
+     * A 204 response code from the server is used for validation.
+     */
+    public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
+
+    /**
+     * The URL used for fallback HTTP captive portal detection when previous HTTP
+     * and HTTPS captive portal detection attemps did not return a conclusive answer.
+     */
+    public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
+
+    /**
+     * What to do when connecting a network that presents a captive portal.
+     * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
+     *
+     * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
+     */
+    public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
+
+    /**
+     * Don't attempt to detect captive portals.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
+
+    /**
+     * When detecting a captive portal, display a notification that
+     * prompts the user to sign in.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
+
+    /**
+     * When detecting a captive portal, immediately disconnect from the
+     * network and do not reconnect to that network in the future.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
+
     static {
         System.loadLibrary("networkstackutilsjni");
     }
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 50eb5d4..bacec78 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -44,6 +44,12 @@
 import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS;
 import static android.net.util.DataStallUtils.DEFAULT_DNS_LOG_SIZE;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTPS_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTP_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_IGNORE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;
@@ -144,9 +150,6 @@
 
     private static final int SOCKET_TIMEOUT_MS = 10000;
     private static final int PROBE_TIMEOUT_MS  = 3000;
-    // Enough for 3 DNS queries 5 seconds apart.
-    // TODO: get this from resources and DeviceConfig instead.
-    private static final int DNS_TIMEOUT_MS = 12500;
 
     enum EvaluationResult {
         VALIDATED(true),
@@ -1178,10 +1181,10 @@
     }
 
     private boolean getIsCaptivePortalCheckEnabled() {
-        String symbol = Settings.Global.CAPTIVE_PORTAL_MODE;
-        int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT;
+        String symbol = CAPTIVE_PORTAL_MODE;
+        int defaultValue = CAPTIVE_PORTAL_MODE_PROMPT;
         int mode = mDependencies.getSetting(mContext, symbol, defaultValue);
-        return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE;
+        return mode != CAPTIVE_PORTAL_MODE_IGNORE;
     }
 
     private boolean getUseHttpsValidation() {
@@ -1191,8 +1194,7 @@
 
     private String getCaptivePortalServerHttpsUrl() {
         return getSettingFromResource(mContext, R.string.config_captive_portal_https_url,
-                R.string.default_captive_portal_https_url,
-                Settings.Global.CAPTIVE_PORTAL_HTTPS_URL);
+                R.string.default_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL);
     }
 
     private int getDnsProbeTimeout() {
@@ -1231,8 +1233,7 @@
      */
     public String getCaptivePortalServerHttpUrl() {
         return getSettingFromResource(mContext, R.string.config_captive_portal_http_url,
-                R.string.default_captive_portal_http_url,
-                Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+                R.string.default_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL);
     }
 
     private int getConsecutiveDnsTimeoutThreshold() {
@@ -1261,8 +1262,8 @@
 
     private URL[] makeCaptivePortalFallbackUrls() {
         try {
-            final String firstUrl = mDependencies.getSetting(mContext,
-                    Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, null);
+            final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL,
+                    null);
 
             final URL[] settingProviderUrls;
             if (!TextUtils.isEmpty(firstUrl)) {
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
index 4d98403..a30d3e4 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
@@ -302,8 +302,9 @@
     }
 
     private void assertDhcpResults(String ipAddress, String gateway, String dnsServersString,
-            String domains, String serverAddress, String vendorInfo, int leaseDuration,
-            boolean hasMeteredHint, int mtu, DhcpResults dhcpResults) throws Exception {
+            String domains, String serverAddress, String serverHostName, String vendorInfo,
+            int leaseDuration, boolean hasMeteredHint, int mtu, DhcpResults dhcpResults)
+                    throws Exception {
         assertEquals(new LinkAddress(ipAddress), dhcpResults.ipAddress);
         assertEquals(v4Address(gateway), dhcpResults.gateway);
 
@@ -316,6 +317,7 @@
 
         assertEquals(domains, dhcpResults.domains);
         assertEquals(v4Address(serverAddress), dhcpResults.serverAddress);
+        assertEquals(serverHostName, dhcpResults.serverHostName);
         assertEquals(vendorInfo, dhcpResults.vendorInfo);
         assertEquals(leaseDuration, dhcpResults.leaseDuration);
         assertEquals(hasMeteredHint, dhcpResults.hasMeteredHint());
@@ -327,6 +329,7 @@
         // TODO: Turn all of these into golden files. This will probably require using
         // androidx.test.InstrumentationRegistry for obtaining a Context object
         // to read such golden files, along with an appropriate Android.mk.
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "451001480000000080118849c0a89003c0a89ff7" +
@@ -347,16 +350,18 @@
             // Options
             "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
             "3a0400000e103b040000189cff00000000000000000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
-                null, "192.168.144.3", null, 7200, false, 0, dhcpResults);
+                null, "192.168.144.3", "", null, 7200, false, 0, dhcpResults);
     }
 
     @Test
     public void testOffer2() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -366,9 +371,9 @@
             "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
             // MAC address.
             "30766ff2a90c00000000000000000000" +
-            // Server name.
-            "0000000000000000000000000000000000000000000000000000000000000000" +
-            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Server name ("dhcp.android.com" plus invalid "AAAA" after null terminator).
+            "646863702e616e64726f69642e636f6d00000000000000000000000000000000" +
+            "0000000000004141414100000000000000000000000000000000000000000000" +
             // File.
             "0000000000000000000000000000000000000000000000000000000000000000" +
             "0000000000000000000000000000000000000000000000000000000000000000" +
@@ -377,13 +382,15 @@
             // Options
             "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
             "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+        // CHECKSTYLE:ON Generated code
 
         assertEquals(337, packet.limit());
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.43.247/24", "192.168.43.1", "192.168.43.1",
-                null, "192.168.43.1", "ANDROID_METERED", 3600, true, 0, dhcpResults);
+                null, "192.168.43.1", "dhcp.android.com", "ANDROID_METERED", 3600, true, 0,
+                dhcpResults);
         assertTrue(dhcpResults.hasMeteredHint());
     }
 
@@ -588,11 +595,12 @@
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
-                null, "192.168.144.3", null, 7200, false, expectedMtu, dhcpResults);
+                null, "192.168.144.3", "", null, 7200, false, expectedMtu, dhcpResults);
     }
 
     @Test
     public void testMtu() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "451001480000000080118849c0a89003c0a89ff7" +
@@ -613,6 +621,7 @@
             // Options
             "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
             "3a0400000e103b040000189cff00000000"));
+        // CHECKSTYLE:ON Generated code
 
         checkMtu(packet, 0, null);
         checkMtu(packet, 0, mtuBytes(1501));
@@ -629,6 +638,7 @@
 
     @Test
     public void testBadHwaddrLength() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -649,6 +659,7 @@
             // Options
             "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
             "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+        // CHECKSTYLE:ON Generated code
         String expectedClientMac = "30766FF2A90C";
 
         final int hwAddrLenOffset = 20 + 8 + 2;
@@ -705,6 +716,7 @@
         //    store any information in the overloaded fields).
         //
         // For now, we just check that it parses correctly.
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "b4cef6000000e80462236e300800" +
@@ -727,16 +739,18 @@
             // Options
             "638253633501023604010101010104ffff000033040000a8c03401030304ac1101010604ac110101" +
             "0000000000000000000000000000000000000000000000ff000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("172.17.152.118/16", "172.17.1.1", "172.17.1.1",
-                null, "1.1.1.1", null, 43200, false, 0, dhcpResults);
+                null, "1.1.1.1", "", null, 43200, false, 0, dhcpResults);
     }
 
     @Test
     public void testBug2111() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // IP header.
             "4500014c00000000ff119beac3eaf3880a3f5d04" +
@@ -757,16 +771,18 @@
             // Options.
             "638253633501023604c00002fe33040000bfc60104fffff00003040a3f50010608c0000201c0000202" +
             "0f0f646f6d61696e3132332e636f2e756b0000000000ff00000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.63.93.4/20", "10.63.80.1", "192.0.2.1,192.0.2.2",
-                "domain123.co.uk", "192.0.2.254", null, 49094, false, 0, dhcpResults);
+                "domain123.co.uk", "192.0.2.254", "", null, 49094, false, 0, dhcpResults);
     }
 
     @Test
     public void testBug2136() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "bcf5ac000000d0c7890000000800" +
@@ -789,17 +805,19 @@
             // Options.
             "6382536335010236040a20ff80330400001c200104fffff00003040a20900106089458413494584135" +
             "0f0b6c616e63732e61632e756b000000000000000000ff00000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         assertEquals("BCF5AC000000", HexDump.toHexString(offerPacket.getClientMac()));
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.32.158.205/20", "10.32.144.1", "148.88.65.52,148.88.65.53",
-                "lancs.ac.uk", "10.32.255.128", null, 7200, false, 0, dhcpResults);
+                "lancs.ac.uk", "10.32.255.128", "", null, 7200, false, 0, dhcpResults);
     }
 
     @Test
     public void testUdpServerAnySourcePort() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "9cd917000000001c2e0000000800" +
@@ -823,6 +841,7 @@
             // Options.
             "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
             "d18180060f0777766d2e6564751c040a0fffffff000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -830,11 +849,12 @@
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.15.122.242/16", "10.15.200.23",
                 "209.129.128.3,209.129.148.3,209.129.128.6",
-                "wvm.edu", "10.1.105.252", null, 86400, false, 0, dhcpResults);
+                "wvm.edu", "10.1.105.252", "", null, 86400, false, 0, dhcpResults);
     }
 
     @Test
     public void testUdpInvalidDstPort() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "9cd917000000001c2e0000000800" +
@@ -858,6 +878,7 @@
             // Options.
             "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
             "d18180060f0777766d2e6564751c040a0fffffff000000"));
+        // CHECKSTYLE:ON Generated code
 
         try {
             DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
@@ -867,6 +888,7 @@
 
     @Test
     public void testMultipleRouters() throws Exception {
+        // CHECKSTYLE:OFF Generated code
         final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
             // Ethernet header.
             "fc3d93000000" + "081735000000" + "0800" +
@@ -889,13 +911,14 @@
             // Options.
             "638253633501023604c0abbd023304000070803a04000038403b04000062700104ffffff00" +
             "0308c0a8bd01ffffff0006080808080808080404ff000000000000"));
+        // CHECKSTYLE:ON Generated code
 
         DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         assertEquals("FC3D93000000", HexDump.toHexString(offerPacket.getClientMac()));
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.189.49/24", "192.168.189.1", "8.8.8.8,8.8.4.4",
-                null, "192.171.189.2", null, 28800, false, 0, dhcpResults);
+                null, "192.171.189.2", "", null, 28800, false, 0, dhcpResults);
     }
 
     @Test
diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
new file mode 100644
index 0000000..fe1bb26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
@@ -0,0 +1,31 @@
+<!--
+     Copyright (C) 2019 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:viewportWidth="22"
+    android:viewportHeight="17"
+    android:width="22dp"
+    android:height="17dp">
+  <path
+      android:fillColor="#FFFFFFFF"
+      android:pathData="M1.22,8.49l0.43-4.96h4.33v1.17H2.67L2.44,7.41c0.41-0.29,0.85-0.43,1.33-0.43c0.77,0,1.38,0.3,1.83,0.9 s0.66,1.41,0.66,2.43c0,1.03-0.24,1.84-0.72,2.43s-1.14,0.88-1.98,0.88c-0.75,0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07,0.57,0.23,1,0.49,1.29c0.26,0.29,0.59,0.43,1.01,0.43c0.47,0,0.84-0.2,1.1-0.61c0.26-0.41,0.4-0.96,0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.96,8.11,3.47,8.11c-0.4,0-0.72,0.1-0.96,0.31L2.19,8.75L1.22,8.49z" />
+  <path
+      android:fillColor="#FFFFFFFF"
+      android:pathData="M14.14,12.24l-0.22,0.27c-0.63,0.73-1.55,1.1-2.76,1.1c-1.08,0-1.92-0.36-2.53-1.07c-0.61-0.71-0.93-1.72-0.94-3.02V7.56 c0-1.39,0.28-2.44,0.84-3.13c0.56-0.7,1.39-1.04,2.51-1.04c0.95,0,1.69,0.26,2.23,0.79c0.54,0.53,0.83,1.28,0.89,2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45c-0.29-0.35-0.74-0.52-1.34-0.52c-0.72,0-1.24,0.23-1.57,0.7C9.14,5.63,8.96,6.37,8.95,7.4v2.03 c0,1,0.19,1.77,0.57,2.31c0.38,0.54,0.93,0.8,1.65,0.8c0.67,0,1.19-0.16,1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z" />
+  <path
+      android:fillColor="#FFFFFFFF"
+      android:pathData="M20.96,8.88h-3.52v3.53h4.1v1.07h-5.35V3.52h5.28V4.6h-4.03V7.8h3.52V8.88z" />
+
+</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4437f49..ccf345b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -390,6 +390,9 @@
     <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
     <string name="data_connection_lte_plus">LTE+</string>
 
+    <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_5ge" translate="false">5Ge</string>
+
     <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
     <string name="data_connection_5g" translate="false">5G</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 2f7e3b18..b7c20aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -46,6 +46,8 @@
 import java.io.PrintWriter;
 import java.util.BitSet;
 import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 
 public class MobileSignalController extends SignalController<
@@ -72,6 +74,8 @@
     private SignalStrength mSignalStrength;
     private MobileIconGroup mDefaultIcons;
     private Config mConfig;
+    // Some specific carriers have 5GE network which is special LTE CA network.
+    private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
 
     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
     // need listener lists anymore.
@@ -235,6 +239,8 @@
                         TelephonyIcons.LTE_PLUS);
             }
         }
+        mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE,
+                TelephonyIcons.LTE_CA_5G_E);
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
     }
 
@@ -400,6 +406,26 @@
         }
     }
 
+    private boolean isCarrierSpecificDataIcon() {
+        if (mConfig.patternOfCarrierSpecificDataIcon == null
+                || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
+            return false;
+        }
+
+        Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
+        String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
+                mServiceState.getOperatorAlphaShortRaw()};
+        for (String opName : operatorNames) {
+            if (!TextUtils.isEmpty(opName)) {
+                Matcher matcher = stringPattern.matcher(opName);
+                if (matcher.find()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * Updates the network's name based on incoming spn and plmn.
      */
@@ -566,12 +592,8 @@
                         + " dataState=" + state.getDataRegState());
             }
             mServiceState = state;
-            if (state != null) {
-                mDataNetType = state.getDataNetworkType();
-                if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
-                        mServiceState.isUsingCarrierAggregation()) {
-                    mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
-                }
+            if (mServiceState != null) {
+                updateDataNetType(mServiceState.getDataNetworkType());
             }
             updateTelephony();
         }
@@ -583,14 +605,21 @@
                         + " type=" + networkType);
             }
             mDataState = state;
-            mDataNetType = networkType;
-            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
-                    mServiceState.isUsingCarrierAggregation()) {
-                mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
-            }
+            updateDataNetType(networkType);
             updateTelephony();
         }
 
+        private void updateDataNetType(int networkType) {
+            mDataNetType = networkType;
+            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
+                if (isCarrierSpecificDataIcon()) {
+                    mDataNetType = NETWORK_TYPE_LTE_CA_5GE;
+                } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) {
+                    mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
+                }
+            }
+        }
+
         @Override
         public void onDataActivity(int direction) {
             if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b4f0fec..5c6634c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -1084,6 +1084,7 @@
         boolean hspaDataDistinguishable;
         boolean inflateSignalStrengths = false;
         boolean alwaysShowDataRatIcon = false;
+        public String patternOfCarrierSpecificDataIcon = "";
 
         /**
          * Mapping from NR 5G status string to an integer. The NR 5G status string should match
@@ -1122,6 +1123,8 @@
                         CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
                 config.hideLtePlus = b.getBoolean(
                         CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
+                config.patternOfCarrierSpecificDataIcon = b.getString(
+                        CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
                 String nr5GIconConfiguration =
                         b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
                 if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 7347f66..2c4b1f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -35,6 +35,7 @@
     static final int ICON_3G = R.drawable.ic_3g_mobiledata;
     static final int ICON_4G = R.drawable.ic_4g_mobiledata;
     static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+    static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
     static final int ICON_1X = R.drawable.ic_1x_mobiledata;
     static final int ICON_5G = R.drawable.ic_5g_mobiledata;
     static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
@@ -204,6 +205,19 @@
             TelephonyIcons.ICON_LTE_PLUS,
             true);
 
+    static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+            "5Ge",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_5ge,
+            TelephonyIcons.ICON_5G_E,
+            true);
+
     static final MobileIconGroup NR_5G = new MobileIconGroup(
             "5G",
             null,
@@ -260,6 +274,7 @@
         ICON_NAME_TO_ICON.put("h+", H_PLUS);
         ICON_NAME_TO_ICON.put("4g", FOUR_G);
         ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
+        ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
         ICON_NAME_TO_ICON.put("lte", LTE);
         ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
         ICON_NAME_TO_ICON.put("5g", NR_5G);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 90c86c7..63fd2fd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2861,7 +2861,7 @@
         try {
             nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            e.rethrowAsRuntimeException();
         }
 
         // With Private DNS bypass support, we can proceed to update the
@@ -3031,7 +3031,7 @@
         try {
             nai.networkMonitor().notifyNetworkDisconnected();
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            e.rethrowAsRuntimeException();
         }
         mNetworkAgentInfos.remove(nai.messenger);
         nai.clatd.update();
@@ -3070,11 +3070,7 @@
             // fallback network the default or requested a new network from the
             // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
             // long time.
-            try {
-                mNetd.networkDestroy(nai.network.netId);
-            } catch (RemoteException | ServiceSpecificException e) {
-                loge("Exception destroying network: " + e);
-            }
+            destroyNativeNetwork(nai);
             mDnsManager.removeNetwork(nai.network);
         }
         synchronized (mNetworkForNetId) {
@@ -3082,6 +3078,35 @@
         }
     }
 
+    private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+        try {
+            // This should never fail.  Specifying an already in use NetID will cause failure.
+            if (networkAgent.isVPN()) {
+                mNetd.networkCreateVpn(networkAgent.network.netId,
+                        (networkAgent.networkMisc == null
+                                || !networkAgent.networkMisc.allowBypass));
+            } else {
+                mNetd.networkCreatePhysical(networkAgent.network.netId,
+                        getNetworkPermission(networkAgent.networkCapabilities));
+            }
+            mDnsResolver.createNetworkCache(networkAgent.network.netId);
+            return true;
+        } catch (RemoteException | ServiceSpecificException e) {
+            loge("Error creating network " + networkAgent.network.netId + ": "
+                    + e.getMessage());
+            return false;
+        }
+    }
+
+    private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+        try {
+            mNetd.networkDestroy(networkAgent.network.netId);
+            mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+        } catch (RemoteException | ServiceSpecificException e) {
+            loge("Exception destroying network: " + e);
+        }
+    }
+
     // If this method proves to be too slow then we can maintain a separate
     // pendingIntent => NetworkRequestInfo map.
     // This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
@@ -3420,7 +3445,7 @@
             try {
                 nai.networkMonitor().setAcceptPartialConnectivity();
             } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
+                e.rethrowAsRuntimeException();
             }
         }
     }
@@ -3456,7 +3481,7 @@
             try {
                 nai.networkMonitor().launchCaptivePortalApp();
             } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
+                e.rethrowAsRuntimeException();
             }
         });
     }
@@ -4084,7 +4109,7 @@
         try {
             nai.networkMonitor().forceReevaluation(uid);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -5464,7 +5489,7 @@
         try {
             networkMonitor.start();
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            e.rethrowAsRuntimeException();
         }
         nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
         NetworkInfo networkInfo = nai.networkInfo;
@@ -5521,7 +5546,7 @@
             try {
                 networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
             } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
+                e.rethrowAsRuntimeException();
             }
             if (networkAgent.everConnected) {
                 notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
@@ -6482,21 +6507,7 @@
             // A network that has just connected has zero requests and is thus a foreground network.
             networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
 
-            try {
-                // This should never fail.  Specifying an already in use NetID will cause failure.
-                if (networkAgent.isVPN()) {
-                    mNMS.createVirtualNetwork(networkAgent.network.netId,
-                            (networkAgent.networkMisc == null ||
-                                !networkAgent.networkMisc.allowBypass));
-                } else {
-                    mNMS.createPhysicalNetwork(networkAgent.network.netId,
-                            getNetworkPermission(networkAgent.networkCapabilities));
-                }
-            } catch (Exception e) {
-                loge("Error creating network " + networkAgent.network.netId + ": "
-                        + e.getMessage());
-                return;
-            }
+            if (!createNativeNetwork(networkAgent)) return;
             networkAgent.created = true;
         }
 
@@ -6527,7 +6538,7 @@
                 networkAgent.networkMonitor().notifyNetworkConnected(
                         networkAgent.linkProperties, networkAgent.networkCapabilities);
             } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
+                e.rethrowAsRuntimeException();
             }
             scheduleUnvalidatedPrompt(networkAgent);
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1ff50b2..6dbe3ad 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2045,28 +2045,6 @@
     }
 
     @Override
-    public void createPhysicalNetwork(int netId, int permission) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.networkCreatePhysical(netId, permission);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void createVirtualNetwork(int netId, boolean secure) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.networkCreateVpn(netId, secure);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public void addInterfaceToNetwork(String iface, int netId) {
         modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
     }
@@ -2143,38 +2121,6 @@
         }
     }
 
-    private int parsePermission(String permission) {
-        if (permission.equals("NETWORK")) {
-            return INetd.PERMISSION_NETWORK;
-        }
-        if (permission.equals("SYSTEM")) {
-            return INetd.PERMISSION_SYSTEM;
-        }
-        return INetd.PERMISSION_NONE;
-    }
-
-    @Override
-    public void setPermission(String permission, int[] uids) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.networkSetPermissionForUser(parsePermission(permission), uids);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void clearPermission(int[] uids) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.networkClearPermissionForUser(uids);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     @Override
     public void allowProtect(int uid) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index e33392d..2321afb 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -263,12 +263,6 @@
     }
 
     public void removeNetwork(Network network) {
-        try {
-            mDnsResolver.clearResolverConfiguration(network.netId);
-        } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error clearing DNS configuration: " + e);
-            return;
-        }
         mPrivateDnsMap.remove(network.netId);
         mPrivateDnsValidationMap.remove(network.netId);
     }
diff --git a/services/net/java/android/net/DhcpResultsParcelable.aidl b/services/net/java/android/net/DhcpResultsParcelable.aidl
index 978638b..c98d9c2 100644
--- a/services/net/java/android/net/DhcpResultsParcelable.aidl
+++ b/services/net/java/android/net/DhcpResultsParcelable.aidl
@@ -24,4 +24,5 @@
     int mtu;
     String serverAddress;
     String vendorInfo;
-}
\ No newline at end of file
+    String serverHostName;
+}
diff --git a/services/net/java/android/net/INetworkMonitor.aidl b/services/net/java/android/net/INetworkMonitor.aidl
index b32ef12..3fc81a3 100644
--- a/services/net/java/android/net/INetworkMonitor.aidl
+++ b/services/net/java/android/net/INetworkMonitor.aidl
@@ -40,6 +40,20 @@
     // for https probe.
     const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
 
+    // Network validation flags indicate probe result and types. If no NETWORK_VALIDATION_RESULT_*
+    // are set, then it's equal to NETWORK_TEST_RESULT_INVALID. If NETWORK_VALIDATION_RESULT_VALID
+    // is set, then the network validates and equal to NETWORK_TEST_RESULT_VALID. If
+    // NETWORK_VALIDATION_RESULT_PARTIAL is set, then the network has partial connectivity which
+    // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. NETWORK_VALIDATION_PROBE_* is set
+    // when the specific probe result of the network is resolved.
+    const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
+    const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+    const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+    const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+    const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+    const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+    const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
+
     void start();
     void launchCaptivePortalApp();
     void notifyCaptivePortalAppFinished(int response);
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/services/net/java/android/net/NattKeepalivePacketData.java
similarity index 100%
rename from core/java/android/net/NattKeepalivePacketData.java
rename to services/net/java/android/net/NattKeepalivePacketData.java
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
index 44d8e0c..172dc24 100644
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
@@ -41,6 +41,7 @@
         p.mtu = results.mtu;
         p.serverAddress = parcelAddress(results.serverAddress);
         p.vendorInfo = results.vendorInfo;
+        p.serverHostName = results.serverHostName;
         return p;
     }
 
@@ -54,6 +55,7 @@
         results.mtu = p.mtu;
         results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
         results.vendorInfo = p.vendorInfo;
+        results.serverHostName = p.serverHostName;
         return results;
     }
 
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index ecb0daf..e727a6e 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -4259,6 +4259,22 @@
          * @hide
          */
         public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
+
+        /**
+         * The current registered raw data network operator name in long alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getOperatorAlphaLongRaw()}.
+         * @hide
+         */
+        public static final String OPERATOR_ALPHA_LONG_RAW = "operator_alpha_long_raw";
+
+        /**
+         * The current registered raw data network operator name in short alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getOperatorAlphaShortRaw()}.
+         * @hide
+         */
+        public static final String OPERATOR_ALPHA_SHORT_RAW = "operator_alpha_short_raw";
     }
 
     /**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 51cff8f..c32e164 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1199,6 +1199,82 @@
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
 
     /**
+     * Override the SPN Display Condition 2 integer bits (lsb). B2, B1 is the last two bits of the
+     * spn display condition coding.
+     *
+     * The default value -1 mean this field is not set.
+     *
+     * B1 = 0: display of registered PLMN name not required when registered PLMN is either HPLMN
+     * or a PLMN in the service provider PLMN list (see EF_SPDI).
+     * B1 = 1: display of registered PLMN name required when registered PLMN is either HPLMN or a
+     * PLMN in the service provider PLMN list(see EF_SPDI).
+     * B2 = 0: display of the service provider name is required when registered PLMN is neither
+     * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI).
+     * B2 = 1: display of the service provider name is not required when registered PLMN is neither
+     * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI).
+     *
+     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.12 EF_SPN.
+     * @hide
+     */
+    public static final String KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT =
+            "spn_display_condition_override_int";
+
+    /**
+     * Override the SPDI - an array of PLMN(MCC + MNC) strings.
+     *
+     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.66 EF_SPDI.
+     * @hide
+     */
+    public static final String KEY_SPDI_OVERRIDE_STRING_ARRAY = "spdi_override_string_array";
+
+    /**
+     * Override the EHPLMNs - an array of PLMN(MCC + MNC) strings.
+     *
+     * To allow provision for multiple HPLMN codes, PLMN codes that are present within this list
+     * shall replace the HPLMN code derived from the IMSI for PLMN selection purposes.
+     *
+     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.84 EF_EHPLMN
+     * Reference: 3GPP TS 23.122 v15.6.0 Section 1.2 Equivalent HPLMN list
+     * @hide
+     */
+    public static final String KEY_EHPLMN_OVERRIDE_STRING_ARRAY = "ehplmn_override_string_array";
+
+    /**
+     * Override the PNN - a string array of comma-separated alpha long and short names:
+     * "alpha_long1,alpha_short1".
+     *
+     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.58 EF_PNN.
+     * @hide
+     */
+    public static final String KEY_PNN_OVERRIDE_STRING_ARRAY = "pnn_override_string_array";
+
+    /**
+     * A string array of OPL records, each with comma-delimited data fields as follows:
+     * "plmn1,lactac_start,lactac_end,index".
+     *
+     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.59 EF_OPL.
+     * @hide
+     */
+    public static final String KEY_OPL_OVERRIDE_STRING_ARRAY = "opl_override_opl_string_array";
+
+    /**
+     * Allow ERI rules to select a carrier name display string when using 3gpp2 access technologies.
+     * If this bit is not set, the carrier name display string will be selected from the carrier
+     * display name resolver which doesn't apply the ERI rules.
+     *
+     * @hide
+     */
+    public static final String KEY_ALLOW_ERI_BOOL = "allow_cdma_eri_bool";
+
+    /**
+     * If true, use the carrier display name(SPN and PLMN) from the carrier display name resolver.
+     *
+     * @hide
+     */
+    public static final String KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL =
+            "enable_carrier_display_name_resolver_bool";
+
+    /**
      * String to override sim country iso.
      * Sim country iso is based on sim MCC which is coarse and doesn't work with dual IMSI SIM where
      * a SIM can have multiple MCC from different countries.
@@ -1312,6 +1388,24 @@
             "hide_lte_plus_data_icon_bool";
 
     /**
+     * The string is used to filter redundant string from PLMN Network Name that's supplied by
+     * specific carrier.
+     *
+     * @hide
+     */
+    public static final String KEY_OPERATOR_NAME_FILTER_PATTERN_STRING =
+            "operator_name_filter_pattern_string";
+
+    /**
+     * The string is used to compare with operator name. If it matches the pattern then show
+     * specific data icon.
+     *
+     * @hide
+     */
+    public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING =
+            "show_carrier_data_icon_pattern_string";
+
+    /**
      * Boolean to decide whether to show precise call failed cause to user
      * @hide
      */
@@ -2800,6 +2894,13 @@
         sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
         sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
         sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+        sDefaults.putInt(KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT, -1);
+        sDefaults.putStringArray(KEY_SPDI_OVERRIDE_STRING_ARRAY, null);
+        sDefaults.putStringArray(KEY_PNN_OVERRIDE_STRING_ARRAY, null);
+        sDefaults.putStringArray(KEY_OPL_OVERRIDE_STRING_ARRAY, null);
+        sDefaults.putStringArray(KEY_EHPLMN_OVERRIDE_STRING_ARRAY, null);
+        sDefaults.putBoolean(KEY_ALLOW_ERI_BOOL, false);
+        sDefaults.putBoolean(KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
         sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, "");
         sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false);
@@ -2946,6 +3047,8 @@
         sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false);
+        sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
+        sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
         sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index a83d8f0..cbe5e71 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -49,10 +49,10 @@
 
     // long alpha Operator Name String or Enhanced Operator Name String
     /** @hide */
-    protected final String mAlphaLong;
+    protected String mAlphaLong;
     // short alpha Operator Name String or Enhanced Operator Name String
     /** @hide */
-    protected final String mAlphaShort;
+    protected String mAlphaShort;
 
     /** @hide */
     protected CellIdentity(String tag, int type, String mcc, String mnc, String alphal,
@@ -145,6 +145,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setOperatorAlphaLong(String alphaLong) {
+        mAlphaLong = alphaLong;
+    }
+
+    /**
      * @return The short alpha tag associated with the current scan result (may be the operator
      * name string or extended operator name string).  May be null if unknown.
      */
@@ -154,6 +161,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setOperatorAlphaShort(String alphaShort) {
+        mAlphaShort = alphaShort;
+    }
+
+    /**
      * @return a CellLocation object for this CellIdentity
      * @hide
      */
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 86cdce1..0ad1abe 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -339,6 +339,9 @@
 
     private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
 
+    private String mOperatorAlphaLongRaw;
+    private String mOperatorAlphaShortRaw;
+
     /**
      * get String description of roaming type
      * @hide
@@ -420,6 +423,8 @@
         mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null :
                 s.getNetworkRegistrationInfoList();
         mNrFrequencyRange = s.mNrFrequencyRange;
+        mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
+        mOperatorAlphaShortRaw = s.mOperatorAlphaShortRaw;
     }
 
     /**
@@ -453,6 +458,8 @@
         mChannelNumber = in.readInt();
         mCellBandwidths = in.createIntArray();
         mNrFrequencyRange = in.readInt();
+        mOperatorAlphaLongRaw = in.readString();
+        mOperatorAlphaShortRaw = in.readString();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -478,6 +485,8 @@
         out.writeInt(mChannelNumber);
         out.writeIntArray(mCellBandwidths);
         out.writeInt(mNrFrequencyRange);
+        out.writeString(mOperatorAlphaLongRaw);
+        out.writeString(mOperatorAlphaShortRaw);
     }
 
     public int describeContents() {
@@ -836,7 +845,9 @@
                 mIsEmergencyOnly,
                 mLteEarfcnRsrpBoost,
                 mNetworkRegistrationInfos,
-                mNrFrequencyRange);
+                mNrFrequencyRange,
+                mOperatorAlphaLongRaw,
+                mOperatorAlphaShortRaw);
     }
 
     @Override
@@ -862,6 +873,8 @@
                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
                         s.mCdmaDefaultRoamingIndicator)
                 && mIsEmergencyOnly == s.mIsEmergencyOnly
+                && equalsHandlesNulls(mOperatorAlphaLongRaw, s.mOperatorAlphaLongRaw)
+                && equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
                 && (mNetworkRegistrationInfos == null
                 ? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
                 && mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
@@ -1019,6 +1032,8 @@
             .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
             .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
             .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
+            .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
+            .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
             .append("}").toString();
     }
 
@@ -1056,6 +1071,8 @@
                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                 .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
                 .build());
+        mOperatorAlphaLongRaw = null;
+        mOperatorAlphaShortRaw = null;
     }
 
     public void setStateOutOfService() {
@@ -1297,6 +1314,8 @@
         m.putInt("ChannelNumber", mChannelNumber);
         m.putIntArray("CellBandwidths", mCellBandwidths);
         m.putInt("mNrFrequencyRange", mNrFrequencyRange);
+        m.putString("operator-alpha-long-raw", mOperatorAlphaLongRaw);
+        m.putString("operator-alpha-short-raw", mOperatorAlphaShortRaw);
     }
 
     /** @hide */
@@ -1910,4 +1929,36 @@
 
         return state;
     }
+
+    /**
+     * @hide
+     */
+    public void setOperatorAlphaLongRaw(String operatorAlphaLong) {
+        mOperatorAlphaLongRaw = operatorAlphaLong;
+    }
+
+    /**
+     * The current registered raw data network operator name in long alphanumeric format.
+     *
+     * @hide
+     */
+    public String getOperatorAlphaLongRaw() {
+        return mOperatorAlphaLongRaw;
+    }
+
+    /**
+     * @hide
+     */
+    public void setOperatorAlphaShortRaw(String operatorAlphaShort) {
+        mOperatorAlphaShortRaw = operatorAlphaShort;
+    }
+
+    /**
+     * The current registered raw data network operator name in short alphanumeric format.
+     *
+     * @hide
+     */
+    public String getOperatorAlphaShortRaw() {
+        return mOperatorAlphaShortRaw;
+    }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 58c05aa..43acfdd 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2065,7 +2065,6 @@
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
             intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
-            intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
         }
     }
 
@@ -2076,9 +2075,6 @@
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
-        //FIXME this is using phoneId and slotIndex interchangeably
-        //Eventually, this should be removed as it is not the slot id
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 82cc1df..add7d38 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2277,12 +2277,15 @@
     }
 
     /**
-     * Returns the ISO country code equivalent of the MCC (Mobile Country Code) of the current
+     * Returns the ISO-3166 country code equivalent of the MCC (Mobile Country Code) of the current
      * registered operator or the cell nearby, if available.
-     * .
+     * <p>
+     * The ISO-3166 country code is provided in lowercase 2 character format.
      * <p>
      * Note: Result may be unreliable on CDMA networks (use {@link #getPhoneType()} to determine
      * if on a CDMA network).
+     * <p>
+     * @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
      */
     public String getNetworkCountryIso() {
         return getNetworkCountryIsoForPhone(getPhoneId());
@@ -3141,7 +3144,10 @@
     }
 
     /**
-     * Returns the ISO country code equivalent for the SIM provider's country code.
+     * Returns the ISO-3166 country code equivalent for the SIM provider's country code.
+     * <p>
+     * The ISO-3166 country code is provided in lowercase 2 character format.
+     * @return the lowercase 2 character ISO-3166 country code, or empty string is not available.
      */
     public String getSimCountryIso() {
         return getSimCountryIsoForPhone(getPhoneId());
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index 0bb1b43..39e9789b 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -33,8 +33,8 @@
      *
      * @hide
      */
-    public Rcs1To1Thread(int threadId) {
-        super(threadId);
+    public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) {
+        super(rcsControllerCall, threadId);
         mThreadId = threadId;
     }
 
@@ -56,7 +56,7 @@
      */
     @WorkerThread
     public long getFallbackThreadId() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
+        return mRcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
     }
 
     /**
@@ -69,7 +69,7 @@
      */
     @WorkerThread
     public void setFallbackThreadId(long fallbackThreadId) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.set1To1ThreadFallbackThreadId(mThreadId, fallbackThreadId));
     }
 
@@ -81,6 +81,7 @@
     @WorkerThread
     public RcsParticipant getRecipient() throws RcsMessageStoreException {
         return new RcsParticipant(
-                RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
+                mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
index 5512c4c..3bd441e 100644
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ b/telephony/java/android/telephony/ims/RcsControllerCall.java
@@ -27,7 +27,13 @@
  * @hide - not meant for public use
  */
 class RcsControllerCall {
-    static <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
+    private final Context mContext;
+
+    RcsControllerCall(Context context) {
+        mContext = context;
+    }
+
+    <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
         IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
         if (iRcs == null) {
             throw new RcsMessageStoreException("Could not connect to RCS storage service");
@@ -40,18 +46,12 @@
         }
     }
 
-    static void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
+    void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
             throws RcsMessageStoreException {
-        IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
-        if (iRcs == null) {
-            throw new RcsMessageStoreException("Could not connect to RCS storage service");
-        }
-
-        try {
+        call(iRcs -> {
             serviceCall.methodOnIRcs(iRcs);
-        } catch (RemoteException exception) {
-            throw new RcsMessageStoreException(exception.getMessage());
-        }
+            return null;
+        });
     }
 
     interface RcsServiceCall<R> {
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 994b27a..9dd0720 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -40,5 +40,5 @@
      *
      * @hide
      */
-    abstract void persist() throws RcsMessageStoreException;
+    abstract void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException;
 }
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
index 8e3f6cd..b44adea 100644
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
@@ -38,7 +38,7 @@
      * descriptor.
      */
     @VisibleForTesting(visibility = PROTECTED)
-    public abstract RcsEvent createRcsEvent();
+    public abstract RcsEvent createRcsEvent(RcsControllerCall rcsControllerCall);
 
     RcsEventDescriptor(Parcel in) {
         mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
index e30745b7..b972d55 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
@@ -39,9 +39,9 @@
         mEvents = events;
     }
 
-    protected RcsEventQueryResult getRcsEventQueryResult() {
+    protected RcsEventQueryResult getRcsEventQueryResult(RcsControllerCall rcsControllerCall) {
         List<RcsEvent> rcsEvents = mEvents.stream()
-                .map(RcsEventDescriptor::createRcsEvent)
+                .map(rcsEvent -> rcsEvent.createRcsEvent(rcsControllerCall))
                 .collect(Collectors.toList());
 
         return new RcsEventQueryResult(mContinuationToken, rcsEvents);
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 3816cd4..9926658 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -103,12 +103,15 @@
     public @interface RcsFileTransferStatus {
     }
 
+    private final RcsControllerCall mRcsControllerCall;
+
     private int mId;
 
     /**
      * @hide
      */
-    RcsFileTransferPart(int id) {
+    RcsFileTransferPart(RcsControllerCall rcsControllerCall, int id) {
+        mRcsControllerCall = rcsControllerCall;
         mId = id;
     }
 
@@ -134,7 +137,7 @@
      */
     @WorkerThread
     public void setFileTransferSessionId(String sessionId) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
     }
 
     /**
@@ -143,7 +146,7 @@
      */
     @WorkerThread
     public String getFileTransferSessionId() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
     }
 
     /**
@@ -155,7 +158,8 @@
      */
     @WorkerThread
     public void setContentUri(Uri contentUri) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
+        mRcsControllerCall.callWithNoReturn(
+                iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
     }
 
     /**
@@ -165,7 +169,7 @@
     @Nullable
     @WorkerThread
     public Uri getContentUri() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
     }
 
     /**
@@ -177,7 +181,7 @@
      */
     @WorkerThread
     public void setContentMimeType(String contentMimeType) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setFileTransferContentType(mId, contentMimeType));
     }
 
@@ -188,7 +192,7 @@
     @WorkerThread
     @Nullable
     public String getContentMimeType() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
     }
 
     /**
@@ -199,7 +203,7 @@
      */
     @WorkerThread
     public void setFileSize(long contentLength) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setFileTransferFileSize(mId, contentLength));
     }
 
@@ -209,7 +213,7 @@
      */
     @WorkerThread
     public long getFileSize() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
     }
 
     /**
@@ -222,7 +226,7 @@
      */
     @WorkerThread
     public void setTransferOffset(long transferOffset) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setFileTransferTransferOffset(mId, transferOffset));
     }
 
@@ -232,7 +236,7 @@
      */
     @WorkerThread
     public long getTransferOffset() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
     }
 
     /**
@@ -244,7 +248,7 @@
     @WorkerThread
     public void setFileTransferStatus(@RcsFileTransferStatus int status)
             throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
     }
 
     /**
@@ -253,7 +257,7 @@
      */
     @WorkerThread
     public @RcsFileTransferStatus int getFileTransferStatus() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
     }
 
     /**
@@ -262,7 +266,7 @@
      */
     @WorkerThread
     public int getWidth() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
     }
 
     /**
@@ -273,7 +277,7 @@
      */
     @WorkerThread
     public void setWidth(int width) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
     }
 
     /**
@@ -282,7 +286,7 @@
      */
     @WorkerThread
     public int getHeight() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
     }
 
     /**
@@ -293,7 +297,7 @@
      */
     @WorkerThread
     public void setHeight(int height) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
     }
 
     /**
@@ -302,7 +306,7 @@
      */
     @WorkerThread
     public long getLength() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
     }
 
     /**
@@ -313,7 +317,7 @@
      */
     @WorkerThread
     public void setLength(long length) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
     }
 
     /**
@@ -323,7 +327,7 @@
      */
     @WorkerThread
     public Uri getPreviewUri() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
     }
 
     /**
@@ -334,7 +338,8 @@
      */
     @WorkerThread
     public void setPreviewUri(Uri previewUri) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
+        mRcsControllerCall.callWithNoReturn(
+                iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
     }
 
     /**
@@ -343,7 +348,7 @@
      */
     @WorkerThread
     public String getPreviewMimeType() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
     }
 
     /**
@@ -354,7 +359,7 @@
      */
     @WorkerThread
     public void setPreviewMimeType(String previewMimeType) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setFileTransferPreviewType(mId, previewMimeType));
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index baec19a..0482f57 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -38,8 +38,8 @@
      *
      * @hide
      */
-    public RcsGroupThread(int threadId) {
-        super(threadId);
+    public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) {
+        super(rcsControllerCall, threadId);
     }
 
     /**
@@ -58,7 +58,7 @@
     @Nullable
     @WorkerThread
     public String getGroupName() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
     }
 
     /**
@@ -69,7 +69,7 @@
      */
     @WorkerThread
     public void setGroupName(String groupName) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
     }
 
     /**
@@ -79,7 +79,7 @@
      */
     @Nullable
     public Uri getGroupIcon() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
     }
 
     /**
@@ -90,7 +90,7 @@
      */
     @WorkerThread
     public void setGroupIcon(@Nullable Uri groupIcon) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
     }
 
     /**
@@ -100,8 +100,9 @@
     @Nullable
     @WorkerThread
     public RcsParticipant getOwner() throws RcsMessageStoreException {
-        return new RcsParticipant(RcsControllerCall.call(
-                iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
+        return new RcsParticipant(
+                mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
     }
 
     /**
@@ -114,7 +115,7 @@
      */
     @WorkerThread
     public void setOwner(@Nullable RcsParticipant participant) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setGroupThreadOwner(mThreadId, participant.getId()));
     }
 
@@ -133,7 +134,7 @@
             return;
         }
 
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.addParticipantToGroupThread(mThreadId, participant.getId()));
     }
 
@@ -150,7 +151,7 @@
             return;
         }
 
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.removeParticipantFromGroupThread(mThreadId, participant.getId()));
     }
 
@@ -170,7 +171,8 @@
                 new RcsParticipantQueryParams.Builder().setThread(this).build();
 
         RcsParticipantQueryResult queryResult = new RcsParticipantQueryResult(
-                RcsControllerCall.call(
+                mRcsControllerCall,
+                mRcsControllerCall.call(
                         iRcs -> iRcs.getParticipants(queryParameters)));
 
         List<RcsParticipant> participantList = queryResult.getParticipants();
@@ -187,7 +189,7 @@
     @Nullable
     @WorkerThread
     public Uri getConferenceUri() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
     }
 
     /**
@@ -200,7 +202,7 @@
     @Nullable
     @WorkerThread
     public void setConferenceUri(Uri conferenceUri) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri));
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 4a6b963..f4beef7f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -23,14 +23,14 @@
  * @hide
  */
 public abstract class RcsGroupThreadEvent extends RcsEvent {
-    private final int mRcsGroupThreadId;
-    private final int mOriginatingParticipantId;
+    private final RcsGroupThread mRcsGroupThread;
+    private final RcsParticipant mOriginatingParticipant;
 
-    RcsGroupThreadEvent(long timestamp, int rcsGroupThreadId,
-            int originatingParticipantId) {
+    RcsGroupThreadEvent(long timestamp, RcsGroupThread rcsGroupThread,
+            RcsParticipant originatingParticipant) {
         super(timestamp);
-        mRcsGroupThreadId = rcsGroupThreadId;
-        mOriginatingParticipantId = originatingParticipantId;
+        mRcsGroupThread = rcsGroupThread;
+        mOriginatingParticipant = originatingParticipant;
     }
 
     /**
@@ -38,7 +38,7 @@
      */
     @NonNull
     public RcsGroupThread getRcsGroupThread() {
-        return new RcsGroupThread(mRcsGroupThreadId);
+        return mRcsGroupThread;
     }
 
     /**
@@ -46,6 +46,6 @@
      */
     @NonNull
     public RcsParticipant getOriginatingParticipant() {
-        return new RcsParticipant(mOriginatingParticipantId);
+        return mOriginatingParticipant;
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 3c6c74f..d17401f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -40,9 +40,10 @@
      * @param newIcon {@link Uri} to the new icon of this {@link RcsGroupThread}
      * @see RcsMessageStore#persistRcsEvent(RcsEvent)
      */
-    public RcsGroupThreadIconChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
-            @NonNull RcsParticipant originatingParticipant, @Nullable Uri newIcon) {
-        super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+    public RcsGroupThreadIconChangedEvent(long timestamp,
+            @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
+            @Nullable Uri newIcon) {
+        super(timestamp, rcsGroupThread, originatingParticipant);
         mNewIcon = newIcon;
     }
 
@@ -61,9 +62,9 @@
      * @hide - not meant for public use.
      */
     @Override
-    public void persist() throws RcsMessageStoreException {
+    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
         // TODO ensure failure throws
-        RcsControllerCall.call(iRcs -> iRcs.createGroupThreadIconChangedEvent(
+        rcsControllerCall.call(iRcs -> iRcs.createGroupThreadIconChangedEvent(
                 getTimestamp(), getRcsGroupThread().getThreadId(),
                 getOriginatingParticipant().getId(), mNewIcon));
     }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
index bcadc80..9350e40 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -38,9 +38,10 @@
 
     @Override
     @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadIconChangedEvent createRcsEvent() {
-        return new RcsGroupThreadIconChangedEvent(mTimestamp, new RcsGroupThread(mRcsGroupThreadId),
-                new RcsParticipant(mOriginatingParticipantId), mNewIcon);
+    public RcsGroupThreadIconChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
+        return new RcsGroupThreadIconChangedEvent(mTimestamp,
+                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId), mNewIcon);
     }
 
     public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 5403253..8430dc4 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -41,7 +41,7 @@
      */
     public RcsGroupThreadNameChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
             @NonNull RcsParticipant originatingParticipant, @Nullable String newName) {
-        super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+        super(timestamp, rcsGroupThread, originatingParticipant);
         mNewName = newName;
     }
 
@@ -60,8 +60,8 @@
      * @hide - not meant for public use.
      */
     @Override
-    public void persist() throws RcsMessageStoreException {
-        RcsControllerCall.call(iRcs -> iRcs.createGroupThreadNameChangedEvent(
+    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+        rcsControllerCall.call(iRcs -> iRcs.createGroupThreadNameChangedEvent(
                 getTimestamp(), getRcsGroupThread().getThreadId(),
                 getOriginatingParticipant().getId(), mNewName));
     }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
index 597fa0a..f9ccdd5 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -37,11 +37,11 @@
 
     @Override
     @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadNameChangedEvent createRcsEvent() {
+    public RcsGroupThreadNameChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
         return new RcsGroupThreadNameChangedEvent(
                 mTimestamp,
-                new RcsGroupThread(mRcsGroupThreadId),
-                new RcsParticipant(mOriginatingParticipantId),
+                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
                 mNewName);
     }
 
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 48be479..2cdf960a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -42,7 +42,7 @@
     public RcsGroupThreadParticipantJoinedEvent(long timestamp,
             @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
             @NonNull RcsParticipant joinedParticipant) {
-        super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+        super(timestamp, rcsGroupThread, originatingParticipant);
         mJoinedParticipantId = joinedParticipant;
     }
 
@@ -59,8 +59,8 @@
      * @hide - not meant for public use.
      */
     @Override
-    public void persist() throws RcsMessageStoreException {
-        RcsControllerCall.call(
+    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+        rcsControllerCall.call(
                 iRcs -> iRcs.createGroupThreadParticipantJoinedEvent(getTimestamp(),
                         getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
                         getJoinedParticipant().getId()));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
index abea10a..4a6803e 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -36,12 +36,13 @@
 
     @Override
     @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadParticipantJoinedEvent createRcsEvent() {
+    public RcsGroupThreadParticipantJoinedEvent createRcsEvent(
+            RcsControllerCall rcsControllerCall) {
         return new RcsGroupThreadParticipantJoinedEvent(
                 mTimestamp,
-                new RcsGroupThread(mRcsGroupThreadId),
-                new RcsParticipant(mOriginatingParticipantId),
-                new RcsParticipant(mJoinedParticipantId));
+                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+                new RcsParticipant(rcsControllerCall, mJoinedParticipantId));
     }
 
     public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index b724a3f..22d48fc 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -44,7 +44,7 @@
     public RcsGroupThreadParticipantLeftEvent(long timestamp,
             @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
             @NonNull RcsParticipant leavingParticipant) {
-        super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+        super(timestamp, rcsGroupThread, originatingParticipant);
         mLeavingParticipant = leavingParticipant;
     }
 
@@ -58,8 +58,8 @@
     }
 
     @Override
-    public void persist() throws RcsMessageStoreException {
-        RcsControllerCall.call(
+    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+        rcsControllerCall.call(
                 iRcs -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
                         getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
                         getLeavingParticipant().getId()));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
index f287db1..9b1085c 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -37,12 +37,12 @@
 
     @Override
     @VisibleForTesting(visibility = PROTECTED)
-    public RcsGroupThreadParticipantLeftEvent createRcsEvent() {
+    public RcsGroupThreadParticipantLeftEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
         return new RcsGroupThreadParticipantLeftEvent(
                 mTimestamp,
-                new RcsGroupThread(mRcsGroupThreadId),
-                new RcsParticipant(mOriginatingParticipantId),
-                new RcsParticipant(mLeavingParticipantId));
+                new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+                new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+                new RcsParticipant(rcsControllerCall, mLeavingParticipantId));
     }
 
     @NonNull
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 06e2a41..87ddbbf 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -26,8 +26,8 @@
     /**
      * @hide
      */
-    RcsIncomingMessage(int id) {
-        super(id);
+    RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) {
+        super(rcsControllerCall, id);
     }
 
     /**
@@ -39,7 +39,7 @@
      */
     @WorkerThread
     public void setArrivalTimestamp(long arrivalTimestamp) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setMessageArrivalTimestamp(mId, true, arrivalTimestamp));
     }
 
@@ -50,7 +50,7 @@
      */
     @WorkerThread
     public long getArrivalTimestamp() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
+        return mRcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
     }
 
     /**
@@ -62,7 +62,7 @@
      */
     @WorkerThread
     public void setSeenTimestamp(long notifiedTimestamp) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp));
     }
 
@@ -73,7 +73,7 @@
      */
     @WorkerThread
     public long getSeenTimestamp() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
+        return mRcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
     }
 
     /**
@@ -83,7 +83,8 @@
     @WorkerThread
     public RcsParticipant getSenderParticipant() throws RcsMessageStoreException {
         return new RcsParticipant(
-                RcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
+                mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index 63dc1ac..0d6ca3c 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -25,20 +25,19 @@
  */
 @SystemService(Context.TELEPHONY_RCS_SERVICE)
 public class RcsManager {
+    private final RcsMessageStore mRcsMessageStore;
 
     /**
      * @hide
      */
-    public RcsManager() {
-        // empty constructor
+    public RcsManager(Context context) {
+        mRcsMessageStore = new RcsMessageStore(context);
     }
 
-    private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
-
     /**
      * Returns an instance of {@link RcsMessageStore}
      */
     public RcsMessageStore getRcsMessageStore() {
-        return sRcsMessageStoreInstance;
+        return mRcsMessageStore;
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b0d0d5a..1c466b9 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -86,6 +86,11 @@
     /**
      * @hide
      */
+    protected final RcsControllerCall mRcsControllerCall;
+
+    /**
+     * @hide
+     */
     protected final int mId;
 
     @IntDef({
@@ -95,7 +100,8 @@
     public @interface RcsMessageStatus {
     }
 
-    RcsMessage(int id) {
+    RcsMessage(RcsControllerCall rcsControllerCall, int id) {
+        mRcsControllerCall = rcsControllerCall;
         mId = id;
     }
 
@@ -115,7 +121,7 @@
      * @see android.telephony.SubscriptionInfo#getSubscriptionId
      */
     public int getSubscriptionId() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
+        return mRcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
     }
 
     /**
@@ -128,7 +134,7 @@
      */
     @WorkerThread
     public void setSubscriptionId(int subId) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
     }
 
     /**
@@ -139,7 +145,7 @@
      */
     @WorkerThread
     public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus));
     }
 
@@ -150,7 +156,7 @@
      */
     @WorkerThread
     public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
+        return mRcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
     }
 
     /**
@@ -163,7 +169,7 @@
      */
     @WorkerThread
     public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(), timestamp));
     }
 
@@ -175,7 +181,7 @@
      */
     @WorkerThread
     public long getOriginationTimestamp() throws RcsMessageStoreException {
-        return RcsControllerCall.call(
+        return mRcsControllerCall.call(
                 iRcs -> iRcs.getMessageOriginationTimestamp(mId, isIncoming()));
     }
 
@@ -189,7 +195,7 @@
      */
     @WorkerThread
     public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(), rcsMessageGlobalId));
     }
 
@@ -200,7 +206,8 @@
      */
     @WorkerThread
     public String getRcsMessageId() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
+        return mRcsControllerCall.call(
+                iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
     }
 
     /**
@@ -209,7 +216,7 @@
      */
     @WorkerThread
     public String getText() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
+        return mRcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
     }
 
     /**
@@ -220,7 +227,8 @@
      */
     @WorkerThread
     public void setText(String text) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
+        mRcsControllerCall.callWithNoReturn(
+                iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
     }
 
     /**
@@ -231,7 +239,7 @@
      */
     @WorkerThread
     public double getLatitude() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
+        return mRcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
     }
 
     /**
@@ -242,7 +250,7 @@
      */
     @WorkerThread
     public void setLatitude(double latitude) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude));
     }
 
@@ -254,7 +262,7 @@
      */
     @WorkerThread
     public double getLongitude() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
+        return mRcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
     }
 
     /**
@@ -265,7 +273,7 @@
      */
     @WorkerThread
     public void setLongitude(double longitude) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude));
     }
 
@@ -282,7 +290,7 @@
     public RcsFileTransferPart insertFileTransfer(
             RcsFileTransferCreationParams fileTransferCreationParameters)
             throws RcsMessageStoreException {
-        return new RcsFileTransferPart(RcsControllerCall.call(
+        return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
                 iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
     }
 
@@ -296,11 +304,11 @@
     public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
         Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
 
-        int[] fileTransferIds = RcsControllerCall.call(
+        int[] fileTransferIds = mRcsControllerCall.call(
                 iRcs -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming()));
 
         for (int fileTransfer : fileTransferIds) {
-            fileTransferParts.add(new RcsFileTransferPart(fileTransfer));
+            fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
         }
 
         return Collections.unmodifiableSet(fileTransferParts);
@@ -319,7 +327,7 @@
             return;
         }
 
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.deleteFileTransfer(fileTransferPart.getId()));
     }
 
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index 5df929b..36bb78a 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -20,13 +20,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
 
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
@@ -35,23 +31,14 @@
  *
  * @hide
  */
-public final class RcsMessageQueryResult implements Parcelable {
-    // The token to continue the query to get the next batch of results
-    private RcsQueryContinuationToken mContinuationToken;
-    // The message type and message ID pairs for all the messages in this query result
-    private List<RcsTypeIdPair> mMessageTypeIdPairs;
+public final class RcsMessageQueryResult {
+    private final RcsControllerCall mRcsControllerCall;
+    private final RcsMessageQueryResultParcelable mRcsMessageQueryResultParcelable;
 
-    /**
-     * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
-     * to create query results
-     *
-     * @hide
-     */
-    public RcsMessageQueryResult(
-            RcsQueryContinuationToken continuationToken,
-            List<RcsTypeIdPair> messageTypeIdPairs) {
-        mContinuationToken = continuationToken;
-        mMessageTypeIdPairs = messageTypeIdPairs;
+    RcsMessageQueryResult(RcsControllerCall rcsControllerCall,
+            RcsMessageQueryResultParcelable rcsMessageQueryResultParcelable) {
+        mRcsControllerCall = rcsControllerCall;
+        mRcsMessageQueryResultParcelable = rcsMessageQueryResultParcelable;
     }
 
     /**
@@ -61,7 +48,7 @@
      */
     @Nullable
     public RcsQueryContinuationToken getContinuationToken() {
-        return mContinuationToken;
+        return mRcsMessageQueryResultParcelable.mContinuationToken;
     }
 
     /**
@@ -71,45 +58,10 @@
      */
     @NonNull
     public List<RcsMessage> getMessages() {
-        List<RcsMessage> messages = new ArrayList<>();
-        for (RcsTypeIdPair typeIdPair : mMessageTypeIdPairs) {
-            if (typeIdPair.getType() == MESSAGE_TYPE_INCOMING) {
-                messages.add(new RcsIncomingMessage(typeIdPair.getId()));
-            } else {
-                messages.add(new RcsOutgoingMessage(typeIdPair.getId()));
-            }
-        }
-
-        return messages;
-    }
-
-    private RcsMessageQueryResult(Parcel in) {
-        mContinuationToken = in.readParcelable(
-                RcsQueryContinuationToken.class.getClassLoader());
-        in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
-    }
-
-    public static final @android.annotation.NonNull Creator<RcsMessageQueryResult> CREATOR =
-            new Creator<RcsMessageQueryResult>() {
-                @Override
-                public RcsMessageQueryResult createFromParcel(Parcel in) {
-                    return new RcsMessageQueryResult(in);
-                }
-
-                @Override
-                public RcsMessageQueryResult[] newArray(int size) {
-                    return new RcsMessageQueryResult[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mContinuationToken, flags);
-        dest.writeTypedList(mMessageTypeIdPairs);
+        return mRcsMessageQueryResultParcelable.mMessageTypeIdPairs.stream()
+                .map(typeIdPair -> typeIdPair.getType() == MESSAGE_TYPE_INCOMING
+                        ? new RcsIncomingMessage(mRcsControllerCall, typeIdPair.getId())
+                        : new RcsOutgoingMessage(mRcsControllerCall, typeIdPair.getId()))
+                .collect(Collectors.toList());
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
rename to telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
index a73ba50..86928bf 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsMessageQueryResult;
+parcelable RcsMessageQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
new file mode 100644
index 0000000..4972f9b
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.ims.RcsTypeIdPair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsMessageQueryResultParcelable implements Parcelable {
+    // The token to continue the query to get the next batch of results
+    final RcsQueryContinuationToken mContinuationToken;
+    // The message type and message ID pairs for all the messages in this query result
+    final List<RcsTypeIdPair> mMessageTypeIdPairs;
+
+    public RcsMessageQueryResultParcelable(
+            RcsQueryContinuationToken continuationToken,
+            List<RcsTypeIdPair> messageTypeIdPairs) {
+        mContinuationToken = continuationToken;
+        mMessageTypeIdPairs = messageTypeIdPairs;
+    }
+
+    private RcsMessageQueryResultParcelable(Parcel in) {
+        mContinuationToken = in.readParcelable(
+                RcsQueryContinuationToken.class.getClassLoader());
+
+        mMessageTypeIdPairs = new ArrayList<>();
+        in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
+    }
+
+    public static final Creator<RcsMessageQueryResultParcelable> CREATOR =
+            new Creator<RcsMessageQueryResultParcelable>() {
+                @Override
+                public RcsMessageQueryResultParcelable createFromParcel(Parcel in) {
+                    return new RcsMessageQueryResultParcelable(in);
+                }
+
+                @Override
+                public RcsMessageQueryResultParcelable[] newArray(int size) {
+                    return new RcsMessageQueryResultParcelable[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mContinuationToken, flags);
+        dest.writeTypedList(mMessageTypeIdPairs);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 6fcb62b..20b47c0 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
+import android.content.Context;
 import android.net.Uri;
 
 import java.util.List;
@@ -30,6 +31,12 @@
  * @hide
  */
 public class RcsMessageStore {
+    RcsControllerCall mRcsControllerCall;
+
+    RcsMessageStore(Context context) {
+        mRcsControllerCall = new RcsControllerCall(context);
+    }
+
     /**
      * Returns the first chunk of existing {@link RcsThread}s in the common storage.
      *
@@ -41,8 +48,8 @@
     @NonNull
     public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
             throws RcsMessageStoreException {
-        return new RcsThreadQueryResult(
-                RcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters)));
+        return new RcsThreadQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters)));
     }
 
     /**
@@ -56,8 +63,8 @@
     @NonNull
     public RcsThreadQueryResult getRcsThreads(@NonNull RcsQueryContinuationToken continuationToken)
             throws RcsMessageStoreException {
-        return new RcsThreadQueryResult(
-                RcsControllerCall.call(iRcs -> iRcs.getRcsThreadsWithToken(continuationToken)));
+        return new RcsThreadQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getRcsThreadsWithToken(continuationToken)));
     }
 
     /**
@@ -72,8 +79,8 @@
     public RcsParticipantQueryResult getRcsParticipants(
             @Nullable RcsParticipantQueryParams queryParameters)
             throws RcsMessageStoreException {
-        return new RcsParticipantQueryResult(
-                RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters)));
+        return new RcsParticipantQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters)));
     }
 
     /**
@@ -89,22 +96,23 @@
     public RcsParticipantQueryResult getRcsParticipants(
             @NonNull RcsQueryContinuationToken continuationToken)
             throws RcsMessageStoreException {
-        return new RcsParticipantQueryResult(
-                RcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken)));
+        return new RcsParticipantQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken)));
     }
 
     /**
      * Returns the first chunk of existing {@link RcsMessage}s in the common storage.
      *
-     * @param queryParameters Parameters to specify to return a subset of all RcsMessages.
-     *                        Passing a value of null will return all messages.
+     * @param queryParams Parameters to specify to return a subset of all RcsMessages.
+     *                    Passing a value of null will return all messages.
      * @throws RcsMessageStoreException if the query could not be completed on the storage
      */
     @WorkerThread
     @NonNull
     public RcsMessageQueryResult getRcsMessages(
-            @Nullable RcsMessageQueryParams queryParameters) throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+            @Nullable RcsMessageQueryParams queryParams) throws RcsMessageStoreException {
+        return new RcsMessageQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getMessages(queryParams)));
     }
 
     /**
@@ -118,7 +126,8 @@
     @NonNull
     public RcsMessageQueryResult getRcsMessages(
             @NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken));
+        return new RcsMessageQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken)));
     }
 
     /**
@@ -132,8 +141,8 @@
     @NonNull
     public RcsEventQueryResult getRcsEvents(
             @Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
-                .getRcsEventQueryResult();
+        return mRcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
+                .getRcsEventQueryResult(mRcsControllerCall);
     }
 
     /**
@@ -147,14 +156,14 @@
     @NonNull
     public RcsEventQueryResult getRcsEvents(
             @NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
-                .getRcsEventQueryResult();
+        return mRcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
+                .getRcsEventQueryResult(mRcsControllerCall);
     }
 
     /**
      * Persists an {@link RcsEvent} to common storage.
      *
-     * @param persistableEvent The {@link RcsEvent} to persist into storage.
+     * @param rcsEvent The {@link RcsEvent} to persist into storage.
      * @throws RcsMessageStoreException if the query could not be completed on the storage
      * @see RcsGroupThreadNameChangedEvent
      * @see RcsGroupThreadIconChangedEvent
@@ -164,8 +173,8 @@
      */
     @WorkerThread
     @NonNull
-    public void persistRcsEvent(RcsEvent persistableEvent) throws RcsMessageStoreException {
-        persistableEvent.persist();
+    public void persistRcsEvent(RcsEvent rcsEvent) throws RcsMessageStoreException {
+        rcsEvent.persist(mRcsControllerCall);
     }
 
     /**
@@ -180,7 +189,8 @@
     public Rcs1To1Thread createRcs1To1Thread(@NonNull RcsParticipant recipient)
             throws RcsMessageStoreException {
         return new Rcs1To1Thread(
-                RcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
+                mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
     }
 
     /**
@@ -202,8 +212,11 @@
         }
 
         int[] finalRecipientIds = recipientIds;
-        return new RcsGroupThread(RcsControllerCall.call(
-                iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon)));
+
+        int threadId = mRcsControllerCall.call(
+                iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon));
+
+        return new RcsGroupThread(mRcsControllerCall, threadId);
     }
 
     /**
@@ -218,7 +231,7 @@
             return;
         }
 
-        boolean isDeleteSucceeded = RcsControllerCall.call(
+        boolean isDeleteSucceeded = mRcsControllerCall.call(
                 iRcs -> iRcs.deleteThread(thread.getThreadId(), thread.getThreadType()));
 
         if (!isDeleteSucceeded) {
@@ -237,7 +250,7 @@
     @NonNull
     public RcsParticipant createRcsParticipant(String canonicalAddress, @Nullable String alias)
             throws RcsMessageStoreException {
-        return new RcsParticipant(
-                RcsControllerCall.call(iRcs -> iRcs.createRcsParticipant(canonicalAddress, alias)));
+        return new RcsParticipant(mRcsControllerCall, mRcsControllerCall.call(
+                iRcs -> iRcs.createRcsParticipant(canonicalAddress, alias)));
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 1b4bfe5..e81231b 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -27,8 +27,8 @@
  * @hide
  */
 public class RcsOutgoingMessage extends RcsMessage {
-    RcsOutgoingMessage(int id) {
-        super(id);
+    RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) {
+        super(rcsControllerCall, id);
     }
 
     /**
@@ -45,12 +45,13 @@
         int[] deliveryParticipants;
         List<RcsOutgoingMessageDelivery> messageDeliveries = new ArrayList<>();
 
-        deliveryParticipants = RcsControllerCall.call(
+        deliveryParticipants = mRcsControllerCall.call(
                 iRcs -> iRcs.getMessageRecipients(mId));
 
         if (deliveryParticipants != null) {
             for (Integer deliveryParticipant : deliveryParticipants) {
-                messageDeliveries.add(new RcsOutgoingMessageDelivery(deliveryParticipant, mId));
+                messageDeliveries.add(new RcsOutgoingMessageDelivery(
+                        mRcsControllerCall, deliveryParticipant, mId));
             }
         }
 
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index 2db49c6..af9a84b 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -25,6 +25,7 @@
  * @hide
  */
 public class RcsOutgoingMessageDelivery {
+    private final RcsControllerCall mRcsControllerCall;
     // The participant that this delivery is intended for
     private final int mRecipientId;
     // The message this delivery is associated with
@@ -35,7 +36,9 @@
      *
      * @hide
      */
-    RcsOutgoingMessageDelivery(int recipientId, int messageId) {
+    RcsOutgoingMessageDelivery(
+            RcsControllerCall rcsControllerCall, int recipientId, int messageId) {
+        mRcsControllerCall = rcsControllerCall;
         mRecipientId = recipientId;
         mRcsOutgoingMessageId = messageId;
     }
@@ -49,7 +52,7 @@
      */
     @WorkerThread
     public void setDeliveredTimestamp(long deliveredTimestamp) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
                 mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp));
     }
 
@@ -61,7 +64,7 @@
      */
     @WorkerThread
     public long getDeliveredTimestamp() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
+        return mRcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
                 mRcsOutgoingMessageId, mRecipientId));
     }
 
@@ -74,7 +77,7 @@
      */
     @WorkerThread
     public void setSeenTimestamp(long seenTimestamp) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
                 mRcsOutgoingMessageId, mRecipientId, seenTimestamp));
     }
 
@@ -86,7 +89,7 @@
      */
     @WorkerThread
     public long getSeenTimestamp() throws RcsMessageStoreException {
-        return RcsControllerCall.call(
+        return mRcsControllerCall.call(
                 iRcs -> iRcs.getOutgoingDeliverySeenTimestamp(mRcsOutgoingMessageId, mRecipientId));
     }
 
@@ -99,7 +102,7 @@
      */
     @WorkerThread
     public void setStatus(@RcsMessage.RcsMessageStatus int status) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
                 mRcsOutgoingMessageId, mRecipientId, status));
     }
 
@@ -109,7 +112,7 @@
      */
     @WorkerThread
     public @RcsMessage.RcsMessageStatus int getStatus() throws RcsMessageStoreException {
-        return RcsControllerCall.call(
+        return mRcsControllerCall.call(
                 iRcs -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId, mRecipientId));
     }
 
@@ -118,7 +121,7 @@
      */
     @NonNull
     public RcsParticipant getRecipient() {
-        return new RcsParticipant(mRecipientId);
+        return new RcsParticipant(mRcsControllerCall, mRecipientId);
     }
 
     /**
@@ -126,6 +129,6 @@
      */
     @NonNull
     public RcsOutgoingMessage getMessage() {
-        return new RcsOutgoingMessage(mRcsOutgoingMessageId);
+        return new RcsOutgoingMessage(mRcsControllerCall, mRcsOutgoingMessageId);
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index bcf134a..9ea55ba 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -24,8 +24,9 @@
  * @hide
  */
 public class RcsParticipant {
+    private final RcsControllerCall mRcsControllerCall;
     // The row ID of this participant in the database
-    private int mId;
+    private final int mId;
 
     /**
      * Constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
@@ -33,7 +34,8 @@
      *
      * @hide
      */
-    public RcsParticipant(int id) {
+    public RcsParticipant(RcsControllerCall rcsControllerCall, int id) {
+        mRcsControllerCall = rcsControllerCall;
         mId = id;
     }
 
@@ -45,7 +47,7 @@
     @Nullable
     @WorkerThread
     public String getCanonicalAddress() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
     }
 
     /**
@@ -57,7 +59,7 @@
     @Nullable
     @WorkerThread
     public String getAlias() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
     }
 
     /**
@@ -70,7 +72,7 @@
      */
     @WorkerThread
     public void setAlias(String alias) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
+        mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
     }
 
     /**
@@ -82,7 +84,7 @@
     @Nullable
     @WorkerThread
     public String getContactId() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
     }
 
     /**
@@ -95,7 +97,8 @@
      */
     @WorkerThread
     public void setContactId(String contactId) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
+        mRcsControllerCall.callWithNoReturn(
+                iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
     }
 
     @Override
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 61801f3..8d2e8f2 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -69,8 +69,8 @@
      * @hide - not meant for public use.
      */
     @Override
-    public void persist() throws RcsMessageStoreException {
-        RcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
+    void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+        rcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
                 getTimestamp(), getParticipant().getId(), getNewAlias()));
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
index b29896c..43b918c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -41,9 +41,9 @@
 
     @Override
     @VisibleForTesting(visibility = PROTECTED)
-    public RcsParticipantAliasChangedEvent createRcsEvent() {
+    public RcsParticipantAliasChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
         return new RcsParticipantAliasChangedEvent(
-                mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
+                mTimestamp, new RcsParticipant(rcsControllerCall, mParticipantId), mNewAlias);
     }
 
     public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 731c94e..0721dfd 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -30,10 +30,13 @@
  * @hide
  */
 public final class RcsParticipantQueryResult {
+    private final RcsControllerCall mRcsControllerCall;
     private final RcsParticipantQueryResultParcelable mRcsParticipantQueryResultParcelable;
 
     RcsParticipantQueryResult(
+            RcsControllerCall rcsControllerCall,
             RcsParticipantQueryResultParcelable rcsParticipantQueryResultParcelable) {
+        mRcsControllerCall = rcsControllerCall;
         mRcsParticipantQueryResultParcelable = rcsParticipantQueryResultParcelable;
     }
 
@@ -55,7 +58,7 @@
     @NonNull
     public List<RcsParticipant> getParticipants() {
         return mRcsParticipantQueryResultParcelable.mParticipantIds.stream()
-                .map(RcsParticipant::new)
+                .map(participantId -> new RcsParticipant(mRcsControllerCall, participantId))
                 .collect(Collectors.toList());
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index cf1dc76..638b12a 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -33,6 +33,7 @@
 public abstract class RcsThread {
     /**
      * The rcs_participant_thread_id that represents this thread in the database
+     *
      * @hide
      */
     protected int mThreadId;
@@ -40,8 +41,14 @@
     /**
      * @hide
      */
-    protected RcsThread(int threadId) {
+    protected final RcsControllerCall mRcsControllerCall;
+
+    /**
+     * @hide
+     */
+    protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) {
         mThreadId = threadId;
+        mRcsControllerCall = rcsControllerCall;
     }
 
     /**
@@ -51,7 +58,7 @@
     @WorkerThread
     @NonNull
     public RcsMessageSnippet getSnippet() throws RcsMessageStoreException {
-        return RcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
+        return mRcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
     }
 
     /**
@@ -64,8 +71,9 @@
     public RcsIncomingMessage addIncomingMessage(
             @NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
             throws RcsMessageStoreException {
-        return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
-                mThreadId, rcsIncomingMessageCreationParams)));
+        int messageId = mRcsControllerCall.call(
+                iRcs -> iRcs.addIncomingMessage(mThreadId, rcsIncomingMessageCreationParams));
+        return new RcsIncomingMessage(mRcsControllerCall, messageId);
     }
 
     /**
@@ -78,10 +86,10 @@
     public RcsOutgoingMessage addOutgoingMessage(
             @NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
             throws RcsMessageStoreException {
-        int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
+        int messageId = mRcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
                 mThreadId, rcsOutgoingMessageCreationParams));
 
-        return new RcsOutgoingMessage(messageId);
+        return new RcsOutgoingMessage(mRcsControllerCall, messageId);
     }
 
     /**
@@ -92,7 +100,7 @@
      */
     @WorkerThread
     public void deleteMessage(@NonNull RcsMessage rcsMessage) throws RcsMessageStoreException {
-        RcsControllerCall.callWithNoReturn(
+        mRcsControllerCall.callWithNoReturn(
                 iRcs -> iRcs.deleteMessage(rcsMessage.getId(), rcsMessage.isIncoming(), mThreadId,
                         isGroup()));
     }
@@ -108,9 +116,10 @@
     @WorkerThread
     @NonNull
     public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
-        RcsMessageQueryParams queryParameters =
+        RcsMessageQueryParams queryParams =
                 new RcsMessageQueryParams.Builder().setThread(this).build();
-        return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+        return new RcsMessageQueryResult(mRcsControllerCall,
+                mRcsControllerCall.call(iRcs -> iRcs.getMessages(queryParams)));
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index c77bdb3..3de25de 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -33,9 +33,12 @@
  * @hide
  */
 public final class RcsThreadQueryResult {
+    private final RcsControllerCall mRcsControllerCall;
     private final RcsThreadQueryResultParcelable mRcsThreadQueryResultParcelable;
 
-    RcsThreadQueryResult(RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+    RcsThreadQueryResult(RcsControllerCall rcsControllerCall,
+            RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+        mRcsControllerCall = rcsControllerCall;
         mRcsThreadQueryResultParcelable = rcsThreadQueryResultParcelable;
     }
 
@@ -58,8 +61,8 @@
     public List<RcsThread> getThreads() {
         return mRcsThreadQueryResultParcelable.mRcsThreadIds.stream()
                 .map(typeIdPair -> typeIdPair.getType() == THREAD_TYPE_1_TO_1
-                        ? new Rcs1To1Thread(typeIdPair.getId())
-                        : new RcsGroupThread(typeIdPair.getId()))
+                        ? new Rcs1To1Thread(mRcsControllerCall, typeIdPair.getId())
+                        : new RcsGroupThread(mRcsControllerCall, typeIdPair.getId()))
                 .collect(Collectors.toList());
     }
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 50dc587..6eb966a 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -23,7 +23,7 @@
 import android.telephony.ims.RcsIncomingMessageCreationParams;
 import android.telephony.ims.RcsMessageSnippet;
 import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsMessageQueryResult;
+import android.telephony.ims.RcsMessageQueryResultParcelable;
 import android.telephony.ims.RcsOutgoingMessageCreationParams;
 import android.telephony.ims.RcsParticipantQueryParams;
 import android.telephony.ims.RcsParticipantQueryResultParcelable;
@@ -49,9 +49,9 @@
     RcsParticipantQueryResultParcelable getParticipantsWithToken(
         in RcsQueryContinuationToken continuationToken);
 
-    RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
+    RcsMessageQueryResultParcelable getMessages(in RcsMessageQueryParams queryParams);
 
-    RcsMessageQueryResult getMessagesWithToken(
+    RcsMessageQueryResultParcelable getMessagesWithToken(
         in RcsQueryContinuationToken continuationToken);
 
     RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index 89d32ab..658c3ed 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -49,9 +49,7 @@
                 RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
 
         RcsGroupThreadIconChangedEvent iconChangedEvent =
-                iconChangedEventDescriptor.createRcsEvent();
-
-
+                iconChangedEventDescriptor.createRcsEvent(null);
 
         assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
         assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 726b9cd..9fe67ad 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -48,7 +48,7 @@
                 .createFromParcel(parcel);
 
         RcsGroupThreadNameChangedEvent nameChangedEvent =
-                nameChangedEventDescriptor.createRcsEvent();
+                nameChangedEventDescriptor.createRcsEvent(null);
 
         assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
         assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index a109310..18d5621 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -47,7 +47,7 @@
                 .createFromParcel(parcel);
 
         RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
-                participantJoinedEventDescriptor.createRcsEvent();
+                participantJoinedEventDescriptor.createRcsEvent(null);
 
         assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
         assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index de2688c..53a6bba 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -48,7 +48,7 @@
                 .createFromParcel(parcel);
 
         RcsGroupThreadParticipantLeftEvent participantLeftEvent =
-                participantLeftEventDescriptor.createRcsEvent();
+                participantLeftEventDescriptor.createRcsEvent(null);
 
         assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
         assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 5724054..dcf68ff 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -47,7 +47,7 @@
                 .createFromParcel(parcel);
 
         RcsParticipantAliasChangedEvent aliasChangedEvent =
-                aliasChangedEventDescriptor.createRcsEvent();
+                aliasChangedEventDescriptor.createRcsEvent(null);
 
         assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
         assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
index beb4f8a..551a228 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -33,7 +33,7 @@
 
     @Test
     public void testCanUnparcel() {
-        RcsParticipant rcsParticipant = new RcsParticipant(1);
+        RcsParticipant rcsParticipant = new RcsParticipant(null, 1);
         RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
                 .setThreadType(THREAD_TYPE_GROUP)
                 .setParticipant(rcsParticipant)
diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
index d8f01e9..f9dbdc7 100644
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
@@ -55,9 +55,10 @@
         mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44");
         mDhcpResults.vendorInfo = "TEST_VENDOR_INFO";
         mDhcpResults.leaseDuration = 3600;
+        mDhcpResults.serverHostName = "dhcp.example.com";
         mDhcpResults.mtu = 1450;
         // Any added DhcpResults field must be included in equals() to be tested properly
-        assertFieldCountEquals(8, DhcpResults.class);
+        assertFieldCountEquals(9, DhcpResults.class);
     }
 
     @Test
@@ -101,6 +102,12 @@
         doDhcpResultsParcelUnparcelTest();
     }
 
+    @Test
+    public void testParcelUnparcelDhcpResults_NullServerHostName() {
+        mDhcpResults.serverHostName = null;
+        doDhcpResultsParcelUnparcelTest();
+    }
+
     private void doDhcpResultsParcelUnparcelTest() {
         final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults));
         assertEquals(mDhcpResults, unparceled);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 64672bd8a..ca1add8 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
@@ -103,6 +105,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
@@ -146,6 +149,7 @@
 import android.net.shared.NetworkMonitorUtils;
 import android.net.shared.PrivateDnsConfig;
 import android.net.util.MultinetworkPolicyTracker;
+import android.os.Binder;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -272,6 +276,7 @@
     @Mock IDnsResolver mMockDnsResolver;
     @Mock INetd mMockNetd;
     @Mock NetworkStackClient mNetworkStack;
+    @Mock PackageManager mPackageManager;
     @Mock UserManager mUserManager;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
@@ -357,7 +362,12 @@
         public Resources getResources() {
             return mResources;
         }
-    }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+   }
 
     public void waitForIdle(int timeoutMsAsInt) {
         long timeoutMs = timeoutMsAsInt;
@@ -1232,6 +1242,7 @@
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
+        mockDefaultPackages();
 
         FakeSettingsProvider.clearSettingsProvider();
         mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1284,7 +1295,24 @@
         FakeSettingsProvider.clearSettingsProvider();
     }
 
-    private static int transportToLegacyType(int transport) {
+    private void mockDefaultPackages() throws Exception {
+        final String testPackageName = mContext.getPackageName();
+        final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
+                testPackageName, PackageManager.GET_PERMISSIONS);
+        when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
+                new String[] {testPackageName});
+        when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
+                eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+
+        when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+                Arrays.asList(new PackageInfo[] {
+                        buildPackageInfo(/* SYSTEM */ false, APP1_UID),
+                        buildPackageInfo(/* SYSTEM */ false, APP2_UID),
+                        buildPackageInfo(/* SYSTEM */ false, VPN_UID)
+                }));
+    }
+
+   private static int transportToLegacyType(int transport) {
         switch (transport) {
             case TRANSPORT_ETHERNET:
                 return TYPE_ETHERNET;
@@ -4891,7 +4919,10 @@
         mCellNetworkAgent.sendLinkProperties(cellLp);
         mCellNetworkAgent.connect(false);
         waitForIdle();
-        // CS tells netd about the empty DNS config for this network.
+
+        verify(mMockDnsResolver, times(1)).createNetworkCache(
+                eq(mCellNetworkAgent.getNetwork().netId));
+        // CS tells dnsresolver about the empty DNS config for this network.
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
         reset(mMockDnsResolver);
 
@@ -4975,6 +5006,8 @@
         mCellNetworkAgent.sendLinkProperties(cellLp);
         mCellNetworkAgent.connect(false);
         waitForIdle();
+        verify(mMockDnsResolver, times(1)).createNetworkCache(
+                eq(mCellNetworkAgent.getNetwork().netId));
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
                 mResolverParamsParcelCaptor.capture());
         ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -5848,12 +5881,17 @@
         cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
         reset(mNetworkManagementService);
         reset(mMockDnsResolver);
+        reset(mMockNetd);
         when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
                 .thenReturn(getClatInterfaceConfig(myIpv4));
 
         // Connect with ipv6 link properties. Expect prefix discovery to be started.
         mCellNetworkAgent.sendLinkProperties(cellLp);
         mCellNetworkAgent.connect(true);
+
+        verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
+        verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
+
         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
         verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
 
@@ -6045,7 +6083,7 @@
         verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
         verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
         verify(mMockDnsResolver, times(1))
-                .clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId));
+                .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
 
         // Disconnect wifi
         ConditionVariable cv = waitForConnectivityBroadcasts(1);
@@ -6169,7 +6207,6 @@
     }
 
     @Test
-    @Ignore
     public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
@@ -6196,7 +6233,6 @@
     }
 
     @Test
-    @Ignore
     public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
@@ -6210,7 +6246,6 @@
     }
 
     @Test
-    @Ignore
     public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
             throws Exception {
         LinkProperties lp = new LinkProperties();
@@ -6226,7 +6261,6 @@
     }
 
     @Test
-    @Ignore
     public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");
@@ -6276,7 +6310,6 @@
     }
 
     @Test
-    @Ignore
     public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName("tun0");