Merge "Suppress all hidden abstract methods in constructable classes."
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 7060347..aa39824 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -177,31 +177,6 @@
     "\\) "
 
 droidstubs {
-    name: "system-api-stubs-docs",
-    defaults: ["metalava-full-api-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args + priv_apps,
-    check_api: {
-        current: {
-            api_file: "api/system-current.txt",
-            removed_api_file: "api/system-removed.txt",
-        },
-        last_released: {
-            api_file: ":android.api.system.latest",
-            removed_api_file: ":removed.api.system.latest",
-            baseline_file: ":system-api-incompatibilities-with-last-released"
-        },
-        api_lint: {
-            enabled: true,
-            new_since: ":android.api.system.latest",
-            baseline_file: "api/system-lint-baseline.txt",
-        },
-    },
-}
-
-droidstubs {
     name: "system-api-stubs-docs-non-updatable",
     defaults: ["metalava-non-updatable-api-stubs-default"],
     arg_files: ["core/res/AndroidManifest.xml"],
diff --git a/apex/permission/Android.bp b/apex/permission/Android.bp
index 71a52bb..e30df05 100644
--- a/apex/permission/Android.bp
+++ b/apex/permission/Android.bp
@@ -21,7 +21,7 @@
 apex_defaults {
     name: "com.android.permission-defaults",
     updatable: true,
-    min_sdk_version: "R",
+    min_sdk_version: "30",
     key: "com.android.permission.key",
     certificate: ":com.android.permission.certificate",
     java_libs: [
diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp
index ede8852..f13861e 100644
--- a/apex/statsd/Android.bp
+++ b/apex/statsd/Android.bp
@@ -35,7 +35,7 @@
     prebuilts: ["com.android.os.statsd.init.rc"],
     name: "com.android.os.statsd-defaults",
     updatable: true,
-    min_sdk_version: "R",
+    min_sdk_version: "30",
     key: "com.android.os.statsd.key",
     certificate: ":com.android.os.statsd.certificate",
 }
diff --git a/api/Android.bp b/api/Android.bp
index ae0d596..471b993 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -57,6 +57,25 @@
 }
 
 genrule {
+    name: "frameworks-base-api-current.srcjar",
+    srcs: [
+        ":api-stubs-docs-non-updatable",
+        ":conscrypt.module.public.api{.public.stubs.source}",
+        ":framework-media{.public.stubs.source}",
+        ":framework-mediaprovider{.public.stubs.source}",
+        ":framework-permission{.public.stubs.source}",
+        ":framework-sdkextensions{.public.stubs.source}",
+        ":framework-statsd{.public.stubs.source}",
+        ":framework-tethering{.public.stubs.source}",
+        ":framework-wifi{.public.stubs.source}",
+    ],
+    out: ["current.srcjar"],
+    tools: ["merge_zips"],
+    cmd: "$(location merge_zips) $(out) $(in)",
+    visibility: ["//visibility:private"], // Used by make module in //development, mind.
+}
+
+genrule {
     name: "frameworks-base-api-removed.txt",
     srcs: [
         ":conscrypt.module.public.api{.public.removed-api.txt}",
diff --git a/api/current.txt b/api/current.txt
index 5d46a68..69f7645 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -96,6 +96,7 @@
     field public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
     field public static final String MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE";
+    field public static final String MANAGE_ONGOING_CALLS = "android.permission.MANAGE_ONGOING_CALLS";
     field public static final String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
@@ -42820,10 +42821,11 @@
     method public String getKeystoreAlias();
     method public int getOrigin();
     method public int getPurposes();
+    method public int getSecurityLevel();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public boolean isInsideSecureHardware();
+    method @Deprecated public boolean isInsideSecureHardware();
     method public boolean isInvalidatedByBiometricEnrollment();
     method public boolean isTrustedUserPresenceRequired();
     method public boolean isUserAuthenticationRequired();
@@ -45849,6 +45851,8 @@
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
     field public static final String EXTRA_AUDIO_CODEC = "android.telecom.extra.AUDIO_CODEC";
+    field public static final String EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ = "android.telecom.extra.AUDIO_CODEC_BANDWIDTH_KHZ";
+    field public static final String EXTRA_AUDIO_CODEC_BITRATE_KBPS = "android.telecom.extra.AUDIO_CODEC_BITRATE_KBPS";
     field public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
@@ -46295,6 +46299,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle);
+    method public boolean hasCompanionInCallServiceAccess();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInCall();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
@@ -46694,6 +46699,7 @@
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
     field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
+    field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
     field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
     field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
@@ -46888,6 +46894,10 @@
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
     field public static final int SERVICE_CLASS_NONE = 0; // 0x0
     field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
+    field public static final int USSD_OVER_CS_ONLY = 2; // 0x2
+    field public static final int USSD_OVER_CS_PREFERRED = 0; // 0x0
+    field public static final int USSD_OVER_IMS_ONLY = 3; // 0x3
+    field public static final int USSD_OVER_IMS_PREFERRED = 1; // 0x1
   }
 
   public static final class CarrierConfigManager.Apn {
diff --git a/api/system-current.txt b/api/system-current.txt
index 55cc12e..dcffa06 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -393,6 +393,7 @@
     field public static final String OPSTR_LOADER_USAGE_STATS = "android:loader_usage_stats";
     field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
     field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
+    field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
     field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
     field public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
@@ -9376,8 +9377,13 @@
     ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
   }
 
+  public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    method public int getNamespace();
+  }
+
   public static final class KeyGenParameterSpec.Builder {
-    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
+    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setNamespace(int);
+    method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
   }
 
 }
@@ -10586,6 +10592,17 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
   }
 
+  public final class CarrierBandwidth implements android.os.Parcelable {
+    ctor public CarrierBandwidth(int, int, int, int);
+    method public int describeContents();
+    method public int getPrimaryDownlinkCapacityKbps();
+    method public int getPrimaryUplinkCapacityKbps();
+    method public int getSecondaryDownlinkCapacityKbps();
+    method public int getSecondaryUplinkCapacityKbps();
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierBandwidth> CREATOR;
+    field public static final int INVALID = -1; // 0xffffffff
+  }
+
   public class CarrierConfigManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
     method @NonNull public static android.os.PersistableBundle getDefaultConfig();
@@ -11202,6 +11219,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierBandwidth getCarrierBandwidth();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -11801,7 +11819,6 @@
     method public int getEmergencyServiceCategories();
     method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
     method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
-    method @NonNull public java.util.Set<android.telephony.ims.RtpHeaderExtensionType> getOfferedRtpHeaderExtensionTypes();
     method @NonNull public android.os.Bundle getProprietaryCallExtras();
     method public int getRestrictCause();
     method public int getServiceType();
@@ -11823,7 +11840,6 @@
     method public void setEmergencyServiceCategories(int);
     method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
     method public void setHasKnownUserIntentEmergency(boolean);
-    method public void setOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
     method public void updateCallType(android.telephony.ims.ImsCallProfile);
     method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
@@ -12332,6 +12348,7 @@
   public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public MmTelFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
     method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
     method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
     method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
diff --git a/config/hiddenapi-temp-blocklist.txt b/config/hiddenapi-temp-blocklist.txt
new file mode 100644
index 0000000..246eeea
--- /dev/null
+++ b/config/hiddenapi-temp-blocklist.txt
@@ -0,0 +1,55 @@
+Landroid/app/IActivityManager$Stub$Proxy;->setActivityController(Landroid/app/IActivityController;Z)V
+Landroid/app/IActivityManager$Stub$Proxy;->updatePersistentConfiguration(Landroid/content/res/Configuration;)V
+Landroid/app/IActivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
+Landroid/app/IInstrumentationWatcher$Stub;-><init>()V
+Landroid/app/INotificationManager$Stub;->TRANSACTION_enqueueNotificationWithTag:I
+Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
+Landroid/bluetooth/IBluetooth$Stub;->TRANSACTION_enable:I
+Landroid/bluetooth/IBluetoothManager$Stub;->TRANSACTION_enable:I
+Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
+Landroid/content/om/IOverlayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/om/IOverlayManager;
+Landroid/content/pm/IPackageManager$Stub;->TRANSACTION_getApplicationInfo:I
+Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
+Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
+Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
+Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
+Landroid/location/IGeofenceProvider$Stub;-><init>()V
+Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
+Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String;
+Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String;
+Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
+Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
+Landroid/net/INetworkPolicyListener$Stub;-><init>()V
+Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
+Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
+Landroid/net/wifi/IWifiManager$Stub;->TRANSACTION_getScanResults:I
+Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager;
+Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
+Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
+Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I
+Landroid/service/euicc/IEuiccService$Stub;-><init>()V
+Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
+Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
+Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
+Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService;
+Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
+Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
+Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V
+Lcom/android/ims/internal/IImsEcbm$Stub;-><init>()V
+Lcom/android/ims/internal/IImsService$Stub;-><init>()V
+Lcom/android/ims/internal/IImsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsService;
+Lcom/android/ims/internal/IImsUt$Stub;-><init>()V
+Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
+Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V
+Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
+Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
+Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
+Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
+Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
+Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
+Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V
+Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager;
+Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
+Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
+Lcom/android/internal/widget/IRemoteViewsFactory$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/IRemoteViewsFactory;
diff --git a/config/hiddenapi-unsupported.txt b/config/hiddenapi-unsupported.txt
index a3543dc..8a377ac 100644
--- a/config/hiddenapi-unsupported.txt
+++ b/config/hiddenapi-unsupported.txt
@@ -26,19 +26,14 @@
 Landroid/app/IActivityManager$Stub$Proxy;->getProcessLimit()I
 Landroid/app/IActivityManager$Stub$Proxy;->getProcessPss([I)[J
 Landroid/app/IActivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/app/IActivityManager$Stub$Proxy;->setActivityController(Landroid/app/IActivityController;Z)V
-Landroid/app/IActivityManager$Stub$Proxy;->updatePersistentConfiguration(Landroid/content/res/Configuration;)V
-Landroid/app/IActivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
 Landroid/app/IAlarmManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IAlarmManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IAlarmManager;
 Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I
 Landroid/app/IAlarmManager$Stub;->TRANSACTION_set:I
 Landroid/app/IAssistDataReceiver$Stub;-><init>()V
-Landroid/app/IInstrumentationWatcher$Stub;-><init>()V
 Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/INotificationManager$Stub$Proxy;->areNotificationsEnabledForPackage(Ljava/lang/String;I)Z
 Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
-Landroid/app/INotificationManager$Stub;->TRANSACTION_enqueueNotificationWithTag:I
 Landroid/app/IProcessObserver$Stub;-><init>()V
 Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
 Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;
@@ -68,9 +63,7 @@
 Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/usage/IUsageStatsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/usage/IUsageStatsManager;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
-Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
 Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
-Landroid/bluetooth/IBluetooth$Stub;->TRANSACTION_enable:I
 Landroid/bluetooth/IBluetoothA2dp$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothA2dp;
 Landroid/bluetooth/IBluetoothCallback$Stub;-><init>()V
 Landroid/bluetooth/IBluetoothGattCallback$Stub;-><init>()V
@@ -79,11 +72,9 @@
 Landroid/bluetooth/IBluetoothHidDeviceCallback$Stub;-><init>()V
 Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/bluetooth/IBluetoothManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothManager;
-Landroid/bluetooth/IBluetoothManager$Stub;->TRANSACTION_enable:I
 Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V
 Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
 Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
-Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -108,7 +99,6 @@
 Landroid/content/ISyncStatusObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncStatusObserver$Stub;-><init>()V
 Landroid/content/ISyncStatusObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncStatusObserver;
-Landroid/content/om/IOverlayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/om/IOverlayManager;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V
@@ -141,7 +131,6 @@
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang/String;
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
 Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
-Landroid/content/pm/IPackageManager$Stub;->TRANSACTION_getApplicationInfo:I
 Landroid/content/pm/IPackageMoveObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageMoveObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageMoveObserver;
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -155,30 +144,20 @@
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
 Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService;
-Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
 Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
-Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
-Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
-Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/IGeocodeProvider;
-Landroid/location/IGeofenceProvider$Stub;-><init>()V
 Landroid/location/ILocationListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationListener$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/location/ILocationListener$Stub;-><init>()V
 Landroid/location/ILocationListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationListener;
 Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
-Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
 Landroid/location/INetInitiatedListener$Stub;-><init>()V
-Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String;
-Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String;
-Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
 Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/media/IAudioService$Stub;-><init>()V
@@ -186,7 +165,6 @@
 Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService;
 Landroid/media/IMediaScannerListener$Stub;-><init>()V
 Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService;
-Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
 Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
 Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V
 Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -200,23 +178,17 @@
 Landroid/net/IConnectivityManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/net/IConnectivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IConnectivityManager;
 Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
-Landroid/net/INetworkPolicyListener$Stub;-><init>()V
 Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager;
 Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkScoreService;
 Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String;
 Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService;
-Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
-Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
 Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
-Landroid/net/wifi/IWifiManager$Stub;->TRANSACTION_getScanResults:I
 Landroid/net/wifi/IWifiScanner$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiScanner$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/net/wifi/IWifiScanner$Stub;-><init>()V
 Landroid/net/wifi/IWifiScanner$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiScanner;
-Landroid/net/wifi/p2p/IWifiP2pManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/p2p/IWifiP2pManager;
-Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
 Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/IDeviceIdentifiersPolicyService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdentifiersPolicyService;
 Landroid/os/IDeviceIdleController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdleController;
@@ -227,8 +199,6 @@
 Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z
 Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
-Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
-Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I
 Landroid/os/IRecoverySystem$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IRecoverySystem;
 Landroid/os/IRemoteCallback$Stub;-><init>()V
 Landroid/os/IUpdateEngine$Stub;-><init>()V
@@ -241,16 +211,11 @@
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
 Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
-Landroid/service/euicc/IEuiccService$Stub;-><init>()V
-Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
 Landroid/service/notification/INotificationListener$Stub;-><init>()V
 Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
 Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
 Landroid/service/wallpaper/IWallpaperConnection$Stub;-><init>()V
 Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
-Landroid/telephony/mbms/IMbmsStreamingSessionCallback$Stub;-><init>()V
-Landroid/telephony/mbms/IStreamingServiceCallback$Stub;-><init>()V
-Landroid/telephony/mbms/vendor/IMbmsStreamingService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/telephony/mbms/vendor/IMbmsStreamingService;
 Landroid/view/accessibility/IAccessibilityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/accessibility/IAccessibilityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/accessibility/IAccessibilityManager;
 Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -274,19 +239,7 @@
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse;
 Landroid/webkit/IWebViewUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/webkit/IWebViewUpdateService;
-Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
-Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
 Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession;
-Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V
-Lcom/android/ims/internal/IImsEcbm$Stub;-><init>()V
-Lcom/android/ims/internal/IImsService$Stub;-><init>()V
-Lcom/android/ims/internal/IImsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsService;
-Lcom/android/ims/internal/IImsUt$Stub;-><init>()V
-Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
-Lcom/android/ims/internal/uce/options/IOptionsService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
-Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
-Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
 Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -313,15 +266,10 @@
 Lcom/android/internal/app/IBatteryStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IBatteryStats$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IBatteryStats;
 Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService;
-Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
 Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
-Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
 Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V
-Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
 Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider;
-Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V
-Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager;
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
 Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
@@ -343,9 +291,7 @@
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
-Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
@@ -355,4 +301,3 @@
 Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
 Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession;
 Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
-Lcom/android/internal/widget/IRemoteViewsFactory$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/IRemoteViewsFactory;
diff --git a/core/api/current.txt b/core/api/current.txt
index b3561a3..055f909 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -96,6 +96,7 @@
     field public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
     field public static final String MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE";
+    field public static final String MANAGE_ONGOING_CALLS = "android.permission.MANAGE_ONGOING_CALLS";
     field public static final String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
@@ -40988,10 +40989,11 @@
     method public String getKeystoreAlias();
     method public int getOrigin();
     method public int getPurposes();
+    method public int getSecurityLevel();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
     method public int getUserAuthenticationValidityDurationSeconds();
-    method public boolean isInsideSecureHardware();
+    method @Deprecated public boolean isInsideSecureHardware();
     method public boolean isInvalidatedByBiometricEnrollment();
     method public boolean isTrustedUserPresenceRequired();
     method public boolean isUserAuthenticationRequired();
@@ -44017,6 +44019,8 @@
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
     field public static final String EXTRA_AUDIO_CODEC = "android.telecom.extra.AUDIO_CODEC";
+    field public static final String EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ = "android.telecom.extra.AUDIO_CODEC_BANDWIDTH_KHZ";
+    field public static final String EXTRA_AUDIO_CODEC_BITRATE_KBPS = "android.telecom.extra.AUDIO_CODEC_BITRATE_KBPS";
     field public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
@@ -44463,6 +44467,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle);
+    method public boolean hasCompanionInCallServiceAccess();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInCall();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
@@ -44862,6 +44867,7 @@
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
     field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
+    field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
     field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
     field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
@@ -45056,6 +45062,10 @@
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
     field public static final int SERVICE_CLASS_NONE = 0; // 0x0
     field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
+    field public static final int USSD_OVER_CS_ONLY = 2; // 0x2
+    field public static final int USSD_OVER_CS_PREFERRED = 0; // 0x0
+    field public static final int USSD_OVER_IMS_ONLY = 3; // 0x3
+    field public static final int USSD_OVER_IMS_PREFERRED = 1; // 0x1
   }
 
   public static final class CarrierConfigManager.Apn {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index dc9789f..18d1064 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -393,6 +393,7 @@
     field public static final String OPSTR_LOADER_USAGE_STATS = "android:loader_usage_stats";
     field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
     field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
+    field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
     field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
     field public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
@@ -8258,8 +8259,13 @@
     ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
   }
 
+  public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    method public int getNamespace();
+  }
+
   public static final class KeyGenParameterSpec.Builder {
-    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
+    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setNamespace(int);
+    method @Deprecated @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUid(int);
   }
 
 }
@@ -9468,6 +9474,17 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
   }
 
+  public final class CarrierBandwidth implements android.os.Parcelable {
+    ctor public CarrierBandwidth(int, int, int, int);
+    method public int describeContents();
+    method public int getPrimaryDownlinkCapacityKbps();
+    method public int getPrimaryUplinkCapacityKbps();
+    method public int getSecondaryDownlinkCapacityKbps();
+    method public int getSecondaryUplinkCapacityKbps();
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierBandwidth> CREATOR;
+    field public static final int INVALID = -1; // 0xffffffff
+  }
+
   public class CarrierConfigManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
     method @NonNull public static android.os.PersistableBundle getDefaultConfig();
@@ -10084,6 +10101,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierBandwidth getCarrierBandwidth();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -10683,7 +10701,6 @@
     method public int getEmergencyServiceCategories();
     method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
     method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
-    method @NonNull public java.util.Set<android.telephony.ims.RtpHeaderExtensionType> getOfferedRtpHeaderExtensionTypes();
     method @NonNull public android.os.Bundle getProprietaryCallExtras();
     method public int getRestrictCause();
     method public int getServiceType();
@@ -10705,7 +10722,6 @@
     method public void setEmergencyServiceCategories(int);
     method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
     method public void setHasKnownUserIntentEmergency(boolean);
-    method public void setOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
     method public void updateCallType(android.telephony.ims.ImsCallProfile);
     method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
@@ -11214,6 +11230,7 @@
   public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public MmTelFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
     method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
     method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
     method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9c51729..6aaf973 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -192,6 +192,7 @@
     field public static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
     field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
     field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
+    field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
     field public static final int OP_START_FOREGROUND = 76; // 0x4c
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e0eea70..c4f13fe 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -846,6 +846,8 @@
     @UnsupportedAppUsage
     public static final int OP_SEND_SMS = AppProtoEnums.APP_OP_SEND_SMS;
     /** @hide */
+    public static final int OP_MANAGE_ONGOING_CALLS = AppProtoEnums.APP_OP_MANAGE_ONGOING_CALLS;
+    /** @hide */
     @UnsupportedAppUsage
     public static final int OP_READ_ICC_SMS = AppProtoEnums.APP_OP_READ_ICC_SMS;
     /** @hide */
@@ -1134,7 +1136,7 @@
 
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 103;
+    public static final int _NUM_OP = 104;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1446,6 +1448,15 @@
     public static final String OPSTR_LOADER_USAGE_STATS = "android:loader_usage_stats";
 
     /**
+     * Grants an app access to the {@link android.telecom.InCallService} API to see
+     * information about ongoing calls and to enable control of calls.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
+
+    /**
      * AppOp granted to apps that we are started via {@code am instrument -e --no-isolated-storage}
      *
      * @hide
@@ -1551,6 +1562,7 @@
             OP_MANAGE_EXTERNAL_STORAGE,
             OP_INTERACT_ACROSS_PROFILES,
             OP_LOADER_USAGE_STATS,
+            OP_MANAGE_ONGOING_CALLS,
     };
 
     /**
@@ -1665,6 +1677,7 @@
             OP_RESERVED_100,                    // OP_RESERVED_100
             OP_RESERVED_101,                    // OP_RESERVED_101
             OP_RESERVED_102,                    // OP_RESERVED_102
+            OP_MANAGE_ONGOING_CALLS,            // MANAGE_ONGOING_CALLS
     };
 
     /**
@@ -1774,6 +1787,7 @@
             OPSTR_RESERVED_100,
             OPSTR_RESERVED_101,
             OPSTR_RESERVED_102,
+            OPSTR_MANAGE_ONGOING_CALLS,
     };
 
     /**
@@ -1884,6 +1898,7 @@
             "RESERVED_100",
             "RESERVED_101",
             "RESERVED_102",
+            "MANAGE_ONGOING_CALLS",
     };
 
     /**
@@ -1995,6 +2010,7 @@
             null, // OP_RESERVED_100
             null, // OP_RESERVED_101
             null, // OP_RESERVED_102
+            Manifest.permission.MANAGE_ONGOING_CALLS,
     };
 
     /**
@@ -2106,6 +2122,7 @@
             null, // OP_RESERVED_100
             null, // OP_RESERVED_101
             null, // OP_RESERVED_102
+            null, // MANAGE_ONGOING_CALLS
     };
 
     /**
@@ -2216,6 +2233,7 @@
             null, // OP_RESERVED_100
             null, // OP_RESERVED_101
             null, // OP_RESERVED_102
+            null, // MANAGE_ONGOING_CALLS
     };
 
     /**
@@ -2325,6 +2343,7 @@
             AppOpsManager.MODE_ERRORED, // OP_RESERVED_100
             AppOpsManager.MODE_ERRORED, // OP_RESERVED_101
             AppOpsManager.MODE_ERRORED, // OP_RESERVED_102
+            AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
     };
 
     /**
@@ -2438,6 +2457,7 @@
             false, // OP_RESERVED_100
             false, // OP_RESERVED_101
             false, // OP_RESERVED_102
+            true, // MANAGE_ONGOING_CALLS
     };
 
     /**
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 7e7710b..0f88811 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,4 +1,4 @@
 # Bug component: 656484
 
-include platform/frameworks/base/services/backup:/OWNERS
+include platform/frameworks/base:/services/backup/OWNERS
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1cca53f..81d9b11 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2101,6 +2101,7 @@
     }
 
     /** @hide */
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     public boolean isOem() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
     }
@@ -2148,11 +2149,13 @@
     }
 
     /** @hide */
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     public boolean isVendor() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
     }
 
     /** @hide */
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
     public boolean isProduct() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0b8db0d..74463fd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -40,7 +40,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.usage.StorageStatsManager;
 import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -3682,7 +3682,7 @@
      * @hide
      */
     @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.R)
     public static final long FILTER_APPLICATION_QUERY = 135549675L;
 
     /** {@hide} */
diff --git a/core/java/android/net/OemNetworkPreferences.java b/core/java/android/net/OemNetworkPreferences.java
index 0778943..6a8e3f9 100644
--- a/core/java/android/net/OemNetworkPreferences.java
+++ b/core/java/android/net/OemNetworkPreferences.java
@@ -36,12 +36,16 @@
     public static final int OEM_NETWORK_PREFERENCE_DEFAULT = 0;
 
     /**
-     * Prefer networks in order: NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_OEM_PAID, default.
+     * If an unmetered network is available, use it.
+     * Otherwise, if a network with the OEM_PAID capability is available, use it.
+     * Otherwise, use the general default network.
      */
     public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1;
 
     /**
-     * Prefer networks in order: NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_OEM_PAID.
+     * If an unmetered network is available, use it.
+     * Otherwise, if a network with the OEM_PAID capability is available, use it.
+     * Otherwise, the app doesn't get a network.
      */
     public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2;
 
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index a985e93..7376830 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -976,11 +976,17 @@
         }
     }
 
-    // NOTE: keep these in sync with android_net_TrafficStats.cpp
-    private static final int TYPE_RX_BYTES = 0;
-    private static final int TYPE_RX_PACKETS = 1;
-    private static final int TYPE_TX_BYTES = 2;
-    private static final int TYPE_TX_PACKETS = 3;
-    private static final int TYPE_TCP_RX_PACKETS = 4;
-    private static final int TYPE_TCP_TX_PACKETS = 5;
+    // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}.
+    /** {@hide} */
+    public static final int TYPE_RX_BYTES = 0;
+    /** {@hide} */
+    public static final int TYPE_RX_PACKETS = 1;
+    /** {@hide} */
+    public static final int TYPE_TX_BYTES = 2;
+    /** {@hide} */
+    public static final int TYPE_TX_PACKETS = 3;
+    /** {@hide} */
+    public static final int TYPE_TCP_RX_PACKETS = 4;
+    /** {@hide} */
+    public static final int TYPE_TCP_TX_PACKETS = 5;
 }
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index d91c458..010459d 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -170,6 +170,15 @@
     int FLAG_ONEWAY             = 0x00000001;
 
     /**
+     * Flag to {@link #transact}: request binder driver to clear transaction data.
+     *
+     * Be very careful when using this flag in Java, since Java objects read from a Java
+     * Parcel may be non-trivial to clear.
+     * @hide
+     */
+    int FLAG_CLEAR_BUF          = 0x00000020;
+
+    /**
      * @hide
      */
     int FLAG_COLLECT_NOTED_APP_OPS = 0x00000002;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 9c7f8be..cf90174 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -277,6 +277,8 @@
     private static final int EX_TRANSACTION_FAILED = -129;
 
     @CriticalNative
+    private static native void nativeMarkSensitive(long nativePtr);
+    @CriticalNative
     private static native int nativeDataSize(long nativePtr);
     @CriticalNative
     private static native int nativeDataAvail(long nativePtr);
@@ -491,6 +493,14 @@
     public static native long getGlobalAllocCount();
 
     /**
+     * Parcel data should be zero'd before realloc'd or deleted.
+     * @hide
+     */
+    public final void markSensitive() {
+        nativeMarkSensitive(mNativePtr);
+    }
+
+    /**
      * Returns the total amount of data contained in the parcel.
      */
     public final int dataSize() {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index ded9be5..ab74199 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -60,7 +60,7 @@
      * uses reflection to read this whenever text is selected (http://b/36095274).
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @UnsupportedAppUsage(trackingBug = 172649311)
     public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
 
     /** @hide */
diff --git a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
index 2a809b1..4ffffc6 100644
--- a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
+++ b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
@@ -46,12 +46,13 @@
  * CarrierMessagingService.
  * @hide
  */
-public abstract class CarrierMessagingServiceWrapper {
+public final class CarrierMessagingServiceWrapper {
     // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
     // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
     private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;
 
     private volatile ICarrierMessagingService mICarrierMessagingService;
+    private Runnable mOnServiceReadyCallback;
 
     /**
      * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
@@ -63,12 +64,14 @@
      * @hide
      */
     public boolean bindToCarrierMessagingService(@NonNull Context context,
-            @NonNull String carrierPackageName) {
+            @NonNull String carrierPackageName,
+            @NonNull Runnable onServiceReadyCallback) {
         Preconditions.checkState(mCarrierMessagingServiceConnection == null);
 
         Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
         intent.setPackage(carrierPackageName);
         mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
+        mOnServiceReadyCallback = onServiceReadyCallback;
         return context.bindService(intent, mCarrierMessagingServiceConnection,
                 Context.BIND_AUTO_CREATE);
     }
@@ -83,22 +86,17 @@
         Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
         context.unbindService(mCarrierMessagingServiceConnection);
         mCarrierMessagingServiceConnection = null;
+        mOnServiceReadyCallback = null;
     }
 
     /**
-     * Implemented by subclasses to use the carrier messaging service once it is ready.
-     * @hide
-     */
-    public abstract void onServiceReady();
-
-    /**
      * Called when connection with service is established.
      *
      * @param carrierMessagingService the carrier messaing service interface
      */
     private void onServiceReady(ICarrierMessagingService carrierMessagingService) {
         mICarrierMessagingService = carrierMessagingService;
-        onServiceReady();
+        if (mOnServiceReadyCallback != null) mOnServiceReadyCallback.run();
     }
 
     /**
@@ -113,11 +111,11 @@
      * @hide
      */
     public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
-            int subId, @NonNull final CarrierMessagingCallbackWrapper callback) {
+            int subId, @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.filterSms(pdu, format, destPort, subId,
-                        new CarrierMessagingCallbackWrapperInternal(callback));
+                        new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -137,11 +135,11 @@
      * @hide
      */
     public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress,
-            int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) {
+            int sendSmsFlag, @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag,
-                        new CarrierMessagingCallbackWrapperInternal(callback));
+                        new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -163,11 +161,11 @@
      */
     public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress,
             int destPort, int sendSmsFlag,
-            @NonNull final CarrierMessagingCallbackWrapper callback) {
+            @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort,
-                        sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
+                        sendSmsFlag, new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -188,11 +186,11 @@
      */
     public void sendMultipartTextSms(@NonNull List<String> parts, int subId,
             @NonNull String destAddress, int sendSmsFlag,
-            @NonNull final CarrierMessagingCallbackWrapper callback) {
+            @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress,
-                        sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
+                        sendSmsFlag, new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -212,11 +210,11 @@
      * @hide
      */
     public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
-            @NonNull final CarrierMessagingCallbackWrapper callback) {
+            @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.sendMms(pduUri, subId, location,
-                        new CarrierMessagingCallbackWrapperInternal(callback));
+                        new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -235,11 +233,11 @@
      * @hide
      */
     public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
-            @NonNull final CarrierMessagingCallbackWrapper callback) {
+            @NonNull final CarrierMessagingCallback callback) {
         if (mICarrierMessagingService != null) {
             try {
                 mICarrierMessagingService.downloadMms(pduUri, subId, location,
-                        new CarrierMessagingCallbackWrapperInternal(callback));
+                        new CarrierMessagingCallbackInternal(callback));
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
@@ -265,7 +263,7 @@
      * {@link CarrierMessagingServiceWrapper}.
      * @hide
      */
-    public abstract static class CarrierMessagingCallbackWrapper {
+    public interface CarrierMessagingCallback {
 
         /**
          * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}.
@@ -277,7 +275,7 @@
          *               {@see CarrierMessagingService#onReceiveTextSms}.
          * @hide
          */
-        public void onFilterComplete(int result) {
+        default void onFilterComplete(int result) {
 
         }
 
@@ -291,7 +289,7 @@
          *                   only if result is {@link CarrierMessagingService#SEND_STATUS_OK}.
          * @hide
          */
-        public void onSendSmsComplete(int result, int messageRef) {
+        default void onSendSmsComplete(int result, int messageRef) {
 
         }
 
@@ -305,7 +303,7 @@
          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
          * @hide
          */
-        public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) {
+        default void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) {
 
         }
 
@@ -319,7 +317,7 @@
          *                    {@link CarrierMessagingService#SEND_STATUS_OK}.
          * @hide
          */
-        public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) {
+        default void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) {
 
         }
 
@@ -330,43 +328,43 @@
          *               and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
          * @hide
          */
-        public void onDownloadMmsComplete(int result) {
+        default void onDownloadMmsComplete(int result) {
 
         }
     }
 
-    private final class CarrierMessagingCallbackWrapperInternal
+    private final class CarrierMessagingCallbackInternal
             extends ICarrierMessagingCallback.Stub {
-        CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper;
+        CarrierMessagingCallback mCarrierMessagingCallback;
 
-        CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) {
-            mCarrierMessagingCallbackWrapper = callback;
+        CarrierMessagingCallbackInternal(CarrierMessagingCallback callback) {
+            mCarrierMessagingCallback = callback;
         }
 
         @Override
         public void onFilterComplete(int result) throws RemoteException {
-            mCarrierMessagingCallbackWrapper.onFilterComplete(result);
+            mCarrierMessagingCallback.onFilterComplete(result);
         }
 
         @Override
         public void onSendSmsComplete(int result, int messageRef) throws RemoteException {
-            mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef);
+            mCarrierMessagingCallback.onSendSmsComplete(result, messageRef);
         }
 
         @Override
         public void onSendMultipartSmsComplete(int result, int[] messageRefs)
                 throws RemoteException {
-            mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs);
+            mCarrierMessagingCallback.onSendMultipartSmsComplete(result, messageRefs);
         }
 
         @Override
         public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException {
-            mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu);
+            mCarrierMessagingCallback.onSendMmsComplete(result, sendConfPdu);
         }
 
         @Override
         public void onDownloadMmsComplete(int result) throws RemoteException {
-            mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result);
+            mCarrierMessagingCallback.onDownloadMmsComplete(result);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java
deleted file mode 100644
index f23d9ed..0000000
--- a/core/java/android/uwb/RangingParams.java
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright 2020 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.uwb;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PersistableBundle;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * An object used when requesting to open a new {@link RangingSession}.
- * <p>Use {@link RangingParams.Builder} to create an instance of this class.
- *
- *  @hide
- */
-public final class RangingParams implements Parcelable {
-    private final boolean mIsInitiator;
-    private final boolean mIsController;
-    private final Duration mSamplePeriod;
-    private final UwbAddress mLocalDeviceAddress;
-    private final List<UwbAddress> mRemoteDeviceAddresses;
-    private final int mChannelNumber;
-    private final int mTransmitPreambleCodeIndex;
-    private final int mReceivePreambleCodeIndex;
-    private final int mStsPhyPacketType;
-    private final PersistableBundle mSpecificationParameters;
-
-    private RangingParams(boolean isInitiator, boolean isController,
-            @NonNull Duration samplingPeriod, @NonNull UwbAddress localDeviceAddress,
-            @NonNull List<UwbAddress> remoteDeviceAddresses, int channelNumber,
-            int transmitPreambleCodeIndex, int receivePreambleCodeIndex,
-            @StsPhyPacketType int stsPhyPacketType,
-            @NonNull PersistableBundle specificationParameters) {
-        mIsInitiator = isInitiator;
-        mIsController = isController;
-        mSamplePeriod = samplingPeriod;
-        mLocalDeviceAddress = localDeviceAddress;
-        mRemoteDeviceAddresses = remoteDeviceAddresses;
-        mChannelNumber = channelNumber;
-        mTransmitPreambleCodeIndex = transmitPreambleCodeIndex;
-        mReceivePreambleCodeIndex = receivePreambleCodeIndex;
-        mStsPhyPacketType = stsPhyPacketType;
-        mSpecificationParameters = specificationParameters;
-    }
-
-    /**
-     * Get if the local device is the initiator
-     *
-     * @return true if the device is the initiator
-     */
-    public boolean isInitiator() {
-        return mIsInitiator;
-    }
-
-    /**
-     * Get if the local device is the controller
-     *
-     * @return true if the device is the controller
-     */
-    public boolean isController() {
-        return mIsController;
-    }
-
-    /**
-     * The desired amount of time between two adjacent samples of measurement
-     *
-     * @return the ranging sample period
-     */
-    @NonNull
-    public Duration getSamplingPeriod() {
-        return mSamplePeriod;
-    }
-
-    /**
-     * Local device's {@link UwbAddress}
-     *
-     * <p>Simultaneous {@link RangingSession}s on the same device can have different results for
-     * {@link #getLocalDeviceAddress()}.
-     *
-     * @return the local device's {@link UwbAddress}
-     */
-    @NonNull
-    public UwbAddress getLocalDeviceAddress() {
-        return mLocalDeviceAddress;
-    }
-
-    /**
-     * Gets a list of all remote device's {@link UwbAddress}
-     *
-     * @return a {@link List} of {@link UwbAddress} representing the remote devices
-     */
-    @NonNull
-    public List<UwbAddress> getRemoteDeviceAddresses() {
-        return mRemoteDeviceAddresses;
-    }
-
-    /**
-     * Channel number used between this device pair as defined by 802.15.4z
-     *
-     * Range: -1, 0-15
-     *
-     * @return the channel to use
-     */
-    public int getChannelNumber() {
-        return mChannelNumber;
-    }
-
-    /**
-     * Preamble index used between this device pair as defined by 802.15.4z
-     *
-     * Range: 0, 0-32
-     *
-     * @return the preamble index to use for transmitting
-     */
-    public int getTxPreambleIndex() {
-        return mTransmitPreambleCodeIndex;
-    }
-
-    /**
-     * preamble index used between this device pair as defined by 802.15.4z
-     *
-     * Range: 0, 13-16, 21-32
-     *
-     * @return the preamble index to use for receiving
-     */
-    public int getRxPreambleIndex() {
-        return mReceivePreambleCodeIndex;
-    }
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            STS_PHY_PACKET_TYPE_SP0,
-            STS_PHY_PACKET_TYPE_SP1,
-            STS_PHY_PACKET_TYPE_SP2,
-            STS_PHY_PACKET_TYPE_SP3})
-    public @interface StsPhyPacketType {}
-
-    /**
-     * PHY packet type SP0 when STS is used as defined by 802.15.4z
-     */
-    public static final int STS_PHY_PACKET_TYPE_SP0 = 0;
-
-    /**
-     * PHY packet type SP1 when STS is used as defined by 802.15.4z
-     */
-    public static final int STS_PHY_PACKET_TYPE_SP1 = 1;
-
-    /**
-     * PHY packet type SP2 when STS is used as defined by 802.15.4z
-     */
-    public static final int STS_PHY_PACKET_TYPE_SP2 = 2;
-
-    /**
-     * PHY packet type SP3 when STS is used as defined by 802.15.4z
-     */
-    public static final int STS_PHY_PACKET_TYPE_SP3 = 3;
-
-    /**
-     * Get the type of PHY packet when STS is used as defined by 802.15.4z
-     *
-     * @return the {@link StsPhyPacketType} to use
-     */
-    @StsPhyPacketType
-    public int getStsPhyPacketType() {
-        return mStsPhyPacketType;
-    }
-
-    /**
-     * Parameters for a specific UWB protocol constructed using a support library.
-     *
-     * <p>Android reserves the '^android.*' namespace
-     *
-     * @return a {@link PersistableBundle} copy of protocol specific parameters
-     */
-    public @Nullable PersistableBundle getSpecificationParameters() {
-        return new PersistableBundle(mSpecificationParameters);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof RangingParams) {
-            RangingParams other = (RangingParams) obj;
-
-            return mIsInitiator == other.mIsInitiator
-                    && mIsController == other.mIsController
-                    && mSamplePeriod.equals(other.mSamplePeriod)
-                    && mLocalDeviceAddress.equals(other.mLocalDeviceAddress)
-                    && mRemoteDeviceAddresses.equals(other.mRemoteDeviceAddresses)
-                    && mChannelNumber == other.mChannelNumber
-                    && mTransmitPreambleCodeIndex == other.mTransmitPreambleCodeIndex
-                    && mReceivePreambleCodeIndex == other.mReceivePreambleCodeIndex
-                    && mStsPhyPacketType == other.mStsPhyPacketType
-                    && mSpecificationParameters.size() == other.mSpecificationParameters.size()
-                    && mSpecificationParameters.kindofEquals(other.mSpecificationParameters);
-        }
-        return false;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hash(mIsInitiator, mIsController, mSamplePeriod, mLocalDeviceAddress,
-                mRemoteDeviceAddresses, mChannelNumber, mTransmitPreambleCodeIndex,
-                mReceivePreambleCodeIndex, mStsPhyPacketType, mSpecificationParameters);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeBoolean(mIsInitiator);
-        dest.writeBoolean(mIsController);
-        dest.writeLong(mSamplePeriod.getSeconds());
-        dest.writeInt(mSamplePeriod.getNano());
-        dest.writeParcelable(mLocalDeviceAddress, flags);
-
-        UwbAddress[] remoteAddresses = new UwbAddress[mRemoteDeviceAddresses.size()];
-        mRemoteDeviceAddresses.toArray(remoteAddresses);
-        dest.writeParcelableArray(remoteAddresses, flags);
-
-        dest.writeInt(mChannelNumber);
-        dest.writeInt(mTransmitPreambleCodeIndex);
-        dest.writeInt(mReceivePreambleCodeIndex);
-        dest.writeInt(mStsPhyPacketType);
-        dest.writePersistableBundle(mSpecificationParameters);
-    }
-
-    public static final @android.annotation.NonNull Creator<RangingParams> CREATOR =
-            new Creator<RangingParams>() {
-                @Override
-                public RangingParams createFromParcel(Parcel in) {
-                    Builder builder = new Builder();
-                    builder.setIsInitiator(in.readBoolean());
-                    builder.setIsController(in.readBoolean());
-                    builder.setSamplePeriod(Duration.ofSeconds(in.readLong(), in.readInt()));
-                    builder.setLocalDeviceAddress(
-                            in.readParcelable(UwbAddress.class.getClassLoader()));
-
-                    UwbAddress[] remoteAddresses =
-                            in.readParcelableArray(null, UwbAddress.class);
-                    for (UwbAddress remoteAddress : remoteAddresses) {
-                        builder.addRemoteDeviceAddress(remoteAddress);
-                    }
-
-                    builder.setChannelNumber(in.readInt());
-                    builder.setTransmitPreambleCodeIndex(in.readInt());
-                    builder.setReceivePreambleCodeIndex(in.readInt());
-                    builder.setStsPhPacketType(in.readInt());
-                    builder.setSpecificationParameters(in.readPersistableBundle());
-
-                    return builder.build();
-                }
-
-                @Override
-                public RangingParams[] newArray(int size) {
-                    return new RangingParams[size];
-                }
-    };
-
-    /**
-     * Builder class for {@link RangingParams}.
-     */
-    public static final class Builder {
-        private boolean mIsInitiator = false;
-        private boolean mIsController = false;
-        private Duration mSamplePeriod = null;
-        private UwbAddress mLocalDeviceAddress = null;
-        private List<UwbAddress> mRemoteDeviceAddresses = new ArrayList<>();
-        private int mChannelNumber = 0;
-        private int mTransmitPreambleCodeIndex = 0;
-        private int mReceivePreambleCodeIndex = 0;
-        private int mStsPhyPacketType = STS_PHY_PACKET_TYPE_SP0;
-        private PersistableBundle mSpecificationParameters = new PersistableBundle();
-
-        /**
-         * Set whether the device is the initiator or responder as defined by IEEE 802.15.4z
-         *
-         * @param isInitiator whether the device is the initiator (true) or responder (false)
-         */
-        public Builder setIsInitiator(boolean isInitiator) {
-            mIsInitiator = isInitiator;
-            return this;
-        }
-
-        /**
-         * Set whether the local device is the controller or controlee as defined by IEEE 802.15.4z
-         *
-         * @param isController whether the device is the controller (true) or controlee (false)
-         */
-        public Builder setIsController(boolean isController) {
-            mIsController = isController;
-            return this;
-        }
-
-        /**
-         * Set the time between ranging samples
-         *
-         * @param samplePeriod the time between ranging samples
-         */
-        public Builder setSamplePeriod(@NonNull Duration samplePeriod) {
-            mSamplePeriod = samplePeriod;
-            return this;
-        }
-
-        /**
-         * Set the local device address
-         *
-         * @param localDeviceAddress the local device's address for the {@link RangingSession}
-         */
-        public Builder setLocalDeviceAddress(@NonNull UwbAddress localDeviceAddress) {
-            mLocalDeviceAddress = localDeviceAddress;
-            return this;
-        }
-
-        /**
-         * Add a remote device's address to the ranging session
-         *
-         * @param remoteDeviceAddress a remote device's address for the {@link RangingSession}
-         * @throws IllegalArgumentException if {@code remoteDeviceAddress} is already present.
-         */
-        public Builder addRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
-            if (mRemoteDeviceAddresses.contains(remoteDeviceAddress)) {
-                throw new IllegalArgumentException(
-                        "Remote device address already added: " + remoteDeviceAddress.toString());
-            }
-            mRemoteDeviceAddresses.add(remoteDeviceAddress);
-            return this;
-        }
-
-        /**
-         * Set the IEEE 802.15.4z channel to use for the {@link RangingSession}
-         * <p>Valid values are in the range [-1, 15]
-         *
-         * @param channelNumber the channel to use for the {@link RangingSession}
-         * @throws IllegalArgumentException if {@code channelNumber} is invalid.
-         */
-        public Builder setChannelNumber(int channelNumber) {
-            if (channelNumber < -1 || channelNumber > 15) {
-                throw new IllegalArgumentException("Invalid channel number");
-            }
-            mChannelNumber = channelNumber;
-            return this;
-        }
-
-        private static final Set<Integer> VALID_TX_PREAMBLE_CODES = new HashSet<Integer>(
-                Arrays.asList(0, 13, 14, 15, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32));
-
-        /**
-         * Set the IEEE 802.15.4z preamble code index to use when transmitting
-         *
-         * <p>Valid values are in the ranges: [0], [13-16], [21-32]
-         *
-         * @param transmitPreambleCodeIndex preamble code index to use for transmitting
-         * @throws IllegalArgumentException if {@code transmitPreambleCodeIndex} is invalid.
-         */
-        public Builder setTransmitPreambleCodeIndex(int transmitPreambleCodeIndex) {
-            if (!VALID_TX_PREAMBLE_CODES.contains(transmitPreambleCodeIndex)) {
-                throw new IllegalArgumentException(
-                        "Invalid transmit preamble: " + transmitPreambleCodeIndex);
-            }
-            mTransmitPreambleCodeIndex = transmitPreambleCodeIndex;
-            return this;
-        }
-
-        private static final Set<Integer> VALID_RX_PREAMBLE_CODES = new HashSet<Integer>(
-                Arrays.asList(0, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32));
-
-        /**
-         * Set the IEEE 802.15.4z preamble code index to use when receiving
-         *
-         * Valid values are in the ranges: [0], [16-32]
-         *
-         * @param receivePreambleCodeIndex preamble code index to use for receiving
-         * @throws IllegalArgumentException if {@code receivePreambleCodeIndex} is invalid.
-         */
-        public Builder setReceivePreambleCodeIndex(int receivePreambleCodeIndex) {
-            if (!VALID_RX_PREAMBLE_CODES.contains(receivePreambleCodeIndex)) {
-                throw new IllegalArgumentException(
-                        "Invalid receive preamble: " + receivePreambleCodeIndex);
-            }
-            mReceivePreambleCodeIndex = receivePreambleCodeIndex;
-            return this;
-        }
-
-        /**
-         * Set the IEEE 802.15.4z PHY packet type when STS is used
-         *
-         * @param stsPhyPacketType PHY packet type when STS is used
-         * @throws IllegalArgumentException if {@code stsPhyPacketType} is invalid.
-         */
-        public Builder setStsPhPacketType(@StsPhyPacketType int stsPhyPacketType) {
-            if (stsPhyPacketType != STS_PHY_PACKET_TYPE_SP0
-                    && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP1
-                    && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP2
-                    && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP3) {
-                throw new IllegalArgumentException("unknown StsPhyPacketType: " + stsPhyPacketType);
-            }
-
-            mStsPhyPacketType = stsPhyPacketType;
-            return this;
-        }
-
-        /**
-         * Set the specification parameters
-         *
-         * <p>Creates a copy of the parameters
-         *
-         * @param parameters specification parameters built from support library
-         */
-        public Builder setSpecificationParameters(@NonNull PersistableBundle parameters) {
-            mSpecificationParameters = new PersistableBundle(parameters);
-            return this;
-        }
-
-        /**
-         * Build the {@link RangingParams} object.
-         *
-         * @throws IllegalStateException if required parameters are missing
-         */
-        public RangingParams build() {
-            if (mSamplePeriod == null) {
-                throw new IllegalStateException("No sample period provided");
-            }
-
-            if (mLocalDeviceAddress == null) {
-                throw new IllegalStateException("Local device address not provided");
-            }
-
-            if (mRemoteDeviceAddresses.size() == 0) {
-                throw new IllegalStateException("No remote device address(es) provided");
-            }
-
-            return new RangingParams(mIsInitiator, mIsController, mSamplePeriod,
-                    mLocalDeviceAddress, mRemoteDeviceAddresses, mChannelNumber,
-                    mTransmitPreambleCodeIndex, mReceivePreambleCodeIndex, mStsPhyPacketType,
-                    mSpecificationParameters);
-        }
-    }
-}
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
index f4033fe..8639269 100644
--- a/core/java/android/uwb/RangingSession.java
+++ b/core/java/android/uwb/RangingSession.java
@@ -30,7 +30,7 @@
  * {@link RangingSession}.
  *
  * <p>To get an instance of {@link RangingSession}, first use
- * {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)} to request to open a
+ * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
  * session. Once the session is opened, a {@link RangingSession} object is provided through
  * {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)}. If opening a
  * session fails, the failure is reported through {@link RangingSession.Callback#onClosed(int)} with
@@ -44,7 +44,7 @@
      */
     public interface Callback {
         /**
-         * Invoked when {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)}
+         * Invoked when {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
          * is successful
          *
          * @param session the newly opened {@link RangingSession}
@@ -77,7 +77,7 @@
 
         /**
          * Indicates that the session failed to open due to erroneous parameters passed
-         * to {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)}
+         * to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
          */
         int CLOSE_REASON_LOCAL_BAD_PARAMETERS = 2;
 
@@ -137,8 +137,8 @@
      * will still be invoked.
      *
      * <p>{@link Callback#onClosed(int)} will be invoked using the same callback
-     * object given to {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)} when
-     * the {@link RangingSession} was opened. The callback will be invoked after each call to
+     * object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
+     * when the {@link RangingSession} was opened. The callback will be invoked after each call to
      * {@link #close()}, even if the {@link RangingSession} is already closed.
      */
     @Override
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index d58d5bf..2f1e2de 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -176,15 +176,14 @@
      * arrangement, a platform may only support hemi-spherical azimuth angles
      * ranging from -pi/2 to pi/2
      */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 2;
+    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3;
 
     /**
      * Indicate support for three dimensional angle of arrival measurement.
      * Typically requires at least three antennas. This mode supports full
      * azimuth angles ranging from -pi to pi.
      */
-    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 3;
-
+    public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4;
 
     /**
      * Gets the {@link AngleOfArrivalSupportType} supported on this platform
@@ -280,7 +279,10 @@
      * <p>An open {@link RangingSession} will be automatically closed if client application process
      * dies.
      *
-     * @param params {@link RangingParams} used to initialize this {@link RangingSession}
+     * <p>A UWB support library must be used in order to construct the {@code parameter}
+     * {@link PersistableBundle}.
+     *
+     * @param parameters the parameters that define the ranging session
      * @param executor {@link Executor} to run callbacks
      * @param callbacks {@link RangingSession.Callback} to associate with the
      *                  {@link RangingSession} that is being opened.
@@ -291,8 +293,9 @@
      *         {@link RangingSession.Callback#onOpenSuccess}.
      */
     @NonNull
-    public AutoCloseable openRangingSession(@NonNull RangingParams params,
-            @NonNull Executor executor, @NonNull RangingSession.Callback callbacks) {
+    public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters,
+            @NonNull Executor executor,
+            @NonNull RangingSession.Callback callbacks) {
         throw new UnsupportedOperationException();
     }
 }
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 9c7ee0c..241570a 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -90,6 +90,14 @@
     env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
 }
 
+static void android_os_Parcel_markSensitive(jlong nativePtr)
+{
+    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+    if (parcel) {
+        parcel->markSensitive();
+    }
+}
+
 static jint android_os_Parcel_dataSize(jlong nativePtr)
 {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
@@ -758,6 +766,8 @@
 
 static const JNINativeMethod gParcelMethods[] = {
     // @CriticalNative
+    {"nativeMarkSensitive",             "(J)V", (void*)android_os_Parcel_markSensitive},
+    // @CriticalNative
     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
     // @CriticalNative
     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 95c295a4..70c2afb 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -804,10 +804,14 @@
   PrepareDir(dir, mode, uid, gid, fail_fn);
 }
 
+static bool BindMount(const std::string& source_dir, const std::string& target_dir) {
+  return !(TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
+                                    MS_BIND | MS_REC, nullptr)) == -1);
+}
+
 static void BindMount(const std::string& source_dir, const std::string& target_dir,
                       fail_fn_t fail_fn) {
-  if (TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
-                               MS_BIND | MS_REC, nullptr)) == -1) {
+  if (!BindMount(source_dir, target_dir)) {
     fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
                          source_dir.c_str(), target_dir.c_str(), strerror(errno)));
   }
@@ -1194,9 +1198,9 @@
 
 // Create an app data directory over tmpfs overlayed CE / DE storage, and bind mount it
 // from the actual app data directory in data mirror.
-static void createAndMountAppData(std::string_view package_name,
+static bool createAndMountAppData(std::string_view package_name,
     std::string_view mirror_pkg_dir_name, std::string_view mirror_data_path,
-    std::string_view actual_data_path, fail_fn_t fail_fn) {
+    std::string_view actual_data_path, fail_fn_t fail_fn, bool call_fail_fn) {
 
   char mirrorAppDataPath[PATH_MAX];
   char actualAppDataPath[PATH_MAX];
@@ -1207,6 +1211,29 @@
   PrepareDir(actualAppDataPath, 0700, AID_ROOT, AID_ROOT, fail_fn);
 
   // Bind mount from original app data directory in mirror.
+  if (call_fail_fn) {
+    BindMount(mirrorAppDataPath, actualAppDataPath, fail_fn);
+  } else if(!BindMount(mirrorAppDataPath, actualAppDataPath)) {
+    ALOGW("Failed to mount %s to %s: %s",
+          mirrorAppDataPath, actualAppDataPath, strerror(errno));
+    return false;
+  }
+  return true;
+}
+
+// There is an app data directory over tmpfs overlaid CE / DE storage
+// bind mount it from the actual app data directory in data mirror.
+static void mountAppData(std::string_view package_name,
+    std::string_view mirror_pkg_dir_name, std::string_view mirror_data_path,
+    std::string_view actual_data_path, fail_fn_t fail_fn) {
+
+  char mirrorAppDataPath[PATH_MAX];
+  char actualAppDataPath[PATH_MAX];
+  snprintf(mirrorAppDataPath, PATH_MAX, "%s/%s", mirror_data_path.data(),
+      mirror_pkg_dir_name.data());
+  snprintf(actualAppDataPath, PATH_MAX, "%s/%s", actual_data_path.data(), package_name.data());
+
+  // Bind mount from original app data directory in mirror.
   BindMount(mirrorAppDataPath, actualAppDataPath, fail_fn);
 }
 
@@ -1284,10 +1311,17 @@
   snprintf(mirrorCePath, PATH_MAX, "%s/%d", mirrorCeParent, userId);
   snprintf(mirrorDePath, PATH_MAX, "/data_mirror/data_de/%s/%d", volume_uuid.data(), userId);
 
-  createAndMountAppData(package_name, package_name, mirrorDePath, actualDePath, fail_fn);
+  createAndMountAppData(package_name, package_name, mirrorDePath, actualDePath, fail_fn,
+                        true /*call_fail_fn*/);
 
   std::string ce_data_path = getAppDataDirName(mirrorCePath, package_name, ce_data_inode, fail_fn);
-  createAndMountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn);
+  if (!createAndMountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn,
+                             false /*call_fail_fn*/)) {
+    // CE might unlocks and the name is decrypted
+    // get the name and mount again
+    ce_data_path=getAppDataDirName(mirrorCePath, package_name, ce_data_inode, fail_fn);
+    mountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn);
+  }
 }
 
 // Relabel directory
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 38981b0..c73aae5 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -33,16 +33,6 @@
 
 // Static whitelist of open paths that the zygote is allowed to keep open.
 static const char* kPathWhitelist[] = {
-        "/apex/com.android.conscrypt/javalib/conscrypt.jar",
-        "/apex/com.android.ipsec/javalib/ike.jar",
-        "/apex/com.android.i18n/javalib/core-icu4j.jar",
-        "/apex/com.android.media/javalib/updatable-media.jar",
-        "/apex/com.android.mediaprovider/javalib/framework-mediaprovider.jar",
-        "/apex/com.android.os.statsd/javalib/framework-statsd.jar",
-        "/apex/com.android.permission/javalib/framework-permission.jar",
-        "/apex/com.android.sdkext/javalib/framework-sdkextensions.jar",
-        "/apex/com.android.wifi/javalib/framework-wifi.jar",
-        "/apex/com.android.tethering/javalib/framework-tethering.jar",
         "/dev/null",
         "/dev/socket/zygote",
         "/dev/socket/zygote_secondary",
@@ -100,11 +90,12 @@
     }
   }
 
-  // Jars from the ART APEX are allowed.
-  static const char* kArtApexPrefix = "/apex/com.android.art/javalib/";
-  if (android::base::StartsWith(path, kArtApexPrefix)
-      && android::base::EndsWith(path, kJarSuffix)) {
-    return true;
+  // Jars from APEXes are allowed. This matches /apex/**/javalib/*.jar.
+  static const char* kApexPrefix = "/apex/";
+  static const char* kApexJavalibPathSuffix = "/javalib";
+  if (android::base::StartsWith(path, kApexPrefix) && android::base::EndsWith(path, kJarSuffix) &&
+      android::base::EndsWith(android::base::Dirname(path), kApexJavalibPathSuffix)) {
+      return true;
   }
 
   // the in-memory file created by ART through memfd_create is allowed.
diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto
index 98ba029..e282acb 100644
--- a/core/proto/android/app/enums.proto
+++ b/core/proto/android/app/enums.proto
@@ -210,4 +210,5 @@
     APP_OP_RESERVED_100 = 100;
     APP_OP_RESERVED_101 = 101;
     APP_OP_RESERVED_102 = 102;
+    APP_OP_MANAGE_ONGOING_CALLS = 103;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 48275f6..a417f0c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2193,6 +2193,11 @@
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows to query ongoing call details and manage ongoing calls
+     <p>Protection level: signature|appop -->
+    <permission android:name="android.permission.MANAGE_ONGOING_CALLS"
+        android:protectionLevel="signature|appop" />
+
     <!-- Allows the app to request network scans from telephony.
          <p>Not for use by third-party applications.
          @SystemApi @hide-->
diff --git a/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java b/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java
deleted file mode 100644
index 8095c99..0000000
--- a/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2020 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.uwb;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.os.Parcel;
-import android.os.PersistableBundle;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.time.Duration;
-
-/**
- * Test of {@link RangingParams}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingParamsTest {
-
-    @Test
-    public void testParams_Build() {
-        UwbAddress local = UwbAddress.fromBytes(new byte[] {(byte) 0xA0, (byte) 0x57});
-        UwbAddress remote = UwbAddress.fromBytes(new byte[] {(byte) 0x4D, (byte) 0x8C});
-        int channel = 9;
-        int rxPreamble = 16;
-        int txPreamble = 21;
-        boolean isController = true;
-        boolean isInitiator = false;
-        @RangingParams.StsPhyPacketType int stsPhyType = RangingParams.STS_PHY_PACKET_TYPE_SP2;
-        Duration samplePeriod = Duration.ofSeconds(1, 234);
-        PersistableBundle specParams = new PersistableBundle();
-        specParams.putString("protocol", "some_protocol");
-
-        RangingParams params = new RangingParams.Builder()
-                .setChannelNumber(channel)
-                .setReceivePreambleCodeIndex(rxPreamble)
-                .setTransmitPreambleCodeIndex(txPreamble)
-                .setLocalDeviceAddress(local)
-                .addRemoteDeviceAddress(remote)
-                .setIsController(isController)
-                .setIsInitiator(isInitiator)
-                .setSamplePeriod(samplePeriod)
-                .setStsPhPacketType(stsPhyType)
-                .setSpecificationParameters(specParams)
-                .build();
-
-        assertEquals(params.getLocalDeviceAddress(), local);
-        assertEquals(params.getRemoteDeviceAddresses().size(), 1);
-        assertEquals(params.getRemoteDeviceAddresses().get(0), remote);
-        assertEquals(params.getChannelNumber(), channel);
-        assertEquals(params.isController(), isController);
-        assertEquals(params.isInitiator(), isInitiator);
-        assertEquals(params.getRxPreambleIndex(), rxPreamble);
-        assertEquals(params.getTxPreambleIndex(), txPreamble);
-        assertEquals(params.getStsPhyPacketType(), stsPhyType);
-        assertEquals(params.getSamplingPeriod(), samplePeriod);
-        assertTrue(params.getSpecificationParameters().kindofEquals(specParams));
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        RangingParams params = new RangingParams.Builder()
-                .setChannelNumber(9)
-                .setReceivePreambleCodeIndex(16)
-                .setTransmitPreambleCodeIndex(21)
-                .setLocalDeviceAddress(UwbTestUtils.getUwbAddress(false))
-                .addRemoteDeviceAddress(UwbTestUtils.getUwbAddress(true))
-                .setIsController(false)
-                .setIsInitiator(true)
-                .setSamplePeriod(Duration.ofSeconds(2))
-                .setStsPhPacketType(RangingParams.STS_PHY_PACKET_TYPE_SP1)
-                .build();
-        params.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        RangingParams fromParcel = RangingParams.CREATOR.createFromParcel(parcel);
-        assertEquals(params, fromParcel);
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 71e6559..d1b4464 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -23,6 +23,7 @@
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterDefs;
+import android.sysprop.Keystore2Properties;
 
 import java.io.IOException;
 import java.security.KeyFactory;
@@ -111,6 +112,26 @@
         putSecretKeyFactoryImpl("HmacSHA512");
     }
 
+    private static boolean sKeystore2Enabled;
+
+    /**
+     * This function indicates whether or not Keystore 2.0 is enabled. Some parts of the
+     * Keystore SPI must behave subtly differently when Keystore 2.0 is enabled. However,
+     * the platform property that indicates that Keystore 2.0 is enabled is not readable
+     * by applications. So we set this value when {@code install()} is called because it
+     * is called by zygote, which can access Keystore2Properties.
+     *
+     * This function can be removed once the transition to Keystore 2.0 is complete.
+     * b/171305684
+     *
+     * @return true if Keystore 2.0 is enabled.
+     * @hide
+     */
+    public static boolean isKeystore2Enabled() {
+        return sKeystore2Enabled;
+    }
+
+
     /**
      * Installs a new instance of this provider (and the
      * {@link AndroidKeyStoreBCWorkaroundProvider}).
@@ -138,6 +159,11 @@
             // priority.
             Security.addProvider(workaroundProvider);
         }
+
+        // {@code install()} is run by zygote when this property is still accessible. We store its
+        // value so that the Keystore SPI can act accordingly without having to access an internal
+        // property.
+        sKeystore2Enabled = Keystore2Properties.keystore2_enabled().orElse(false);
     }
 
     private void putSecretKeyFactoryImpl(String algorithm) {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 9707260..3694d63 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -211,7 +211,11 @@
                 userAuthenticationValidWhileOnBody,
                 trustedUserPresenceRequired,
                 invalidatedByBiometricEnrollment,
-                userConfirmationRequired);
+                userConfirmationRequired,
+                // Keystore 1.0 does not tell us the exact security level of the key
+                // so we report an unknown but secure security level.
+                insideSecureHardware ? KeyProperties.SECURITY_LEVEL_UNKNOWN_SECURE
+                        : KeyProperties.SECURITY_LEVEL_SOFTWARE);
     }
 
     private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
diff --git a/keystore/java/android/security/keystore/ArrayUtils.java b/keystore/java/android/security/keystore/ArrayUtils.java
index f519c7c..c8c1de4 100644
--- a/keystore/java/android/security/keystore/ArrayUtils.java
+++ b/keystore/java/android/security/keystore/ArrayUtils.java
@@ -18,6 +18,8 @@
 
 import libcore.util.EmptyArray;
 
+import java.util.function.Consumer;
+
 /**
  * @hide
  */
@@ -107,4 +109,16 @@
             return result;
         }
     }
+
+    /**
+     * Runs {@code consumer.accept()} for each element of {@code array}.
+     * @param array
+     * @param consumer
+     * @hide
+     */
+    public static void forEach(int[] array, Consumer<Integer> consumer) {
+        for (int i : array) {
+            consumer.accept(i);
+        }
+    }
 }
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 688c4a7..e9aac7d 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -27,7 +27,6 @@
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Build;
 import android.security.GateKeeper;
-import android.security.KeyStore;
 import android.text.TextUtils;
 
 import java.math.BigInteger;
@@ -246,7 +245,7 @@
     private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048
 
     private final String mKeystoreAlias;
-    private final int mUid;
+    private final int mNamespace;
     private final int mKeySize;
     private final AlgorithmParameterSpec mSpec;
     private final X500Principal mCertificateSubject;
@@ -286,7 +285,7 @@
      */
     public KeyGenParameterSpec(
             String keyStoreAlias,
-            int uid,
+            int namespace,
             int keySize,
             AlgorithmParameterSpec spec,
             X500Principal certificateSubject,
@@ -337,7 +336,7 @@
         }
 
         mKeystoreAlias = keyStoreAlias;
-        mUid = uid;
+        mNamespace = namespace;
         mKeySize = keySize;
         mSpec = spec;
         mCertificateSubject = certificateSubject;
@@ -382,11 +381,43 @@
      * Returns the UID which will own the key. {@code -1} is an alias for the UID of the current
      * process.
      *
+     * @deprecated See deprecation message on {@link KeyGenParameterSpec.Builder#setUid(int)}.
+     *             Known namespaces will be translated to their legacy UIDs. Unknown
+     *             Namespaces will yield {@link IllegalStateException}.
+     *
      * @hide
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int getUid() {
-        return mUid;
+        if (!AndroidKeyStoreProvider.isKeystore2Enabled()) {
+            // If Keystore2 has not been enabled we have to behave as if mNamespace is actually
+            // a UID, because we are still being used with the old Keystore SPI.
+            // TODO This if statement and body can be removed when the Keystore 2 migration is
+            //      complete. b/171563717
+            return mNamespace;
+        }
+        try {
+            return KeyProperties.namespaceToLegacyUid(mNamespace);
+        } catch (IllegalArgumentException e) {
+            throw new IllegalStateException("getUid called on KeyGenParameterSpec with non legacy"
+                    + " keystore namespace.", e);
+        }
+    }
+
+    /**
+     * Returns the target namespace for the key.
+     * See {@link KeyGenParameterSpec.Builder#setNamespace(int)}.
+     *
+     * @return The numeric namespace as configured in the keystore2_key_contexts files of Android's
+     *         SEPolicy.
+     *         TODO b/171806779 link to public Keystore 2.0 documentation.
+     *              See bug for more details for now.
+     * @hide
+     */
+    @SystemApi
+    public int getNamespace() {
+        return mNamespace;
     }
 
     /**
@@ -767,7 +798,7 @@
         private final String mKeystoreAlias;
         private @KeyProperties.PurposeEnum int mPurposes;
 
-        private int mUid = KeyStore.UID_SELF;
+        private int mNamespace = KeyProperties.NAMESPACE_APPLICATION;
         private int mKeySize = -1;
         private AlgorithmParameterSpec mSpec;
         private X500Principal mCertificateSubject;
@@ -830,7 +861,7 @@
          */
         public Builder(@NonNull KeyGenParameterSpec sourceSpec) {
             this(sourceSpec.getKeystoreAlias(), sourceSpec.getPurposes());
-            mUid = sourceSpec.getUid();
+            mNamespace = sourceSpec.getNamespace();
             mKeySize = sourceSpec.getKeySize();
             mSpec = sourceSpec.getAlgorithmParameterSpec();
             mCertificateSubject = sourceSpec.getCertificateSubject();
@@ -873,12 +904,51 @@
          *
          * @param uid UID or {@code -1} for the UID of the current process.
          *
+         * @deprecated Setting the UID of the target namespace is based on a hardcoded
+         * hack in the Keystore service. This is no longer supported with Keystore 2.0/Android S.
+         * Instead, dedicated non UID based namespaces can be configured in SEPolicy using
+         * the keystore2_key_contexts files. The functionality of this method will be supported
+         * by mapping knows special UIDs, such as WIFI, to the newly configured SELinux based
+         * namespaces. Unknown UIDs will yield {@link IllegalArgumentException}.
+         *
          * @hide
          */
         @SystemApi
         @NonNull
+        @Deprecated
         public Builder setUid(int uid) {
-            mUid = uid;
+            if (!AndroidKeyStoreProvider.isKeystore2Enabled()) {
+                // If Keystore2 has not been enabled we have to behave as if mNamespace is actually
+                // a UID, because we are still being used with the old Keystore SPI.
+                // TODO This if statement and body can be removed when the Keystore 2 migration is
+                //      complete. b/171563717
+                mNamespace = uid;
+                return this;
+            }
+            mNamespace = KeyProperties.legacyUidToNamespace(uid);
+            return this;
+        }
+
+        /**
+         * Set the designated SELinux namespace that the key shall live in. The caller must
+         * have sufficient permissions to install a key in the given namespace. Namespaces
+         * can be created using SEPolicy. The keystore2_key_contexts files map numeric
+         * namespaces to SELinux labels, and SEPolicy can be used to grant access to these
+         * namespaces to the desired target context. This is the preferred way to share
+         * keys between system and vendor components, e.g., WIFI settings and WPA supplicant.
+         *
+         * @param namespace Numeric SELinux namespace as configured in keystore2_key_contexts
+         *                  of Android's SEPolicy.
+         *                  TODO b/171806779 link to public Keystore 2.0 documentation.
+         *                       See bug for more details for now.
+         * @return this Builder object.
+         *
+         * @hide
+         */
+        @SystemApi
+        @NonNull
+        public Builder setNamespace(int namespace) {
+            mNamespace = namespace;
             return this;
         }
 
@@ -1489,7 +1559,7 @@
         public KeyGenParameterSpec build() {
             return new KeyGenParameterSpec(
                     mKeystoreAlias,
-                    mUid,
+                    mNamespace,
                     mKeySize,
                     mSpec,
                     mCertificateSubject,
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index d891a25..7158d0c 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -84,6 +84,7 @@
     private final boolean mTrustedUserPresenceRequired;
     private final boolean mInvalidatedByBiometricEnrollment;
     private final boolean mUserConfirmationRequired;
+    private final @KeyProperties.SecurityLevelEnum int mSecurityLevel;
 
     /**
      * @hide
@@ -107,7 +108,8 @@
             boolean userAuthenticationValidWhileOnBody,
             boolean trustedUserPresenceRequired,
             boolean invalidatedByBiometricEnrollment,
-            boolean userConfirmationRequired) {
+            boolean userConfirmationRequired,
+            @KeyProperties.SecurityLevelEnum int securityLevel) {
         mKeystoreAlias = keystoreKeyAlias;
         mInsideSecureHardware = insideSecureHardware;
         mOrigin = origin;
@@ -131,6 +133,7 @@
         mTrustedUserPresenceRequired = trustedUserPresenceRequired;
         mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
         mUserConfirmationRequired = userConfirmationRequired;
+        mSecurityLevel = securityLevel;
     }
 
     /**
@@ -144,7 +147,10 @@
      * Returns {@code true} if the key resides inside secure hardware (e.g., Trusted Execution
      * Environment (TEE) or Secure Element (SE)). Key material of such keys is available in
      * plaintext only inside the secure hardware and is not exposed outside of it.
+     *
+     * @deprecated This method is superseded by @see getSecurityLevel.
      */
+    @Deprecated
     public boolean isInsideSecureHardware() {
         return mInsideSecureHardware;
     }
@@ -355,4 +361,17 @@
     public boolean isTrustedUserPresenceRequired() {
         return mTrustedUserPresenceRequired;
     }
+
+    /**
+     * Returns the security level that the key is protected by.
+     * {@code KeyProperties.SecurityLevelEnum.TRUSTED_ENVIRONMENT} and
+     * {@code KeyProperties.SecurityLevelEnum.STRONGBOX} indicate that the key material resides
+     * in secure hardware. Key material of such keys is available in
+     * plaintext only inside the secure hardware and is not exposed outside of it.
+     *
+     * <p>See {@link KeyProperties}.{@code SecurityLevelEnum} constants.
+     */
+    public @KeyProperties.SecurityLevelEnum int getSecurityLevel() {
+        return mSecurityLevel;
+    }
 }
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 9050c69..5928540 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.security.KeyStore;
 import android.security.keymaster.KeymasterDefs;
 
 import libcore.util.EmptyArray;
@@ -857,4 +858,43 @@
         }
     }
 
+    /**
+     * This value indicates the implicit keystore namespace of the calling application.
+     * It is used by default. Only select system components can choose a different namespace
+     * which it must be configured in SEPolicy.
+     * @hide
+     */
+    public static final int NAMESPACE_APPLICATION = -1;
+
+    /**
+     * For legacy support, translate namespaces into known UIDs.
+     * @hide
+     */
+    public static int namespaceToLegacyUid(int namespace) {
+        switch (namespace) {
+            case NAMESPACE_APPLICATION:
+                return KeyStore.UID_SELF;
+            // TODO Translate WIFI and VPN UIDs once the namespaces are defined.
+            //  b/171305388 and b/171305607
+            default:
+                throw new IllegalArgumentException("No UID corresponding to namespace "
+                        + namespace);
+        }
+    }
+
+    /**
+     * For legacy support, translate namespaces into known UIDs.
+     * @hide
+     */
+    public static int legacyUidToNamespace(int uid) {
+        switch (uid) {
+            case KeyStore.UID_SELF:
+                return NAMESPACE_APPLICATION;
+            // TODO Translate WIFI and VPN UIDs once the namespaces are defined.
+            //  b/171305388 and b/171305607
+            default:
+                throw new IllegalArgumentException("No namespace corresponding to uid "
+                        + uid);
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 4390004..36da7aa 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,4 +1,5 @@
 # sysui owners
 hwwang@google.com
 mrenouf@google.com
-winsonc@google.com
\ No newline at end of file
+winsonc@google.com
+madym@google.com
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
index 7e7710b..0f88811 100644
--- a/packages/SettingsProvider/src/android/provider/settings/OWNERS
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -1,4 +1,4 @@
 # Bug component: 656484
 
-include platform/frameworks/base/services/backup:/OWNERS
+include platform/frameworks/base:/services/backup/OWNERS
 
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
index 7e7710b..0f88811 100644
--- a/packages/SettingsProvider/test/src/android/provider/OWNERS
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -1,4 +1,4 @@
 # Bug component: 656484
 
-include platform/frameworks/base/services/backup:/OWNERS
+include platform/frameworks/base:/services/backup/OWNERS
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 93825ca..fba1e79 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1917,10 +1917,13 @@
         }
         if (DBG) log("Adding legacy route " + bestRoute +
                 " for UID/PID " + uid + "/" + Binder.getCallingPid());
+
+        final String dst = bestRoute.getDestinationLinkAddress().toString();
+        final String nextHop = bestRoute.hasGateway()
+                ? bestRoute.getGateway().getHostAddress() : "";
         try {
-            mNMS.addLegacyRouteForNetId(netId, bestRoute, uid);
-        } catch (Exception e) {
-            // never crash - catch them all
+            mNetd.networkAddLegacyRoute(netId, bestRoute.getInterface(), dst, nextHop , uid);
+        } catch (RemoteException | ServiceSpecificException e) {
             if (DBG) loge("Exception trying to add a route: " + e);
             return false;
         }
@@ -6443,8 +6446,8 @@
                 && !nai.networkAgentConfig.allowBypass
                 && nc.getOwnerUid() != Process.SYSTEM_UID
                 && lp.getInterfaceName() != null
-                && (lp.hasIPv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute())
-                && (lp.hasIPv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
+                && (lp.hasIpv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute())
+                && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
     }
 
     private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 3385393..0563fcd 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -43,7 +43,6 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
 
 public class NetworkNotificationManager {
 
@@ -74,7 +73,12 @@
 
     private static final String TAG = NetworkNotificationManager.class.getSimpleName();
     private static final boolean DBG = true;
-    private static final boolean VDBG = false;
+
+    // Notification channels used by ConnectivityService mainline module, it should be aligned with
+    // SystemNotificationChannels.
+    public static final String NOTIFICATION_NETWORK_STATUS = "NETWORK_STATUS";
+    public static final String NOTIFICATION_NETWORK_ALERTS = "NETWORK_ALERTS";
+    public static final String NOTIFICATION_VPN = "VPN";
 
     // The context is for the current user (system server)
     private final Context mContext;
@@ -259,8 +263,7 @@
         // the tag.
         final boolean hasPreviousNotification = previousNotifyType != null;
         final String channelId = (highPriority && !hasPreviousNotification)
-                ? SystemNotificationChannels.NETWORK_ALERTS
-                : SystemNotificationChannels.NETWORK_STATUS;
+                ? NOTIFICATION_NETWORK_ALERTS : NOTIFICATION_NETWORK_STATUS;
         Notification.Builder builder = new Notification.Builder(mContext, channelId)
                 .setWhen(System.currentTimeMillis())
                 .setShowWhen(notifyType == NotificationType.NETWORK_SWITCH)
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8b56a2b..411828c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -27,12 +27,12 @@
 
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.connectivity.NetworkNotificationManager.NOTIFICATION_VPN;
 
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -111,7 +111,6 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.net.VpnProfile;
-import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.ConnectivityService;
 import com.android.server.DeviceIdleInternal;
@@ -1333,16 +1332,17 @@
             // Restricted users are not allowed to create VPNs, they are tied to Owner
             enforceNotRestrictedUser();
 
-            ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
-                    null, 0, mUserId);
+            final PackageManager packageManager = mUserIdContext.getPackageManager();
+            if (packageManager == null) {
+                throw new UnsupportedOperationException("Cannot get PackageManager.");
+            }
+            final ResolveInfo info = packageManager.resolveService(intent, 0 /* flags */);
             if (info == null) {
                 throw new SecurityException("Cannot find " + config.user);
             }
             if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
                 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
             }
-        } catch (RemoteException e) {
-            throw new SecurityException("Cannot find " + config.user);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -1945,7 +1945,7 @@
             final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser(
                     intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user);
             final Notification.Builder builder =
-                    new Notification.Builder(mContext, SystemNotificationChannels.VPN)
+                    new Notification.Builder(mContext, NOTIFICATION_VPN)
                             .setSmallIcon(R.drawable.vpn_connected)
                             .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
                             .setContentText(mContext.getString(R.string.vpn_lockdown_config))
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index fe97f70..ea24532 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -148,9 +148,25 @@
         addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE,
                 new AsciiValidator(3), DEST_BROADCAST);
 
-        // TODO: Handle messages for the Deck Control.
+        ParameterValidator statusRequestValidator = new OneByteRangeValidator(0x01, 0x03);
+        addValidationInfo(
+                Constants.MESSAGE_DECK_CONTROL, new OneByteRangeValidator(0x01, 0x04), DEST_DIRECT);
+        addValidationInfo(
+                Constants.MESSAGE_DECK_STATUS, new OneByteRangeValidator(0x11, 0x1F), DEST_DIRECT);
+        addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT);
+        addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT);
 
         // TODO: Handle messages for the Tuner Control.
+        addValidationInfo(
+                Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT);
+        addValidationInfo(
+                Constants.MESSAGE_SELECT_ANALOG_SERVICE,
+                new SelectAnalogueServiceValidator(),
+                DEST_DIRECT);
+        addValidationInfo(
+                Constants.MESSAGE_SELECT_DIGITAL_SERVICE,
+                new SelectDigitalServiceValidator(),
+                DEST_DIRECT);
 
         // Messages for the Vendor Specific Commands.
         VariableLengthValidator maxLengthValidator = new VariableLengthValidator(0, 14);
@@ -176,9 +192,10 @@
                 Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT);
 
         // Messages for the Remote Control Passthrough.
-        // TODO: Parse the first parameter and determine if it can have the next parameter.
-        addValidationInfo(Constants.MESSAGE_USER_CONTROL_PRESSED,
-                new VariableLengthValidator(1, 2), DEST_DIRECT);
+        addValidationInfo(
+                Constants.MESSAGE_USER_CONTROL_PRESSED,
+                new UserControlPressedValidator(),
+                DEST_DIRECT);
 
         // Messages for the Power Status.
         addValidationInfo(
@@ -515,6 +532,28 @@
     }
 
     /**
+     * Check if the given value is a valid Channel Identifier. A valid value is one which falls
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
+     * 17)
+     *
+     * @param params Channel Identifier parameters
+     * @param offset start offset of Channel Identifier
+     * @return true if the Channel Identifier is valid
+     */
+    private boolean isValidChannelIdentifier(byte[] params, int offset) {
+        // First 6 bits contain Channel Number Format
+        int channelNumberFormat = params[offset] & 0xFC;
+        if (channelNumberFormat == 0x04) {
+            // Validate it contains 1-part Channel Number data (16 bits)
+            return params.length - offset >= 3;
+        } else if (channelNumberFormat == 0x08) {
+            // Validate it contains Major Channel Number and Minor Channel Number (26 bits)
+            return params.length - offset >= 4;
+        }
+        return false;
+    }
+
+    /**
      * Check if the given value is a valid Digital Service Identification. A valid value is one
      * which falls within the range description defined in CEC 1.4 Specification : Operand
      * Descriptions (Section 17)
@@ -544,15 +583,7 @@
         } else if (serviceIdentificationMethod == 0x80) {
             // Services identified by Channel
             if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) {
-                // First 6 bits contain Channel Number Format
-                int channelNumberFormat = params[offset] & 0xFC;
-                if (channelNumberFormat == 0x04) {
-                    // Validate it contains 1-part Channel Number data (16 bits)
-                    return params.length - offset >= 3;
-                } else if (channelNumberFormat == 0x08) {
-                    // Validate it contains Major Channel Number and Minor Channel Number (26 bits)
-                    return params.length - offset >= 4;
-                }
+                return isValidChannelIdentifier(params, offset);
             }
         }
         return false;
@@ -632,6 +663,65 @@
         return false;
     }
 
+    /**
+     * Check if the given value is a valid Play mode. A valid value is one which falls within the
+     * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+     *
+     * @param value Play mode
+     * @return true if the Play mode is valid
+     */
+    private boolean isValidPlayMode(int value) {
+        return (isWithinRange(value, 0x05, 0x07)
+                || isWithinRange(value, 0x09, 0x0B)
+                || isWithinRange(value, 0x15, 0x17)
+                || isWithinRange(value, 0x19, 0x1B)
+                || isWithinRange(value, 0x24, 0x25)
+                || (value == 0x20));
+    }
+
+    /**
+     * Check if the given value is a valid UI Broadcast type. A valid value is one which falls
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
+     * 17)
+     *
+     * @param value UI Broadcast type
+     * @return true if the UI Broadcast type is valid
+     */
+    private boolean isValidUiBroadcastType(int value) {
+        return ((value == 0x00)
+                || (value == 0x01)
+                || (value == 0x10)
+                || (value == 0x20)
+                || (value == 0x30)
+                || (value == 0x40)
+                || (value == 0x50)
+                || (value == 0x60)
+                || (value == 0x70)
+                || (value == 0x80)
+                || (value == 0x90)
+                || (value == 0x91)
+                || (value == 0xA0));
+    }
+
+    /**
+     * Check if the given value is a valid UI Sound Presenation Control. A valid value is one which
+     * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions
+     * (Section 17)
+     *
+     * @param value UI Sound Presenation Control
+     * @return true if the UI Sound Presenation Control is valid
+     */
+    private boolean isValidUiSoundPresenationControl(int value) {
+        value = value & 0xFF;
+        return ((value == 0x20)
+                || (value == 0x30)
+                || (value == 0x80)
+                || (value == 0x90)
+                || (value == 0xA0)
+                || (isWithinRange(value, 0xB1, 0xB3))
+                || (isWithinRange(value, 0xC1, 0xC3)));
+    }
+
     private class PhysicalAddressValidator implements ParameterValidator {
         @Override
         public int isValid(byte[] params) {
@@ -863,4 +953,78 @@
             return toErrorCode(isValidTimerStatusData(params, 0));
         }
     }
+
+    /**
+     * Check if the given play mode parameter is valid. A valid parameter should lie within the
+     * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+     */
+    private class PlayModeValidator implements ParameterValidator {
+        @Override
+        public int isValid(byte[] params) {
+            if (params.length < 1) {
+                return ERROR_PARAMETER_SHORT;
+            }
+            return toErrorCode(isValidPlayMode(params[0]));
+        }
+    }
+
+    /**
+     * Check if the given select analogue service parameter is valid. A valid parameter should lie
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions
+     * (Section 17)
+     */
+    private class SelectAnalogueServiceValidator implements ParameterValidator {
+        @Override
+        public int isValid(byte[] params) {
+            if (params.length < 4) {
+                return ERROR_PARAMETER_SHORT;
+            }
+            return toErrorCode(isValidAnalogueBroadcastType(params[0])
+                    && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 1))
+                    && isValidBroadcastSystem(params[3]));
+        }
+    }
+
+    /**
+     * Check if the given select digital service parameter is valid. A valid parameter should lie
+     * within the range description defined in CEC 1.4 Specification : Operand Descriptions
+     * (Section 17)
+     */
+    private class SelectDigitalServiceValidator implements ParameterValidator {
+        @Override
+        public int isValid(byte[] params) {
+            if (params.length < 4) {
+                return ERROR_PARAMETER_SHORT;
+            }
+            return toErrorCode(isValidDigitalServiceIdentification(params, 0));
+        }
+    }
+
+    /** Check if the given user control press parameter is valid. */
+    private class UserControlPressedValidator implements ParameterValidator {
+        @Override
+        public int isValid(byte[] params) {
+            if (params.length < 1) {
+                return ERROR_PARAMETER_SHORT;
+            }
+            if (params.length == 1) {
+                return OK;
+            }
+            int uiCommand = params[0];
+            switch (uiCommand) {
+                case HdmiCecKeycode.CEC_KEYCODE_PLAY_FUNCTION:
+                    return toErrorCode(isValidPlayMode(params[1]));
+                case HdmiCecKeycode.CEC_KEYCODE_TUNE_FUNCTION:
+                    return (params.length >= 4
+                            ? toErrorCode(isValidChannelIdentifier(params, 1))
+                            : ERROR_PARAMETER_SHORT);
+                case HdmiCecKeycode.CEC_KEYCODE_SELECT_BROADCAST_TYPE:
+                    return toErrorCode(isValidUiBroadcastType(params[1]));
+                case HdmiCecKeycode.CEC_KEYCODE_SELECT_SOUND_PRESENTATION:
+                    return toErrorCode(isValidUiSoundPresenationControl(params[1]));
+                default:
+                    return OK;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 06cebac..661d38d 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -18,6 +18,8 @@
 
 import static android.provider.Settings.ACTION_VPN_SETTINGS;
 
+import static com.android.server.connectivity.NetworkNotificationManager.NOTIFICATION_VPN;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
@@ -42,7 +44,6 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
-import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.ConnectivityService;
 import com.android.server.EventLogTags;
 import com.android.server.connectivity.Vpn;
@@ -256,7 +257,7 @@
 
     private void showNotification(int titleRes, int iconRes) {
         final Notification.Builder builder =
-                new Notification.Builder(mContext, SystemNotificationChannels.VPN)
+                new Notification.Builder(mContext, NOTIFICATION_VPN)
                         .setWhen(0)
                         .setSmallIcon(iconRes)
                         .setContentTitle(mContext.getString(titleRes))
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 12c24d4..81a6641 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1084,12 +1084,10 @@
             return nativeIfaceStats;
         } else {
             // When tethering offload is in use, nativeIfaceStats does not contain usage from
-            // offload, add it back here.
-            // When tethering offload is not in use, nativeIfaceStats contains tethering usage.
-            // this does not cause double-counting of tethering traffic, because
-            // NetdTetheringStatsProvider returns zero NetworkStats
-            // when called with STATS_PER_IFACE.
-            return nativeIfaceStats + getTetherStats(iface, type);
+            // offload, add it back here. Note that the included statistics might be stale
+            // since polling newest stats from hardware might impact system health and not
+            // suitable for TrafficStats API use cases.
+            return nativeIfaceStats + getProviderIfaceStats(iface, type);
         }
     }
 
@@ -1100,39 +1098,28 @@
             return nativeTotalStats;
         } else {
             // Refer to comment in getIfaceStats
-            return nativeTotalStats + getTetherStats(IFACE_ALL, type);
+            return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
         }
     }
 
-    private long getTetherStats(String iface, int type) {
-        final NetworkStats tetherSnapshot;
-        final long token = Binder.clearCallingIdentity();
-        try {
-            tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Error get TetherStats: " + e);
-            return 0;
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        HashSet<String> limitIfaces;
+    private long getProviderIfaceStats(@Nullable String iface, int type) {
+        final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
+        final HashSet<String> limitIfaces;
         if (iface == IFACE_ALL) {
             limitIfaces = null;
         } else {
-            limitIfaces = new HashSet<String>();
+            limitIfaces = new HashSet<>();
             limitIfaces.add(iface);
         }
-        NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces);
-        if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type +
-                " entry=" + entry);
+        final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
         switch (type) {
-            case 0: // TYPE_RX_BYTES
+            case TrafficStats.TYPE_RX_BYTES:
                 return entry.rxBytes;
-            case 1: // TYPE_RX_PACKETS
+            case TrafficStats.TYPE_RX_PACKETS:
                 return entry.rxPackets;
-            case 2: // TYPE_TX_BYTES
+            case TrafficStats.TYPE_TX_BYTES:
                 return entry.txBytes;
-            case 3: // TYPE_TX_PACKETS
+            case TrafficStats.TYPE_TX_PACKETS:
                 return entry.txPackets;
             default:
                 return 0;
@@ -1429,14 +1416,6 @@
         final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
         Trace.traceEnd(TRACE_TAG_NETWORK);
 
-        // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
-        // providers that isn't already counted by dev and XT stats.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether");
-        final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        xtSnapshot.combineAllValues(tetherSnapshot);
-        devSnapshot.combineAllValues(tetherSnapshot);
-
         // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
         // from stats providers that isn't already counted by dev and XT stats.
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
@@ -1511,29 +1490,7 @@
         final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
         final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
 
-        // Request asynchronous stats update from all providers for next poll. And wait a bit of
-        // time to allow providers report-in given that normally binder call should be fast. Note
-        // that size of list might be changed because addition/removing at the same time. For
-        // addition, the stats of the missed provider can only be collected in next poll;
-        // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
-        // once that happened.
-        // TODO: request with a valid token.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
-        final int registeredCallbackCount = mStatsProviderCbList.size();
-        mStatsProviderSem.drainPermits();
-        invokeForAllStatsProviderCallbacks(
-                (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
-        try {
-            mStatsProviderSem.tryAcquire(registeredCallbackCount,
-                    MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            // Strictly speaking it's possible a provider happened to deliver between the timeout
-            // and the log, and that doesn't matter too much as this is just a debug log.
-            Log.d(TAG, "requestStatsUpdate - providers responded "
-                    + mStatsProviderSem.availablePermits()
-                    + "/" + registeredCallbackCount + " : " + e);
-        }
-        Trace.traceEnd(TRACE_TAG_NETWORK);
+        performPollFromProvidersLocked();
 
         // TODO: consider marking "untrusted" times in historical stats
         final long currentTime = mClock.millis();
@@ -1578,6 +1535,33 @@
         Trace.traceEnd(TRACE_TAG_NETWORK);
     }
 
+    @GuardedBy("mStatsLock")
+    private void performPollFromProvidersLocked() {
+        // Request asynchronous stats update from all providers for next poll. And wait a bit of
+        // time to allow providers report-in given that normally binder call should be fast. Note
+        // that size of list might be changed because addition/removing at the same time. For
+        // addition, the stats of the missed provider can only be collected in next poll;
+        // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
+        // once that happened.
+        // TODO: request with a valid token.
+        Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
+        final int registeredCallbackCount = mStatsProviderCbList.size();
+        mStatsProviderSem.drainPermits();
+        invokeForAllStatsProviderCallbacks(
+                (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
+        try {
+            mStatsProviderSem.tryAcquire(registeredCallbackCount,
+                    MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            // Strictly speaking it's possible a provider happened to deliver between the timeout
+            // and the log, and that doesn't matter too much as this is just a debug log.
+            Log.d(TAG, "requestStatsUpdate - providers responded "
+                    + mStatsProviderSem.availablePermits()
+                    + "/" + registeredCallbackCount + " : " + e);
+        }
+        Trace.traceEnd(TRACE_TAG_NETWORK);
+    }
+
     /**
      * Sample recent statistics summary into {@link EventLog}.
      */
@@ -1931,9 +1915,13 @@
     }
 
     /**
-     * Return snapshot of current tethering statistics. Will return empty
-     * {@link NetworkStats} if any problems are encountered.
+     * Return snapshot of current non-offloaded tethering statistics. Will return empty
+     * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE}
+     * since it is already included by {@link #nativeGetIfaceStat}.
+     * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats.
      */
+    // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
+    //  tethering stats.
     private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
         try {
             return mNetworkManager.getNetworkStatsTethering(how);
@@ -2226,13 +2214,6 @@
         }
     }
 
-    private static int TYPE_RX_BYTES;
-    private static int TYPE_RX_PACKETS;
-    private static int TYPE_TX_BYTES;
-    private static int TYPE_TX_PACKETS;
-    private static int TYPE_TCP_RX_PACKETS;
-    private static int TYPE_TCP_TX_PACKETS;
-
     private static native long nativeGetTotalStat(int type, boolean useBpfStats);
     private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
     private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3d63606..7fa3225 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10564,7 +10564,7 @@
                     continue;
                 }
                 final PackageSetting staticLibPkgSetting = getPackageSetting(
-                        toStaticSharedLibraryPackageName(sharedLibraryInfo.getPackageName(),
+                        toStaticSharedLibraryPackageName(sharedLibraryInfo.getName(),
                                 sharedLibraryInfo.getLongVersion()));
                 if (staticLibPkgSetting == null) {
                     Slog.wtf(TAG, "Shared lib without setting: " + sharedLibraryInfo);
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 0275f3e..10b248a 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -215,21 +215,6 @@
 };
 
 int register_android_server_net_NetworkStatsService(JNIEnv* env) {
-    jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService");
-    jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I");
-    jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I");
-    jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I");
-    jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I");
-    jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I");
-    jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I");
-
-    env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES);
-    env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS);
-    env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES);
-    env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS);
-    env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS);
-    env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS);
-
     return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
                                     NELEM(gMethods));
 }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 72ad366..29bf374 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -22,13 +22,14 @@
 
 // Version of services.net for usage by the wifi mainline module.
 // Note: This is compiled against module_current.
-// TODO(b/145825329): This should be moved to networkstack-client,
+// TODO(b/172457099): This should be moved to networkstack-client,
 // with dependencies moved to frameworks/libs/net right.
 java_library {
     name: "services.net-module-wifi",
     srcs: [
         ":framework-services-net-module-wifi-shared-srcs",
         ":net-module-utils-srcs",
+        ":net-utils-services-common-srcs",
         "java/android/net/ip/IpClientCallbacks.java",
         "java/android/net/ip/IpClientManager.java",
         "java/android/net/ip/IpClientUtil.java",
@@ -39,6 +40,7 @@
         "java/android/net/TcpKeepalivePacketData.java",
     ],
     sdk_version: "module_current",
+    min_sdk_version: "30",
     libs: [
         "unsupportedappusage",
         "framework-wifi-util-lib",
@@ -49,7 +51,6 @@
         "netd_aidl_interface-V3-java",
         "netlink-client",
         "networkstack-client",
-        "net-utils-services-common",
     ],
     apex_available: [
         "com.android.wifi",
diff --git a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
index c03a5a7..e4daddc 100644
--- a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
+++ b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
@@ -185,22 +185,23 @@
      * is useful for when device is powering off.
      */
     @MainThread
-    synchronized void saveImmediately(@NonNull String fileName, @NonNull T data) {
-        mScheduledFileDataMap.put(fileName, data);
+    void saveImmediately(@NonNull String fileName, @NonNull T data) {
+        synchronized (this) {
+            mScheduledFileDataMap.put(fileName, data);
+        }
         triggerScheduledFlushEarly();
     }
 
     @MainThread
-    private synchronized void triggerScheduledFlushEarly() {
-        if (mScheduledFileDataMap.isEmpty() || mScheduledExecutorService.isShutdown()) {
-            return;
-        }
-        // Cancel existing future.
-        if (mScheduledFuture != null) {
-
-            // We shouldn't need to interrupt as this method and threaded task
-            // #flushScheduledData are both synchronized.
-            mScheduledFuture.cancel(true);
+    private void triggerScheduledFlushEarly() {
+        synchronized (this) {
+            if (mScheduledFileDataMap.isEmpty() || mScheduledExecutorService.isShutdown()) {
+                return;
+            }
+            // Cancel existing future.
+            if (mScheduledFuture != null) {
+                mScheduledFuture.cancel(true);
+            }
         }
 
         // Submit flush and blocks until it completes. Blocking will prevent the device from
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 1944965..0d878b4 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -28,7 +28,6 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UpdateEngine;
 import android.os.UpdateEngineCallback;
 import android.provider.DeviceConfig;
@@ -227,8 +226,8 @@
         }
 
         // Sample for a fraction of app launches.
-        int traceFrequency =
-                SystemProperties.getInt("persist.profcollectd.applaunch_trace_freq", 2);
+        int traceFrequency = DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
+                "applaunch_trace_freq", 2);
         int randomNum = ThreadLocalRandom.current().nextInt(100);
         if (randomNum < traceFrequency) {
             try {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index 553df3b..63d7dbd 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -353,6 +353,147 @@
         assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
     }
 
+    @Test
+    public void isValid_deckControl() {
+        assertMessageValidity("40:42:01:6E").isEqualTo(OK);
+        assertMessageValidity("40:42:04").isEqualTo(OK);
+
+        assertMessageValidity("4F:42:01").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:42:04").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:42").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:42:05").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_deckStatus() {
+        assertMessageValidity("40:1B:11:58").isEqualTo(OK);
+        assertMessageValidity("40:1B:1F").isEqualTo(OK);
+
+        assertMessageValidity("4F:1B:11").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:1B:1F").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:1B").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:1B:10").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:1B:20").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_statusRequest() {
+        assertMessageValidity("40:08:01").isEqualTo(OK);
+        assertMessageValidity("40:08:02:5C").isEqualTo(OK);
+        assertMessageValidity("40:1A:01:F8").isEqualTo(OK);
+        assertMessageValidity("40:1A:03").isEqualTo(OK);
+
+        assertMessageValidity("4F:08:01").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:08:03").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("4F:1A:01").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:1A:03").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:08").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:1A").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:08:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:08:05").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:1A:00").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:1A:04").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_play() {
+        assertMessageValidity("40:41:16:E3").isEqualTo(OK);
+        assertMessageValidity("40:41:20").isEqualTo(OK);
+
+        assertMessageValidity("4F:41:16").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:41:20").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:41").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:41:04").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:41:18").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:41:23").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:41:26").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_selectAnalogueService() {
+        assertMessageValidity("40:92:00:13:0F:00:96").isEqualTo(OK);
+        assertMessageValidity("40:92:02:EA:60:1F").isEqualTo(OK);
+
+        assertMessageValidity("4F:92:00:13:0F:00").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:92:02:EA:60:1F").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:92:00:13:0F").isEqualTo(ERROR_PARAMETER_SHORT);
+        // Invalid Analogue Broadcast type
+        assertMessageValidity("40:92:03:EA:60:1F").isEqualTo(ERROR_PARAMETER);
+        // Invalid Analogue Frequency
+        assertMessageValidity("40:92:00:FF:FF:00").isEqualTo(ERROR_PARAMETER);
+        // Invalid Broadcast system
+        assertMessageValidity("40:92:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_selectDigitalService() {
+        assertMessageValidity("40:93:00:11:CE:90:0F:00:78").isEqualTo(OK);
+        assertMessageValidity("40:93:10:13:0B:34:38").isEqualTo(OK);
+        assertMessageValidity("40:93:9A:06:F9:D3:E6").isEqualTo(OK);
+        assertMessageValidity("40:93:91:09:F4:40:C8").isEqualTo(OK);
+
+        assertMessageValidity("4F:93:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:93:10:13:0B:34:38").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:93:9A:06:F9").isEqualTo(ERROR_PARAMETER_SHORT);
+        // Invalid Digital Broadcast System
+        assertMessageValidity("40:93:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER);
+        // Invalid Digital Broadcast System
+        assertMessageValidity("40:93:A0:07:95:F1").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for ARIB Broadcast system
+        assertMessageValidity("40:93:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for ATSC Broadcast system
+        assertMessageValidity("40:93:10:13:0B:34").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for DVB Broadcast system
+        assertMessageValidity("40:93:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER);
+        // Invalid channel number format
+        assertMessageValidity("40:93:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for 2 part channel number
+        assertMessageValidity("40:93:91:09:F4:40").isEqualTo(ERROR_PARAMETER);
+    }
+
+    @Test
+    public void isValid_UserControlPressed() {
+        assertMessageValidity("40:44:07").isEqualTo(OK);
+        assertMessageValidity("40:44:52:A7").isEqualTo(OK);
+
+        assertMessageValidity("40:44:60").isEqualTo(OK);
+        assertMessageValidity("40:44:60:1A").isEqualTo(OK);
+
+        assertMessageValidity("40:44:67").isEqualTo(OK);
+        assertMessageValidity("40:44:67:04:00:B1").isEqualTo(OK);
+        assertMessageValidity("40:44:67:09:C8:72:C8").isEqualTo(OK);
+
+        assertMessageValidity("40:44:68").isEqualTo(OK);
+        assertMessageValidity("40:44:68:93").isEqualTo(OK);
+        assertMessageValidity("40:44:69").isEqualTo(OK);
+        assertMessageValidity("40:44:69:7C").isEqualTo(OK);
+        assertMessageValidity("40:44:6A").isEqualTo(OK);
+        assertMessageValidity("40:44:6A:B4").isEqualTo(OK);
+
+        assertMessageValidity("40:44:56").isEqualTo(OK);
+        assertMessageValidity("40:44:56:60").isEqualTo(OK);
+
+        assertMessageValidity("40:44:57").isEqualTo(OK);
+        assertMessageValidity("40:44:57:A0").isEqualTo(OK);
+
+        assertMessageValidity("4F:44:07").isEqualTo(ERROR_DESTINATION);
+        assertMessageValidity("F0:44:52:A7").isEqualTo(ERROR_SOURCE);
+        assertMessageValidity("40:44").isEqualTo(ERROR_PARAMETER_SHORT);
+        assertMessageValidity("40:44:67:04:B1").isEqualTo(ERROR_PARAMETER_SHORT);
+        // Invalid Play mode
+        assertMessageValidity("40:44:60:04").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:44:60:08").isEqualTo(ERROR_PARAMETER);
+        assertMessageValidity("40:44:60:26").isEqualTo(ERROR_PARAMETER);
+        // Invalid Channel Identifier - Channel number format
+        assertMessageValidity("40:44:67:11:8A:42").isEqualTo(ERROR_PARAMETER);
+        // Insufficient data for 2 - part channel number
+        assertMessageValidity("40:44:67:09:C8:72").isEqualTo(ERROR_PARAMETER);
+        // Invalid UI Broadcast type
+        assertMessageValidity("40:44:56:11").isEqualTo(ERROR_PARAMETER);
+        // Invalid UI Sound Presentation Control
+        assertMessageValidity("40:44:57:40").isEqualTo(ERROR_PARAMETER);
+    }
+
     private IntegerSubject assertMessageValidity(String message) {
         return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
     }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index bbf34df..724a9e4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -767,6 +767,19 @@
             "android.telecom.extra.AUDIO_CODEC";
 
     /**
+     * Float connection extra key used to store the audio codec bitrate in kbps for the current
+     * {@link Connection}.
+     */
+    public static final String EXTRA_AUDIO_CODEC_BITRATE_KBPS =
+            "android.telecom.extra.AUDIO_CODEC_BITRATE_KBPS";
+
+    /**
+     * Float connection extra key used to store the audio codec bandwidth in khz for the current
+     * {@link Connection}.
+     */
+    public static final String EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ =
+            "android.telecom.extra.AUDIO_CODEC_BANDWIDTH_KHZ";
+    /**
      * Connection event used to inform Telecom that it should play the on hold tone.  This is used
      * to play a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 724c171..fbb1701 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -1589,6 +1590,30 @@
     }
 
     /**
+     * Returns whether the caller has {@link InCallService} access for companion apps.
+     *
+     * A companion app is an app associated with a physical wearable device via the
+     * {@link android.companion.CompanionDeviceManager} API.
+     *
+     * @return {@code true} if the caller has {@link InCallService} access for
+     *      companion app; {@code false} otherwise.
+     */
+    public boolean hasCompanionInCallServiceAccess() {
+        try {
+            if (isServiceConnected()) {
+                return getTelecomService().hasCompanionInCallServiceAccess(
+                        mContext.getOpPackageName());
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling hasCompanionInCallServiceAccess().", e);
+            if (!isSystemProcess()) {
+                e.rethrowAsRuntimeException();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns whether there is an ongoing call originating from a managed
      * {@link ConnectionService}.  An ongoing call can be in dialing, ringing, active or holding
      * states.
@@ -2384,6 +2409,10 @@
         }
     }
 
+    private boolean isSystemProcess() {
+        return Process.myUid() == Process.SYSTEM_UID;
+    }
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index a28a999..6dc096d 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -179,6 +179,11 @@
     boolean isInCall(String callingPackage, String callingFeatureId);
 
     /**
+     * @see TelecomServiceImpl#hasCompanionInCallServiceAccess
+     */
+    boolean hasCompanionInCallServiceAccess(String callingPackage);
+
+    /**
      * @see TelecomServiceImpl#isInManagedCall
      */
     boolean isInManagedCall(String callingPackage, String callingFeatureId);
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 7aecfdd..d1412b7 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -32,6 +32,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -314,7 +315,7 @@
                 String[] packageNames = new String[enabledCarrierPackages.size()];
                 enabledCarrierPackages.toArray(packageNames);
                 permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
-                        UserHandle.of(userId), Runnable::run, isSuccess -> { });
+                        UserHandle.of(userId), TelephonyUtils.DIRECT_EXECUTOR, isSuccess -> { });
             }
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Could not reach PackageManager", e);
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 7736473..02d7410 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -34,6 +34,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 
@@ -44,6 +45,8 @@
     public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
     public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
 
+    public static final Executor DIRECT_EXECUTOR = Runnable::run;
+
     /**
      * Verify that caller holds {@link android.Manifest.permission#DUMP}.
      *
diff --git a/telephony/java/android/telephony/CarrierBandwidth.aidl b/telephony/java/android/telephony/CarrierBandwidth.aidl
new file mode 100644
index 0000000..d0861b8
--- /dev/null
+++ b/telephony/java/android/telephony/CarrierBandwidth.aidl
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2020 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;
+parcelable CarrierBandwidth;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java
new file mode 100644
index 0000000..17747a3
--- /dev/null
+++ b/telephony/java/android/telephony/CarrierBandwidth.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Defines downlink and uplink capacity of a network in kbps
+ * @hide
+ */
+@SystemApi
+public final class CarrierBandwidth implements Parcelable {
+    /**
+     * Any field that is not reported shall be set to INVALID
+     */
+    public static final int INVALID = -1;
+
+    /**
+     * Estimated downlink capacity in kbps of the primary carrier.
+     * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth.
+     * This will be {@link #INVALID} if the network is not connected
+     */
+    private int mPrimaryDownlinkCapacityKbps;
+
+    /**
+     * Estimated uplink capacity in kbps of the primary carrier.
+     * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth.
+     * This will be {@link #INVALID} if the network is not connected
+     */
+    private int mPrimaryUplinkCapacityKbps;
+
+    /**
+     * Estimated downlink capacity in kbps of the secondary carrier in a dual connected network.
+     * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth.
+     * This will be {@link #INVALID} if the network is not connected
+     */
+    private int mSecondaryDownlinkCapacityKbps;
+
+    /**
+     * Estimated uplink capacity in kbps of the secondary carrier in a dual connected network.
+     * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth.
+     * This will be {@link #INVALID} if the network is not connected
+     */
+    private int mSecondaryUplinkCapacityKbps;
+
+    /** @hide **/
+    public CarrierBandwidth(Parcel in) {
+        mPrimaryDownlinkCapacityKbps = in.readInt();
+        mPrimaryUplinkCapacityKbps = in.readInt();
+        mSecondaryDownlinkCapacityKbps = in.readInt();
+        mSecondaryUplinkCapacityKbps = in.readInt();
+    }
+
+    /** @hide **/
+    public CarrierBandwidth() {
+        mPrimaryDownlinkCapacityKbps = INVALID;
+        mPrimaryUplinkCapacityKbps = INVALID;
+        mSecondaryDownlinkCapacityKbps = INVALID;
+        mSecondaryUplinkCapacityKbps = INVALID;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param primaryDownlinkCapacityKbps Estimated downlink capacity in kbps of
+     *        the primary carrier.
+     * @param primaryUplinkCapacityKbps Estimated uplink capacity in kbps of
+     *        the primary carrier.
+     * @param secondaryDownlinkCapacityKbps Estimated downlink capacity in kbps of
+     *        the secondary carrier
+     * @param secondaryUplinkCapacityKbps Estimated uplink capacity in kbps of
+     *        the secondary carrier
+     */
+    public CarrierBandwidth(int primaryDownlinkCapacityKbps, int primaryUplinkCapacityKbps,
+            int secondaryDownlinkCapacityKbps, int secondaryUplinkCapacityKbps) {
+        mPrimaryDownlinkCapacityKbps = primaryDownlinkCapacityKbps;
+        mPrimaryUplinkCapacityKbps = primaryUplinkCapacityKbps;
+        mSecondaryDownlinkCapacityKbps = secondaryDownlinkCapacityKbps;
+        mSecondaryUplinkCapacityKbps = secondaryUplinkCapacityKbps;
+    }
+
+    /**
+     * Retrieves the upstream bandwidth for the primary network in Kbps.  This always only refers to
+     * the estimated first hop transport bandwidth.
+     * This will be INVALID if the network is not connected
+     *
+     * @return The estimated first hop upstream (device to network) bandwidth.
+     */
+    public int getPrimaryDownlinkCapacityKbps() {
+        return mPrimaryDownlinkCapacityKbps;
+    }
+
+    /**
+     * Retrieves the downstream bandwidth for the primary network in Kbps.  This always only refers
+     * to the estimated first hop transport bandwidth.
+     * This will be INVALID if the network is not connected
+     *
+     * @return The estimated first hop downstream (network to device) bandwidth.
+     */
+    public int getPrimaryUplinkCapacityKbps() {
+        return mPrimaryUplinkCapacityKbps;
+    }
+
+    /**
+     * Retrieves the upstream bandwidth for the secondary network in Kbps.  This always only refers
+     * to the estimated first hop transport bandwidth.
+     * This will be INVALID if the network is not connected
+     *
+     * @return The estimated first hop upstream (device to network) bandwidth.
+     */
+    public int getSecondaryDownlinkCapacityKbps() {
+        return mSecondaryDownlinkCapacityKbps;
+    }
+
+    /**
+     * Retrieves the downstream bandwidth for the secondary network in Kbps.  This always only
+     * refers to the estimated first hop transport bandwidth.
+     * This will be INVALID if the network is not connected
+     *
+     * @return The estimated first hop downstream (network to device) bandwidth.
+     */
+    public int getSecondaryUplinkCapacityKbps() {
+        return mSecondaryUplinkCapacityKbps;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "CarrierBandwidth: {primaryDownlinkCapacityKbps=" + mPrimaryDownlinkCapacityKbps
+                + " primaryUplinkCapacityKbps=" + mPrimaryUplinkCapacityKbps
+                + " secondaryDownlinkCapacityKbps=" + mSecondaryDownlinkCapacityKbps
+                + " secondaryUplinkCapacityKbps=" + mSecondaryUplinkCapacityKbps
+                + "}";
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mPrimaryDownlinkCapacityKbps,
+                mPrimaryUplinkCapacityKbps,
+                mSecondaryDownlinkCapacityKbps,
+                mSecondaryUplinkCapacityKbps);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == null || !(o instanceof CallQuality) || hashCode() != o.hashCode()) {
+            return false;
+        }
+        if (this == o) {
+            return true;
+        }
+        CarrierBandwidth s = (CarrierBandwidth) o;
+        return (mPrimaryDownlinkCapacityKbps == s.mPrimaryDownlinkCapacityKbps
+                && mPrimaryUplinkCapacityKbps == s.mPrimaryUplinkCapacityKbps
+                && mSecondaryDownlinkCapacityKbps == s.mSecondaryDownlinkCapacityKbps
+                && mSecondaryDownlinkCapacityKbps == s.mSecondaryDownlinkCapacityKbps);
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     * @hide
+     */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mPrimaryDownlinkCapacityKbps);
+        dest.writeInt(mPrimaryUplinkCapacityKbps);
+        dest.writeInt(mSecondaryDownlinkCapacityKbps);
+        dest.writeInt(mSecondaryUplinkCapacityKbps);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<CarrierBandwidth> CREATOR =
+            new Parcelable.Creator() {
+            public CarrierBandwidth createFromParcel(Parcel in) {
+                return new CarrierBandwidth(in);
+            }
+
+            public CarrierBandwidth[] newArray(int size) {
+                return new CarrierBandwidth[size];
+            }
+    };
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0d55706..2ffc14e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -79,6 +79,30 @@
      */
     public static final int SERVICE_CLASS_VOICE = ImsSsData.SERVICE_CLASS_VOICE;
 
+    /**
+     * Only send USSD over IMS while CS is out of service, otherwise send USSD over CS.
+     * {@link #KEY_CARRIER_USSD_METHOD_INT}
+     */
+    public static final int USSD_OVER_CS_PREFERRED   = 0;
+
+    /**
+     * Send USSD over IMS or CS while IMS is out of service or silent redial over CS if needed.
+     * {@link #KEY_CARRIER_USSD_METHOD_INT}
+     */
+    public static final int USSD_OVER_IMS_PREFERRED  = 1;
+
+    /**
+     * Only send USSD over CS.
+     * {@link #KEY_CARRIER_USSD_METHOD_INT}
+     */
+    public static final int USSD_OVER_CS_ONLY        = 2;
+
+    /**
+     * Only send USSD over IMS and disallow silent redial over CS.
+     * {@link #KEY_CARRIER_USSD_METHOD_INT}
+     */
+    public static final int USSD_OVER_IMS_ONLY       = 3;
+
     private final Context mContext;
 
     /**
@@ -584,6 +608,20 @@
     public static final String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
 
     /**
+     * Specify the method of selection for UE sending USSD requests. The default value is
+     * {@link #USSD_OVER_CS_PREFERRED}.
+     * <p> Available options:
+     * <ul>
+     *   <li>0: {@link #USSD_OVER_CS_PREFERRED} </li>
+     *   <li>1: {@link #USSD_OVER_IMS_PREFERRED} </li>
+     *   <li>2: {@link #USSD_OVER_CS_ONLY} </li>
+     *   <li>3: {@link #USSD_OVER_IMS_ONLY} </li>
+     * </ul>
+     */
+    public static final String KEY_CARRIER_USSD_METHOD_INT =
+            "carrier_ussd_method_int";
+
+    /**
      * Flag specifying whether to show an alert dialog for 5G disable when the user disables VoLTE.
      * By default this value is {@code false}.
      *
@@ -3969,6 +4007,7 @@
         sDefaults.putBoolean(KEY_CARRIER_SETTINGS_ENABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VT_AVAILABLE_BOOL, false);
+        sDefaults.putInt(KEY_CARRIER_USSD_METHOD_INT, USSD_OVER_CS_PREFERRED);
         sDefaults.putBoolean(KEY_VOLTE_5G_LIMITED_ALERT_DIALOG_BOOL, false);
         sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
         sDefaults.putBoolean(KEY_ALLOW_MERGING_RTT_CALLS_BOOL, false);
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 28feab2..42d7707 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -22,7 +22,12 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.telephony.BinderCacheManager;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.ims.aidl.IImsRcsController;
+
+import com.android.internal.telephony.ITelephony;
 
 /**
  * Provides access to information about Telephony IMS services on the device.
@@ -30,8 +35,6 @@
 @SystemService(Context.TELEPHONY_IMS_SERVICE)
 public class ImsManager {
 
-    private Context mContext;
-
     /**
      * <p>Broadcast Action: Indicates that a previously allowed IMS operation was rejected by the
      * network due to the network returning a "forbidden" response. This may be due to a
@@ -87,6 +90,14 @@
     public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE =
             "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
 
+    // Cache Telephony Binder interfaces, one cache per process.
+    private static final BinderCacheManager<ITelephony> sTelephonyCache =
+            new BinderCacheManager<>(ImsManager::getITelephonyInterface);
+    private static final BinderCacheManager<IImsRcsController> sRcsCache =
+            new BinderCacheManager<>(ImsManager::getIImsRcsControllerInterface);
+
+    private final Context mContext;
+
     /**
      * Use {@link Context#getSystemService(String)} to get an instance of this class.
      * @hide
@@ -108,7 +119,7 @@
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
         }
 
-        return new ImsRcsManager(mContext, subscriptionId);
+        return new ImsRcsManager(mContext, subscriptionId, sRcsCache);
     }
 
     /**
@@ -124,17 +135,19 @@
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
         }
 
-        return new ImsMmTelManager(subscriptionId);
+        return new ImsMmTelManager(subscriptionId, sTelephonyCache);
     }
 
     /**
-     * Create an instance of SipDelegateManager for the subscription id specified.
+     * Create an instance of {@link SipDelegateManager} for the subscription id specified.
      * <p>
-     * Used for RCS single registration cases, where an IMS application needs to forward SIP
-     * traffic through the device's IMS service.
-     * @param subscriptionId The ID of the subscription that this SipDelegateManager will use.
+     * Allows an IMS application to forward SIP traffic through the device's IMS service,
+     * which is used for cellular carriers that require the device to share a single IMS
+     * registration for both MMTEL and RCS features.
+     * @param subscriptionId The ID of the subscription that this {@link SipDelegateManager} will
+     *                       be bound to.
      * @throws IllegalArgumentException if the subscription is invalid.
-     * @return a SipDelegateManager instance for the specified subscription ID.
+     * @return a {@link SipDelegateManager} instance for the specified subscription ID.
      * @hide
      */
     @SystemApi
@@ -144,6 +157,22 @@
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
         }
 
-        return new SipDelegateManager(mContext, subscriptionId);
+        return new SipDelegateManager(mContext, subscriptionId, sRcsCache);
+    }
+
+    private static IImsRcsController getIImsRcsControllerInterface() {
+        return IImsRcsController.Stub.asInterface(
+                TelephonyFrameworkInitializer
+                        .getTelephonyServiceManager()
+                        .getTelephonyImsServiceRegisterer()
+                        .get());
+    }
+
+    private static ITelephony getITelephonyInterface() {
+        return ITelephony.Stub.asInterface(
+                TelephonyFrameworkInitializer
+                        .getTelephonyServiceManager()
+                        .getTelephonyServiceRegisterer()
+                        .get());
     }
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index f8a200a..8507d85 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.TransportType;
@@ -635,7 +636,8 @@
                 .append(" cellIdentity=").append(mCellIdentity)
                 .append(" voiceSpecificInfo=").append(mVoiceSpecificInfo)
                 .append(" dataSpecificInfo=").append(mDataSpecificInfo)
-                .append(" nrState=").append(nrStateToString(mNrState))
+                .append(" nrState=").append(Build.IS_DEBUGGABLE
+                        ? nrStateToString(mNrState) : "****")
                 .append(" rRplmn=").append(mRplmn)
                 .append(" isUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
                 .append("}").toString();
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 41b3ee6..dedb1af 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1102,7 +1102,8 @@
                     .append(", isUsingCarrierAggregation=").append(isUsingCarrierAggregation())
                     .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
                     .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
-                    .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
+                    .append(", mNrFrequencyRange=").append(Build.IS_DEBUGGABLE
+                            ? mNrFrequencyRange : FREQUENCY_RANGE_UNKNOWN)
                     .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
                     .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
                     .append(", mIsDataRoamingFromRegistration=")
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 88aec51..27aadd5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -13440,6 +13440,33 @@
     }
 
     /**
+     * Get carrier bandwidth. In case of Dual connected network this will report
+     * bandwidth per primary and secondary network.
+     * @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public CarrierBandwidth getCarrierBandwidth() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getCarrierBandwidth(getSubId());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "getCarrierBandwidth RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+
+        //Should not reach. Adding return statement to make compiler happy
+        return null;
+    }
+
+    /**
      * Called when userActivity is signalled in the power manager.
      * This should only be called from system Uid.
      * @hide
diff --git a/telephony/java/android/telephony/ims/DelegateMessageCallback.java b/telephony/java/android/telephony/ims/DelegateMessageCallback.java
new file mode 100644
index 0000000..beec4a6
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateMessageCallback.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.telephony.ims.stub.SipDelegate;
+
+/**
+ * Callback interface provided to the SipTransport implementation to notify a remote application of
+ * the following:
+ * <ul>
+ *     <li>A new incoming SIP message associated with the feature tags the SipDelegate registered
+ *     with has been received or an in-dialog request to this SipDelegate has been received.</li>
+ *     <li>Acknowledge that an outgoing SIP message from the RCS application has been sent
+ *     successfully or notify the application of the reason why it was not sent</li>
+ * </ul>
+ * @hide
+ */
+public interface DelegateMessageCallback {
+
+    /**
+     * Send a new incoming SIP message to the remote application for processing.
+     */
+    void onMessageReceived(@NonNull SipMessage message);
+
+    /**
+     * Notify the remote application that a previous request to send a SIP message using
+     * {@link SipDelegate#sendMessage} has succeeded.
+     *
+     * @param viaTransactionId The transaction ID found in the via header field of the
+     *         previously sent {@link SipMessage}.
+     */
+    void onMessageSent(@NonNull String viaTransactionId);
+
+    /**
+     * Notify the remote application that a previous request to send a SIP message using
+     * {@link SipDelegate#sendMessage} has failed.
+     *
+     * @param viaTransactionId The Transaction ID found in the via header field of the previously
+     *         sent {@link SipMessage}.
+     * @param reason The reason for the failure.
+     */
+    void onMessageSendFailure(@NonNull String viaTransactionId,
+            @SipDelegateManager.MessageFailureReason int reason);
+}
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl b/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl
new file mode 100644
index 0000000..756ea92
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 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;
+
+parcelable DelegateRegistrationState;
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
new file mode 100644
index 0000000..4facfa7
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2020 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.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Contains the full state of the IMS feature tags associated with a SipDelegate and managed by the
+ * ImsService.
+ * @hide
+ */
+public final class DelegateRegistrationState implements Parcelable {
+
+    /**
+     * This feature tag has been deregistered for an unknown reason. Outgoing out-of-dialog SIP
+     * messages associated with feature tags that are not registered will fail.
+     */
+    public static final int DEREGISTERED_REASON_UNKNOWN = 0;
+
+    /**
+     * This feature tag has been deregistered because it is not provisioned to be used on this radio
+     * access technology or PDN. Outgoing out-of-dialog SIP messages associated with feature tags
+     * that are not registered will fail.
+     * <p>
+     * There may be new incoming SIP dialog requests on a feature that that is not provisioned. It
+     * is still expected that the SipDelegateConnection responds to the request.
+     */
+    public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1;
+
+    /**
+     * This feature tag has been deregistered because IMS has been deregistered. All outgoing SIP
+     * messages will fail until IMS registration occurs.
+     */
+    public static final int DEREGISTERED_REASON_NOT_REGISTERED = 2;
+
+    /**
+     * This feature tag is being deregistered because the PDN that the IMS registration is on is
+     *changing.
+     * All open SIP dialogs need to be closed before the PDN change can proceed.
+     */
+    public static final int DEREGISTERING_REASON_PDN_CHANGE = 3;
+
+    /**
+     * This feature tag is being deregistered due to a provisioning change. This can be triggered by
+     * many things, such as a provisioning change triggered by the carrier network, a radio access
+     * technology change by the modem causing a different set of feature tags to be provisioned, or
+     * a user triggered hange, such as data being enabled/disabled.
+     * <p>
+     * All open SIP dialogs associated with the new deprovisioned feature tag need to be closed
+     * before the IMS registration modification can proceed.
+     */
+    public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4;
+
+    /**
+     * This feature tag is deregistering because the SipDelegate associated with this feature tag
+     * needs to change its supported feature set.
+     * <p>
+     * All open SIP Dialogs associated with this feature tag must be closed before this operation
+     * can proceed.
+     */
+    public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5;
+
+    /**
+     * This feature tag is deregistering because the SipDelegate is in the process of being
+     * destroyed.
+     * <p>
+     * All open SIP Dialogs associated with this feature tag must be closed before this operation
+     * can proceed.
+     */
+    public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "DEREGISTERED_REASON_", value = {
+            DEREGISTERED_REASON_UNKNOWN,
+            DEREGISTERED_REASON_NOT_PROVISIONED,
+            DEREGISTERED_REASON_NOT_REGISTERED
+    })
+    public @interface DeregisteredReason {}
+
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "DEREGISTERING_REASON_", value = {
+            DEREGISTERING_REASON_PDN_CHANGE,
+            DEREGISTERING_REASON_PROVISIONING_CHANGE,
+            DEREGISTERING_REASON_FEATURE_TAGS_CHANGING,
+            DEREGISTERING_REASON_DESTROY_PENDING
+    })
+    public @interface DeregisteringReason {}
+
+    private final ArrayList<String> mRegisteredTags = new ArrayList<>();
+    private final ArrayList<FeatureTagState> mDeregisteringTags = new ArrayList<>();
+    private final ArrayList<FeatureTagState> mDeregisteredTags = new ArrayList<>();
+
+    /**
+     * Builder used to create new instances of {@link DelegateRegistrationState}.
+     */
+    public static class Builder {
+
+        private final DelegateRegistrationState mState;
+
+        /* Create a new instance of {@link Builder} */
+        public Builder() {
+            mState = new DelegateRegistrationState();
+        }
+
+        /**
+         * Add a feature tag that is currently included in the current network IMS Registration.
+         * @param featureTag The IMS media feature tag included in the current IMS registration.
+         * @return The in-progress Builder instance for RegistrationState.
+         */
+        public Builder addRegisteredFeatureTag(@NonNull String featureTag) {
+            if (!mState.mRegisteredTags.contains(featureTag)) {
+                mState.mRegisteredTags.add(featureTag);
+            }
+            return this;
+        }
+
+        /**
+         * Add a list of feature tags that are currently included in the current network IMS
+         * Registration.
+         * @param featureTags The IMS media feature tags included in the current IMS registration.
+         * @return The in-progress Builder instance for RegistrationState.
+         */
+        public Builder addRegisteredFeatureTags(@NonNull Set<String> featureTags) {
+            mState.mRegisteredTags.addAll(featureTags);
+            return this;
+        }
+
+        /**
+         * Add a feature tag that is in the current network IMS Registration, but is in the progress
+         * of being deregistered and requires action from the RCS application before the IMS
+         * registration can be modified.
+         *
+         * See {@link DeregisteringReason} for more information regarding what is required by the
+         * RCS application to proceed.
+         *
+         * @param featureTag The media feature tag that has limited or no availability due to its
+         *         current deregistering state.
+         * @param reason The reason why the media feature tag has moved to the deregistering state.
+         *         The availability of the feature tag depends on the {@link DeregisteringReason}.
+         * @return The in-progress Builder instance for RegistrationState.
+         */
+        public Builder addDeregisteringFeatureTag(@NonNull String featureTag,
+                @DeregisteringReason int reason) {
+            boolean ftExists = mState.mDeregisteringTags.stream().anyMatch(
+                    f -> f.getFeatureTag().equals(featureTag));
+            if (!ftExists) {
+                mState.mDeregisteringTags.add(new FeatureTagState(featureTag, reason));
+            }
+            return this;
+        }
+
+        /**
+         * Add a feature tag that is currently not included in the network RCS registration. See
+         * {@link DeregisteredReason} for more information regarding the reason for why the feature
+         * tag is not registered.
+         * @param featureTag The media feature tag that is not registered.
+         * @param reason The reason why the media feature tag has been deregistered.
+         * @return The in-progress Builder instance for RegistrationState.
+         */
+        public Builder addDeregisteredFeatureTag(@NonNull String featureTag,
+                @DeregisteredReason int reason) {
+            boolean ftExists = mState.mDeregisteredTags.stream().anyMatch(
+                    f -> f.getFeatureTag().equals(featureTag));
+            if (!ftExists) {
+                mState.mDeregisteredTags.add(new FeatureTagState(featureTag, reason));
+            }
+            return this;
+        }
+
+        /**
+         * @return the finalized instance.
+         */
+        public DelegateRegistrationState build() {
+            return mState;
+        }
+    }
+
+    /**
+     * The builder should be used to construct a new instance of this class.
+     */
+    private DelegateRegistrationState() {}
+
+    /**
+     * Used for unparcelling only.
+     */
+    private DelegateRegistrationState(Parcel source) {
+        source.readList(mRegisteredTags, null /*classloader*/);
+        readStateFromParcel(source, mDeregisteringTags);
+        readStateFromParcel(source, mDeregisteredTags);
+    }
+
+    /**
+     * Get the feature tags that this SipDelegate is associated with that are currently part of the
+     * network IMS registration. SIP Messages both in and out of a SIP Dialog may be sent and
+     * received using these feature tags.
+     * @return A Set of feature tags that the SipDelegate has associated with that are included in
+     * the network IMS registration.
+     */
+    public @NonNull Set<String> getRegisteredFeatureTags() {
+        return new ArraySet<>(mRegisteredTags);
+    }
+
+    /**
+     * Get the feature tags that this SipDelegate is associated with that are currently part of the
+     * network IMS registration but are in the process of being deregistered.
+     * <p>
+     * Any incoming SIP messages associated with a feature tag included in this list will still be
+     * delivered. Outgoing SIP messages that are still in-dialog will be delivered to the
+     * SipDelegate, but outgoing out-of-dialog SIP messages with  a feature tag that is included in
+     * this list will fail.
+     * <p>
+     * The SipDelegate will stay in this state for a limited period of time while it waits for the
+     * RCS application to perform a specific action. More details on the actions that can cause this
+     * state as well as the expected response are included in the reason codes and can be found in
+     * {@link DeregisteringReason}.
+     * @return A Set of feature tags that the SipDelegate has associated with that are included in
+     * the network IMS registration but are in the process of deregistering.
+     */
+    public @NonNull Set<FeatureTagState> getDeregisteringFeatureTags() {
+        return new ArraySet<>(mDeregisteringTags);
+    }
+
+    /**
+     * Get the list of feature tags that are associated with this SipDelegate but are not currently
+     * included in the network IMS registration.
+     * <p>
+     * See {@link DeregisteredReason} codes for more information related to the reasons why this may
+     * occur.
+     * <p>
+     * Due to network race conditions, there may still be onditions where an incoming out-of-dialog
+     * SIP message is delivered for a feature tag that is considered deregistered. Due to this
+     * condition, in-dialog outgoing SIP messages for deregistered feature tags will still be
+     * allowed as long as they are in response to a dialog started by a remote party. Any outgoing
+     * out-of-dialog SIP messages associated with feature tags included in this list will fail to be
+     * sent.
+     * @return A list of feature tags that the SipDelegate has associated with that not included in
+     * the network IMS registration.
+     */
+    public @NonNull Set<FeatureTagState> getDeregisteredFeatureTags() {
+        return new ArraySet<>(mDeregisteredTags);
+    }
+
+    public static final Creator<DelegateRegistrationState> CREATOR =
+            new Creator<DelegateRegistrationState>() {
+        @Override
+        public DelegateRegistrationState createFromParcel(Parcel source) {
+            return new DelegateRegistrationState(source);
+        }
+
+        @Override
+        public DelegateRegistrationState[] newArray(int size) {
+            return new DelegateRegistrationState[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeList(mRegisteredTags);
+        writeStateToParcel(dest, mDeregisteringTags);
+        writeStateToParcel(dest, mDeregisteredTags);
+    }
+
+    private void writeStateToParcel(Parcel dest, List<FeatureTagState> state) {
+        dest.writeInt(state.size());
+        for (FeatureTagState s : state) {
+            dest.writeString(s.getFeatureTag());
+            dest.writeInt(s.getState());
+        }
+    }
+
+    private void readStateFromParcel(Parcel source, List<FeatureTagState> emptyState) {
+        int len = source.readInt();
+        for (int i = 0; i < len; i++) {
+            String ft = source.readString();
+            int reason = source.readInt();
+            emptyState.add(new FeatureTagState(ft, reason));
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DelegateRegistrationState that = (DelegateRegistrationState) o;
+        return mRegisteredTags.equals(that.mRegisteredTags)
+                && mDeregisteringTags.equals(that.mDeregisteringTags)
+                && mDeregisteredTags.equals(that.mDeregisteredTags);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.aidl b/telephony/java/android/telephony/ims/DelegateRequest.aidl
new file mode 100644
index 0000000..60c990f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 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;
+
+parcelable DelegateRequest;
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.java b/telephony/java/android/telephony/ims/DelegateRequest.java
new file mode 100644
index 0000000..f384901
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateRequest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.ArraySet;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Contains information required for the creation of a {@link SipDelegate} and the associated
+ * SipDelegateConnection given back to the requesting application.
+ * @hide
+ */
+public final class DelegateRequest implements Parcelable {
+
+    private final ArrayList<String> mFeatureTags;
+
+    /**
+     * Create a new DelegateRequest, which will be used to create a SipDelegate by the ImsService.
+     * @param featureTags The list of IMS feature tags that will be associated with the SipDelegate
+     *                    created using this DelegateRequest. All feature tags are expected to be in
+     *                    the format defined in RCC.07 section 2.6.1.3.
+     */
+    public DelegateRequest(@NonNull Set<String> featureTags) {
+        if (featureTags == null) {
+            throw new IllegalStateException("Invalid arguments, featureTags List can not be null");
+        }
+        mFeatureTags = new ArrayList<>(featureTags);
+    }
+
+    /**
+     * @return the list of IMS feature tag associated with this DelegateRequest in the format
+     * defined in RCC.07 section 2.6.1.3.
+     */
+    public Set<String> getFeatureTags() {
+        return new ArraySet<>(mFeatureTags);
+    }
+
+    /**
+     * Internal constructor used only for unparcelling.
+     */
+    private DelegateRequest(Parcel in) {
+        mFeatureTags = new ArrayList<>();
+        in.readList(mFeatureTags, null /*classLoader*/);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeList(mFeatureTags);
+    }
+
+    public static final @NonNull Creator<DelegateRequest> CREATOR = new Creator<DelegateRequest>() {
+        @Override
+        public DelegateRequest createFromParcel(Parcel source) {
+            return new DelegateRequest(source);
+        }
+
+        @Override
+        public DelegateRequest[] newArray(int size) {
+            return new DelegateRequest[size];
+        }
+    };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DelegateRequest that = (DelegateRequest) o;
+        return mFeatureTags.equals(that.mFeatureTags);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFeatureTags);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/DelegateStateCallback.java b/telephony/java/android/telephony/ims/DelegateStateCallback.java
new file mode 100644
index 0000000..0f1afc4
--- /dev/null
+++ b/telephony/java/android/telephony/ims/DelegateStateCallback.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.telephony.ims.stub.SipDelegate;
+import android.telephony.ims.stub.SipTransportImplBase;
+
+import java.util.List;
+
+/**
+ * Callback interface to notify a remote application of the following:
+ * <ul>
+ *     <li>the {@link SipDelegate} associated with this callback has been created or destroyed in
+ *         response to a creation or destruction request from the framework</li>
+ *     <li>the SIP IMS configuration associated with this {@link SipDelegate} has changed</li>
+ *     <li>the IMS registration of the feature tags associated with this {@link SipDelegate} have
+ *         changed.</li>
+ * </ul>
+ * @hide
+ */
+public interface DelegateStateCallback {
+
+    /**
+     * This must be called by the ImsService after {@link SipTransportImplBase#createSipDelegate} is
+     * called by the framework to notify the framework and remote application that the
+     * {@link SipDelegate} has been successfully created.
+     *
+     * @param delegate The SipDelegate created to service the DelegateRequest.
+     * @param deniedTags A List of {@link FeatureTagState}, which contains the feature tags
+     *    associated with this {@link SipDelegate} that have no access to send/receive SIP messages
+     *    as well as a reason for why the feature tag is denied. For more information on the reason
+     *    why the feature tag was denied access, see the
+     *    {@link SipDelegateManager.DeniedReason} reasons. This is considered a permanent denial due
+     *    to this {@link SipDelegate} not supporting a feature or this ImsService already
+     *    implementing this feature elsewhere. If all features of this {@link SipDelegate} are
+     *    denied, {@link #onCreated(SipDelegate, List)} should still be called as the framework will
+     *    later call {@link SipTransportImplBase#destroySipDelegate(SipDelegate, int)} to clean the
+     *    delegate up.
+     */
+    void onCreated(@NonNull SipDelegate delegate, @Nullable List<FeatureTagState> deniedTags);
+
+    /**
+     * This must be called by the ImsService after the framework calls
+     * {@link SipTransportImplBase#destroySipDelegate} to notify the framework and remote
+     * application that the procedure to destroy the {@link SipDelegate} has been completed.
+     * @param reasonCode The reason for closing this delegate.
+     */
+    void onDestroyed(@SipDelegateManager.SipDelegateDestroyReason int reasonCode);
+
+    /**
+     * Call to notify the remote application of a configuration change associated with this
+     * {@link SipDelegate}.
+     * <p>
+     * The remote application will not be able to proceed sending SIP messages until after this
+     * configuration is sent the first time, so this configuration should be sent as soon as the
+     * {@link SipDelegate} has access to these configuration parameters.
+     * <p>
+     * Incoming SIP messages should not be routed to the remote application until AFTER this
+     * configuration change is sent to ensure that the remote application can respond correctly.
+     * Similarly, if there is an event that triggers the IMS configuration to change, incoming SIP
+     * messages routing should be delayed until the {@link SipDelegate} sends the IMS configuration
+     * change event to reduce conditions where the remote application is using a stale IMS
+     * configuration.
+     */
+    void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config);
+
+    /**
+     * Call to notify the remote application that the {@link SipDelegate} has modified the IMS
+     * registration state of the RCS feature tags that were requested as part of the initial
+     * {@link DelegateRequest}.
+     * <p>
+     * See {@link DelegateRegistrationState} for more information about how IMS Registration state
+     * should be communicated the associated SipDelegateConnection in cases such as
+     * IMS deregistration, handover, PDN change, provisioning changes, etc…
+     * <p>
+     * Note: Even after the status of the feature tags are updated here to deregistered, the
+     * SipDelegate must still be able to handle these messages and call
+     * {@link DelegateMessageCallback#onMessageSendFailure} to notify the RCS application that the
+     * message was not sent.
+     *
+     * @param registrationState The current network IMS registration state for all feature tags
+     *         associated with this SipDelegate.
+     */
+    void onFeatureTagRegistrationChanged(@NonNull DelegateRegistrationState registrationState);
+}
diff --git a/telephony/java/android/telephony/ims/FeatureTagState.aidl b/telephony/java/android/telephony/ims/FeatureTagState.aidl
new file mode 100644
index 0000000..bce5574
--- /dev/null
+++ b/telephony/java/android/telephony/ims/FeatureTagState.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 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;
+
+parcelable FeatureTagState;
diff --git a/telephony/java/android/telephony/ims/FeatureTagState.java b/telephony/java/android/telephony/ims/FeatureTagState.java
new file mode 100644
index 0000000..060be6f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/FeatureTagState.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Maps an IMS media feature tag 3gpp universal resource name (URN) previously mapped to a
+ * {@link SipDelegate} in the associated {@link DelegateRequest} to its current availability
+ * state as set by the ImsService managing the related IMS registration.
+ *
+ * This class is only used to report more information about a IMS feature tag that is not fully
+ * available at this time.
+ * <p>
+ * Please see {@link DelegateRegistrationState}, {@link DelegateStateCallback}, and
+ * {@link DelegateConnectionStateCallback} for more information about how this class is used to
+ * convey the state of IMS feature tags that were requested by {@link DelegateRequest} but are not
+ * currently available.
+ * @hide
+ */
+public final class FeatureTagState implements Parcelable {
+
+    private final String mFeatureTag;
+    private final int mState;
+
+    /**
+     * Associate an IMS feature tag with its current state. See {@link DelegateRegistrationState}
+     * and {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged(
+     * DelegateRegistrationState, List)} and
+     * {@link DelegateStateCallback#onCreated(SipDelegate, List)} for examples on how and when this
+     * is used.
+     *
+     * @param featureTag The IMS feature tag that is deregistered, in the process of
+     *                   deregistering, or denied.
+     * @param state The {@link DelegateRegistrationState.DeregisteredReason},
+     *         {@link DelegateRegistrationState.DeregisteringReason}, or
+     *         {@link SipDelegateManager.DeniedReason} associated with this feature tag.
+     */
+    public FeatureTagState(@NonNull String featureTag, int state) {
+        mFeatureTag = featureTag;
+        mState = state;
+    }
+
+    /**
+     * Used for constructing instances during un-parcelling.
+     */
+    private FeatureTagState(Parcel source) {
+        mFeatureTag = source.readString();
+        mState = source.readInt();
+    }
+
+    /**
+     * @return The IMS feature tag string that is in the process of deregistering,
+     * deregistered, or denied.
+     */
+    public @NonNull String getFeatureTag() {
+        return mFeatureTag;
+    }
+
+    /**
+     * @return The reason for why the feature tag is currently in the process of deregistering,
+     * has been deregistered, or has been denied. See {@link DelegateRegistrationState} and
+     * {@link DelegateConnectionStateCallback} for more information.
+     */
+    public int getState() {
+        return mState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mFeatureTag);
+        dest.writeInt(mState);
+    }
+
+    public static final Creator<FeatureTagState> CREATOR = new Creator<FeatureTagState>() {
+        @Override
+        public FeatureTagState createFromParcel(Parcel source) {
+            return new FeatureTagState(source);
+        }
+
+        @Override
+        public FeatureTagState[] newArray(int size) {
+            return new FeatureTagState[size];
+        }
+    };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        FeatureTagState that = (FeatureTagState) o;
+        return mState == that.mState
+                && mFeatureTag.equals(that.mFeatureTag);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFeatureTag, mState);
+    }
+
+    @Override
+    public String toString() {
+        return "FeatureTagState{" + "mFeatureTag='" + mFeatureTag + ", mState=" + mState + '}';
+    }
+}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 9a55cec..1b51936 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -450,8 +450,6 @@
     /** Indicates if we have known the intent of the user for the call is emergency */
     private boolean mHasKnownUserIntentEmergency = false;
 
-    private Set<RtpHeaderExtensionType> mOfferedRtpHeaderExtensionTypes = new ArraySet<>();
-
     private Set<RtpHeaderExtensionType> mAcceptedRtpHeaderExtensionTypes = new ArraySet<>();
 
     /**
@@ -692,7 +690,6 @@
         out.writeBoolean(mHasKnownUserIntentEmergency);
         out.writeInt(mRestrictCause);
         out.writeInt(mCallerNumberVerificationStatus);
-        out.writeArray(mOfferedRtpHeaderExtensionTypes.toArray());
         out.writeArray(mAcceptedRtpHeaderExtensionTypes.toArray());
     }
 
@@ -708,9 +705,6 @@
         mHasKnownUserIntentEmergency = in.readBoolean();
         mRestrictCause = in.readInt();
         mCallerNumberVerificationStatus = in.readInt();
-        Object[] offered = in.readArray(RtpHeaderExtensionType.class.getClassLoader());
-        mOfferedRtpHeaderExtensionTypes = Arrays.stream(offered)
-                .map(o -> (RtpHeaderExtensionType) o).collect(Collectors.toSet());
         Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader());
         mAcceptedRtpHeaderExtensionTypes = Arrays.stream(accepted)
                 .map(o -> (RtpHeaderExtensionType) o).collect(Collectors.toSet());
@@ -1106,46 +1100,13 @@
     }
 
     /**
-     * For an incoming or outgoing call, indicates the {@link RtpHeaderExtensionType}s which the
-     * caller is offering to make available.
-     * <p>
-     * For outgoing calls, an {@link ImsService} will reserve
-     * {@link RtpHeaderExtensionType#getLocalIdentifier()} identifiers the telephony stack has
-     * proposed to use and not use these same local identifiers.  The offered header extension
-     * types for an outgoing call can be found in the
-     * {@link ImsCallProfile#getOfferedRtpHeaderExtensionTypes()} and will be available to the
-     * {@link ImsService} in {@link MmTelFeature#createCallSession(ImsCallProfile)}.
-     * The {@link ImsService} sets the accepted {@link #setAcceptedRtpHeaderExtensionTypes(Set)}
-     * when the SDP offer/accept process has completed.
-     * <p>
-     * According to RFC8285, RTP header extensions available to a call are determined using the
-     * offer/accept phase of the SDP protocol (see RFC4566).
-     *
-     * @return the {@link RtpHeaderExtensionType}s which were offered by other end of the call.
-     */
-    public @NonNull Set<RtpHeaderExtensionType> getOfferedRtpHeaderExtensionTypes() {
-        return mOfferedRtpHeaderExtensionTypes;
-    }
-
-    /**
-     * Sets the offered {@link RtpHeaderExtensionType}s for this call.
-     * <p>
-     * According to RFC8285, RTP header extensions available to a call are determined using the
-     * offer/accept phase of the SDP protocol (see RFC4566).
-     *
-     * @param rtpHeaderExtensions the {@link RtpHeaderExtensionType}s which are offered.
-     */
-    public void setOfferedRtpHeaderExtensionTypes(@NonNull Set<RtpHeaderExtensionType>
-                    rtpHeaderExtensions) {
-        mOfferedRtpHeaderExtensionTypes.clear();
-        mOfferedRtpHeaderExtensionTypes.addAll(rtpHeaderExtensions);
-    }
-
-    /**
      * Gets the {@link RtpHeaderExtensionType}s which have been accepted by both ends of the call.
      * <p>
      * According to RFC8285, RTP header extensions available to a call are determined using the
      * offer/accept phase of the SDP protocol (see RFC4566).
+     * <p>
+     * The offered header extension types supported by the framework and exposed to the
+     * {@link ImsService} via {@link MmTelFeature#changeOfferedRtpHeaderExtensionTypes(Set)}.
      *
      * @return the {@link RtpHeaderExtensionType}s which were accepted by the other end of the call.
      */
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index a4f2a31..d1a893f 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.BinderCacheManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
@@ -213,6 +214,7 @@
     }
 
     private final int mSubId;
+    private final BinderCacheManager<ITelephony> mBinderCache;
 
     /**
      * Create an instance of {@link ImsMmTelManager} for the subscription id specified.
@@ -242,7 +244,8 @@
             throw new IllegalArgumentException("Invalid subscription ID");
         }
 
-        return new ImsMmTelManager(subId);
+        return new ImsMmTelManager(subId, new BinderCacheManager<>(
+                ImsMmTelManager::getITelephonyInterface));
     }
 
     /**
@@ -250,8 +253,9 @@
      * @hide
      */
     @VisibleForTesting
-    public ImsMmTelManager(int subId) {
+    public ImsMmTelManager(int subId, BinderCacheManager<ITelephony> binderCache) {
         mSubId = subId;
+        mBinderCache = binderCache;
     }
 
     /**
@@ -1367,7 +1371,11 @@
         }
     }
 
-    private static ITelephony getITelephony() {
+    private ITelephony getITelephony() {
+        return mBinderCache.getBinder();
+    }
+
+    private static ITelephony getITelephonyInterface() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 TelephonyFrameworkInitializer
                         .getTelephonyServiceManager()
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 8b6dac8..4292aae 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.BinderCacheManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
@@ -149,14 +150,17 @@
 
     private final int mSubId;
     private final Context mContext;
+    private final BinderCacheManager<IImsRcsController> mBinderCache;
 
     /**
      * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class.
      * @hide
      */
-    public ImsRcsManager(Context context, int subId) {
+    public ImsRcsManager(Context context, int subId,
+            BinderCacheManager<IImsRcsController> binderCache) {
         mSubId = subId;
         mContext = context;
+        mBinderCache = binderCache;
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java
new file mode 100644
index 0000000..6bfdc2c
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.telephony.ims.stub.SipDelegate;
+
+/**
+ * Represents a connection to the remote {@link SipDelegate} that is managed by the
+ * {@link ImsService} implementing IMS for the subscription that is associated with it.
+ * <p>
+ * The remote delegate will handle messages sent by this {@link SipDelegateConnection}, notifying
+ * the associated {@link DelegateMessageCallback} when the message was either sent successfully or
+ * failed to be sent.
+ * <p>
+ * It is also the responsibility of this {@link SipDelegateConnection} to acknowledge when incoming
+ * SIP messages have been received successfully via
+ * {@link DelegateMessageCallback#onMessageReceived(SipMessage)} or when there was an error
+ * receiving the message using {@link #notifyMessageReceived(String)} and
+ * {@link #notifyMessageReceiveError(String, int)}.
+ *
+ * @see SipDelegateManager#createSipDelegate
+ * @hide
+ */
+public interface SipDelegateConnection {
+
+    /**
+     * Send a SIP message to the SIP delegate to be sent over the carrier’s network. The
+     * {@link SipMessage} will either be acknowledged with
+     * {@link DelegateMessageCallback#onMessageSent(String)} upon successful sending of this message
+     * or {@link DelegateMessageCallback#onMessageSendFailure(String, int)} if there was an error
+     * sending the message.
+     * @param sipMessage The SipMessage to be sent.
+     * @param configVersion The SipDelegateImsConfiguration version used to construct the
+     *                      SipMessage. See {@link SipDelegateImsConfiguration#getVersion} for more
+     *                      information on this parameter and why it is used.
+     */
+    void sendMessage(@NonNull SipMessage sipMessage, int configVersion);
+
+    /**
+     * Notify the {@link SipDelegate} that a SIP message received from
+     * {@link DelegateMessageCallback#onMessageReceived(SipMessage)} has been received successfully
+     * and is being processed.
+     * @param viaTransactionId Per RFC3261 Sec 8.1.1.7 the transaction ID associated with the Via
+     *         branch parameter.
+     */
+    void notifyMessageReceived(@NonNull String viaTransactionId);
+
+    /**
+     * Notify the SIP delegate that the SIP message has been received from
+     * {@link DelegateMessageCallback#onMessageReceived(SipMessage)}, however there was an error
+     * processing it.
+     * @param viaTransactionId Per RFC3261 Sec 8.1.1.7 the transaction ID associated with the Via
+     *         branch parameter.
+     * @param reason The reason why the error occurred.
+     */
+    void notifyMessageReceiveError(@NonNull String viaTransactionId,
+            @SipDelegateManager.MessageFailureReason int reason);
+}
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl
new file mode 100644
index 0000000..44ae1b1
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 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;
+
+parcelable SipDelegateImsConfiguration;
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
new file mode 100644
index 0000000..8abd0ee
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.annotation.StringDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.telephony.ims.stub.SipDelegate;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the
+ * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s.
+ * <p>
+ * The IMS service must generate new instances of this configuration as the IMS configuration
+ * managed by the IMS service changes. Along with each {@link SipDelegateImsConfiguration} instance
+ * containing the configuration is the "version", which should be incremented every time a new
+ * {@link SipDelegateImsConfiguration} instance is created. The {@link SipDelegateConnection} will
+ * include the version of the {@link SipDelegateImsConfiguration} instance that it used in order for
+ * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration
+ * to generate the {@link SipMessage} and return
+ * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in
+ * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can
+ * regenerate that {@link SipMessage} using the correct {@link SipDelegateImsConfiguration}
+ * instance.
+ * <p>
+ * Every time the IMS configuration state changes in the IMS service, a full configuration should
+ * be generated. The new  {@link SipDelegateImsConfiguration} instance should not be an incremental
+ * update.
+ * @hide
+ */
+public class SipDelegateImsConfiguration implements Parcelable {
+
+    /**
+     * IPV4 Address type.
+     * <p>
+     * Used as a potential value for {@link #KEY_SIP_CONFIG_IPTYPE_STRING}.
+     */
+    public static final String IPTYPE_IPV4 = "IPV4";
+
+    /**
+     * IPV6 Address type.
+     * <p>
+     * Used as a potential value for {@link #KEY_SIP_CONFIG_IPTYPE_STRING}.
+     */
+    public static final String IPTYPE_IPV6 = "IPV6";
+
+    /**
+     * The SIP transport uses UDP.
+     * <p>
+     * Used as a potential value for {@link #KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING}.
+     */
+    public static final String SIP_TRANSPORT_UDP = "UDP";
+
+    /**
+     * The SIP transport uses TCP.
+     * <p>
+     * Used as a potential value for {@link #KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING}.
+     */
+    public static final String SIP_TRANSPORT_TCP = "TCP";
+
+    /**
+     * Flag specifying if SIP compact form is enabled
+     */
+    public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL =
+            "sip_config_is_compact_form_enabled_bool";
+
+    /**
+     * Flag specifying if SIP keepalives are enabled
+     */
+    public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL =
+            "sip_config_is_keepalive_enabled_bool";
+
+    /**
+     * Maximum SIP payload to be sent on UDP. If the SIP message payload is greater than max udp
+     * payload size, then TCP must be used
+     */
+    public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT =
+            "sip_config_udp_max_payload_size_int";
+
+    /**
+     * Transport protocol used for SIP signaling.
+     * Available options are: {@link #SIP_TRANSPORT_UDP }, {@link #SIP_TRANSPORT_TCP }
+     */
+    public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING =
+            "sip_config_protocol_type_string";
+
+    /**
+     * IMS public user identifier string
+     */
+    public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING =
+            "sip_config_ue_public_user_id_string";
+
+    /**
+     * IMS private user identifier string
+     */
+    public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING =
+            "sip_config_ue_private_user_id_string";
+
+    /**
+     * IMS home domain string
+     */
+    public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string";
+
+    /**
+     * IMEI string. Application can include the Instance-ID feature tag " +sip.instance" in the
+     * Contact header with a value of the device IMEI in the form "urn:gsma:imei:<device IMEI>".
+     */
+    public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string";
+
+    /**
+     * IP address type for SIP signaling.
+     * Available options are: {@link #IPTYPE_IPV6}, {@link #IPTYPE_IPV4}
+     */
+    public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string";
+
+    /**
+     * Local IPaddress used for SIP signaling.
+     */
+    public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING =
+            "sip_config_ue_default_ipaddress_string";
+
+    /**
+     * Local port used for sending SIP traffic
+     */
+    public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT =
+            "sip_config_ue_default_port_int";
+
+    /**
+     * SIP server / PCSCF default ip address
+     */
+    public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING =
+            "sip_config_server_default_ipaddress_string";
+
+    /**
+     * SIP server / PCSCF port used for sending SIP traffic
+     */
+    public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT =
+            "sip_config_server_default_port_int";
+
+    /**
+     * Flag specifying if Network Address Translation is enabled and UE is behind a NAT.
+     */
+    public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL =
+            "sip_config_is_nat_enabled_bool";
+
+    /**
+     * UE's public IPaddress when UE is behind a NAT.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING =
+            "sip_config_ue_public_ipaddress_with_nat_string";
+
+    /**
+     * UE's public SIP port when UE is behind a NAT.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT =
+            "sip_config_ue_public_port_with_nat_int";
+
+    /**
+     * Flag specifying if Globally routable user-agent uri (GRUU) is enabled as per TS 23.808
+     */
+    public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL =
+            "sip_config_is_gruu_enabled_bool";
+
+    /**
+     * UE's Globally routable user-agent uri if this feature is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING =
+            "sip_config_ue_public_gruu_string";
+
+    /**
+     * Flag specifying if SIP over IPSec is enabled.
+     */
+    public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL =
+            "sip_config_is_ipsec_enabled_bool";
+    /**
+     * UE's SIP port used to send traffic when IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT =
+            "sip_config_ue_ipsec_client_port_int";
+
+    /**
+     * UE's SIP port used to receive traffic when IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT =
+            "sip_config_ue_ipsec_server_port_int";
+
+    /**
+     * UE's SIP port used for the previous IPsec security association if IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT =
+            "sip_config_ue_ipsec_old_client_port_int";
+
+    /**
+     * Port number used by the SIP server to send SIP traffic when IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT =
+            "sip_config_server_ipsec_client_port_int";
+
+    /**
+     * Port number used by the SIP server to receive incoming SIP traffic when IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT =
+            "sip_config_server_ipsec_server_port_int";
+
+    /**
+     * Port number used by the SIP server to send SIP traffic on the previous IPSec security
+     * association when IPSec is enabled.
+     * <p>
+     * This key will not exist if {@link #KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL} is {@code false}.
+     */
+    public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT =
+            "sip_config_server_ipsec_old_client_port_int";
+    /**
+     * SIP Authentication header string
+     */
+    public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING =
+            "sip_config_auhentication_header_string";
+
+    /**
+     * SIP Authentication nonce string
+     */
+    public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING =
+            "sip_config_authentication_nonce_string";
+
+    /**
+     * SIP service route header string
+     */
+    public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING =
+            "sip_config_service_route_header_string";
+
+    /**
+     * SIP security verify header string
+     */
+    public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING =
+            "sip_config_security_verify_header_string";
+
+    /**
+     * SIP Path header string
+     */
+    public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING =
+            "sip_config_path_header_string";
+
+    /**
+     * SIP User part string in contact header
+     */
+    public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING =
+            "sip_config_uri_user_part_string";
+
+    /**
+     * SIP P-access-network-info header string
+     */
+    public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING =
+            "sip_config_p_access_network_info_header_string";
+
+    /**
+     * SIP P-last-access-network-info header string
+     */
+    public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING =
+            "sip_config_p_last_access_network_info_header_string";
+
+    /**
+     * SIP P-associated-uri header string
+     */
+    public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING =
+            "sip_config_p_associated_uri_header_string";
+
+    /**@hide*/
+    @StringDef(prefix = "KEY_SIP_CONFIG", suffix = "_STRING", value = {
+            KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING,
+            KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING,
+            KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING,
+            KEY_SIP_CONFIG_HOME_DOMAIN_STRING,
+            KEY_SIP_CONFIG_IMEI_STRING,
+            KEY_SIP_CONFIG_IPTYPE_STRING,
+            KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING,
+            KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING,
+            KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING,
+            KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING,
+            KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING,
+            KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING,
+            KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING,
+            KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING,
+            KEY_SIP_CONFIG_PATH_HEADER_STRING,
+            KEY_SIP_CONFIG_URI_USER_PART_STRING,
+            KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING,
+            KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING,
+            KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StringConfigKey {}
+
+    /**@hide*/
+    @StringDef(prefix = "KEY_SIP_CONFIG", suffix = "_INT", value = {
+            KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT,
+            KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT,
+            KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT,
+            KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT,
+            KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT,
+            KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT,
+            KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT,
+            KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT,
+            KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT,
+            KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IntConfigKey {}
+
+    /**@hide*/
+    @StringDef(prefix = "KEY_SIP_CONFIG", suffix = "_BOOL", value = {
+            KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL,
+            KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL,
+            KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL,
+            KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL,
+            KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BooleanConfigKey {}
+
+    /**
+     * Builder class to be used when constructing a new SipDelegateImsConfiguration.
+     */
+    public static class Builder {
+        private final long mVersion;
+        private final PersistableBundle mBundle;
+
+        /**
+         * Creates an empty implementation of SipDelegateImsConfiguration.
+         * @param version The version associated with the SipDelegateImsConfiguration being built.
+         *                See {@link #getVersion} for more information.
+         */
+        public Builder(int version) {
+            mVersion = version;
+            mBundle = new PersistableBundle();
+        }
+        /**
+         * Clones an existing implementation of SipDelegateImsConfiguration to handle situations
+         * where only a small number of parameters have changed from the previous configuration.
+         * <p>
+         * Automatically increments the version of this configuration by 1. See {@link #getVersion}
+         * for more information.
+         */
+        public Builder(@NonNull SipDelegateImsConfiguration config) {
+            mVersion = config.getVersion() + 1;
+            mBundle = config.copyBundle();
+        }
+        /**
+         * Put a string value into this configuration bundle for the given key.
+         */
+        public Builder putString(@StringConfigKey String key, String value) {
+            mBundle.putString(key, value);
+            return this;
+        }
+
+        /**
+         * Replace the existing default value with a new value for a given key.
+         */
+        public Builder putInt(@IntConfigKey String key, int value) {
+            mBundle.putInt(key, value);
+            return this;
+        }
+
+        /**
+         * Replace the existing default value with a new value for a given key.
+         */
+        public Builder putBoolean(@BooleanConfigKey String key, boolean value) {
+            mBundle.putBoolean(key, value);
+            return this;
+        }
+
+        /**
+         * @return a new SipDelegateImsConfiguration from this Builder.
+         */
+        public SipDelegateImsConfiguration build() {
+            return new SipDelegateImsConfiguration(mVersion, mBundle);
+        }
+    }
+
+    private final long mVersion;
+    private final PersistableBundle mBundle;
+
+    private SipDelegateImsConfiguration(long version, PersistableBundle bundle) {
+        mVersion = version;
+        mBundle = bundle;
+    }
+
+    private SipDelegateImsConfiguration(Parcel source) {
+        mVersion = source.readLong();
+        mBundle = source.readPersistableBundle();
+    }
+
+    /**
+     * @return the string value associated with a given key or {@code null} if it doesn't exist.
+     */
+    public @StringConfigKey String getString(String key) {
+        return mBundle.getString(key);
+    }
+
+    /**
+     * @return the Integer value associated with a given key or {@code null} if the value doesn't
+     * exist.
+     */
+    public @IntConfigKey Integer getInt(String key) {
+        if (!mBundle.containsKey(key)) {
+            return null;
+        }
+        return mBundle.getInt(key);
+    }
+
+    /**
+     * @return the Integer value associated with a given key or {@code null} if the value doesn't
+     * exist.
+     */
+    public @BooleanConfigKey Boolean getBoolen(String key) {
+        if (!mBundle.containsKey(key)) {
+            return null;
+        }
+        return mBundle.getBoolean(key);
+    }
+
+    /**
+     * @return a shallow copy of the full configuration.
+     */
+    public PersistableBundle copyBundle() {
+        return new PersistableBundle(mBundle);
+    }
+
+    /**
+     * An integer representing the version number of this SipDelegateImsConfiguration.
+     * {@link SipMessage}s that are created using this configuration will also have a this
+     * version number associated with them, which will allow the IMS service to validate that the
+     * {@link SipMessage} was using the latest configuration during creation and not a stale
+     * configuration due to race conditions between the configuration being updated and the RCS
+     * application not receiving the updated configuration before generating a new message.
+     *
+     * @return the version number associated with this {@link SipDelegateImsConfiguration}.
+     */
+    public long getVersion() {
+        return mVersion;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(mVersion);
+        dest.writePersistableBundle(mBundle);
+    }
+
+    public static final Creator<SipDelegateImsConfiguration> CREATOR =
+            new Creator<SipDelegateImsConfiguration>() {
+        @Override
+        public SipDelegateImsConfiguration createFromParcel(Parcel source) {
+            return new SipDelegateImsConfiguration(source);
+        }
+
+        @Override
+        public SipDelegateImsConfiguration[] newArray(int size) {
+            return new SipDelegateImsConfiguration[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 82c8a9c..337b7d4 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -17,29 +17,251 @@
 package android.telephony.ims;
 
 import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
+import android.telephony.BinderCacheManager;
 import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.ims.aidl.IImsRcsController;
+import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper;
+import android.telephony.ims.stub.DelegateConnectionMessageCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
 /**
- * Manages the creation and destruction of SipDelegates, which allow an IMS application to forward
- * SIP messages for the purposes of providing a single IMS registration to the carrier's IMS network
- * from multiple sources.
+ * Manages the creation and destruction of SipDelegates for the {@link ImsService} managing IMS
+ * for the subscription ID that this SipDelegateManager has been created for.
+ *
+ * This allows multiple IMS applications to forward SIP messages to/from their application for the
+ * purposes of providing a single IMS registration to the carrier's IMS network from potentially
+ * many IMS stacks implementing a subset of the supported MMTEL/RCS features.
  * @hide
  */
 @SystemApi
 public class SipDelegateManager {
 
+    /**
+     * The SIP message has failed being sent or received for an unknown reason.
+     * <p>
+     * The caller should retry a message that failed with this response.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_UNKNOWN = 0;
+
+    /**
+     * The remote service associated with this connection has died and the message was not
+     * properly sent/received.
+     * <p>
+     * This is considered a permanent error and the system will automatically begin the teardown and
+     * destruction of the SipDelegate. No further messages should be sent on this transport.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_DELEGATE_DEAD = 1;
+
+    /**
+     * The message has not been sent/received because the delegate is in the process of closing and
+     * has become unavailable. No further messages should be sent/received on this delegate.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_DELEGATE_CLOSED = 2;
+
+    /**
+     * The SIP message has an invalid start line and the message can not be sent.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_INVALID_START_LINE = 3;
+
+    /**
+     * One or more of the header fields in the header section of the outgoing SIP message is invalid
+     * and the SIP message can not be sent.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS = 4;
+
+    /**
+     * The body content of the SIP message is invalid and the message can not be sent.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT = 5;
+
+    /**
+     * The feature tag associated with the outgoing message does not match any known feature tags
+     * and this message can not be sent.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG = 6;
+
+    /**
+     * The feature tag associated with the outgoing message is not enabled for the associated
+     * SipDelegateConnection and can not be sent.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE = 7;
+
+    /**
+     * The link to the network has been lost and the outgoing message has failed to send.
+     * <p>
+     * This message should be retried when connectivity to the network is re-established. See
+     * {@link android.net.ConnectivityManager.NetworkCallback} for how this can be determined.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE = 8;
+
+    /**
+     * The outgoing SIP message has not been sent due to the SipDelegate not being registered for
+     * IMS at this time.
+     * <p>
+     * This is considered a temporary failure, the message should not be retried until an IMS
+     * registration change callback is received via
+     * {@link DelegateConnectionStateCallback#onFeatureTagStatusChanged}
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9;
+
+    /**
+     * The outgoing SIP message has not been sent because the {@link SipDelegateImsConfiguration}
+     * version associated with the outgoing {@link SipMessage} is now stale and has failed
+     * validation checks.
+     * <p>
+     * The @link SipMessage} should be recreated using the newest
+     * {@link SipDelegateImsConfiguration} and sent again.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10;
+
+    /**
+     * The outgoing SIP message has not been sent because the internal state of the associated
+     * {@link SipDelegate} is changing and has temporarily brought the transport down.
+     * <p>
+     * This is considered a temporary error and the {@link SipDelegateConnection} should resend the
+     * message once {@link DelegateRegistrationState#DEREGISTERING_REASON_FEATURE_TAGS_CHANGING} is
+     * no longer reported.
+     * @hide
+     */
+    public static final int MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION = 11;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "MESSAGE_FAILURE_REASON_", value = {
+            MESSAGE_FAILURE_REASON_UNKNOWN,
+            MESSAGE_FAILURE_REASON_DELEGATE_DEAD,
+            MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+            MESSAGE_FAILURE_REASON_INVALID_START_LINE,
+            MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS,
+            MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT,
+            MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG,
+            MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE,
+            MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE,
+            MESSAGE_FAILURE_REASON_NOT_REGISTERED,
+            MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION,
+            MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION
+    })
+    public @interface MessageFailureReason {}
+
+
+    /**
+     * Access to use this feature tag has been denied for an unknown reason.
+     * @hide
+     */
+    public static final int DENIED_REASON_UNKNOWN = 0;
+
+    /**
+     * This feature tag is allowed to be used by this SipDelegateConnection, but it is in use by
+     * another SipDelegateConnection and can not be associated with this delegate. The feature tag
+     * will stay in this state until the feature tag is release by the other application.
+     * @hide
+     */
+    public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1;
+
+    /**
+     * Access to use this feature tag has been denied because this application does not have the
+     * permissions required to access this feature tag.
+     * @hide
+     */
+    public static final int DENIED_REASON_NOT_ALLOWED = 2;
+
+    /**
+     * Access to use this feature tag has been denied because single registration is not allowed by
+     * the carrier at this time. The application should fall back to dual registration if
+     * applicable.
+     * @hide
+     */
+    public static final int DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED = 3;
+
+    /**
+     * This feature tag is not recognized as a valid feature tag by the SipDelegate and has been
+     * denied.
+     * @hide
+     */
+    public static final int DENIED_REASON_INVALID = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "DENIED_REASON_", value = {
+            DENIED_REASON_UNKNOWN,
+            DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE,
+            DENIED_REASON_NOT_ALLOWED,
+            DENIED_REASON_SINGLE_REGISTRATION_NOT_ALLOWED,
+            DENIED_REASON_INVALID
+    })
+    public @interface DeniedReason {}
+
+    /**
+     * The SipDelegate has closed due to an unknown reason.
+     * @hide
+     */
+    public static final int SIP_DELEGATE_DESTROY_REASON_UNKNOWN = 0;
+
+    /**
+     * The SipDelegate has closed because the IMS service has died unexpectedly.
+     * @hide
+     */
+    public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD = 1;
+
+    /**
+     * The SipDelegate has closed because the IMS application has requested that the connection be
+     * destroyed.
+     * @hide
+     */
+    public static final int SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP = 2;
+
+    /**
+     * The SipDelegate has closed because the IMS service does not support the creation of
+     * SipDelegates.
+     * @hide
+     */
+    public static final int SIP_DELEGATE_DESTROY_REASON_SERVICE_NOT_SUPPORTED = 3;
+
+    /**
+     * The SipDelegate has been closed due to the user disabling RCS.
+     * @hide
+     */
+    public static final int SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "SIP_DELEGATE_DESTROY_REASON", value = {
+            SIP_DELEGATE_DESTROY_REASON_UNKNOWN,
+            SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD,
+            SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP,
+            SIP_DELEGATE_DESTROY_REASON_SERVICE_NOT_SUPPORTED,
+            SIP_DELEGATE_DESTROY_REASON_USER_DISABLED_RCS
+    })
+    public @interface SipDelegateDestroyReason {}
+
     private final Context mContext;
     private final int mSubId;
+    private final BinderCacheManager<IImsRcsController> mBinderCache;
 
     /**
      * Only visible for testing. To instantiate an instance of this class, please use
@@ -47,9 +269,11 @@
      * @hide
      */
     @VisibleForTesting
-    public SipDelegateManager(Context context, int subId) {
+    public SipDelegateManager(Context context, int subId,
+            BinderCacheManager<IImsRcsController> binderCache) {
         mContext = context;
         mSubId = subId;
+        mBinderCache = binderCache;
     }
 
     /**
@@ -69,7 +293,7 @@
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean isSupported() throws ImsException {
         try {
-            IImsRcsController controller = getIImsRcsController();
+            IImsRcsController controller = mBinderCache.getBinder();
             if (controller == null) {
                 throw new ImsException("Telephony server is down",
                         ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
@@ -83,11 +307,90 @@
         }
     }
 
-    private IImsRcsController getIImsRcsController() {
-        IBinder binder = TelephonyFrameworkInitializer
-                .getTelephonyServiceManager()
-                .getTelephonyImsServiceRegisterer()
-                .get();
-        return IImsRcsController.Stub.asInterface(binder);
+    /**
+     * Request that the ImsService implementation create a SipDelegate, which will configure the
+     * ImsService to forward SIP traffic that matches the filtering criteria set in supplied
+     * {@link DelegateRequest} to the application that the supplied callbacks are registered for.
+     * <p>
+     * This API requires that the caller is running as part of a long-running process and will
+     * always be available to handle incoming messages. One mechanism that can be used for this is
+     * the {@link android.service.carrier.CarrierMessagingClientService}, which the framework keeps
+     * a persistent binding to when the app is the default SMS application.
+     * @param request The parameters that are associated with the SipDelegate creation request that
+     *                will be used to create the SipDelegate connection.
+     * @param executor The executor that will be used to call the callbacks associated with this
+     *          SipDelegate.
+     * @param dc The callback that will be used to notify the listener of the creation/destruction
+     *           of the remote SipDelegate as well as changes to the state of the remote SipDelegate
+     *           connection.
+     * @param mc The callback that will be used to notify the listener of new incoming SIP messages
+     *           as well as the status of messages that were sent by the associated
+     *           SipDelegateConnection.
+     * @throws ImsException Thrown if there was a problem communicating with the ImsService
+     * associated with this SipDelegateManager. See {@link ImsException#getCode()}.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor,
+            @NonNull DelegateConnectionStateCallback dc,
+            @NonNull DelegateConnectionMessageCallback mc) throws ImsException {
+        if (request == null || executor == null || dc == null || mc == null) {
+            throw new IllegalArgumentException("Invalid arguments passed into createSipDelegate");
+        }
+        try {
+            SipDelegateConnectionAidlWrapper wrapper =
+                    new SipDelegateConnectionAidlWrapper(executor, dc, mc);
+            IImsRcsController controller = mBinderCache.listenOnBinder(wrapper,
+                    wrapper::binderDied);
+            if (controller == null) {
+                throw new ImsException("Telephony server is down",
+                        ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+            }
+            controller.createSipDelegate(mSubId, request, wrapper.getStateCallbackBinder(),
+                    wrapper.getMessageCallbackBinder());
+        } catch (ServiceSpecificException e) {
+            throw new ImsException(e.getMessage(), e.errorCode);
+        } catch (RemoteException e) {
+            throw new ImsException(e.getMessage(),
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Destroy a previously created {@link SipDelegateConnection} that was created using
+     * {@link #createSipDelegate}.
+     * <p>
+     * This will also clean up all related callbacks in the associated ImsService.
+     * @param delegateConnection The SipDelegateConnection to destroy.
+     * @param reason The reason for why this SipDelegateConnection was destroyed.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection,
+            @SipDelegateDestroyReason int reason) {
+
+        if (delegateConnection == null) {
+            throw new IllegalArgumentException("invalid argument passed into destroySipDelegate");
+        }
+        if (delegateConnection instanceof SipDelegateConnectionAidlWrapper) {
+            SipDelegateConnectionAidlWrapper w =
+                    (SipDelegateConnectionAidlWrapper) delegateConnection;
+            try {
+                IImsRcsController c = mBinderCache.removeRunnable(w);
+                c.destroySipDelegate(mSubId, w.getSipDelegateBinder(), reason);
+            } catch (RemoteException e) {
+                // Connection to telephony died, but this will signal destruction of SipDelegate
+                // eventually anyway, so return normally.
+                try {
+                    w.getStateCallbackBinder().onDestroyed(
+                            SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+                } catch (RemoteException ignore) {
+                    // Local to process.
+                }
+            }
+        } else {
+            throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
+                    + " into this method");
+        }
     }
 }
diff --git a/telephony/java/android/telephony/ims/SipMessage.aidl b/telephony/java/android/telephony/ims/SipMessage.aidl
new file mode 100644
index 0000000..5140f8a
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipMessage.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020 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;
+
+parcelable SipMessage;
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
new file mode 100644
index 0000000..c3b1be2
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 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.annotation.NonNull;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a partially encoded SIP message. See RFC 3261 for more information on how SIP
+ * messages are structured and used.
+ * <p>
+ * The SIP message is represented in a partially encoded form in order to allow for easier
+ * verification and should not be used as a generic SIP message container.
+ * @hide
+ */
+public final class SipMessage implements Parcelable {
+    // Should not be set to true for production!
+    private static final boolean IS_DEBUGGING = Build.IS_ENG;
+
+    private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS",
+            "BYE", "CANCEL", "REGISTER"};
+
+    private final String mStartLine;
+    private final String mHeaderSection;
+    private final byte[] mContent;
+
+    /**
+     * Represents a partially encoded SIP message.
+     *
+     * @param startLine The start line of the message, containing either the request-line or
+     *                  status-line.
+     * @param headerSection A String containing the full unencoded SIP message header.
+     * @param content UTF-8 encoded SIP message body.
+     */
+    public SipMessage(@NonNull String startLine, @NonNull String headerSection,
+            @NonNull byte[] content) {
+        if (startLine == null || headerSection == null || content == null) {
+            throw new IllegalArgumentException("One or more null parameters entered");
+        }
+        mStartLine = startLine;
+        mHeaderSection = headerSection;
+        mContent = content;
+    }
+
+    /**
+     * Private constructor used only for unparcelling.
+     */
+    private SipMessage(Parcel source) {
+        mStartLine = source.readString();
+        mHeaderSection = source.readString();
+        mContent = new byte[source.readInt()];
+        source.readByteArray(mContent);
+    }
+    /**
+     * @return The start line of the SIP message, which contains either the request-line or
+     * status-line.
+     */
+    public @NonNull String getStartLine() {
+        return mStartLine;
+    }
+
+    /**
+     * @return The full, unencoded header section of the SIP message.
+     */
+    public @NonNull String getHeaderSection() {
+        return mHeaderSection;
+    }
+
+    /**
+     * @return only the UTF-8 encoded SIP message body.
+     */
+    public @NonNull byte[] getContent() {
+        return mContent;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mStartLine);
+        dest.writeString(mHeaderSection);
+        dest.writeInt(mContent.length);
+        dest.writeByteArray(mContent);
+    }
+
+    public static final Creator<SipMessage> CREATOR = new Creator<SipMessage>() {
+        @Override
+        public SipMessage createFromParcel(Parcel source) {
+            return new SipMessage(source);
+        }
+
+        @Override
+        public SipMessage[] newArray(int size) {
+            return new SipMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder();
+        b.append("StartLine: [");
+        if (IS_DEBUGGING) {
+            b.append(mStartLine);
+        } else {
+            b.append(sanitizeStartLineRequest(mStartLine));
+        }
+        b.append("], [");
+        b.append("Header: [");
+        if (IS_DEBUGGING) {
+            b.append(mHeaderSection);
+        } else {
+            // only identify transaction id/call ID when it is available.
+            b.append("***");
+        }
+        b.append("], ");
+        b.append("Content: [NOT SHOWN]");
+        return b.toString();
+    }
+
+    /**
+     * Start lines containing requests are formatted: METHOD SP Request-URI SP SIP-Version CRLF.
+     * Detect if this is a REQUEST and redact Request-URI portion here, as it contains PII.
+     */
+    private String sanitizeStartLineRequest(String startLine) {
+        String[] splitLine = startLine.split(" ");
+        if (splitLine == null || splitLine.length == 0)  {
+            return "(INVALID STARTLINE)";
+        }
+        for (String method : SIP_REQUEST_METHODS) {
+            if (splitLine[0].contains(method)) {
+                return splitLine[0] + " <Request-URI> " + splitLine[2];
+            }
+        }
+        return startLine;
+    }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
index b9a6b3c..37fec7a 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
@@ -21,6 +21,7 @@
 import android.telephony.ims.aidl.IImsSmsListener;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.RtpHeaderExtensionType;
 
 import android.telephony.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
@@ -29,6 +30,8 @@
 import com.android.ims.internal.IImsRegistrationListener;
 import com.android.ims.internal.IImsUt;
 
+import java.util.List;
+
 /**
  * See MmTelFeature for more information.
  * {@hide}
@@ -37,6 +40,7 @@
     void setListener(IImsMmTelListener l);
     int getFeatureState();
     ImsCallProfile createCallProfile(int callSessionType, int callType);
+    void changeOfferedRtpHeaderExtensionTypes(in List<RtpHeaderExtensionType> types);
     IImsCallSession createCallSession(in ImsCallProfile profile);
     int shouldProcessCall(in String[] uris);
     IImsUt getUtInterface();
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 8e84e93..f218e35 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -17,10 +17,15 @@
 package android.telephony.ims.aidl;
 
 import android.net.Uri;
+import android.telephony.ims.DelegateRequest;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
 import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
-import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
 
 import com.android.ims.ImsFeatureContainer;
 import com.android.ims.internal.IImsServiceFeatureCallback;
@@ -58,6 +63,10 @@
 
     // SipDelegateManager
     boolean isSipDelegateSupported(int subId);
+    void createSipDelegate(int subId, in DelegateRequest request,
+            ISipDelegateConnectionStateCallback delegateState,
+            ISipDelegateMessageCallback delegateMessage);
+    void destroySipDelegate(int subId, ISipDelegate connection, int reason);
 
     // Internal commands that should not be made public
     void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
new file mode 100644
index 0000000..477ee95
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 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.aidl;
+
+import android.telephony.ims.SipMessage;
+
+/**
+ * See {@link SipDelegate} and {@link SipDelegateConnection} for docs regarding this callback.
+ * {@hide}
+ */
+oneway interface ISipDelegate {
+    void sendMessage(in SipMessage sipMessage, int configVersion);
+    void notifyMessageReceived(in String viaTransactionId);
+    void notifyMessageReceiveError(in String viaTransactionId, int reason);
+
+    // only used by SipDelegate.
+    void closeDialog(in String callId);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl
new file mode 100644
index 0000000..ddfcb99
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020 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.aidl;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.aidl.ISipDelegate;
+
+/**
+ * See {@link SipDelegateConnectionStateCallback} for docs regarding this callback.
+ * {@hide}
+ */
+oneway interface ISipDelegateConnectionStateCallback {
+    void onCreated(ISipDelegate c);
+    void onFeatureTagStatusChanged(in DelegateRegistrationState registrationState,
+                in List<FeatureTagState> deniedFeatureTags);
+    void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig);
+    void onDestroyed(int reason);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl
new file mode 100644
index 0000000..30b7d6c
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateMessageCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 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.aidl;
+
+import android.telephony.ims.SipMessage;
+
+/**
+ * See {@link DelegateMessageCallback} and {@link DelegateConnectionMessageCallback} for docs
+ * regarding this callback.
+ * {@hide}
+ */
+oneway interface ISipDelegateMessageCallback {
+   void onMessageReceived(in SipMessage message);
+   void onMessageSent(in String viaTransactionId);
+   void onMessageSendFailure(in String viaTransactionId, int reason);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl
new file mode 100644
index 0000000..609ee26
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020 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.aidl;
+
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.aidl.ISipDelegate;
+
+/**
+ * See {@link SipDelegateStateCallback} for docs regarding this callback.
+ * {@hide}
+ */
+oneway interface ISipDelegateStateCallback {
+    void onCreated(ISipDelegate c, in List<FeatureTagState> deniedFeatureTags);
+    void onFeatureTagRegistrationChanged(in DelegateRegistrationState registrationState);
+    void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig);
+    void onDestroyed(int reason);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
index fe23343..cd88839 100644
--- a/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISipTransport.aidl
@@ -16,9 +16,17 @@
 
 package android.telephony.ims.aidl;
 
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+
 /**
  * Interface for commands to the SIP Transport implementation.
  * {@hide}
  */
-interface ISipTransport {
+oneway interface ISipTransport {
+    void createSipDelegate(in DelegateRequest request, ISipDelegateStateCallback dc,
+            ISipDelegateMessageCallback mc);
+    void destroySipDelegate(ISipDelegate delegate, int reason);
 }
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
new file mode 100644
index 0000000..a7f62cc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2020 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.aidl;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateStateCallback;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.stub.SipDelegate;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of callbacks by wrapping the internal AIDL from telephony. Also implements
+ * ISipDelegate internally when {@link DelegateStateCallback#onCreated(SipDelegate, List)} is called
+ * in order to trampoline events back to telephony.
+ * @hide
+ */
+public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback {
+
+    private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
+        @Override
+        public void sendMessage(SipMessage sipMessage, int configVersion) {
+            SipDelegate d = mDelegate;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> d.sendMessage(sipMessage, configVersion));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void notifyMessageReceived(String viaTransactionId)  {
+            SipDelegate d = mDelegate;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> d.notifyMessageReceived(viaTransactionId));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+        }
+
+        @Override
+        public void notifyMessageReceiveError(String viaTransactionId, int reason) {
+            SipDelegate d = mDelegate;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> d.notifyMessageReceiveError(viaTransactionId, reason));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
+        }
+
+        @Override
+        public void closeDialog(String callId)  {
+            SipDelegate d = mDelegate;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> d.closeDialog(callId));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    };
+
+    private final ISipDelegateMessageCallback mMessageBinder;
+    private final ISipDelegateStateCallback mStateBinder;
+    private final Executor mExecutor;
+
+    private volatile SipDelegate mDelegate;
+
+    public SipDelegateAidlWrapper(Executor executor, ISipDelegateStateCallback stateBinder,
+            ISipDelegateMessageCallback messageBinder) {
+        mExecutor = executor;
+        mStateBinder = stateBinder;
+        mMessageBinder = messageBinder;
+    }
+
+    @Override
+    public void onMessageReceived(SipMessage message) {
+        try {
+            mMessageBinder.onMessageReceived(message);
+        } catch (RemoteException e) {
+            // BinderDied will be called on SipTransport instance to trigger destruction. Notify
+            // failure message failure locally for now.
+            SipDelegate d = mDelegate;
+            if (d != null) {
+                notifyLocalMessageFailedToBeReceived(message,
+                        SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+            }
+        }
+    }
+
+    @Override
+    public void onMessageSent(String viaTransactionId) {
+        try {
+            mMessageBinder.onMessageSent(viaTransactionId);
+        } catch (RemoteException e) {
+            // BinderDied will trigger destroySipDelegate, so just ignore this locally.
+        }
+    }
+
+    @Override
+    public void onMessageSendFailure(String viaTransactionId, int reason) {
+        try {
+            mMessageBinder.onMessageSendFailure(viaTransactionId, reason);
+        } catch (RemoteException e) {
+            // BinderDied will trigger destroySipDelegate, so just ignore this locally.
+        }
+    }
+
+    @Override
+    public void onCreated(@NonNull SipDelegate delegate,
+            @Nullable List<FeatureTagState> deniedTags) {
+        mDelegate = delegate;
+        try {
+            mStateBinder.onCreated(mDelegateBinder, deniedTags);
+        } catch (RemoteException e) {
+            // BinderDied will trigger destroySipDelegate, so just ignore this locally.
+        }
+    }
+
+    @Override
+    public void onFeatureTagRegistrationChanged(DelegateRegistrationState registrationState) {
+        try {
+            mStateBinder.onFeatureTagRegistrationChanged(registrationState);
+        } catch (RemoteException e) {
+            // BinderDied will trigger destroySipDelegate, so just ignore this locally.
+        }
+    }
+
+    @Override
+    public void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config) {
+        try {
+            mStateBinder.onImsConfigurationChanged(config);
+        } catch (RemoteException e) {
+            // BinderDied will trigger destroySipDelegate, so just ignore this locally.
+        }
+    }
+
+    @Override
+    public void onDestroyed(int reasonCode) {
+        mDelegate = null;
+        try {
+            mStateBinder.onDestroyed(reasonCode);
+        } catch (RemoteException e) {
+            // Do not worry about this if the remote side is already dead.
+        }
+    }
+
+    public SipDelegate getDelegate()  {
+        return mDelegate;
+    }
+
+    public ISipDelegate getDelegateBinder() {
+        return mDelegateBinder;
+    }
+
+    private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
+        //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
+        // transaction ID can not be parsed.
+        SipDelegate d = mDelegate;
+        if (d != null) {
+            mExecutor.execute(() -> d.notifyMessageReceiveError(null, reason));
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
new file mode 100644
index 0000000..3bd1a46
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2020 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.aidl;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+import android.telephony.ims.stub.DelegateConnectionMessageCallback;
+import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.telephony.ims.stub.SipDelegate;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Wrapper class implementing {@link SipDelegateConnection} using AIDL, which is returned to the
+ * local process. Also holds a reference to incoming connection message and state AIDL impl to
+ * trampoline events to callbacks as well as notify the local process in the event that the remote
+ * process becomes unavailable.
+ * <p>
+ * When the remote {@link SipDelegate} is created, this instance tracks the
+ * {@link ISipDelegate} associated with it and implements the
+ * {@link SipDelegateConnection} sent back to the local callback.
+ * @hide
+ */
+public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection,
+        IBinder.DeathRecipient {
+    private static final String LOG_TAG = "SipDelegateCAW";
+
+    private final ISipDelegateConnectionStateCallback.Stub mStateBinder =
+            new ISipDelegateConnectionStateCallback.Stub() {
+        @Override
+        public void onCreated(ISipDelegate c) {
+            associateSipDelegate(c);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() ->
+                        mStateCallback.onCreated(SipDelegateConnectionAidlWrapper.this));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onFeatureTagStatusChanged(DelegateRegistrationState registrationState,
+                List<FeatureTagState> deniedFeatureTags) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() ->
+                        mStateCallback.onFeatureTagStatusChanged(registrationState,
+                                new ArraySet<>(deniedFeatureTags)));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onImsConfigurationChanged(SipDelegateImsConfiguration registeredSipConfig) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() ->
+                        mStateCallback.onImsConfigurationChanged(registeredSipConfig));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onDestroyed(int reason) {
+            invalidateSipDelegateBinder();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() ->
+                        mStateCallback.onDestroyed(reason));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    };
+
+    private final ISipDelegateMessageCallback.Stub mMessageBinder =
+            new ISipDelegateMessageCallback.Stub() {
+                @Override
+                public void onMessageReceived(SipMessage message) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() ->
+                                mMessageCallback.onMessageReceived(message));
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
+                public void onMessageSent(String viaTransactionId) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() ->
+                                mMessageCallback.onMessageSent(viaTransactionId));
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+
+                @Override
+                public void onMessageSendFailure(String viaTransactionId, int reason) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        mExecutor.execute(() ->
+                                mMessageCallback.onMessageSendFailure(viaTransactionId, reason));
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            };
+
+
+    private final Executor mExecutor;
+    private final DelegateConnectionStateCallback mStateCallback;
+    private final DelegateConnectionMessageCallback mMessageCallback;
+    private final AtomicReference<ISipDelegate> mDelegateBinder =
+            new AtomicReference<>();
+
+    /**
+     * Wrap the local state and message callbacks, calling the implementation of these interfaces
+     * when the remote process calls these methods.
+     */
+    public SipDelegateConnectionAidlWrapper(Executor executor,
+            DelegateConnectionStateCallback stateCallback,
+            DelegateConnectionMessageCallback messageCallback) {
+        mExecutor = executor;
+        mStateCallback = stateCallback;
+        mMessageCallback = messageCallback;
+    }
+
+    @Override
+    public void sendMessage(SipMessage sipMessage, int configVersion) {
+        try {
+            ISipDelegate conn = getSipDelegateBinder();
+            if (conn == null) {
+                notifyLocalMessageFailedToSend(sipMessage,
+                        SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
+                return;
+            }
+            conn.sendMessage(sipMessage, configVersion);
+        } catch (RemoteException e) {
+            notifyLocalMessageFailedToSend(sipMessage,
+                        SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
+        }
+    }
+
+    @Override
+    public void notifyMessageReceived(String viaTransactionId) {
+        try {
+            ISipDelegate conn = getSipDelegateBinder();
+            if (conn == null) {
+                return;
+            }
+            conn.notifyMessageReceived(viaTransactionId);
+        } catch (RemoteException e) {
+            // Nothing to do here, app will eventually get remote death callback.
+        }
+    }
+
+    @Override
+    public void notifyMessageReceiveError(String viaTransactionId, int reason) {
+        try {
+            ISipDelegate conn = getSipDelegateBinder();
+            if (conn == null) {
+                return;
+            }
+            conn.notifyMessageReceiveError(viaTransactionId, reason);
+        } catch (RemoteException e) {
+            // Nothing to do here, app will eventually get remote death callback.
+        }
+    }
+
+    // Also called upon IImsRcsController death (telephony process dies).
+    @Override
+    public void binderDied() {
+        invalidateSipDelegateBinder();
+        mExecutor.execute(() -> mStateCallback.onDestroyed(
+                SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD));
+    }
+
+    /**
+     * @return Implementation of state binder.
+     */
+    public ISipDelegateConnectionStateCallback getStateCallbackBinder() {
+        return mStateBinder;
+    }
+
+    /**
+     * @return Implementation of message binder.
+     */
+    public ISipDelegateMessageCallback getMessageCallbackBinder() {
+        return mMessageBinder;
+    }
+
+    /**
+     * @return The ISipDelegateConnection associated with this wrapper.
+     */
+    public ISipDelegate getSipDelegateBinder() {
+        return mDelegateBinder.get();
+    }
+
+    private void associateSipDelegate(ISipDelegate c) {
+        if (c != null) {
+            try {
+                c.asBinder().linkToDeath(this, 0 /*flags*/);
+            } catch (RemoteException e) {
+                // already dead.
+                c = null;
+            }
+        }
+        mDelegateBinder.set(c);
+    }
+
+    private void invalidateSipDelegateBinder() {
+        ISipDelegate oldVal = mDelegateBinder.getAndUpdate((unused) -> null);
+        if (oldVal != null) {
+            try {
+                oldVal.asBinder().unlinkToDeath(this, 0 /*flags*/);
+            } catch (NoSuchElementException e) {
+                Log.i(LOG_TAG, "invalidateSipDelegateBinder: " + e);
+            }
+        }
+    }
+
+    private void notifyLocalMessageFailedToSend(SipMessage m, int reason) {
+        //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
+        // transaction ID can not be parsed.
+        mExecutor.execute(() ->
+                mMessageCallback.onMessageSendFailure(null, reason));
+    }
+}
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index d7b0e0f..e570fb6 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -27,6 +27,8 @@
 import android.telephony.ims.ImsCallProfile;
 import android.telephony.ims.ImsCallSession;
 import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.RtpHeaderExtensionType;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsMmTelFeature;
 import android.telephony.ims.aidl.IImsMmTelListener;
@@ -37,6 +39,7 @@
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.stub.ImsSmsImplBase;
 import android.telephony.ims.stub.ImsUtImplBase;
+import android.util.ArraySet;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsEcbm;
@@ -45,6 +48,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Set;
 
 /**
  * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
@@ -93,6 +98,18 @@
         }
 
         @Override
+        public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types)
+                throws RemoteException {
+            synchronized (mLock) {
+                try {
+                    MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(new ArraySet<>(types));
+                } catch (Exception e) {
+                    throw new RemoteException(e.getMessage());
+                }
+            }
+        }
+
+        @Override
         public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
             synchronized (mLock) {
                 return createCallSessionInterface(profile);
@@ -623,6 +640,24 @@
     }
 
     /**
+     * Called by the framework to report a change to the RTP header extension types which should be
+     * offered during SDP negotiation (see RFC8285 for more information).
+     * <p>
+     * The {@link ImsService} should report the RTP header extensions which were accepted during
+     * SDP negotiation using {@link ImsCallProfile#setAcceptedRtpHeaderExtensionTypes(Set)}.
+     *
+     * @param extensionTypes The RTP header extensions the framework wishes to offer during
+     *                       outgoing and incoming call setup.  An empty list indicates that there
+     *                       are no framework defined RTP header extension types to offer.
+     * @hide
+     */
+    @SystemApi
+    public void changeOfferedRtpHeaderExtensionTypes(
+            @NonNull Set<RtpHeaderExtensionType> extensionTypes) {
+        // Base implementation - should be overridden if RTP header extension handling is supported.
+    }
+
+    /**
      * @hide
      */
     public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java
new file mode 100644
index 0000000..59f9601
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionMessageCallback.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.stub;
+
+import android.annotation.NonNull;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+
+/**
+ * The callback associated with a {@link SipDelegateConnection}, which handles newly received
+ * messages as well as the result of sending a SIP message.
+ * @hide
+ */
+public interface DelegateConnectionMessageCallback {
+
+    /**
+     * A new {@link SipMessage} has been received from the delegate.
+     * @param message the {@link SipMessage} routed to this RCS application.
+     */
+    void onMessageReceived(@NonNull SipMessage message);
+
+    /**
+     * A message previously sent to the SIP delegate using
+     * {@link SipDelegateConnection#sendMessage} has been successfully sent.
+     * @param viaTransactionId The transaction ID found in the via header field of the
+     *                         previously sent {@link SipMessage}.
+     */
+    void onMessageSent(@NonNull String viaTransactionId);
+
+    /**
+     * A message previously sent to the SIP delegate using
+     * {@link SipDelegateConnection#sendMessage} has failed to be sent.
+     * @param viaTransactionId The Transaction ID found in the via header field of the
+     *                         previously sent {@link SipMessage}.
+     * @param reason The reason for the failure.
+     */
+    void onMessageSendFailure(String viaTransactionId,
+            @SipDelegateManager.MessageFailureReason int reason);
+}
diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java
new file mode 100644
index 0000000..9761805
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2020 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.stub;
+
+import android.annotation.NonNull;
+import android.telephony.ims.DelegateRegistrationState;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.FeatureTagState;
+import android.telephony.ims.SipDelegateConnection;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+
+import java.util.Set;
+
+/**
+ * The callback associated with a {@link SipDelegateConnection} that manages the state of the
+ * SipDelegateConnection.
+ * <p>
+ * After {@link SipDelegateManager#createSipDelegate} is used to request a new
+ * {@link SipDelegateConnection} be created, {@link #onCreated} will be called with the
+ * {@link SipDelegateConnection} instance that must be used to communicate with the remote
+ * {@link SipDelegate}.
+ * <p>
+ * After, {@link #onFeatureTagStatusChanged} will always be called at least once with the current
+ * status of the feature tags that have been requested. The application may receive multiple
+ * {@link #onFeatureTagStatusChanged} callbacks over the lifetime of the associated
+ * {@link SipDelegateConnection}, which will signal changes to how SIP messages associated with
+ * those feature tags will be handled.
+ * <p>
+ * In order to start sending SIP messages, the SIP configuration parameters will need to be
+ * received, so the messaging application should make no assumptions about these parameters and wait
+ * until {@link #onImsConfigurationChanged(SipDelegateImsConfiguration)} has been called. This is
+ * guaranteed to happen after the first {@link #onFeatureTagStatusChanged} if there is at least one
+ * feature tag that has been successfully associated with the {@link SipDelegateConnection}. If all
+ * feature tags were denied, no IMS configuration will be sent.
+ * <p>
+ * The {@link SipDelegateConnection} will stay associated with this RCS application until either the
+ * RCS application calls {@link SipDelegateManager#destroySipDelegate} or telephony destroys the
+ * {@link SipDelegateConnection}. In both cases, {@link #onDestroyed(int)}  will be called.
+ * Telephony destroying the {@link SipDelegateConnection} instance is rare and will only happen in
+ * rare cases, such as if telephony itself or IMS service dies unexpectedly. See
+ * {@link SipDelegateManager.SipDelegateDestroyReason} reasons for more information on all of the
+ * cases that will trigger the {@link SipDelegateConnection} to be destroyed.
+ *
+ * @hide
+ */
+public interface DelegateConnectionStateCallback {
+
+    /**
+     * A {@link SipDelegateConnection} has been successfully created for the
+     * {@link DelegateRequest} used when calling {@link SipDelegateManager#createSipDelegate}.
+     */
+    void onCreated(@NonNull SipDelegateConnection c);
+
+    /**
+     * The status of the RCS feature tags that were requested as part of the initial
+     * {@link DelegateRequest}.
+     * <p>
+     * There are four states that each RCS feature tag can be in: registered, deregistering,
+     * deregistered, and denied.
+     * <p>
+     * When a feature tag is considered registered, SIP messages associated with that feature tag
+     * may be sent and received freely.
+     * <p>
+     * When a feature tag is deregistering, the network IMS registration still contains the feature
+     * tag, however the IMS service and associated {@link SipDelegate} is in the progress of
+     * modifying the IMS registration to remove this feature tag and requires the application to
+     * perform an action before the IMS registration can change. The specific action required for
+     * the SipDelegate to continue modifying the IMS registration can be found in the definition of
+     * each {@link DelegateRegistrationState.DeregisteringReason}.
+     * <p>
+     * When a feature tag is in the deregistered state, new out-of-dialog SIP messages for that
+     * feature tag will be rejected, however due to network race conditions, the RCS application
+     * should still be able to handle new out-of-dialog SIP requests from the network. This may not
+     * be possible, however, if the IMS registration itself was lost. See the
+     * {@link DelegateRegistrationState.DeregisteredReason} reasons for more information on how SIP
+     * messages are handled in each of these cases.
+     * <p>
+     * If a feature tag is denied, no incoming messages will be routed to the associated
+     * {@link DelegateConnectionMessageCallback} and all outgoing SIP messages related to this
+     * feature tag will be rejected. See {@link SipDelegateManager.DeniedReason}
+     * reasons for more information about the conditions when this will happen.
+     * <p>
+     * The set of feature tags contained in the registered, deregistering, deregistered, and denied
+     * lists will always equal the set of feature tags requested in the initial
+     * {@link DelegateRequest}.
+     * <p>
+     * Transitions of feature tags from registered, deregistering, and deregistered and vice-versa
+     * may happen quite often, however transitions to/from denied are rare and only occur if the
+     * user has changed the role of your application to add/remove support for one or more requested
+     * feature tags or carrier provisioning has enabled or disabled single registration entirely.
+     * Please see {@link SipDelegateManager.DeniedReason} reasons for an explanation of each of
+     * these cases as well as what may cause them to change.
+     *
+     * @param registrationState The new IMS registration state of each of the feature tags
+     *     associated with the {@link SipDelegate}.
+     * @param deniedFeatureTags A list of {@link FeatureTagState} objects, each containing a feature
+     *     tag associated with this {@link SipDelegateConnection} that has no access to
+     *     send/receive SIP messages as well as a reason for why the feature tag is denied. For more
+     *     information on the reason why the feature tag was denied access, see the
+     *     {@link SipDelegateManager.DeniedReason} reasons.
+     */
+    void onFeatureTagStatusChanged(@NonNull DelegateRegistrationState registrationState,
+            @NonNull Set<FeatureTagState> deniedFeatureTags);
+
+
+    /**
+     * IMS configuration of the underlying IMS stack used by this IMS application for construction
+     * of the SIP messages that will be sent over the carrier's network.
+     * <p>
+     * There should never be assumptions made about the configuration of the underling IMS stack and
+     * the IMS application should wait for this indication before sending out any outgoing SIP
+     * messages.
+     * <p>
+     * Configuration may change due to IMS registration changes as well as
+     * other optional events on the carrier network. If IMS stack is already registered at the time
+     * of callback registration, then this method shall be invoked with the current configuration.
+     * Otherwise, there may be a delay in this method being called if initial IMS registration has
+     * not compleed yet.
+     *
+     * @param registeredSipConfig The configuration of the IMS stack registered on the IMS network.
+     */
+    void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration registeredSipConfig);
+
+    /**
+     * The previously created {@link SipDelegateConnection} instance delivered via
+     * {@link #onCreated(SipDelegateConnection)} has been destroyed. This interface should no longer
+     * be used for any SIP message handling.
+     *
+     * @param reason The reason for the failure.
+     */
+    void onDestroyed(@SipDelegateManager.SipDelegateDestroyReason int reason);
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 12abdd1..a6f5c45 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -17,6 +17,8 @@
 package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.RemoteException;
@@ -126,6 +128,57 @@
     }
 
     /**
+     * Called by the framework to request that the ImsService perform the network registration
+     * of all SIP delegates associated with this ImsService.
+     * <p>
+     * If the SIP delegate feature tag configuration has changed, then this method will be
+     * called in order to let the ImsService know that it can pick up these changes in the IMS
+     * registration.
+     * @hide
+     */
+    public void updateSipDelegateRegistration() {
+        // Stub implementation, ImsService should implement this
+    }
+
+
+    /**
+     * Called by the framework to request that the ImsService perform the network deregistration of
+     * all SIP delegates associated with this ImsService.
+     * <p>
+     * This is typically called in situations where the user has changed the configuration of the
+     * device (for example, the default messaging application) and the framework is reconfiguring
+     * the tags associated with each IMS application.
+     * <p>
+     * This should not affect the registration of features managed by the ImsService itself, such as
+     * feature tags related to MMTEL registration.
+     * @hide
+     */
+    public void triggerSipDelegateDeregistration() {
+        // Stub implementation, ImsService should implement this
+    }
+
+    /**
+     * Called by the framework to notify the ImsService that a SIP delegate connection has received
+     * a SIP message containing a permanent failure response (such as a 403) or an indication that a
+     * SIP response timer has timed out in response to an outgoing SIP message. This method will be
+     * called when this condition occurs to trigger the ImsService to tear down the full IMS
+     * registration and re-register again.
+     *
+     * @param sipCode The SIP error code that represents a permanent failure that was received in
+     *    response to a request generated by the IMS application. See RFC3261 7.2 for the general
+     *    classes of responses available here, however the codes that generate this condition may
+     *    be carrier specific.
+     * @param sipReason The reason associated with the SIP error code. {@code null} if there was no
+     *    reason associated with the error.
+     * @hide
+     */
+    public void triggerNetworkReregistration(@IntRange(from = 100, to = 699) int sipCode,
+            @Nullable String sipReason) {
+        // Stub implementation, ImsService should implement this
+    }
+
+
+    /**
      * Notify the framework that the device is connected to the IMS network.
      *
      * @param imsRadioTech the radio access technology. Valid values are defined as
diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java
new file mode 100644
index 0000000..3ec9709
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 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.stub;
+
+import android.annotation.NonNull;
+import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.SipDelegateImsConfiguration;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipMessage;
+
+/**
+ * The {@link SipDelegate} is implemented by the {@link ImsService} and allows a privileged
+ * IMS application to use this delegate to send SIP messages as well as acknowledge the receipt of
+ * incoming SIP messages delivered to the application over the existing IMS registration, allowing
+ * for a single IMS registration for multiple IMS applications.
+ * <p>
+ * Once the SIP delegate is created for that application,
+ * {@link ImsRegistrationImplBase#updateSipDelegateRegistration()} will be called, indicating that
+ * the application is finished setting up SipDelegates and the existing IMS registration may be
+ * modified to include the features managed by these SipDelegates.
+ * <p>
+ * This SipDelegate will need to notify the remote application of the registration of these features
+ * as well as the associated {@link SipDelegateImsConfiguration} before the application can start
+ * sending/receiving SIP messages via the transport. See
+ * {@link android.telephony.ims.DelegateStateCallback} for more information.
+ * @hide
+ */
+public interface SipDelegate {
+
+    /**
+     * The framework calls this method when a remote RCS application wishes to send a new outgoing
+     * SIP message.
+     * <p>
+     * Once sent, this SIP delegate should notify the remote application of the success or
+     * failure using {@link DelegateMessageCallback#onMessageSent(String)} or
+     * {@link DelegateMessageCallback#onMessageSendFailure(String, int)}.
+     * @param message The SIP message to be sent over the operator’s network.
+     * @param configVersion The SipDelegateImsConfiguration version used to construct the
+     *         SipMessage. See {@link SipDelegateImsConfiguration} for more information. If the
+     *         version specified here does not match the most recently constructed
+     *         {@link SipDelegateImsConfiguration}, this message should fail validation checks and
+     *         {@link DelegateMessageCallback#onMessageSendFailure} should be called with code
+     *         {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION}.
+     */
+    void sendMessage(@NonNull SipMessage message, int configVersion);
+
+    /**
+     * The framework is requesting that routing resources associated with the SIP dialog using the
+     * provided Call-ID to be cleaned up.
+     * <p>
+     * Typically a SIP Dialog close event will be signalled by that dialog receiving a BYE or 200 OK
+     * message, however, in some cases, the framework will request that the ImsService close the
+     * dialog due to the open dialog holding up an event such as applying a provisioning change or
+     * handing over to another transport type.
+     * @param callId The call-ID header value associated with the ongoing SIP Dialog that the
+     *         framework is requesting be closed.
+     */
+    void closeDialog(@NonNull String callId);
+
+    /**
+     * The remote application has received the SIP message and is processing it.
+     * @param viaTransactionId The Transaction ID found in the via header field of the
+     *                         previously sent {@link SipMessage}.
+     */
+    void notifyMessageReceived(@NonNull String viaTransactionId);
+
+    /**
+     * The remote application has either not received the SIP message or there was an error
+     * processing it.
+     * @param viaTransactionId The Transaction ID found in the via header field of the
+     *                         previously sent {@link SipMessage}.
+     * @param reason The reason why the message was not correctly received.
+     */
+    void notifyMessageReceiveError(@NonNull String viaTransactionId,
+            @SipDelegateManager.MessageFailureReason int reason);
+}
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index b2b2914..b48f631 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -18,27 +18,75 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.os.Binder;
+import android.os.IBinder;
+import android.telephony.ims.DelegateMessageCallback;
+import android.telephony.ims.DelegateRequest;
+import android.telephony.ims.DelegateStateCallback;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
 import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.aidl.SipDelegateAidlWrapper;
+import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
- * Manages the creation and destruction of SipDelegates in order to proxy SIP traffic to other
- * IMS applications in order to support IMS single registration.
+ * The ImsService implements this class to manage the creation and destruction of
+ * {@link SipDelegate}s.
+ *
+ * {@link SipDelegate}s allow the ImsService to forward SIP traffic generated and consumed by IMS
+ * applications as a delegate to the associated carrier's IMS Network in order to support using a
+ * single IMS registration for all MMTEL and RCS signalling traffic.
  * @hide
  */
 @SystemApi
 public class SipTransportImplBase {
+    private static final String LOG_TAG = "SipTransportIB";
+
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            mBinderExecutor.execute(() -> binderDiedInternal());
+        }
+    };
+
+    private final ISipTransport.Stub mSipTransportImpl = new ISipTransport.Stub() {
+        @Override
+        public void createSipDelegate(DelegateRequest request, ISipDelegateStateCallback dc,
+                ISipDelegateMessageCallback mc) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mBinderExecutor.execute(() -> createSipDelegateInternal(request, dc, mc));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void destroySipDelegate(ISipDelegate delegate, int reason) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mBinderExecutor.execute(() -> destroySipDelegateInternal(delegate, reason));
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    };
 
     private final Executor mBinderExecutor;
-    private final ISipTransport mSipTransportImpl = new ISipTransport.Stub() {
-
-    };
+    private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
 
     /**
      * Create an implementation of SipTransportImplBase.
      *
-     * @param executor The executor that remote calls from the framework should be called on.
+     * @param executor The executor that remote calls from the framework will be called on. This
+     *                 includes the methods here as well as the methods in {@link SipDelegate}.
      */
     public SipTransportImplBase(@NonNull Executor executor) {
         if (executor == null) {
@@ -49,6 +97,79 @@
     }
 
     /**
+     * Called by the Telephony framework to request the creation of a new {@link SipDelegate}.
+     * <p>
+     * The implementation must call {@link DelegateStateCallback#onCreated(SipDelegate, List)} with
+     * the {@link SipDelegate} that is associated with the {@link DelegateRequest}.
+     * <p>
+     * This method will be called on the Executor specified in
+     * {@link SipTransportImplBase#SipTransportImplBase(Executor)}.
+     *
+     * @param request A SIP delegate request containing the parameters that the remote RCS
+     * application wishes to use.
+     * @param dc A callback back to the remote application to be used to communicate state callbacks
+     *           for the SipDelegate.
+     * @param mc A callback back to the remote application to be used to send SIP messages to the
+     *           remote application and acknowledge the sending of outgoing SIP messages.
+     * @hide
+     */
+    public void createSipDelegate(@NonNull DelegateRequest request,
+            @NonNull DelegateStateCallback dc, @NonNull DelegateMessageCallback mc) {
+        throw new UnsupportedOperationException("destroySipDelegate not implemented!");
+    }
+
+    /**
+     * Destroys the SipDelegate associated with a remote IMS application.
+     * <p>
+     * After the delegate is destroyed, {@link DelegateStateCallback#onDestroyed(int)} must be
+     * called to notify listeners of its destruction to release associated resources.
+     * <p>
+     * This method will be called on the Executor specified in
+     * {@link SipTransportImplBase#SipTransportImplBase(Executor)}.
+     * @param delegate The delegate to be destroyed.
+     * @param reason The reason the remote connection to this {@link SipDelegate} is being
+     *         destroyed.
+     * @hide
+     */
+    public void destroySipDelegate(@NonNull SipDelegate delegate,
+            @SipDelegateManager.SipDelegateDestroyReason int reason) {
+        throw new UnsupportedOperationException("destroySipDelegate not implemented!");
+    }
+
+    private void createSipDelegateInternal(DelegateRequest r, ISipDelegateStateCallback cb,
+            ISipDelegateMessageCallback mc) {
+        SipDelegateAidlWrapper wrapper = new SipDelegateAidlWrapper(mBinderExecutor, cb, mc);
+        mDelegates.add(wrapper);
+        createSipDelegate(r, wrapper, wrapper);
+    }
+
+    private void destroySipDelegateInternal(ISipDelegate d, int reason) {
+        SipDelegateAidlWrapper result = null;
+        for (SipDelegateAidlWrapper w : mDelegates) {
+            if (Objects.equals(d, w.getDelegateBinder())) {
+                result = w;
+                break;
+            }
+        }
+
+        if (result != null) {
+            mDelegates.remove(result);
+            destroySipDelegate(result.getDelegate(), reason);
+        } else {
+            Log.w(LOG_TAG, "destroySipDelegateInternal, could not findSipDelegate corresponding to "
+                    + d);
+        }
+    }
+
+    private void binderDiedInternal() {
+        for (SipDelegateAidlWrapper w : mDelegates) {
+            destroySipDelegate(w.getDelegate(),
+                    SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+        }
+        mDelegates.clear();
+    }
+
+    /**
      * @return The IInterface used by the framework.
      * @hide
      */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 36d01f4..d16cb16 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -31,6 +31,7 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.CallForwardingInfo;
+import android.telephony.CarrierBandwidth;
 import android.telephony.CarrierRestrictionRules;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
@@ -2232,4 +2233,10 @@
      * @return true if dual connectivity is enabled else false
      */
     boolean isNrDualConnectivityEnabled(int subId);
+
+    /**
+     * Get carrier bandwidth per primary and secondary carrier
+     * @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
+     */
+    CarrierBandwidth getCarrierBandwidth(int subId);
 }
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 7abe189..cd9406c 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -35,7 +35,6 @@
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
-import static android.net.NetworkStats.STATS_PER_IFACE;
 import static android.net.NetworkStats.STATS_PER_UID;
 import static android.net.NetworkStats.TAG_ALL;
 import static android.net.NetworkStats.TAG_NONE;
@@ -994,7 +993,7 @@
     public void testTethering() throws Exception {
         // pretend first mobile network comes online
         expectDefaultSettings();
-        NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)};
+        final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)};
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
@@ -1004,23 +1003,39 @@
         incrementCurrentTime(HOUR_IN_MILLIS);
         expectDefaultSettings();
 
+        // Register custom provider and retrieve callback.
+        final TestableNetworkStatsProviderBinder provider =
+                new TestableNetworkStatsProviderBinder();
+        final INetworkStatsProviderCallback cb =
+                mService.registerNetworkStatsProvider("TEST-TETHERING-OFFLOAD", provider);
+        assertNotNull(cb);
+        final long now = getElapsedRealtime();
+
         // Traffic seen by kernel counters (includes software tethering).
-        final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1)
+        final NetworkStats swIfaceStats = new NetworkStats(now, 1)
                 .insertEntry(TEST_IFACE, 1536L, 12L, 384L, 3L);
         // Hardware tethering traffic, not seen by kernel counters.
-        final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1)
-                .insertEntry(TEST_IFACE, 512L, 4L, 128L, 1L);
+        final NetworkStats tetherHwIfaceStats = new NetworkStats(now, 1)
+                .insertEntry(new NetworkStats.Entry(TEST_IFACE, UID_ALL, SET_DEFAULT,
+                        TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+                        512L, 4L, 128L, 1L, 0L));
+        final NetworkStats tetherHwUidStats = new NetworkStats(now, 1)
+                .insertEntry(new NetworkStats.Entry(TEST_IFACE, UID_TETHERING, SET_DEFAULT,
+                        TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+                        512L, 4L, 128L, 1L, 0L));
+        cb.notifyStatsUpdated(0 /* unused */, tetherHwIfaceStats, tetherHwUidStats);
 
-        // Traffic for UID_RED.
-        final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
+        // Fake some traffic done by apps on the device (as opposed to tethering), and record it
+        // into UID stats (as opposed to iface stats).
+        final NetworkStats localUidStats = new NetworkStats(now, 1)
                 .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
-        // All tethering traffic, both hardware and software.
-        final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
-                .insertEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
+        // Software per-uid tethering traffic.
+        final NetworkStats tetherSwUidStats = new NetworkStats(now, 1)
+                .insertEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1408L, 10L, 256L, 1L,
                         0L);
 
-        expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);
-        expectNetworkStatsUidDetail(uidStats, tetherStats);
+        expectNetworkStatsSummary(swIfaceStats);
+        expectNetworkStatsUidDetail(localUidStats, tetherSwUidStats);
         forcePollAndWaitForIdle();
 
         // verify service recorded history
@@ -1362,12 +1377,6 @@
     }
 
     private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
-        expectNetworkStatsSummary(summary, new NetworkStats(0L, 0));
-    }
-
-    private void expectNetworkStatsSummary(NetworkStats summary, NetworkStats tetherStats)
-            throws Exception {
-        expectNetworkStatsTethering(STATS_PER_IFACE, tetherStats);
         expectNetworkStatsSummaryDev(summary.clone());
         expectNetworkStatsSummaryXt(summary.clone());
     }
@@ -1380,11 +1389,6 @@
         when(mStatsFactory.readNetworkStatsSummaryXt()).thenReturn(summary);
     }
 
-    private void expectNetworkStatsTethering(int how, NetworkStats stats)
-            throws Exception {
-        when(mNetManager.getNetworkStatsTethering(how)).thenReturn(stats);
-    }
-
     private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
         expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0));
     }
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 1cc5073..8b89959 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -76,25 +76,34 @@
     "//packages/apps/Settings/tests/robotests", // TODO(b/161767237): remove
 ]
 
-// wifi-service needs pre-jarjared version of framework-wifi so it can reference copied utility
-// classes before they are renamed.
-java_library {
-    name: "framework-wifi-pre-jarjar",
+// defaults shared between `framework-wifi` & `framework-wifi-pre-jarjar`
+// java_sdk_library `framework-wifi` needs sources to generate stubs, so it cannot reuse
+// `framework-wifi-pre-jarjar`
+java_defaults {
+    name: "framework-wifi-defaults",
     defaults: ["wifi-module-sdk-version-defaults"],
-    sdk_version: "module_current",
     static_libs: [
         "framework-wifi-util-lib",
         "android.hardware.wifi-V1.0-java-constants",
+        "modules-utils-build",
     ],
     libs: [
-        "framework-annotations-lib",
         "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
     ],
     srcs: [
         ":framework-wifi-updatable-sources",
         ":framework-wifi-util-lib-aidls",
     ],
-    // java_api_finder must accompany `srcs`
+}
+
+// wifi-service needs pre-jarjared version of framework-wifi so it can reference copied utility
+// classes before they are renamed.
+java_library {
+    name: "framework-wifi-pre-jarjar",
+    defaults: ["framework-wifi-defaults"],
+    sdk_version: "module_current",
+    libs: ["framework-annotations-lib"],
+    // java_api_finder must accompany `srcs` (`srcs` defined in `framework-wifi-defaults`)
     plugins: ["java_api_finder"],
     installable: false,
     visibility: [
@@ -108,18 +117,7 @@
     name: "framework-wifi",
     defaults: [
         "framework-module-defaults",
-        "wifi-module-sdk-version-defaults",
-    ],
-    static_libs: [
-        "framework-wifi-util-lib",
-        "android.hardware.wifi-V1.0-java-constants",
-    ],
-    libs: [
-        "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
-    ],
-    srcs: [
-        ":framework-wifi-updatable-sources",
-        ":framework-wifi-util-lib-aidls",
+        "framework-wifi-defaults",
     ],
 
     jarjar_rules: ":wifi-jarjar-rules",
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index b489be2..ff06a18 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -124,3 +124,4 @@
 rule com.android.internal.util.Protocol* com.android.wifi.x.@0
 
 rule com.android.net.module.util.** com.android.wifi.x.@0
+rule com.android.modules.utils.** com.android.wifi.x.@0
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
index 6a39959..b710a14 100644
--- a/wifi/tests/Android.bp
+++ b/wifi/tests/Android.bp
@@ -31,10 +31,11 @@
     static_libs: [
         "androidx.test.rules",
         "core-test-rules",
+        "frameworks-base-testutils",
         "guava",
         "mockito-target-minus-junit4",
+        "modules-utils-build",
         "net-tests-utils",
-        "frameworks-base-testutils",
         "truth-prebuilt",
     ],
 
@@ -47,4 +48,8 @@
         "device-tests",
         "mts",
     ],
+
+    // static libs used by both framework-wifi & FrameworksWifiApiTests. Need to rename test usage
+    // to a different package name to prevent conflict with the copy in production code.
+    jarjar_rules: "test-jarjar-rules.txt",
 }
diff --git a/wifi/tests/test-jarjar-rules.txt b/wifi/tests/test-jarjar-rules.txt
new file mode 100644
index 0000000..41b97ab
--- /dev/null
+++ b/wifi/tests/test-jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.android.modules.utils.** com.android.wifi.test.x.@0