Merge "Fix typo"
diff --git a/Android.bp b/Android.bp
index ab85a0a..5bd3329 100644
--- a/Android.bp
+++ b/Android.bp
@@ -271,6 +271,8 @@
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
+            // TODO: remove when moved to the below package
+            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
         ],
     },
@@ -507,6 +509,9 @@
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
+            // TODO: remove when moved to the below package
+            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
+            "packages/modules/Connectivity/framework/aidl-export",
         ],
     },
     // These are libs from framework-internal-utils that are required (i.e. being referenced)
diff --git a/api/OWNERS b/api/OWNERS
index a027270..4d8ed03 100644
--- a/api/OWNERS
+++ b/api/OWNERS
@@ -4,3 +4,6 @@
 file:platform/packages/modules/common:/OWNERS
 
 per-file Android.bp = file:platform/build/soong:/OWNERS
+
+# For metalava team to disable lint checks in platform
+per-file Android.bp = aurimas@google.com,emberrose@google.com,sjgilbert@google.com
\ No newline at end of file
diff --git a/core/api/current.txt b/core/api/current.txt
index a5b1d1f..0ffc2c5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -19114,6 +19114,7 @@
     method public boolean isSink();
     method public boolean isSource();
     field public static final int TYPE_AUX_LINE = 19; // 0x13
+    field public static final int TYPE_BLE_BROADCAST = 30; // 0x1e
     field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
     field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
     field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
@@ -25227,6 +25228,7 @@
     method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean);
   }
 
   public final class IpSecAlgorithm implements android.os.Parcelable {
@@ -25370,6 +25372,7 @@
 
   public abstract class PlatformVpnProfile {
     method public final boolean getExcludeLocalRoutes();
+    method public final boolean getRequiresInternetValidation();
     method public final int getType();
     method @NonNull public final String getTypeString();
     field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
@@ -25606,7 +25609,8 @@
   public class VpnManager {
     method public void deleteProvisionedVpnProfile();
     method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
-    method public void startProvisionedVpnProfile();
+    method @Deprecated public void startProvisionedVpnProfile();
+    method @NonNull public String startProvisionedVpnProfileSession();
     method public void stopProvisionedVpnProfile();
   }
 
@@ -39767,13 +39771,14 @@
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_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_SUPPORTS_TETHERING_BOOL = "carrier_supports_tethering_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 @Deprecated 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";
-    field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
-    field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
+    field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+    field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
     field @Deprecated public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
@@ -40002,14 +40007,23 @@
   }
 
   public static final class CarrierConfigManager.Ims {
+    field public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY = "ims.key_capability_type_call_composer_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = "ims.key_capability_type_options_uce_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = "ims.key_capability_type_presence_uce_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = "ims.key_capability_type_sms_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = "ims.key_capability_type_ut_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = "ims.key_capability_type_video_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = "ims.key_capability_type_voice_int_array";
     field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
     field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
     field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
     field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
+    field public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE = "ims.mmtel_requires_provisioning_bundle";
     field public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT = "ims.non_rcs_capabilities_cache_expiration_sec_int";
     field public static final String KEY_PREFIX = "ims.";
     field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
     field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array";
+    field public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = "ims.rcs_requires_provisioning_bundle";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
   }
 
@@ -41632,6 +41646,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
     method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getAllowedNetworkTypesForReason(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
     method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription();
@@ -41692,6 +41707,7 @@
     method public int getSubscriptionId();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle);
     method public int getSupportedModemCount();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getSupportedRadioAccessFamily();
     method @Nullable public String getTypeAllocationCode();
     method @Nullable public String getTypeAllocationCode(int);
     method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
@@ -41737,6 +41753,7 @@
     method public String sendEnvelopeWithStatus(String);
     method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
     method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
@@ -41773,6 +41790,8 @@
     field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
     field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
+    field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
+    field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -41843,6 +41862,26 @@
     field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2
     field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
+    field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
+    field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
+    field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
+    field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
+    field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
+    field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
+    field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
+    field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
+    field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
+    field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
+    field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
+    field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
+    field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
+    field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
+    field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
     field public static final int NETWORK_TYPE_EHRPD = 14; // 0xe
@@ -42424,6 +42463,7 @@
   public class ImsManager {
     method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+    method @NonNull public android.telephony.ims.ProvisioningManager getProvisioningManager(int);
     field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
     field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
     field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
@@ -42674,6 +42714,23 @@
     field public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1; // 0x1
   }
 
+  public class ProvisioningManager {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isProvisioningRequiredForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isRcsProvisioningRequiredForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerFeatureProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, int, boolean);
+    method public void unregisterFeatureProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback);
+  }
+
+  public static class ProvisioningManager.FeatureProvisioningCallback {
+    ctor public ProvisioningManager.FeatureProvisioningCallback();
+    method public void onFeatureProvisioningChanged(int, int, boolean);
+    method public void onRcsFeatureProvisioningChanged(int, int, boolean);
+  }
+
   public class RcsUceAdapter {
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
   }
@@ -42714,6 +42771,27 @@
     field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
   }
 
+  public class RcsFeature {
+  }
+
+  public static class RcsFeature.RcsImsCapabilities {
+    field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
+    field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
+    field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
+  }
+
+}
+
+package android.telephony.ims.stub {
+
+  public class ImsRegistrationImplBase {
+    field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
+    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+    field public static final int REGISTRATION_TECH_NR = 3; // 0x3
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 4480e04..7d68ee1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11690,7 +11690,6 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesBitmask();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesForReason(int);
     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>);
@@ -11733,7 +11732,6 @@
     method public int getSimCardState();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -11784,7 +11782,6 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
@@ -11834,10 +11831,8 @@
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
-    field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
     field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3
     field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1
-    field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
     field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
     field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
     field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
@@ -11876,26 +11871,6 @@
     field public static final int KEY_TYPE_WLAN = 2; // 0x2
     field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
     field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
-    field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
-    field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
-    field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
-    field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
-    field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
-    field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
-    field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
-    field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
-    field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
-    field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
-    field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
-    field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
-    field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
-    field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
-    field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
-    field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
-    field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
     field public static final int NR_DUAL_CONNECTIVITY_DISABLE = 2; // 0x2
     field public static final int NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE = 3; // 0x3
     field public static final int NR_DUAL_CONNECTIVITY_ENABLE = 1; // 0x1
@@ -12921,13 +12896,21 @@
 
   public class ImsService extends android.app.Service {
     ctor public ImsService();
-    method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
-    method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
-    method public void disableIms(int);
-    method public void enableIms(int);
-    method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+    method @Nullable public android.telephony.ims.feature.MmTelFeature createEmergencyOnlyMmTelFeature(int);
+    method @Deprecated public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+    method @Nullable public android.telephony.ims.feature.MmTelFeature createMmTelFeatureForSubscription(int, int);
+    method @Deprecated public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+    method @Nullable public android.telephony.ims.feature.RcsFeature createRcsFeatureForSubscription(int, int);
+    method @Deprecated public void disableIms(int);
+    method public void disableImsForSubscription(int, int);
+    method @Deprecated public void enableIms(int);
+    method public void enableImsForSubscription(int, int);
+    method @Deprecated public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+    method @NonNull public android.telephony.ims.stub.ImsConfigImplBase getConfigForSubscription(int, int);
+    method @NonNull public java.util.concurrent.Executor getExecutor();
     method public long getImsServiceCapabilities();
-    method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+    method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+    method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int);
     method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
     method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
     method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
@@ -13151,18 +13134,16 @@
   public class ProvisioningManager {
     method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
@@ -13546,6 +13527,7 @@
 
   public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public MmTelFeature();
+    ctor public MmTelFeature(@NonNull java.util.concurrent.Executor);
     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);
@@ -13579,7 +13561,7 @@
   }
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
-    ctor @Deprecated public RcsFeature();
+    ctor public RcsFeature();
     ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
     method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
@@ -13596,9 +13578,6 @@
     method public void addCapabilities(int);
     method public boolean isCapable(int);
     method public void removeCapabilities(int);
-    field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
-    field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
-    field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
   }
 
 }
@@ -13684,6 +13663,7 @@
   }
 
   public class ImsConfigImplBase {
+    ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor);
     ctor public ImsConfigImplBase();
     method public int getConfigInt(int);
     method public String getConfigString(int);
@@ -13736,6 +13716,7 @@
 
   public class ImsRegistrationImplBase {
     ctor public ImsRegistrationImplBase();
+    ctor public ImsRegistrationImplBase(@NonNull java.util.concurrent.Executor);
     method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
     method public final void onRegistered(int);
     method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes);
@@ -13746,11 +13727,6 @@
     method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String);
     method public void triggerSipDelegateDeregistration();
     method public void updateSipDelegateRegistration();
-    field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
-    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
-    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
-    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
-    field public static final int REGISTRATION_TECH_NR = 3; // 0x3
   }
 
   public class ImsSmsImplBase {
@@ -13848,6 +13824,7 @@
   }
 
   public class SipTransportImplBase {
+    ctor public SipTransportImplBase();
     ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
     method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
     method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index b531f81..ae72657 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2500,7 +2500,6 @@
     method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 7787963..27f3fc5 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -164,6 +164,18 @@
         "com/android/internal/util/IndentingPrintWriter.java",
         "com/android/internal/util/MessageUtils.java",
         "com/android/internal/util/WakeupMessage.java",
+        // TODO: delete as soon as NetworkStatsFactory stops using
+        "com/android/internal/util/ProcFileReader.java",
+    ],
+}
+
+// keep these files in sync with the packages/modules/Connectivity jarjar-rules.txt for
+// the connectivity module.
+filegroup {
+    name: "framework-connectivity-api-shared-srcs",
+    srcs: [
+        "android/util/IndentingPrintWriter.java",
+        "com/android/internal/util/FileRotator.java",
     ],
 }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6cfa39c..ab64596 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1452,18 +1452,27 @@
                     mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
-                boolean ok = false;
+                final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
                 try {
-                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                    copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
-                    // The 'close()' is the trigger for any server-side image manipulation,
-                    // so we must do that before waiting for completion.
-                    fos.close();
-                    completion.waitForCompletion();
+                    // If the stream can't be decoded, treat it as an invalid input.
+                    if (tmp != null) {
+                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+                        // The 'close()' is the trigger for any server-side image manipulation,
+                        // so we must do that before waiting for completion.
+                        fos.close();
+                        completion.waitForCompletion();
+                    } else {
+                        throw new IllegalArgumentException(
+                                "Resource 0x" + Integer.toHexString(resid) + " is invalid");
+                    }
                 } finally {
                     // Might be redundant but completion shouldn't wait unless the write
                     // succeeded; this is a fallback if it threw past the close+wait.
                     IoUtils.closeQuietly(fos);
+                    if (tmp != null) {
+                        tmp.recycle();
+                    }
                 }
             }
         } catch (RemoteException e) {
@@ -1705,13 +1714,22 @@
                     result, which, completion, mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
+                final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
                 try {
-                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                    copyStreamToWallpaperFile(bitmapData, fos);
-                    fos.close();
-                    completion.waitForCompletion();
+                    // If the stream can't be decoded, treat it as an invalid input.
+                    if (tmp != null) {
+                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+                        fos.close();
+                        completion.waitForCompletion();
+                    } else {
+                        throw new IllegalArgumentException("InputStream is invalid");
+                    }
                 } finally {
                     IoUtils.closeQuietly(fos);
+                    if (tmp != null) {
+                        tmp.recycle();
+                    }
                 }
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 271efe4..070efa3 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -38,7 +38,7 @@
     /** VpnManager APIs */
     boolean provisionVpnProfile(in VpnProfile profile, String packageName);
     void deleteVpnProfile(String packageName);
-    void startVpnProfile(String packageName);
+    String startVpnProfile(String packageName);
     void stopVpnProfile(String packageName);
 
     /** Always-on VPN APIs */
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 036607b..ec752fd 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -159,8 +159,9 @@
             boolean isMetered,
             int maxMtu,
             boolean restrictToTestNetworks,
-            boolean excludeLocalRoutes) {
-        super(type, excludeLocalRoutes);
+            boolean excludeLocalRoutes,
+            boolean requiresInternetValidation) {
+        super(type, excludeLocalRoutes, requiresInternetValidation);
 
         checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
         checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
@@ -181,7 +182,7 @@
         mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
         if (excludeLocalRoutes && !isBypassable) {
             throw new IllegalArgumentException(
-                    "Vpn should be byassable if excludeLocalRoutes is set");
+                    "Vpn must be bypassable if excludeLocalRoutes is set");
         }
 
         mIsBypassable = isBypassable;
@@ -238,7 +239,7 @@
      * that provides Authentication, and one that provides Encryption. Authenticated Encryption with
      * Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption.
      *
-     * @param allowedAlgorithms The list to be validated
+     * @param algorithmNames The list to be validated
      */
     private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
         // First, make sure no insecure algorithms were proposed.
@@ -400,7 +401,9 @@
                 mIsBypassable,
                 mIsMetered,
                 mMaxMtu,
-                mIsRestrictedToTestNetworks);
+                mIsRestrictedToTestNetworks,
+                mExcludeLocalRoutes,
+                mRequiresInternetValidation);
     }
 
     @Override
@@ -425,7 +428,8 @@
                 && mIsMetered == other.mIsMetered
                 && mMaxMtu == other.mMaxMtu
                 && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
-                && mExcludeLocalRoutes == other.mExcludeLocalRoutes;
+                && mExcludeLocalRoutes == other.mExcludeLocalRoutes
+                && mRequiresInternetValidation == other.mRequiresInternetValidation;
     }
 
     /**
@@ -439,7 +443,7 @@
     @NonNull
     public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
         final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
-                mIsRestrictedToTestNetworks, mExcludeLocalRoutes);
+                mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
         profile.type = mType;
         profile.server = mServerAddr;
         profile.ipsecIdentifier = mUserIdentity;
@@ -544,6 +548,7 @@
             Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
         }
         builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
+        builder.setRequiresInternetValidation(profile.requiresInternetValidation);
 
         return builder.build();
     }
@@ -776,6 +781,7 @@
 
         @Nullable private ProxyInfo mProxyInfo;
         @NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS;
+        private boolean mRequiresInternetValidation = false;
         private boolean mIsBypassable = false;
         private boolean mIsMetered = true;
         private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
@@ -988,6 +994,30 @@
         }
 
         /**
+         * Request that this VPN undergoes Internet validation.
+         *
+         * If this is true, the platform will perform basic validation checks for Internet
+         * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+         * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+         * capability.
+         *
+         * If this is false, the platform assumes the VPN either is always capable of reaching the
+         * Internet or intends not to. In this case, the VPN network capabilities will
+         * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+         * immediately after it connects, whether it can reach public Internet destinations or not.
+         *
+         * @param requiresInternetValidation {@code true} if the framework should attempt to
+         *                                   validate this VPN for Internet connectivity. Defaults
+         *                                   to {@code false}.
+         */
+        @NonNull
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+        public Builder setRequiresInternetValidation(boolean requiresInternetValidation) {
+            mRequiresInternetValidation = requiresInternetValidation;
+            return this;
+        }
+
+        /**
          * Marks the VPN network as metered.
          *
          * <p>A VPN network is classified as metered when the user is sensitive to heavy data usage
@@ -1103,7 +1133,8 @@
                     mIsMetered,
                     mMaxMtu,
                     mIsRestrictedToTestNetworks,
-                    mExcludeLocalRoutes);
+                    mExcludeLocalRoutes,
+                    mRequiresInternetValidation);
         }
     }
 }
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
index 3c45799..8bd1c8d 100644
--- a/core/java/android/net/PlatformVpnProfile.java
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -16,10 +16,6 @@
 
 package android.net;
 
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
@@ -67,11 +63,15 @@
 
     /** @hide */
     protected final boolean mExcludeLocalRoutes;
+    /** @hide */
+    protected final boolean mRequiresInternetValidation;
 
     /** @hide */
-    PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes) {
+    PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes,
+            boolean requiresValidation) {
         mType = type;
         mExcludeLocalRoutes = excludeLocalRoutes;
+        mRequiresInternetValidation = requiresValidation;
     }
 
     /** Returns the profile integer type. */
@@ -80,14 +80,30 @@
         return mType;
     }
 
-
     /**
-     * Returns if the local traffic is exempted from the VPN.
+     * Returns whether the local traffic is exempted from the VPN.
      */
     public final boolean getExcludeLocalRoutes() {
         return mExcludeLocalRoutes;
     }
 
+    /**
+     * Returns whether this VPN should undergo Internet validation.
+     *
+     * If this is true, the platform will perform basic validation checks for Internet
+     * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+     * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+     * capability.
+     *
+     * If this is false, the platform assumes the VPN either is always capable of reaching the
+     * Internet or intends not to. In this case, the VPN network capabilities will
+     * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+     * immediately after it connects, whether it can reach public Internet destinations or not.
+     */
+    public final boolean getRequiresInternetValidation() {
+        return mRequiresInternetValidation;
+    }
+
     /** Returns a type string describing the VPN profile type */
     @NonNull
     public final String getTypeString() {
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 3193826..5aad997 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -211,25 +211,18 @@
     public static final int ERROR_CODE_NETWORK_TIMEOUT = 1;
 
     /**
-     * An error code to indicate that the connection is refused.
-     *
-     * @hide
-     */
-    public static final int ERROR_CODE_NETWORK_CONNECT = 2;
-
-    /**
      * An error code to indicate the connection was reset. (e.g. SocketException)
      *
      * @hide
      */
-    public static final int ERROR_CODE_NETWORK_CONNECTION_RESET = 3;
+    public static final int ERROR_CODE_NETWORK_RESET = 2;
 
     /**
      * An error code to indicate that there is an IOException.
      *
      * @hide
      */
-    public static final int ERROR_CODE_NETWORK_IO = 4;
+    public static final int ERROR_CODE_NETWORK_IO = 3;
 
     /** @hide */
     @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY,
@@ -317,17 +310,32 @@
     /**
      * Request the startup of a previously provisioned VPN.
      *
+     * @return A unique key corresponding to this session.
      * @throws SecurityException exception if user or device settings prevent this VPN from being
-     *     setup, or if user consent has not been granted
+     *         setup, or if user consent has not been granted
      */
-    public void startProvisionedVpnProfile() {
+    @NonNull
+    public String startProvisionedVpnProfileSession() {
         try {
-            mService.startVpnProfile(mContext.getOpPackageName());
+            return mService.startVpnProfile(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /**
+     * Request the startup of a previously provisioned VPN.
+     *
+     * @throws SecurityException exception if user or device settings prevent this VPN from being
+     *         setup, or if user consent has not been granted
+     * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a
+     *             session key for the caller to diagnose the errors.
+     */
+    @Deprecated
+    public void startProvisionedVpnProfile() {
+        startProvisionedVpnProfileSession();
+    }
+
     /** Tear down the VPN provided by the calling app (if any) */
     public void stopProvisionedVpnProfile() {
         try {
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a5a40ad..4e69952 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -26,6 +26,7 @@
      * @param dsuSlot Name used to identify this installation
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean startInstallation(@utf8InCpp String dsuSlot);
 
     /**
@@ -36,6 +37,7 @@
      * @param readOnly True if this partition is readOnly
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
 
     /**
@@ -43,12 +45,14 @@
      *
      * @return true if the partition installation completes without error.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean closePartition();
 
     /**
      * Finish a previously started installation. Installations without
      * a cooresponding finishInstallation() will be cleaned up during device boot.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean finishInstallation();
 
     /**
@@ -57,6 +61,7 @@
      *
      * @return GsiProgress
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     GsiProgress getInstallationProgress();
 
     /**
@@ -66,21 +71,25 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean abort();
 
     /**
      * @return true if the device is running an DynamicAnroid image
      */
+    @RequiresNoPermission
     boolean isInUse();
 
     /**
      * @return true if the device has an DynamicSystem image installed
      */
+    @RequiresNoPermission
     boolean isInstalled();
 
     /**
      * @return true if the device has an DynamicSystem image enabled
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean isEnabled();
 
     /**
@@ -88,6 +97,7 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean remove();
 
     /**
@@ -97,6 +107,7 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean setEnable(boolean enable, boolean oneShot);
 
     /**
@@ -106,6 +117,7 @@
      * @param fd            fd that points to a ashmem
      * @param size          size of the ashmem file
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean setAshmem(in ParcelFileDescriptor fd, long size);
 
     /**
@@ -115,6 +127,7 @@
      * @param bytes         number of bytes that can be read from stream.
      * @return              true on success, false otherwise.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean submitFromAshmem(long bytes);
 
     /**
@@ -124,10 +137,12 @@
      * @return              true on success, false if partition doesn't have a
      *                      valid VBMeta block to retrieve the AVB key from.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean getAvbPublicKey(out AvbPublicKey dst);
 
     /**
      * Returns the suggested scratch partition size for overlayFS.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     long suggestScratchSize();
 }
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index c199b96..28c078e 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,3 +1,4 @@
+per-file Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
 per-file FeatureFlagUtils.java = sbasi@google.com
 per-file FeatureFlagUtils.java = tmfang@google.com
 
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2ae56f8..f174498 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -105,6 +105,7 @@
     public boolean allowIPv4;
     public boolean allowIPv6;
     public boolean isMetered = true;
+    public boolean requiresInternetValidation = false;
     public Network[] underlyingNetworks;
     public ProxyInfo proxyInfo;
 
@@ -131,6 +132,7 @@
         allowIPv4 = other.allowIPv4;
         allowIPv6 = other.allowIPv6;
         isMetered = other.isMetered;
+        requiresInternetValidation = other.requiresInternetValidation;
         underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
                 other.underlyingNetworks, other.underlyingNetworks.length) : null;
         proxyInfo = other.proxyInfo;
@@ -189,6 +191,7 @@
         out.writeInt(allowIPv4 ? 1 : 0);
         out.writeInt(allowIPv6 ? 1 : 0);
         out.writeInt(isMetered ? 1 : 0);
+        out.writeInt(requiresInternetValidation ? 1 : 0);
         out.writeTypedArray(underlyingNetworks, flags);
         out.writeParcelable(proxyInfo, flags);
     }
@@ -216,6 +219,7 @@
             config.allowIPv4 = in.readInt() != 0;
             config.allowIPv6 = in.readInt() != 0;
             config.isMetered = in.readInt() != 0;
+            config.requiresInternetValidation = in.readInt() != 0;
             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
             config.proxyInfo = in.readParcelable(null);
             return config;
@@ -248,6 +252,8 @@
                 .append(", allowBypass=").append(allowBypass)
                 .append(", allowIPv4=").append(allowIPv4)
                 .append(", allowIPv6=").append(allowIPv6)
+                .append(", isMetered=").append(isMetered)
+                .append(", requiresInternetValidation").append(requiresInternetValidation)
                 .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
                 .append(", proxyInfo=").append(proxyInfo)
                 .append("}")
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index d8dc143..bd3e898 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -144,23 +144,26 @@
     public final boolean isRestrictedToTestNetworks;             // 24
 
     public final boolean excludeLocalRoutes;                     // 25
+    public final boolean requiresInternetValidation;             // 26
 
     // Helper fields.
     @UnsupportedAppUsage
     public transient boolean saveLogin = false;
 
     public VpnProfile(String key) {
-        this(key, false, false);
+        this(key, false, false, false);
     }
 
     public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
-        this(key, isRestrictedToTestNetworks, false);
+        this(key, isRestrictedToTestNetworks, false, false);
     }
 
-    public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes) {
+    public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
+            boolean requiresInternetValidation) {
         this.key = key;
         this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
         this.excludeLocalRoutes = excludeLocalRoutes;
+        this.requiresInternetValidation = requiresInternetValidation;
     }
 
     @UnsupportedAppUsage
@@ -191,6 +194,7 @@
         areAuthParamsInline = in.readBoolean();
         isRestrictedToTestNetworks = in.readBoolean();
         excludeLocalRoutes = in.readBoolean();
+        requiresInternetValidation = in.readBoolean();
     }
 
     /**
@@ -239,6 +243,7 @@
         out.writeBoolean(areAuthParamsInline);
         out.writeBoolean(isRestrictedToTestNetworks);
         out.writeBoolean(excludeLocalRoutes);
+        out.writeBoolean(requiresInternetValidation);
     }
 
     /**
@@ -258,9 +263,11 @@
             // 14-19: Standard profile, with option for serverCert, proxy
             // 24: Standard profile with serverCert, proxy and platform-VPN parameters
             // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
-            // 26: Standard profile with platform-VPN parameters and excludeLocalRoutes
-            if ((values.length < 14 || values.length > 19)
-                    && values.length != 24 && values.length != 25 && values.length != 26) {
+            // 26:                                            ...and excludeLocalRoutes
+            //     (26 can only be found on dogfood devices)
+            // 27:                                            ...and requiresInternetValidation
+            if ((values.length < 14 || (values.length > 19 && values.length < 24)
+                    || values.length > 27)) {
                 return null;
             }
 
@@ -278,8 +285,15 @@
                 excludeLocalRoutes = false;
             }
 
+            final boolean requiresInternetValidation;
+            if (values.length >= 27) {
+                requiresInternetValidation = Boolean.parseBoolean(values[26]);
+            } else {
+                requiresInternetValidation = false;
+            }
+
             VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
-                    excludeLocalRoutes);
+                    excludeLocalRoutes, requiresInternetValidation);
             profile.name = values[0];
             profile.type = Integer.parseInt(values[1]);
             if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -390,6 +404,7 @@
         builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
 
         builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
+        builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
 
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
@@ -471,7 +486,7 @@
             key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
             l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
             proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
-            isRestrictedToTestNetworks, excludeLocalRoutes);
+            isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
     }
 
     /** Checks VPN profiles for interior equality. */
@@ -505,11 +520,12 @@
                 && maxMtu == other.maxMtu
                 && areAuthParamsInline == other.areAuthParamsInline
                 && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
-                && excludeLocalRoutes == other.excludeLocalRoutes;
+                && excludeLocalRoutes == other.excludeLocalRoutes
+                && requiresInternetValidation == other.requiresInternetValidation;
     }
 
     @NonNull
-    public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+    public static final Creator<VpnProfile> CREATOR = new Creator<>() {
         @Override
         public VpnProfile createFromParcel(Parcel in) {
             return new VpnProfile(in);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 611f644..f258f84 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -713,7 +713,7 @@
                 "--setuid=1000",
                 "--setgid=1000",
                 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
-                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
+                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                 "--capabilities=" + capabilities + "," + capabilities,
                 "--nice-name=system_server",
                 "--runtime-args",
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 2b7f8b2..354dd9a 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -4,3 +4,4 @@
 per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
 per-file Protocol* = etancohen@google.com, lorenzo@google.com
 per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
+per-file *Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 3af55fe..d2d7213 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -81,27 +81,37 @@
 
     void binderDied(const wp<hardware::IBinder>& who)
     {
-        if (mObject != NULL) {
-            JNIEnv* env = javavm_to_jnienv(mVM);
+        JNIEnv* env = javavm_to_jnienv(mVM);
 
-            env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie);
+        // Serialize with our containing HwBinderDeathRecipientList so that we can't
+        // delete the global ref on object while the list is being iterated.
+        sp<HwBinderDeathRecipientList> list = mList.promote();
+        if (list == nullptr) return;
+
+        jobject object;
+        {
+            AutoMutex _l(list->lock());
+
+            // this function now owns the global ref - to the rest of the code, it looks like
+            // this binder already died, but we won't actually delete the reference until
+            // the Java code has processed the death
+            object = mObject;
+
+            // Demote from strong ref to weak for after binderDied() has been delivered,
+            // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
+            mObjectWeak = env->NewWeakGlobalRef(mObject);
+            mObject = nullptr;
+        }
+
+        if (object != nullptr) {
+            env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice,
+                                      object, mCookie);
             if (env->ExceptionCheck()) {
                 ALOGE("Uncaught exception returned from death notification.");
                 env->ExceptionClear();
             }
 
-            // Serialize with our containing HwBinderDeathRecipientList so that we can't
-            // delete the global ref on mObject while the list is being iterated.
-            sp<HwBinderDeathRecipientList> list = mList.promote();
-            if (list != NULL) {
-                AutoMutex _l(list->lock());
-
-                // Demote from strong ref to weak after binderDied() has been delivered,
-                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
-                mObjectWeak = env->NewWeakGlobalRef(mObject);
-                env->DeleteGlobalRef(mObject);
-                mObject = NULL;
-            }
+            env->DeleteGlobalRef(object);
         }
     }
 
@@ -115,7 +125,7 @@
         }
     }
 
-    bool matches(jobject obj) {
+    bool matchesLocked(jobject obj) {
         bool result;
         JNIEnv* env = javavm_to_jnienv(mVM);
 
@@ -129,7 +139,7 @@
         return result;
     }
 
-    void warnIfStillLive() {
+    void warnIfStillLiveLocked() {
         if (mObject != NULL) {
             // Okay, something is wrong -- we have a hard reference to a live death
             // recipient on the VM side, but the list is being torn down.
@@ -176,7 +186,7 @@
     AutoMutex _l(mLock);
 
     for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
-        deathRecipient->warnIfStillLive();
+        deathRecipient->warnIfStillLiveLocked();
     }
 }
 
@@ -201,7 +211,7 @@
     AutoMutex _l(mLock);
 
     for(auto iter = mList.rbegin(); iter != mList.rend(); iter++) {
-        if ((*iter)->matches(recipient)) {
+        if ((*iter)->matchesLocked(recipient)) {
             return (*iter);
         }
     }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42e470b..5bfc321 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1611,7 +1611,7 @@
      * Return the paint's Align value for drawing text. This controls how the
      * text is positioned relative to its origin. LEFT align means that all of
      * the text will be drawn to the right of its origin (i.e. the origin
-     * specifieds the LEFT edge of the text) and so on.
+     * specifies the LEFT edge of the text) and so on.
      *
      * @return the paint's Align value for drawing text.
      */
@@ -1623,7 +1623,7 @@
      * Set the paint's text alignment. This controls how the
      * text is positioned relative to its origin. LEFT align means that all of
      * the text will be drawn to the right of its origin (i.e. the origin
-     * specifieds the LEFT edge of the text) and so on.
+     * specifies the LEFT edge of the text) and so on.
      *
      * @param align set the paint's Align value for drawing text.
      */
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 9b2effc..0fadae2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -288,7 +288,7 @@
      * context at a time.
      *
      * @param texName The name of the OpenGL ES texture that will be created.  This texture name
-     * must be unusued in the OpenGL ES context that is current on the calling thread.
+     * must be unused in the OpenGL ES context that is current on the calling thread.
      */
     public void attachToGLContext(int texName) {
         int err = nativeAttachToGLContext(texName);
diff --git a/keystore/OWNERS b/keystore/OWNERS
index a63ca46..7ab9d76 100644
--- a/keystore/OWNERS
+++ b/keystore/OWNERS
@@ -1,4 +1,4 @@
+eranm@google.com
 jbires@google.com
 jdanis@google.com
-robbarnes@google.com
 swillden@google.com
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index 1034847..3d53cfb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -108,7 +108,7 @@
             try {
                 return request.execute(service);
             } catch (ServiceSpecificException e) {
-                throw getKeyStoreException(e.errorCode);
+                throw getKeyStoreException(e.errorCode, e.getMessage());
             } catch (RemoteException e) {
                 if (firstTry) {
                     Log.w(TAG, "Looks like we may have lost connection to the Keystore "
@@ -120,7 +120,7 @@
                     firstTry = false;
                 } else {
                     Log.e(TAG, "Cannot connect to Keystore daemon.", e);
-                    throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+                    throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
                 }
             }
         }
@@ -322,26 +322,32 @@
         }
     }
 
-    static KeyStoreException getKeyStoreException(int errorCode) {
+    static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
         if (errorCode > 0) {
             // KeyStore layer error
             switch (errorCode) {
                 case ResponseCode.LOCKED:
-                    return new KeyStoreException(errorCode, "User authentication required");
+                    return new KeyStoreException(errorCode, "User authentication required",
+                            serviceErrorMessage);
                 case ResponseCode.UNINITIALIZED:
-                    return new KeyStoreException(errorCode, "Keystore not initialized");
+                    return new KeyStoreException(errorCode, "Keystore not initialized",
+                            serviceErrorMessage);
                 case ResponseCode.SYSTEM_ERROR:
-                    return new KeyStoreException(errorCode, "System error");
+                    return new KeyStoreException(errorCode, "System error", serviceErrorMessage);
                 case ResponseCode.PERMISSION_DENIED:
-                    return new KeyStoreException(errorCode, "Permission denied");
+                    return new KeyStoreException(errorCode, "Permission denied",
+                            serviceErrorMessage);
                 case ResponseCode.KEY_NOT_FOUND:
-                    return new KeyStoreException(errorCode, "Key not found");
+                    return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage);
                 case ResponseCode.VALUE_CORRUPTED:
-                    return new KeyStoreException(errorCode, "Key blob corrupted");
+                    return new KeyStoreException(errorCode, "Key blob corrupted",
+                            serviceErrorMessage);
                 case ResponseCode.KEY_PERMANENTLY_INVALIDATED:
-                    return new KeyStoreException(errorCode, "Key permanently invalidated");
+                    return new KeyStoreException(errorCode, "Key permanently invalidated",
+                            serviceErrorMessage);
                 default:
-                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
+                    return new KeyStoreException(errorCode, String.valueOf(errorCode),
+                            serviceErrorMessage);
             }
         } else {
             // Keymaster layer error
@@ -350,10 +356,12 @@
                     // The name of this parameter significantly differs between Keymaster and
                     // framework APIs. Use the framework wording to make life easier for developers.
                     return new KeyStoreException(errorCode,
-                            "Invalid user authentication validity duration");
+                            "Invalid user authentication validity duration",
+                            serviceErrorMessage);
                 default:
                     return new KeyStoreException(errorCode,
-                            KeymasterDefs.getErrorMessage(errorCode));
+                            KeymasterDefs.getErrorMessage(errorCode),
+                            serviceErrorMessage);
             }
         }
     }
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index 6db2745..54184db 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -158,6 +158,16 @@
     }
 
     /**
+     * @hide
+     */
+    public KeyStoreException(int errorCode, @Nullable String message,
+            @Nullable String keystoreErrorMessage) {
+        super(message + " (internal Keystore code: " + errorCode + " message: "
+                + keystoreErrorMessage + ")");
+        mErrorCode = errorCode;
+    }
+
+    /**
      * Returns the internal error code. Only for use by the platform.
      *
      * @hide
diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java
index e6c1ea8..737ff2b 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -75,7 +75,7 @@
                     );
                 }
                 default:
-                    throw KeyStore2.getKeyStoreException(e.errorCode);
+                    throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
             }
         } catch (RemoteException e) {
             // Log exception and report invalid operation handle.
@@ -85,7 +85,8 @@
                     "Remote exception while advancing a KeyStoreOperation.",
                     e
             );
-            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "");
+            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "",
+                    e.getMessage());
         }
     }
 
diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java
index b85dd74..9c0b46c 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -54,12 +54,12 @@
         try {
             return request.execute();
         } catch (ServiceSpecificException e) {
-            throw KeyStore2.getKeyStoreException(e.errorCode);
+            throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
         } catch (RemoteException e) {
             // Log exception and report invalid operation handle.
             // This should prompt the caller drop the reference to this operation and retry.
             Log.e(TAG, "Could not connect to Keystore.", e);
-            throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+            throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
         }
     }
 
@@ -117,7 +117,7 @@
                         break;
                     }
                     default:
-                        throw KeyStore2.getKeyStoreException(e.errorCode);
+                        throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
                 }
             } catch (RemoteException e) {
                 Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
new file mode 100644
index 0000000..31c7422
--- /dev/null
+++ b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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.security.keystore;
+
+import static org.junit.Assert.assertTrue;
+
+import android.security.KeyStoreException;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class KeyStoreExceptionTest {
+    @Test
+    public void testKeystoreMessageIsIncluded() {
+        final String primaryMessage = "some_message";
+        final String keystoreMessage = "ks_message";
+        KeyStoreException exception = new KeyStoreException(-1, primaryMessage, keystoreMessage);
+
+        String exceptionMessage = exception.getMessage();
+        assertTrue(exceptionMessage.contains(primaryMessage));
+        assertTrue(exceptionMessage.contains(keystoreMessage));
+
+        String exceptionString = exception.toString();
+        assertTrue(exceptionString.contains(primaryMessage));
+        assertTrue(exceptionString.contains(keystoreMessage));
+    }
+}
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index d17c328..8150e78 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -686,6 +686,12 @@
         std::unordered_set<uint32_t> finalized_ids;
         const auto lib_alias = child_chunk.header<ResTable_staged_alias_header>();
         if (!lib_alias) {
+          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small.";
+          return {};
+        }
+        if ((child_chunk.data_size() / sizeof(ResTable_staged_alias_entry))
+            < dtohl(lib_alias->count)) {
+          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small to hold entries.";
           return {};
         }
         const auto entry_begin = child_chunk.data_ptr().convert<ResTable_staged_alias_entry>();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2fed468..00561be 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -287,7 +287,7 @@
     };
 
     // Need at least 4 because we do quad buffer. Add a 5th for good measure.
-    RingBuffer<SwapHistory, 5> mSwapHistory;
+    RingBuffer<SwapHistory, 7> mSwapHistory;
     int64_t mFrameNumber = -1;
     int64_t mDamageId = 0;
 
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index a186566..3edb101 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -177,6 +177,11 @@
      */
     public static final int TYPE_HDMI_EARC         = 29;
 
+    /**
+     * A device type describing a Bluetooth Low Energy (BLE) broadcast group.
+     */
+    public static final int TYPE_BLE_BROADCAST   = 30;
+
     /** @hide */
     @IntDef(flag = false, prefix = "TYPE", value = {
             TYPE_BUILTIN_EARPIECE,
@@ -207,7 +212,8 @@
             TYPE_REMOTE_SUBMIX,
             TYPE_BLE_HEADSET,
             TYPE_BLE_SPEAKER,
-            TYPE_ECHO_REFERENCE}
+            TYPE_ECHO_REFERENCE,
+            TYPE_BLE_BROADCAST}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceType {}
@@ -264,7 +270,8 @@
             TYPE_HEARING_AID,
             TYPE_BUILTIN_SPEAKER_SAFE,
             TYPE_BLE_HEADSET,
-            TYPE_BLE_SPEAKER}
+            TYPE_BLE_SPEAKER,
+            TYPE_BLE_BROADCAST}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceTypeOut {}
@@ -296,6 +303,7 @@
             case TYPE_BUILTIN_SPEAKER_SAFE:
             case TYPE_BLE_HEADSET:
             case TYPE_BLE_SPEAKER:
+            case TYPE_BLE_BROADCAST:
                 return true;
             default:
                 return false;
@@ -627,6 +635,7 @@
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_BROADCAST, TYPE_BLE_BROADCAST);
 
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -684,6 +693,7 @@
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET);
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_BROADCAST, AudioSystem.DEVICE_OUT_BLE_BROADCAST);
 
         // privileges mapping to input device
         EXT_TO_INT_INPUT_DEVICE_MAPPING = new SparseIntArray();
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index ebe0882..9211c53 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -90,7 +90,8 @@
      * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER})
      * use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by
      * {@link BluetoothDevice#getAddress()}.
-     * - Deivces that do not have an address will indicate an empty string "".
+     * - Bluetooth LE broadcast group ({@link AudioManager#DEVICE_OUT_BLE_BROADCAST} use the group number.
+     * - Devices that do not have an address will indicate an empty string "".
      */
     public String address() {
         return mAddress;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d8893cb..ce2bccf 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5404,6 +5404,10 @@
      */
     public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER;
     /** @hide
+     * The audio output device code for a BLE audio brodcast group.
+     */
+    public static final int DEVICE_OUT_BLE_BROADCAST = AudioSystem.DEVICE_OUT_BLE_BROADCAST;
+    /** @hide
      * This is not used as a returned value from {@link #getDevicesForStream}, but could be
      *  used in the future in a set method to select whatever default device is chosen by the
      *  platform-specific implementation.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 143b11f..33b877c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -982,6 +982,8 @@
     public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000;
     /** @hide */
     public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001;
+    /** @hide */
+    public static final int DEVICE_OUT_BLE_BROADCAST = 0x20000002;
 
     /** @hide */
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -1042,6 +1044,7 @@
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_BROADCAST);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
 
         DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
@@ -1072,6 +1075,7 @@
         DEVICE_OUT_ALL_BLE_SET = new HashSet<>();
         DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET);
         DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER);
+        DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_BROADCAST);
     }
 
     // input devices
@@ -1255,6 +1259,7 @@
     /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller";
     /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset";
     /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker";
+    /** @hide */ public static final String DEVICE_OUT_BLE_BROADCAST_NAME = "ble_broadcast";
 
     /** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
     /** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -1354,6 +1359,8 @@
             return DEVICE_OUT_BLE_HEADSET_NAME;
         case DEVICE_OUT_BLE_SPEAKER:
             return DEVICE_OUT_BLE_SPEAKER_NAME;
+        case DEVICE_OUT_BLE_BROADCAST:
+            return DEVICE_OUT_BLE_BROADCAST_NAME;
         case DEVICE_OUT_DEFAULT:
         default:
             return Integer.toString(device);
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
index 061f323..42c0044 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 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.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index b0a647e..95f7ef4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -81,8 +81,8 @@
         when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false);
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -94,8 +94,8 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -107,7 +107,7 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isTrue();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index d3d6e03..6f30ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread
 import android.app.Dialog
+import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
@@ -88,7 +89,7 @@
         bouncerOrRun(createAction(cvh.cws.ci.controlId, {
             cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
             if (cvh.usePanel()) {
-                showDetail(cvh, control.getAppIntent().getIntent())
+                showDetail(cvh, control.getAppIntent())
             } else {
                 cvh.action(CommandAction(templateId))
             }
@@ -116,7 +117,7 @@
             // Long press snould only be called when there is valid control state, otherwise ignore
             cvh.cws.control?.let {
                 cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
-                showDetail(cvh, it.getAppIntent().getIntent())
+                showDetail(cvh, it.getAppIntent())
             }
         }, false /* blockable */))
     }
@@ -167,10 +168,10 @@
         bgExecutor.execute { vibrator.vibrate(effect) }
     }
 
-    private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
+    private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
         bgExecutor.execute {
             val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
-                intent,
+                pendingIntent.getIntent(),
                 PackageManager.MATCH_DEFAULT_ONLY
             )
 
@@ -178,7 +179,7 @@
                 // make sure the intent is valid before attempting to open the dialog
                 if (activities.isNotEmpty() && taskViewFactory.isPresent) {
                     taskViewFactory.get().create(context, uiExecutor, {
-                        dialog = DetailDialog(activityContext, it, intent, cvh).also {
+                        dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
                             it.setOnDismissListener { _ -> dialog = null }
                             it.show()
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 8a47a36..4758ab0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -43,7 +43,7 @@
 class DetailDialog(
     val activityContext: Context?,
     val taskView: TaskView,
-    val intent: Intent,
+    val pendingIntent: PendingIntent,
     val cvh: ControlViewHolder
 ) : Dialog(
     activityContext ?: cvh.context,
@@ -59,6 +59,14 @@
 
     var detailTaskId = INVALID_TASK_ID
 
+    private val fillInIntent = Intent().apply {
+        putExtra(EXTRA_USE_PANEL, true)
+
+        // Apply flags to make behaviour match documentLaunchMode=always.
+        addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+        addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+    }
+
     fun removeDetailTask() {
         if (detailTaskId == INVALID_TASK_ID) return
         ActivityTaskManager.getInstance().removeTask(detailTaskId)
@@ -67,13 +75,6 @@
 
     val stateCallback = object : TaskView.Listener {
         override fun onInitialized() {
-            val launchIntent = Intent(intent)
-            launchIntent.putExtra(EXTRA_USE_PANEL, true)
-
-            // Apply flags to make behaviour match documentLaunchMode=always.
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-
             val options = activityContext?.let {
                 ActivityOptions.makeCustomAnimation(
                     it,
@@ -82,9 +83,8 @@
                 )
             } ?: ActivityOptions.makeBasic()
             taskView.startActivity(
-                PendingIntent.getActivity(context, 0, launchIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
-                null /* fillInIntent */,
+                pendingIntent,
+                fillInIntent,
                 options,
                 getTaskViewBounds()
             )
@@ -97,6 +97,9 @@
 
         override fun onTaskCreated(taskId: Int, name: ComponentName?) {
             detailTaskId = taskId
+            requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
+                setAlpha(1f)
+            }
         }
 
         override fun onReleased() {
@@ -121,6 +124,7 @@
 
         requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
             addView(taskView)
+            setAlpha(0f)
         }
 
         requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@
                 removeDetailTask()
                 dismiss()
                 context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
-                v.context.startActivity(intent)
+                pendingIntent.send()
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
index c50365f..71c5fad 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
@@ -15,7 +15,8 @@
 class SensorUseDialog(
     context: Context,
     val sensor: Int,
-    val clickListener: DialogInterface.OnClickListener
+    val clickListener: DialogInterface.OnClickListener,
+    val dismissListener: DialogInterface.OnDismissListener
 ) : SystemUIDialog(context) {
 
     // TODO move to onCreate (b/200815309)
@@ -69,6 +70,8 @@
                 context.getString(com.android.internal.R.string
                         .cancel), clickListener)
 
+        setOnDismissListener(dismissListener)
+
         setCancelable(false)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index b0071d9..dae375a 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -50,7 +50,7 @@
     private val keyguardStateController: KeyguardStateController,
     private val keyguardDismissUtil: KeyguardDismissUtil,
     @Background private val bgHandler: Handler
-) : Activity(), DialogInterface.OnClickListener {
+) : Activity(), DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
 
     companion object {
         private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName
@@ -120,7 +120,7 @@
             }
         }
 
-        mDialog = SensorUseDialog(this, sensor, this)
+        mDialog = SensorUseDialog(this, sensor, this, this)
         mDialog!!.show()
     }
 
@@ -212,4 +212,8 @@
                     .suppressSensorPrivacyReminders(sensor, suppressed)
         }
     }
+
+    override fun onDismiss(dialog: DialogInterface?) {
+        finish()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
new file mode 100644
index 0000000..87b9172
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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 com.android.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.wm.shell.TaskView
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class DetailDialogTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var taskView: TaskView
+    @Mock
+    private lateinit var controlViewHolder: ControlViewHolder
+    @Mock
+    private lateinit var pendingIntent: PendingIntent
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun testPendingIntentIsUnModified() {
+        // GIVEN the dialog is created with a PendingIntent
+        val dialog = createDialog(pendingIntent)
+
+        // WHEN the TaskView is initialized
+        dialog.stateCallback.onInitialized()
+
+        // THEN the PendingIntent used to call startActivity is unmodified by systemui
+        verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
+    }
+
+    private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
+        return DetailDialog(
+            mContext,
+            taskView,
+            pendingIntent,
+            controlViewHolder
+        )
+    }
+}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index e29e894..e924012 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -16,8 +16,9 @@
 
 package com.android.server;
 
+import android.annotation.EnforcePermission;
+import android.annotation.RequiresNoPermission;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.gsi.AvbPublicKey;
 import android.gsi.GsiProgress;
 import android.gsi.IGsiService;
@@ -53,20 +54,12 @@
     }
 
     private IGsiService getGsiService() {
-        checkPermission();
         if (mGsiService != null) {
             return mGsiService;
         }
         return IGsiService.Stub.asInterface(ServiceManager.waitForService("gsiservice"));
     }
 
-    private void checkPermission() {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission");
-        }
-    }
-
     class GsiServiceCallback extends IGsiServiceCallback.Stub {
         // 0 for success
         private int mResult = -1;
@@ -82,6 +75,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean startInstallation(String dsuSlot) throws RemoteException {
         IGsiService service = getGsiService();
         mGsiService = service;
@@ -124,6 +118,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean createPartition(String name, long size, boolean readOnly)
             throws RemoteException {
         IGsiService service = getGsiService();
@@ -135,6 +130,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean closePartition() throws RemoteException {
         IGsiService service = getGsiService();
         if (service.closePartition() != 0) {
@@ -145,6 +141,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean finishInstallation() throws RemoteException {
         IGsiService service = getGsiService();
         if (service.closeInstall() != 0) {
@@ -155,21 +152,25 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public GsiProgress getInstallationProgress() throws RemoteException {
         return getGsiService().getInstallProgress();
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean abort() throws RemoteException {
         return getGsiService().cancelGsiInstall();
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isInUse() {
         return SystemProperties.getBoolean("ro.gsid.image_running", false);
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isInstalled() {
         boolean installed = SystemProperties.getBoolean("gsid.image_installed", false);
         Slog.i(TAG, "isInstalled(): " + installed);
@@ -177,11 +178,13 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean isEnabled() throws RemoteException {
         return getGsiService().isGsiEnabled();
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean remove() throws RemoteException {
         try {
             GsiServiceCallback callback = new GsiServiceCallback();
@@ -197,6 +200,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
         IGsiService gsiService = getGsiService();
         if (enable) {
@@ -220,6 +224,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean setAshmem(ParcelFileDescriptor ashmem, long size) {
         try {
             return getGsiService().setGsiAshmem(ashmem, size);
@@ -229,6 +234,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean submitFromAshmem(long size) {
         try {
             return getGsiService().commitGsiChunkFromAshmem(size);
@@ -238,6 +244,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean getAvbPublicKey(AvbPublicKey dst) {
         try {
             return getGsiService().getAvbPublicKey(dst) == 0;
@@ -247,6 +254,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public long suggestScratchSize() throws RemoteException {
         return getGsiService().suggestScratchSize();
     }
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index b48e21e..7b8cce5 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -340,17 +340,18 @@
      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
      * exclusively by the Settings app, and passed into the platform at startup time.
      *
+     * @return A unique key corresponding to this session.
      * @throws IllegalArgumentException if no profile was found for the given package name.
      * @hide
      */
     @Override
-    public void startVpnProfile(@NonNull String packageName) {
+    public String startVpnProfile(@NonNull String packageName) {
         final int callingUid = Binder.getCallingUid();
         verifyCallingUidAndPackage(packageName, callingUid);
         final int user = UserHandle.getUserId(callingUid);
         synchronized (mVpns) {
             throwIfLockdownEnabled();
-            mVpns.get(user).startVpnProfile(packageName);
+            return mVpns.get(user).startVpnProfile(packageName);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 6230919..583fb89 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -191,7 +191,9 @@
                             } else if (KEY_COMPACT_THROTTLE_1.equals(name)
                                     || KEY_COMPACT_THROTTLE_2.equals(name)
                                     || KEY_COMPACT_THROTTLE_3.equals(name)
-                                    || KEY_COMPACT_THROTTLE_4.equals(name)) {
+                                    || KEY_COMPACT_THROTTLE_4.equals(name)
+                                    || KEY_COMPACT_THROTTLE_5.equals(name)
+                                    || KEY_COMPACT_THROTTLE_6.equals(name)) {
                                 updateCompactionThrottles();
                             } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
                                 updateCompactStatsdSampleRate();
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9a9c3ea..3fb49e4 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -151,6 +151,7 @@
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -203,6 +204,7 @@
     private final NetworkInfo mNetworkInfo;
     private int mLegacyState;
     @VisibleForTesting protected String mPackage;
+    private String mSessionKey;
     private int mOwnerUID;
     private boolean mIsPackageTargetingAtLeastQ;
     @VisibleForTesting
@@ -1302,6 +1304,7 @@
                 .setLegacyType(ConnectivityManager.TYPE_VPN)
                 .setLegacyTypeName("VPN")
                 .setBypassableVpn(mConfig.allowBypass && !mLockdown)
+                .setVpnRequiresValidation(mConfig.requiresInternetValidation)
                 .build();
 
         capsBuilder.setOwnerUid(mOwnerUID);
@@ -2503,6 +2506,7 @@
             mProfile = profile;
             mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
             mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
+            mSessionKey = UUID.randomUUID().toString();
         }
 
         @Override
@@ -2824,6 +2828,7 @@
          */
         private void disconnectVpnRunner() {
             mActiveNetwork = null;
+            mSessionKey = null;
             mIsRunning = false;
 
             resetIkeState();
@@ -3314,7 +3319,7 @@
      *
      * @param packageName the package name of the app provisioning this profile
      */
-    public synchronized void startVpnProfile(@NonNull String packageName) {
+    public synchronized String startVpnProfile(@NonNull String packageName) {
         requireNonNull(packageName, "No package name provided");
 
         enforceNotRestrictedUser();
@@ -3332,6 +3337,7 @@
             }
 
             startVpnProfilePrivileged(profile, packageName);
+            return mSessionKey;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3363,6 +3369,7 @@
             }
             mConfig.startTime = SystemClock.elapsedRealtime();
             mConfig.proxyInfo = profile.proxy;
+            mConfig.requiresInternetValidation = profile.requiresInternetValidation;
 
             switch (profile.type) {
                 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 27f22c4..c12522b 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -75,6 +75,8 @@
     protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
     protected int mLastKeyRepeatCount = 0;
 
+    HdmiCecStandbyModeHandler mStandbyHandler;
+
     // Stores recent changes to the active source in the CEC network.
     private final ArrayBlockingQueue<HdmiCecController.Dumpable> mActiveSourceHistory =
             new ArrayBlockingQueue<>(MAX_HDMI_ACTIVE_SOURCE_HISTORY);
@@ -263,6 +265,11 @@
         if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {
             return Constants.NOT_HANDLED;
         }
+        if (mService.isPowerStandby()
+                && !mService.isWakeUpMessageReceived()
+                && mStandbyHandler.handleCommand(message)) {
+            return Constants.HANDLED;
+        }
         // Cache incoming message if it is included in the list of cacheable opcodes.
         mCecMessageCache.cacheMessage(message);
         return onMessage(message);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 0bb1285..c549b55 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -112,6 +112,7 @@
             mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false);
         mSystemAudioControlFeatureEnabled =
             mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);
+        mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
     }
 
     private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml";
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 37ee76b7..4071858 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -64,6 +64,7 @@
 
     HdmiCecLocalDevicePlayback(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6e7a2a0..3d218cf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -91,8 +91,6 @@
     @GuardedBy("mLock")
     private boolean mSystemAudioMute = false;
 
-    private final HdmiCecStandbyModeHandler mStandbyHandler;
-
     // If true, do not do routing control/send active source for internal source.
     // Set to true when the device was woken up by <Text/Image View On>.
     private boolean mSkipRoutingControl;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
index 57fe9e6..1c296e5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiDeviceInfo;
 import android.util.SparseArray;
 
 /**
@@ -56,7 +57,8 @@
     private final class AutoOnHandler implements CecMessageHandler {
         @Override
         public boolean handle(HdmiCecMessage message) {
-            if (!mTv.getAutoWakeup()) {
+            HdmiCecLocalDeviceTv tv = (HdmiCecLocalDeviceTv) mDevice;
+            if (!tv.getAutoWakeup()) {
                 mAborterRefused.handle(message);
                 return true;
             }
@@ -78,7 +80,7 @@
     }
 
     private final HdmiControlService mService;
-    private final HdmiCecLocalDeviceTv mTv;
+    private final HdmiCecLocalDevice mDevice;
 
     private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
     private final CecMessageHandler mDefaultHandler = new Aborter(
@@ -92,13 +94,7 @@
     private final UserControlProcessedHandler
             mUserControlProcessedHandler = new UserControlProcessedHandler();
 
-    public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) {
-        mService = service;
-        mTv = tv;
-
-        addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
-        addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
-
+    private void addCommonHandlers() {
         addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
@@ -112,19 +108,6 @@
         addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
         addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
 
-        // If TV supports the following messages during power-on, ignore them and do nothing,
-        // else reply with <Feature Abort>["Unrecognized Opcode"]
-        // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
-        addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander);
-
-        // If TV supports the following messages during power-on, reply with <Feature Abort>["Not
-        // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"]
-        // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>,
-        // <Tuner Stem Increment>, <Menu Status>.
-        addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
-        addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
-        addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
-
         addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
         addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
         addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
@@ -145,6 +128,34 @@
         addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
     }
 
+    private void addTvHandlers() {
+        addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
+        addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
+
+        // If TV supports the following messages during power-on, ignore them and do nothing,
+        // else reply with <Feature Abort>["Unrecognized Opcode"]
+        // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
+        addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander);
+
+        // If TV supports the following messages during power-on, reply with <Feature Abort>["Not
+        // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"]
+        // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>,
+        // <Tuner Stem Increment>, <Menu Status>.
+        addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
+        addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
+        addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
+    }
+
+    public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDevice device) {
+        mService = service;
+        mDevice = device;
+
+        addCommonHandlers();
+        if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) {
+            addTvHandlers();
+        }
+    }
+
     private void addHandler(int opcode, CecMessageHandler handler) {
         mCecMessageHandlers.put(opcode, handler);
     }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3e52f5e..5b7f5c8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2837,7 +2837,7 @@
                 return;
             }
             final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
-            if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
+            if (targetWindow != null) {
                 mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
             }
             mLastImeTargetWindow = targetWindow;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 81106b1..b66c466 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,12 +15,14 @@
  */
 package com.android.server.net;
 
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
 import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
 import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
 import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
 import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
@@ -29,6 +31,7 @@
 import static android.os.PowerExemptionManager.reasonCodeToString;
 import static android.os.Process.INVALID_UID;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.ProcessCapability;
 import android.net.NetworkPolicyManager;
@@ -81,13 +84,18 @@
 
     private final Object mLock = new Object();
 
-    void networkBlocked(int uid, UidBlockedState uidBlockedState) {
+    void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
         synchronized (mLock) {
             if (LOGD || uid == mDebugUid) {
                 Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
             }
-            mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
-                    uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+            if (uidBlockedState == null) {
+                mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
+                        BLOCKED_REASON_NONE);
+            } else {
+                mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
+                        uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b52e527..b685d48 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1038,6 +1038,8 @@
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(getActivityType()));
+        pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput=");
+                pw.println(mImeInsetsFrozenUntilStartInput);
         if (requestedVrComponent != null) {
             pw.print(prefix);
             pw.print("requestedVrComponent=");
@@ -4932,6 +4934,10 @@
                 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
                 break;
             case DESTROYED:
+                if (app != null && (mVisible || mVisibleRequested)) {
+                    // The app may be died while visible (no PAUSED state).
+                    mAtmService.updateBatteryStats(this, false);
+                }
                 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
                 // Fall through.
             case DESTROYING:
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9335846..bb8d6ef 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3969,11 +3969,11 @@
      * which controls the visibility and animation of the input method window.
      */
     void updateImeInputAndControlTarget(WindowState target) {
+        if (target != null && target.mActivityRecord != null) {
+            target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+        }
         if (mImeInputTarget != target) {
             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
-            if (target != null && target.mActivityRecord != null) {
-                target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
-            }
             setImeInputTarget(target);
             updateImeControlTarget();
         }
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 62a16f7..c5f990d 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -60,6 +60,12 @@
     private static ProfcollectForwardingService sSelfService;
     private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());
 
+    private IProviderStatusCallback mProviderStatusCallback = new IProviderStatusCallback.Stub() {
+        public void onProviderReady() {
+            mHandler.sendEmptyMessage(ProfcollectdHandler.MESSAGE_REGISTER_SCHEDULERS);
+        }
+    };
+
     public ProfcollectForwardingService(Context context) {
         super(context);
 
@@ -93,13 +99,23 @@
             }
             BackgroundThread.get().getThreadHandler().post(() -> {
                 if (serviceHasSupportedTraceProvider()) {
-                    registerObservers();
-                    ProfcollectBGJobService.schedule(getContext());
+                    registerProviderStatusCallback();
                 }
             });
         }
     }
 
+    private void registerProviderStatusCallback() {
+        if (mIProfcollect == null) {
+            return;
+        }
+        try {
+            mIProfcollect.registerProviderStatusCallback(mProviderStatusCallback);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, e.getMessage());
+        }
+    }
+
     private boolean serviceHasSupportedTraceProvider() {
         if (mIProfcollect == null) {
             return false;
@@ -141,6 +157,7 @@
         }
 
         public static final int MESSAGE_BINDER_CONNECT = 0;
+        public static final int MESSAGE_REGISTER_SCHEDULERS = 1;
 
         @Override
         public void handleMessage(android.os.Message message) {
@@ -148,6 +165,10 @@
                 case MESSAGE_BINDER_CONNECT:
                     connectNativeService();
                     break;
+                case MESSAGE_REGISTER_SCHEDULERS:
+                    registerObservers();
+                    ProfcollectBGJobService.schedule(getContext());
+                    break;
                 default:
                     throw new AssertionError("Unknown message: " + message);
             }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 4c39768..77e49ad 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -892,6 +892,7 @@
         int sourceAddress = Constants.ADDR_TV;
         byte[] params = {0x00, 0x01, 0x02, 0x03};
         int vendorId = 0x123456;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
 
         VendorCommandListener vendorCmdListener =
                 new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
@@ -913,6 +914,7 @@
         int sourceAddress = Constants.ADDR_TV;
         byte[] params = {0x00, 0x01, 0x02, 0x03};
         int vendorId = 0x123456;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
 
         VendorCommandListener vendorCmdListener =
                 new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
@@ -936,6 +938,7 @@
         byte[] params = {0x00, 0x01, 0x02, 0x03};
         int vendorId = 0x123456;
         int diffVendorId = 0x345678;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
 
         VendorCommandListener vendorCmdListener =
                 new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 6f04f17..29fa2d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -37,6 +37,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Process.NOBODY_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.InsetsState.ITYPE_IME;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -127,6 +128,8 @@
 import android.view.IRemoteAnimationRunner.Stub;
 import android.view.IWindowManager;
 import android.view.IWindowSession;
+import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 import android.view.Surface;
@@ -2884,6 +2887,41 @@
         assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
     }
 
+    @UseTestDisplay(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+
+        InsetsSource imeSource = new InsetsSource(ITYPE_IME);
+        app.getInsetsState().addSource(imeSource);
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.updateImeInputAndControlTarget(app);
+
+        InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+        assertFalse(state.getSource(ITYPE_IME).isVisible());
+        assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty());
+
+        // Simulate app is closing and expect IME insets is frozen.
+        mDisplayContent.mOpeningApps.clear();
+        app.mActivityRecord.commitVisibility(false, false);
+        app.mActivityRecord.onWindowsGone();
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Simulate app re-start input or turning screen off/on then unlocked by un-secure
+        // keyguard to back to the app, expect IME insets is not frozen
+        imeSource.setFrame(new Rect(100, 400, 500, 500));
+        app.getInsetsState().addSource(imeSource);
+        app.getInsetsState().setSourceVisible(ITYPE_IME, true);
+        mDisplayContent.updateImeInputAndControlTarget(app);
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Verify when IME is visible and the app can receive the right IME insets from policy.
+        makeWindowVisibleAndDrawn(app, mImeWindow);
+        state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+        assertTrue(state.getSource(ITYPE_IME).isVisible());
+        assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
+    }
+
     private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.mStartingSurface);
         assertNotNull(atoken.mStartingData);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 43d07b9..d7135a5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -168,7 +168,10 @@
     /**
      * This flag specifies whether VoLTE availability is based on provisioning. By default this is
      * false.
+     * Used for UCE to determine if EAB provisioning checks should be based on provisioning.
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead.
      */
+    @Deprecated
     public static final String
             KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
@@ -349,6 +352,12 @@
             KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
 
     /**
+     * Flag indicating if the carrier supports tethering of mobile data.
+     */
+    public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL =
+            "carrier_supports_tethering_bool";
+
+    /**
      * Flag indicating whether radio is to be restarted on error PDP_FAIL_REGULAR_DEACTIVATION
      * This is false by default.
      *
@@ -858,7 +867,12 @@
     /**
      * Flag specifying whether provisioning is required for VoLTE, Video Telephony, and WiFi
      * Calling.
+
+     * Combines VoLTE, VT, VoWiFI calling provisioning into one parameter.
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+     * finer-grained control.
      */
+    @Deprecated
     public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
             = "carrier_volte_provisioning_required_bool";
 
@@ -872,7 +886,11 @@
      * and enable the UT over IMS capability for the subscription when the subscription is loaded.
      *
      * The default value for this key is {@code false}.
+     *
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+     * determining if UT requires provisioning.
      */
+    @Deprecated
     public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL =
             "carrier_ut_provisioning_required_bool";
 
@@ -4631,6 +4649,95 @@
         public static final String KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG =
                 KEY_PREFIX + "rcs_request_retry_interval_millis_long";
 
+        /**
+         * A bundle which specifies the MMTEL capability and registration technology
+         * that requires provisioning. If a tuple is not present, the
+         * framework will not require that the tuple requires provisioning before
+         * enabling the capability.
+         * <p> Possible keys in this bundle are
+         * <ul>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_UT_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_SMS_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY}</li>
+         * </ul>
+         * <p> The values are defined in
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+         */
+        public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE =
+                KEY_PREFIX + "mmtel_requires_provisioning_bundle";
+
+        /**
+         * This MmTelFeature supports Voice calling (IR.92)
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE
+         */
+        public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_voice_int_array";
+
+        /**
+         * This MmTelFeature supports Video (IR.94)
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO
+         */
+        public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_video_int_array";
+
+        /**
+         * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT
+         */
+        public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_ut_int_array";
+
+        /**
+         * This MmTelFeature supports SMS (IR.92)
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS
+         */
+        public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_sms_int_array";
+
+        /**
+         * This MmTelFeature supports Call Composer (section 2.4 of RCC.20)
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER
+         */
+        public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_call_composer_int_array";
+
+        /**
+         * A bundle which specifies the RCS capability and registration technology
+         * that requires provisioning. If a tuple is not present, the
+         * framework will not require that the tuple requires provisioning before
+         * enabling the capability.
+         * <p> Possible keys in this bundle are
+         * <ul>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY}</li>
+         * </ul>
+         * <p> The values are defined in
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+         */
+        public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE =
+                KEY_PREFIX + "rcs_requires_provisioning_bundle";
+
+        /**
+         * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the
+         * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS.
+         * If not set, this RcsFeature should not service capability requests.
+         * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE
+         */
+        public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_options_uce_int_array";
+
+        /**
+         * This carrier supports User Capability Exchange using a presence server as defined by the
+         * framework. If set, the RcsFeature should support capability exchange using a presence
+         * server. If not set, this RcsFeature should not publish capabilities or service capability
+         * requests using presence.
+         * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE
+         */
+        public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY =
+                KEY_PREFIX + "key_capability_type_presence_uce_int_array";
+
         private Ims() {}
 
         private static PersistableBundle getDefaults() {
@@ -4667,6 +4774,20 @@
                     "+g.gsma.rcs.botversion=\"#=1,#=2\"",
                     "+g.gsma.rcs.cpimext"});
 
+            /**
+             * @see #KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
+             */
+            PersistableBundle mmtel_requires_provisioning_int_array = new PersistableBundle();
+            defaults.putPersistableBundle(
+                    KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE, mmtel_requires_provisioning_int_array);
+
+            /**
+             * @see #KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+             */
+            PersistableBundle rcs_requires_provisioning_int_array = new PersistableBundle();
+            defaults.putPersistableBundle(
+                    KEY_RCS_REQUIRES_PROVISIONING_BUNDLE, rcs_requires_provisioning_int_array);
+
             return defaults;
         }
     }
@@ -5415,6 +5536,7 @@
         sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
         sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
         sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
+        sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
         sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false);
         sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{});
         sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index fc76f99..6b9871c 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -160,6 +160,26 @@
         return new SipDelegateManager(mContext, subscriptionId, sRcsCache, sTelephonyCache);
     }
 
+
+    /**
+     * Create an instance of {@link ProvisioningManager} for the subscription id specified.
+     * <p>
+     * Provides a ProvisioningManager instance to carrier apps to update carrier provisioning
+     * information, as well as provides a callback so that apps can listen for changes
+     * in MMTEL/RCS provisioning
+     * @param subscriptionId The ID of the subscription that this ProvisioningManager will use.
+     * @throws IllegalArgumentException if the subscription is invalid.
+     * @return a ProvisioningManager instance with the specific subscription ID.
+     */
+    @NonNull
+    public ProvisioningManager getProvisioningManager(int subscriptionId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+            throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+        }
+
+        return new ProvisioningManager(subscriptionId);
+    }
+
     private static IImsRcsController getIImsRcsControllerInterface() {
         return IImsRcsController.Stub.asInterface(
                 TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index aab6daa..4934f11 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8765,7 +8765,8 @@
      * @param allowedNetworkTypes The bitmask of allowed network types.
      * @return true on success; false on any failure.
      * @hide
-     * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
+     * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead with reason
+     * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -8799,10 +8800,7 @@
 
     /**
      * To indicate allowed network type change is requested by user.
-     *
-     * @hide
      */
-    @SystemApi
     public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0;
 
     /**
@@ -8821,10 +8819,7 @@
      * Carrier configuration won't affect the settings configured through
      * other reasons and will result in allowing network types that are in both
      * configurations (i.e intersection of both sets).
-     *
-     * @hide
      */
-    @SystemApi
     public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2;
 
     /**
@@ -8838,35 +8833,23 @@
     /**
      * Set the allowed network types of the device and provide the reason triggering the allowed
      * network change.
+     * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE or
+     * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * This can be called for following reasons
      * <ol>
      * <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER}
-     * <li>Allowed network types control by power manager
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER}
      * <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}
-     * <li>Allowed network types control by the user-controlled "Allow 2G" toggle
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}
      * </ol>
      * This API will result in allowing an intersection of allowed network types for all reasons,
      * including the configuration done through other reasons.
      *
-     * The functionality of this API with the parameter
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API
-     * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of
-     * {@link TelephonyManager#setAllowedNetworkTypes}.
-     * <p>
-     * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
-     * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
-     * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
-     * setPreferredNetworkTypesBitmap is used instead.
-     *
      * @param reason the reason the allowed network type change is taking place
-     * @param allowedNetworkTypes The bitmask of allowed network types.
+     * @param allowedNetworkTypes The bitmask of allowed network type
      * @throws IllegalStateException if the Telephony process is not currently available.
      * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
-     * @hide
+     * @throws SecurityException if the caller does not have the required privileges
      */
-    @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     @RequiresFeature(
             enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
@@ -8896,18 +8879,19 @@
      *
      * {@link #getAllowedNetworkTypesForReason} returns allowed network type for a
      * specific reason.
+     * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
+     * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param reason the reason the allowed network type change is taking place
      * @return the allowed network type bitmask
      * @throws IllegalStateException    if the Telephony process is not currently available.
      * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
-     * @hide
+     * @throws SecurityException if the caller does not have the required permission/privileges
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @RequiresFeature(
             enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
             value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
-    @SystemApi
     public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
             @AllowedNetworkTypesReason int reason) {
         if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -13026,127 +13010,88 @@
     // 2G
     /**
      * network type bitmask unknown.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L;
     /**
      * network type bitmask indicating the support of radio tech GSM.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_GSM = (1 << (NETWORK_TYPE_GSM -1));
     /**
      * network type bitmask indicating the support of radio tech GPRS.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_GPRS = (1 << (NETWORK_TYPE_GPRS -1));
     /**
      * network type bitmask indicating the support of radio tech EDGE.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EDGE = (1 << (NETWORK_TYPE_EDGE -1));
     /**
      * network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B).
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_CDMA = (1 << (NETWORK_TYPE_CDMA -1));
     /**
      * network type bitmask indicating the support of radio tech 1xRTT.
-     * @hide
      */
-    @SystemApi
+    @SuppressLint("AllUpper")
     public static final long NETWORK_TYPE_BITMASK_1xRTT = (1 << (NETWORK_TYPE_1xRTT - 1));
     // 3G
     /**
      * network type bitmask indicating the support of radio tech EVDO 0.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_0 = (1 << (NETWORK_TYPE_EVDO_0 -1));
     /**
      * network type bitmask indicating the support of radio tech EVDO A.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_A = (1 << (NETWORK_TYPE_EVDO_A - 1));
     /**
      * network type bitmask indicating the support of radio tech EVDO B.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_B = (1 << (NETWORK_TYPE_EVDO_B -1));
     /**
      * network type bitmask indicating the support of radio tech EHRPD.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EHRPD = (1 << (NETWORK_TYPE_EHRPD -1));
     /**
      * network type bitmask indicating the support of radio tech HSUPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSUPA = (1 << (NETWORK_TYPE_HSUPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSDPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSDPA = (1 << (NETWORK_TYPE_HSDPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSPA = (1 << (NETWORK_TYPE_HSPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPAP.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSPAP = (1 << (NETWORK_TYPE_HSPAP -1));
     /**
      * network type bitmask indicating the support of radio tech UMTS.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_UMTS = (1 << (NETWORK_TYPE_UMTS -1));
     /**
      * network type bitmask indicating the support of radio tech TD_SCDMA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << (NETWORK_TYPE_TD_SCDMA -1));
     // 4G
     /**
      * network type bitmask indicating the support of radio tech LTE.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_LTE = (1 << (NETWORK_TYPE_LTE -1));
     /**
      * network type bitmask indicating the support of radio tech LTE CA (carrier aggregation).
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_LTE_CA = (1 << (NETWORK_TYPE_LTE_CA -1));
 
     /**
      * network type bitmask indicating the support of radio tech NR(New Radio) 5G.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_NR = (1 << (NETWORK_TYPE_NR -1));
 
     /**
      * network type bitmask indicating the support of radio tech IWLAN.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1));
 
     /** @hide */
@@ -13201,12 +13146,11 @@
     /**
      * @return Modem supported radio access family bitmask
      *
-     * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+     * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
      * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
-     * @hide
+     *
+     * @throws SecurityException if the caller does not have the required permission
      */
-    @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
         try {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 9ab5aeb..be233b8 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.LongDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -41,14 +42,22 @@
 import android.telephony.ims.stub.SipTransportImplBase;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
@@ -172,8 +181,28 @@
     // call ImsFeature#onFeatureRemoved.
     private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
 
-    private IImsServiceControllerListener mListener;
+    // A map of slot id -> boolean array, where each entry in the boolean array corresponds to an
+    // ImsFeature that was created for a slot id and not a sub id for backwards compatibility
+    // purposes.
+    private final SparseArray<SparseBooleanArray> mCreateImsFeatureWithSlotIdFlagMap =
+            new SparseArray<>();
 
+    private IImsServiceControllerListener mListener;
+    private Executor mExecutor;
+
+    /**
+     * Create a new ImsService.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. Vendor specifies the
+     * {@link Executor} that the methods stubs will be called. If mExecutor is set to null by
+     * vendor use Runnable::run.
+     */
+    public ImsService() {
+        mExecutor = ImsService.this.getExecutor();
+        if (mExecutor == null) {
+            mExecutor = Runnable::run;
+        }
+    }
 
     /**
      * Listener that notifies the framework of ImsService changes.
@@ -200,79 +229,163 @@
         }
 
         @Override
-        public IImsMmTelFeature createMmTelFeature(int slotId) {
-            return createMmTelFeatureInternal(slotId);
+        public IImsMmTelFeature createMmTelFeature(int slotId, int subId) {
+            MmTelFeature f  = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+            if (f == null) {
+                return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId, subId),
+                        "createMmTelFeature");
+            } else {
+                return f.getBinder();
+            }
         }
 
         @Override
-        public IImsRcsFeature createRcsFeature(int slotId) {
-            return createRcsFeatureInternal(slotId);
+        public IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+            MmTelFeature f  = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+            if (f == null) {
+                return executeMethodAsyncForResult(() -> createEmergencyOnlyMmTelFeatureInternal(
+                        slotId), "createEmergencyOnlyMmTelFeature");
+            } else {
+                return f.getBinder();
+            }
+        }
+
+        @Override
+        public IImsRcsFeature createRcsFeature(int slotId, int subId) {
+            RcsFeature f  = (RcsFeature) getImsFeature(slotId, ImsFeature.FEATURE_RCS);
+            if (f == null) {
+                return executeMethodAsyncForResult(() ->
+                        createRcsFeatureInternal(slotId, subId), "createRcsFeature");
+            } else {
+                return f.getBinder();
+            }
         }
 
         @Override
         public void addFeatureStatusCallback(int slotId, int featureType,
                 IImsFeatureStatusCallback c) {
-            ImsService.this.addImsFeatureStatusCallback(slotId, featureType, c);
+            executeMethodAsync(() -> ImsService.this.addImsFeatureStatusCallback(
+                    slotId, featureType, c), "addFeatureStatusCallback");
         }
 
         @Override
         public void removeFeatureStatusCallback(int slotId, int featureType,
                 IImsFeatureStatusCallback c) {
-            ImsService.this.removeImsFeatureStatusCallback(slotId, featureType, c);
+            executeMethodAsync(() -> ImsService.this.removeImsFeatureStatusCallback(
+                    slotId, featureType, c), "removeFeatureStatusCallback");
         }
 
         @Override
-        public void removeImsFeature(int slotId, int featureType) {
-            ImsService.this.removeImsFeature(slotId, featureType);
+        public void removeImsFeature(int slotId, int featureType, boolean changeSubId) {
+            if (changeSubId && isImsFeatureCreatedForSlot(slotId, featureType)) {
+                Log.w(LOG_TAG, "Do not remove Ims feature for compatibility");
+                return;
+            }
+            executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType),
+                    "removeImsFeature");
+            setImsFeatureCreatedForSlot(slotId, featureType, false);
         }
 
         @Override
         public ImsFeatureConfiguration querySupportedImsFeatures() {
-            return ImsService.this.querySupportedImsFeatures();
+            return executeMethodAsyncForResult(() -> ImsService.this.querySupportedImsFeatures(),
+                    "ImsFeatureConfiguration");
         }
 
         @Override
         public long getImsServiceCapabilities() {
-            long caps = ImsService.this.getImsServiceCapabilities();
-            long sanitizedCaps = sanitizeCapabilities(caps);
-            if (caps != sanitizedCaps) {
-                Log.w(LOG_TAG, "removing invalid bits from field: 0x"
-                        + Long.toHexString(caps ^ sanitizedCaps));
-            }
-            return sanitizedCaps;
+            return executeMethodAsyncForResult(() -> {
+                long caps = ImsService.this.getImsServiceCapabilities();
+                long sanitizedCaps = sanitizeCapabilities(caps);
+                if (caps != sanitizedCaps) {
+                    Log.w(LOG_TAG, "removing invalid bits from field: 0x"
+                            + Long.toHexString(caps ^ sanitizedCaps));
+                }
+                return sanitizedCaps;
+            }, "getImsServiceCapabilities");
         }
 
         @Override
         public void notifyImsServiceReadyForFeatureCreation() {
-            ImsService.this.readyForFeatureCreation();
+            executeMethodAsync(() -> ImsService.this.readyForFeatureCreation(),
+                    "notifyImsServiceReadyForFeatureCreation");
         }
 
         @Override
-        public IImsConfig getConfig(int slotId) {
-            ImsConfigImplBase c = ImsService.this.getConfig(slotId);
-            return c != null ? c.getIImsConfig() : null;
+        public IImsConfig getConfig(int slotId, int subId) {
+            return executeMethodAsyncForResult(() -> {
+                ImsConfigImplBase c =
+                        ImsService.this.getConfigForSubscription(slotId, subId);
+                if (c != null) {
+                    c.setDefaultExecutor(mExecutor);
+                    return c.getIImsConfig();
+                } else {
+                    return null;
+                }
+            }, "getConfig");
         }
 
         @Override
-        public IImsRegistration getRegistration(int slotId) {
-            ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
-            return r != null ? r.getBinder() : null;
+        public IImsRegistration getRegistration(int slotId, int subId) {
+            return executeMethodAsyncForResult(() -> {
+                ImsRegistrationImplBase r =
+                        ImsService.this.getRegistrationForSubscription(slotId, subId);
+                if (r != null) {
+                    r.setDefaultExecutor(mExecutor);
+                    return r.getBinder();
+                } else {
+                    return null;
+                }
+            }, "getRegistration");
         }
 
         @Override
         public ISipTransport getSipTransport(int slotId) {
-            SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
-            return s != null ? s.getBinder() : null;
+            return executeMethodAsyncForResult(() -> {
+                SipTransportImplBase s =  ImsService.this.getSipTransport(slotId);
+                if (s != null) {
+                    s.setDefaultExecutor(mExecutor);
+                    return s.getBinder();
+                } else {
+                    return null;
+                }
+            }, "getSipTransport");
         }
 
         @Override
-        public void enableIms(int slotId) {
-            ImsService.this.enableIms(slotId);
+        public void enableIms(int slotId, int subId) {
+            executeMethodAsync(() ->
+                    ImsService.this.enableImsForSubscription(slotId, subId), "enableIms");
         }
 
         @Override
-        public void disableIms(int slotId) {
-            ImsService.this.disableIms(slotId);
+        public void disableIms(int slotId, int subId) {
+            executeMethodAsync(() ->
+                    ImsService.this.disableImsForSubscription(slotId, subId), "disableIms");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
+            }
         }
     };
 
@@ -288,18 +401,11 @@
         return null;
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public SparseArray<ImsFeature> getFeatures(int slotId) {
-        return mFeaturesBySlot.get(slotId);
-    }
-
-    private IImsMmTelFeature createMmTelFeatureInternal(int slotId) {
-        MmTelFeature f = createMmTelFeature(slotId);
+    private IImsMmTelFeature createMmTelFeatureInternal(int slotId, int subscriptionId) {
+        MmTelFeature f = createMmTelFeatureForSubscription(slotId, subscriptionId);
         if (f != null) {
             setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+            f.setDefaultExecutor(mExecutor);
             return f.getBinder();
         } else {
             Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
@@ -307,9 +413,22 @@
         }
     }
 
-    private IImsRcsFeature createRcsFeatureInternal(int slotId) {
-        RcsFeature f = createRcsFeature(slotId);
+    private IImsMmTelFeature createEmergencyOnlyMmTelFeatureInternal(int slotId) {
+        MmTelFeature f = createEmergencyOnlyMmTelFeature(slotId);
         if (f != null) {
+            setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+            f.setDefaultExecutor(mExecutor);
+            return f.getBinder();
+        } else {
+            Log.e(LOG_TAG, "createEmergencyOnlyMmTelFeatureInternal: null feature returned.");
+            return null;
+        }
+    }
+
+    private IImsRcsFeature createRcsFeatureInternal(int slotId, int subI) {
+        RcsFeature f = createRcsFeatureForSubscription(slotId, subI);
+        if (f != null) {
+            f.setDefaultExecutor(mExecutor);
             setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
             return f.getBinder();
         } else {
@@ -388,6 +507,49 @@
             f.onFeatureRemoved();
             features.remove(featureType);
         }
+
+    }
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public ImsFeature getImsFeature(int slotId, int featureType) {
+        synchronized (mFeaturesBySlot) {
+            // Get SparseArray for Features, by querying slot Id
+            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+            if (features == null) {
+                return null;
+            }
+            return features.get(featureType);
+        }
+    }
+
+    private void setImsFeatureCreatedForSlot(int slotId,
+            @ImsFeature.FeatureType int featureType, boolean createdForSlot) {
+        synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+            getImsFeatureCreatedForSlot(slotId).put(featureType, createdForSlot);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean isImsFeatureCreatedForSlot(int slotId,
+            @ImsFeature.FeatureType int featureType) {
+        synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+            return getImsFeatureCreatedForSlot(slotId).get(featureType);
+        }
+    }
+
+    private SparseBooleanArray getImsFeatureCreatedForSlot(int slotId) {
+        SparseBooleanArray createFlag = mCreateImsFeatureWithSlotIdFlagMap.get(slotId);
+        if (createFlag == null) {
+            createFlag = new SparseBooleanArray();
+            mCreateImsFeatureWithSlotIdFlagMap.put(slotId, createFlag);
+        }
+        return createFlag;
     }
 
     /**
@@ -446,27 +608,95 @@
     }
 
     /**
+     * The framework has enabled IMS for the subscription specified, the ImsService should register
+     * for IMS and perform all appropriate initialization to bring up all ImsFeatures.
+     *
+     * @param slotId The slot ID that IMS will be enabled for.
+     * @param subscriptionId The subscription ID that IMS will be enabled for.
+     */
+    public void enableImsForSubscription(int slotId, int subscriptionId) {
+        enableIms(slotId);
+    }
+
+    /**
+     * The framework has disabled IMS for the subscription specified. The ImsService must deregister
+     * for IMS and set capability status to false for all ImsFeatures.
+     * @param slotId The slot ID that IMS will be disabled for.
+     * @param subscriptionId The subscription ID that IMS will be disabled for.
+     */
+    public void disableImsForSubscription(int slotId, int subscriptionId) {
+        disableIms(slotId);
+    }
+
+    /**
      * The framework has enabled IMS for the slot specified, the ImsService should register for IMS
      * and perform all appropriate initialization to bring up all ImsFeatures.
+     * @deprecated Use {@link #enableImsForSubscription} instead.
      */
+    @Deprecated
     public void enableIms(int slotId) {
     }
 
     /**
      * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
      * and set capability status to false for all ImsFeatures.
+     * @deprecated Use {@link #disableImsForSubscription} instead.
      */
+    @Deprecated
     public void disableIms(int slotId) {
     }
 
     /**
      * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
+     * specified subscription.
+     *
+     * @param subscriptionId The subscription ID that the MMTEL Feature is being created for.
+     * @return The newly created {@link MmTelFeature} associated with the subscription or null if
+     * the feature is not supported.
+     */
+    public @Nullable MmTelFeature createMmTelFeatureForSubscription(int slotId,
+            int subscriptionId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+        return createMmTelFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+     * specified subscription.
+     *
+     * @param subscriptionId The subscription ID that the RCS Feature is being created for.
+     * @return The newly created {@link RcsFeature} associated with the subscription or null if the
+     * feature is not supported.
+     */
+    public @Nullable RcsFeature createRcsFeatureForSubscription(int slotId, int subscriptionId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_RCS, true);
+        return createRcsFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new emergency-only {@link MmTelFeature} is
+     * created for the specified slot. For emergency calls, there is no known Subscription Id.
+     *
+     * @param slotId The slot ID that the MMTEL Feature is being created for.
+     * @return An MmTelFeature instance to be used for the slot ID when there is not
+     * subscription inserted. Only requested when there is no subscription active on
+     * the specified slot.
+     */
+    public @Nullable MmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+        return createMmTelFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
      * specified slot.
+     * @deprecated Use {@link #createMmTelFeatureForSubscription} instead
      *
      * @param slotId The slot ID that the MMTEL Feature is being created for.
      * @return The newly created {@link MmTelFeature} associated with the slot or null if the
      * feature is not supported.
      */
+    @Deprecated
     public MmTelFeature createMmTelFeature(int slotId) {
         return null;
     }
@@ -474,32 +704,62 @@
     /**
      * When called, the framework is requesting that a new {@link RcsFeature} is created for the
      * specified slot.
+     * @deprecated Use {@link #createRcsFeatureForSubscription} instead
      *
      * @param slotId The slot ID that the RCS Feature is being created for.
      * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
      * is not supported.
      */
+    @Deprecated
     public RcsFeature createRcsFeature(int slotId) {
         return null;
     }
 
     /**
+     * Return the {@link ImsConfigImplBase} implementation associated with the provided
+     * subscription. This will be used by the platform to get/set specific IMS related
+     * configurations.
+     *
+     * @param subscriptionId The subscription ID that the IMS configuration is associated with.
+     * @return ImsConfig implementation that is associated with the specified subscription.
+     */
+    public @NonNull ImsConfigImplBase getConfigForSubscription(int slotId, int subscriptionId) {
+        return getConfig(slotId);
+    }
+
+    /**
+     * Return the {@link ImsRegistrationImplBase} implementation associated with the provided
+     * subscription.
+     *
+     * @param subscriptionId The subscription ID that is associated with the IMS Registration.
+     * @return the ImsRegistration implementation associated with the subscription.
+     */
+    public @NonNull ImsRegistrationImplBase getRegistrationForSubscription(int slotId,
+            int subscriptionId) {
+        return getRegistration(slotId);
+    }
+
+    /**
      * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
      * will be used by the platform to get/set specific IMS related configurations.
+     * @deprecated use {@link #getConfigForSubscription} instead.
      *
      * @param slotId The slot that the IMS configuration is associated with.
      * @return ImsConfig implementation that is associated with the specified slot.
      */
+    @Deprecated
     public ImsConfigImplBase getConfig(int slotId) {
         return new ImsConfigImplBase();
     }
 
     /**
      * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
+     * @deprecated use  {@link #getRegistrationForSubscription} instead.
      *
      * @param slotId The slot that is associated with the IMS Registration.
      * @return the ImsRegistration implementation associated with the slot.
      */
+    @Deprecated
     public ImsRegistrationImplBase getRegistration(int slotId) {
         return new ImsRegistrationImplBase();
     }
@@ -562,4 +822,15 @@
         result.append("}");
         return result.toString();
     }
+
+    /**
+     * The ImsService will now be able to define an Executor that the ImsService can be used to
+     * execute the methods. By default all ImsService level method calls will use this Executor.
+     * The ImsService has set the default executor as Runnable::run,
+     * Should be override or default executor will be used.
+     *  @return an Executor used to execute methods called remotely by the framework.
+     */
+    public @NonNull Executor getExecutor() {
+        return Runnable::run;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index abc5606..5aef8a6 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -33,6 +33,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyManager;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature;
@@ -53,17 +54,11 @@
  * IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
  * applications and may vary. It is up to the carrier and OEM applications to ensure that the
  * correct provisioning keys are being used when integrating with a vendor's ImsService.
- *
- * Note: For compatibility purposes, the integer values [0 - 99] used in
- * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
- * previously defined in the Android framework. Please do not redefine new provisioning keys in this
- * range or it may generate collisions with existing keys. Some common constants have also been
- * defined in this class to make integrating with other system apps easier.
- * @hide
  */
-@SystemApi
 public class ProvisioningManager {
 
+    private static final String TAG = "ProvisioningManager";
+
     /**@hide*/
     @StringDef(prefix = "STRING_QUERY_RESULT_ERROR_", value = {
             STRING_QUERY_RESULT_ERROR_GENERIC,
@@ -74,14 +69,18 @@
 
     /**
      * The query from {@link #getProvisioningStringValue(int)} has resulted in an unspecified error.
+     * @hide
      */
+    @SystemApi
     public static final String STRING_QUERY_RESULT_ERROR_GENERIC =
             "STRING_QUERY_RESULT_ERROR_GENERIC";
 
     /**
      * The query from {@link #getProvisioningStringValue(int)} has resulted in an error because the
      * ImsService implementation was not ready for provisioning queries.
+     * @hide
      */
+    @SystemApi
     public static final String STRING_QUERY_RESULT_ERROR_NOT_READY =
             "STRING_QUERY_RESULT_ERROR_NOT_READY";
 
@@ -93,12 +92,16 @@
 
     /**
      * The integer result of provisioning for the queried key is disabled.
+     * @hide
      */
+    @SystemApi
     public static final int PROVISIONING_VALUE_DISABLED = 0;
 
     /**
      * The integer result of provisioning for the queried key is enabled.
+     * @hide
      */
+    @SystemApi
     public static final int PROVISIONING_VALUE_ENABLED = 1;
 
 
@@ -443,27 +446,31 @@
 
     /**
      * Override the user-defined WiFi Roaming enabled setting for this subscription, defined in
-     * {@link SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, for the purposes of provisioning
-     * the subscription for WiFi Calling.
+     * {@link android.telephony.SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI},
+     * for the purposes of provisioning the subscription for WiFi Calling.
      *
-     * @see #getProvisioningIntValue(int)
      * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26;
 
     /**
      * Override the user-defined WiFi mode for this subscription, defined in
-     * {@link SubscriptionManager#WFC_MODE_CONTENT_URI}, for the purposes of provisioning
-     * this subscription for WiFi Calling.
+     * {@link android.telephony.SubscriptionManager#WFC_MODE_CONTENT_URI},
+     * for the purposes of provisioning this subscription for WiFi Calling.
      *
      * Valid values for this key are:
      * {@link ImsMmTelManager#WIFI_MODE_WIFI_ONLY},
      * {@link ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED}, or
      * {@link ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}.
      *
-     * @see #getProvisioningIntValue(int)
      * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27;
 
     /**
@@ -862,7 +869,9 @@
      * <p>Value is in String format.
      * @see #setProvisioningStringValue(int, String)
      * @see #getProvisioningStringValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67;
 
     /**
@@ -884,7 +893,9 @@
 
     /**
      * Callback for IMS provisioning changes.
+     * @hide
      */
+    @SystemApi
     public static class Callback {
 
         private static class CallbackBinder extends IImsConfigCallback.Stub {
@@ -954,11 +965,105 @@
         }
     }
 
+    /**
+     * Callback for IMS provisioning feature changes.
+     */
+    public static class FeatureProvisioningCallback {
+
+        private static class CallbackBinder extends IFeatureProvisioningCallback.Stub {
+
+            private final FeatureProvisioningCallback mFeatureProvisioningCallback;
+            private Executor mExecutor;
+
+            private CallbackBinder(FeatureProvisioningCallback featureProvisioningCallback) {
+                mFeatureProvisioningCallback = featureProvisioningCallback;
+            }
+
+            @Override
+            public final void onFeatureProvisioningChanged(
+                    int capability, int tech, boolean isProvisioned) {
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() ->
+                            mFeatureProvisioningCallback.onFeatureProvisioningChanged(
+                                    capability, tech, isProvisioned));
+                } finally {
+                    restoreCallingIdentity(callingIdentity);
+                }
+            }
+
+            @Override
+            public final void onRcsFeatureProvisioningChanged(
+                    int capability, int tech, boolean isProvisioned) {
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() ->
+                            mFeatureProvisioningCallback.onRcsFeatureProvisioningChanged(
+                                    capability, tech, isProvisioned));
+                } finally {
+                    restoreCallingIdentity(callingIdentity);
+                }
+            }
+
+            private void setExecutor(Executor executor) {
+                mExecutor = executor;
+            }
+        }
+
+        private final CallbackBinder mBinder = new CallbackBinder(this);
+
+        /**
+         * The IMS MMTEL provisioning has changed for a specific capability and IMS
+         * registration technology.
+         * @param capability The MMTEL capability that provisioning has changed for.
+         * @param tech The IMS registration technology associated with the MMTEL capability that
+         * provisioning has changed for.
+         * @param isProvisioned {@code true} if the capability is provisioned for the technology
+         * specified, or {@code false} if the capability is not provisioned for the technology
+         * specified.
+         */
+        public void onFeatureProvisioningChanged(
+                @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+                @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+                boolean isProvisioned) {
+            // Base Implementation
+        }
+
+        /**
+         * The IMS RCS provisioning has changed for a specific capability and IMS
+         * registration technology.
+         * @param capability The RCS capability that provisioning has changed for.
+         * @param tech The IMS registration technology associated with the RCS capability that
+         * provisioning has changed for.
+         * @param isProvisioned {@code true} if the capability is provisioned for the technology
+         * specified, or {@code false} if the capability is not provisioned for the technology
+         * specified.
+         */
+        public void onRcsFeatureProvisioningChanged(
+                @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+                @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+                boolean isProvisioned) {
+            // Base Implementation
+        }
+
+        /**@hide*/
+        public final IFeatureProvisioningCallback getBinder() {
+            return mBinder;
+        }
+
+        /**@hide*/
+        public void setExecutor(Executor executor) {
+            mBinder.setExecutor(executor);
+        }
+    }
+
     private int mSubId;
 
     /**
      * The callback for RCS provisioning changes.
+     * @hide
      */
+    @SystemApi
     public static class RcsProvisioningCallback {
         private static class CallbackBinder extends IRcsConfigCallback.Stub {
 
@@ -1096,7 +1201,9 @@
      * @param subId The ID of the subscription that this ProvisioningManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
      * @throws IllegalArgumentException if the subscription is invalid.
+     * @hide
      */
+    @SystemApi
     public static @NonNull ProvisioningManager createForSubscriptionId(int subId) {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
@@ -1105,7 +1212,9 @@
         return new ProvisioningManager(subId);
     }
 
-    private ProvisioningManager(int subId) {
+    /**@hide*/
+    //@SystemApi
+    public ProvisioningManager(int subId) {
         mSubId = subId;
     }
 
@@ -1114,6 +1223,12 @@
      *
      * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
      * etc...), this callback will automatically be removed.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     * </ul>
+     *
      * @param executor The {@link Executor} to call the callback methods on
      * @param callback The provisioning callbackto be registered.
      * @see #unregisterProvisioningChangedCallback(Callback)
@@ -1124,7 +1239,9 @@
      * the {@link ImsService} associated with the subscription is not available. This can happen if
      * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
      * reason.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull Callback callback) throws ImsException {
@@ -1142,12 +1259,20 @@
      * Unregister an existing {@link Callback}. When the subscription associated with this
      * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
      * removed. If this method is called for an inactive subscription, it will result in a no-op.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     * </ul>
+     *
      * @param callback The existing {@link Callback} to be removed.
      * @see #registerProvisioningChangedCallback(Executor, Callback)
      *
      * @throws IllegalArgumentException if the subscription associated with this callback is
      * invalid.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
         try {
@@ -1158,6 +1283,62 @@
     }
 
     /**
+     * Register a new {@link FeatureProvisioningCallback}, which is used to listen for
+     * IMS feature provisioning updates.
+     * <p>
+     * When the subscription associated with this callback is removed (SIM removed,
+     * ESIM swap,etc...), this callback will automatically be removed.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @param executor The executor that the callback methods will be called on.
+     * @param callback The callback instance being registered.
+     * @throws ImsException if the subscription associated with this callback is
+     * valid, but the {@link ImsService the service crashed, for example. See
+     * {@link ImsException#getCode()} for a more detailed reason.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public void registerFeatureProvisioningChangedCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull FeatureProvisioningCallback callback) throws ImsException {
+        callback.setExecutor(executor);
+        try {
+            getITelephony().registerFeatureProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (ServiceSpecificException e) {
+            throw new ImsException(e.getMessage(), e.errorCode);
+        } catch (RemoteException | IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Unregisters a previously registered {@link FeatureProvisioningCallback}
+     * instance.  When the subscription associated with this
+     * callback is removed (SIM removed, ESIM swap, etc...), this callback will
+     * automatically be removed. If this method is called for an inactive
+     * subscription, it will result in a no-op.
+     *
+     * @param callback The existing {@link FeatureProvisioningCallback} to be removed.
+     * @see #registerFeatureProvisioningChangedCallback(Executor, FeatureProvisioningCallback)
+     */
+    public void unregisterFeatureProvisioningChangedCallback(
+            @NonNull FeatureProvisioningCallback callback) {
+        try {
+            getITelephony().unregisterFeatureProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Query for the integer value associated with the provided key.
      *
      * This operation is blocking and should not be performed on the UI thread.
@@ -1166,7 +1347,9 @@
      * @return an integer value for the provided key, or
      * {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN} if the key doesn't exist.
      * @throws IllegalArgumentException if the key provided was invalid.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public int getProvisioningIntValue(int key) {
@@ -1186,7 +1369,9 @@
      * @return a String value for the provided key, {@code null} if the key doesn't exist, or
      * {@link StringResultError} if there was an error getting the value for the provided key.
      * @throws IllegalArgumentException if the key provided was invalid.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @Nullable @StringResultError String getProvisioningStringValue(int key) {
@@ -1207,7 +1392,15 @@
      * @param key An integer that represents the provisioning key, which is defined by the OEM.
      * @param value a integer value for the provided key.
      * @return the result of setting the configuration value.
+     * @hide
+     *
+     * Note: For compatibility purposes, the integer values [0 - 99] used in
+     * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
+     * previously defined in the Android framework. Please do not redefine new provisioning keys
+     * in this range or it may generate collisions with existing keys. Some common constants have
+     * also been defined in this class to make integrating with other system apps easier.
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
@@ -1227,7 +1420,9 @@
      *     should be appropriately namespaced to avoid collision.
      * @param value a String value for the provided key.
      * @return the result of setting the configuration value.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
@@ -1247,8 +1442,14 @@
      * does not support the capability/technology combination specified, this operation will be a
      * no-op.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
-     * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+     * <p>Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the calling app has carrier privileges (see</li>
+     *     <li>{@link TelephonyManager#hasCarrierPrivileges}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
      * @param isProvisioned true if the device is provisioned for UT over IMS, false otherwise.
      */
     @WorkerThread
@@ -1256,9 +1457,10 @@
     public void setProvisioningStatusForCapability(
             @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int tech,  boolean isProvisioned) {
+
         try {
             getITelephony().setImsProvisioningStatusForCapability(mSubId, capability, tech,
-                    isProvisioned);
+                        isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -1272,14 +1474,21 @@
      * {@link ImsRegistrationImplBase.ImsRegistrationTech} combination specified, this method will
      * always return {@code true}.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
-     * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
      * @return true if the device is provisioned for the capability or does not require
      * provisioning, false if the capability does require provisioning and has not been
      * provisioned yet.
      */
     @WorkerThread
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
     public boolean getProvisioningStatusForCapability(
             @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
@@ -1297,17 +1506,93 @@
      * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return
      * {@code true}.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * @see CarrierConfigManager.Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
      * @return true if the device is provisioned for the capability or does not require
      * provisioning, false if the capability does require provisioning and has not been
      * provisioned yet.
+     * @deprecated Use {@link #getRcsProvisioningStatusForCapability(int, int)} instead,
+     * as this only retrieves provisioning information for
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+     * @hide
      */
+    @Deprecated
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean getRcsProvisioningStatusForCapability(
             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
         try {
-            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability);
+            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability,
+            ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Get the provisioning status for the IMS RCS capability specified.
+     *
+     * If provisioning is not required for the queried
+     * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method
+     * will always return {@code true}.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+     * @return true if the device is provisioned for the capability or does not require
+     * provisioning, false if the capability does require provisioning and has not been
+     * provisioned yet.
+     */
+    @WorkerThread
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean getRcsProvisioningStatusForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Set the provisioning status for the IMS RCS capability using the specified subscription.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE}</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+
+     * Provisioning may or may not be required, depending on the carrier configuration. If
+     * provisioning is not required for the carrier associated with this subscription or the device
+     * does not support the capability/technology combination specified, this operation will be a
+     * no-op.
+     *
+     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * @param isProvisioned true if the device is provisioned for the RCS capability specified,
+     *                      false otherwise.
+     * @deprecated Use {@link #setRcsProvisioningStatusForCapability(int, int, boolean)} instead,
+     * as this method only sets provisioning information for
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @WorkerThread
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void setRcsProvisioningStatusForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            boolean isProvisioned) {
+        try {
+            getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
+                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -1321,7 +1606,14 @@
      * does not support the capability/technology combination specified, this operation will be a
      * no-op.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
      * @param isProvisioned true if the device is provisioned for the RCS capability specified,
      *                      false otherwise.
      */
@@ -1329,31 +1621,92 @@
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setRcsProvisioningStatusForCapability(
             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
-            boolean isProvisioned) {
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) {
         try {
             getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
-                    isProvisioned);
+                    tech, isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
     }
 
     /**
+     * Indicates whether provisioning for the MMTEL capability and IMS registration technology
+     * specified is required or not
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li> or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @return true if provisioning is required for the MMTEL capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean isProvisioningRequiredForCapability(
+            @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().isProvisioningRequiredForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+
+    /**
+     * Indicates whether provisioning for the RCS capability and IMS registration technology
+     * specified is required or not
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li> or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @return true if provisioning is required for the RCS capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean isRcsProvisioningRequiredForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().isRcsProvisioningRequiredForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+
+    /**
      * Notify the framework that an RCS autoconfiguration XML file has been received for
      * provisioning.
-     * <p>
-     * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has
-     * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * <p>Requires Permission:
+     * <ul>
+     *     <li>{@link Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the calling app has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
      * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
      * @param isCompressed The XML file is compressed in gzip format and must be decompressed
      *         before being read.
-     *
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
         if (config == null) {
             throw new IllegalArgumentException("Must include a non-null config XML file.");
         }
+
         try {
             getITelephony().notifyRcsAutoConfigurationReceived(mSubId, config, isCompressed);
         } catch (RemoteException e) {
@@ -1372,7 +1725,9 @@
      * <p>Contains {@link #EXTRA_SUBSCRIPTION_ID} to specify the subscription index for which
      * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
      * status.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
@@ -1380,7 +1735,9 @@
 
     /**
      * Integer extra to specify subscription index.
+     * @hide
      */
+    @SystemApi
     public static final String EXTRA_SUBSCRIPTION_ID =
             "android.telephony.ims.extra.SUBSCRIPTION_ID";
 
@@ -1390,22 +1747,30 @@
      * <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE},
      * {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of
      * {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}.
+     * @hide
      */
+    @SystemApi
     public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
 
     /**
      * RCS VoLTE single registration is supported by the device and carrier.
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_CAPABLE                       = 0;
 
     /**
      * RCS VoLTE single registration is not supported by the device.
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_DEVICE_NOT_CAPABLE            = 0x01;
 
     /**
      * RCS VoLTE single registration is not supported by the carrier
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_CARRIER_NOT_CAPABLE           = 0x01 << 1;
 
     /**
@@ -1415,11 +1780,14 @@
      * provisioning is done using autoconfiguration, then these parameters shall be
      * sent in the HTTP get request to fetch the RCS provisioning. RCS client
      * configuration must be provided by the application before registering for the
-     * provisioning status events {@link #registerRcsProvisioningCallback()}
+     * provisioning status events
+     * {@link #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)}
      * When the IMS/RCS service receives the RCS client configuration, it will detect
      * the change in the configuration, and trigger the auto-configuration as needed.
      * @param rcc RCS client configuration {@link RcsClientConfiguration}
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void setRcsClientConfiguration(
             @NonNull RcsClientConfiguration rcc) throws ImsException {
@@ -1440,18 +1808,21 @@
      * <ul>
      *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
      *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-     *     <li>or that the caller has carrier privileges (see
+     *     <li>or that the calling app has carrier privileges (see
      *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
      * </ul>
+     *
      * @return true if IMS single registration is capable at this time, or false otherwise
-     * @throws ImsException If the remote ImsService is not available for
-     * any reason or the subscription associated with this instance is no
-     * longer active. See {@link ImsException#getCode()} for more
-     * information.
+     * @throws ImsException If the remote ImsService is not available for any reason or
+     * the subscription associated with this instance is no longer active.
+     * See {@link ImsException#getCode()} for more information.
      * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this
      * device supports IMS single registration.
+     * @hide
      */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
         try {
@@ -1478,8 +1849,6 @@
     * <ul>
     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
     *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-    *     <li>or that the caller has carrier privileges (see
-    *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
     * </ul>
     *
     * @param executor The {@link Executor} to call the callback methods on
@@ -1497,8 +1866,11 @@
     * params (See {@link #setRcsClientConfiguration}) and re register the
     * callback.
     * See {@link ImsException#getCode()} for a more detailed reason.
+    * @hide
     */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void registerRcsProvisioningCallback(
             @NonNull @CallbackExecutor Executor executor,
@@ -1525,8 +1897,6 @@
      * <ul>
      *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
      *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-     *     <li>or that the caller has carrier privileges (see
-     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
      * </ul>
      *
      * @param callback The existing {@link RcsProvisioningCallback} to be
@@ -1534,8 +1904,11 @@
      * @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)
      * @throws IllegalArgumentException if the subscription associated with
      * this callback is invalid.
+     * @hide
      */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void unregisterRcsProvisioningCallback(
             @NonNull RcsProvisioningCallback callback) {
@@ -1556,9 +1929,10 @@
      * {@link RcsProvisioningCallback} may expect to receive
      * {@link RcsProvisioningCallback#onConfigurationReset}, then
      * {@link RcsProvisioningCallback#onConfigurationChanged} when the new
-     * RCS configuration is received and notified by
-     * {@link #notifyRcsAutoConfigurationReceived}
+     * RCS configuration is received and notified by {@link #notifyRcsAutoConfigurationReceived}
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void triggerRcsReconfiguration() {
         try {
diff --git a/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
new file mode 100644
index 0000000..63ec4aa
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 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;
+
+/**
+ * Provides callback interface for FeatureProvisioning when a value has changed.
+ *
+ * {@hide}
+ */
+oneway interface IFeatureProvisioningCallback {
+    void onFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+    void onRcsFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index c6966b3..ae6166f 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -32,18 +32,19 @@
  */
 interface IImsServiceController {
     void setListener(IImsServiceControllerListener l);
-    IImsMmTelFeature createMmTelFeature(int slotId);
-    IImsRcsFeature createRcsFeature(int slotId);
+    IImsMmTelFeature createMmTelFeature(int slotId, int subId);
+    IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId);
+    IImsRcsFeature createRcsFeature(int slotId, int subId);
     ImsFeatureConfiguration querySupportedImsFeatures();
     long getImsServiceCapabilities();
     void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
     void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
     // Synchronous call to ensure the ImsService is ready before continuing with feature creation.
     void notifyImsServiceReadyForFeatureCreation();
-    void removeImsFeature(int slotId, int featureType);
-    IImsConfig getConfig(int slotId);
-    IImsRegistration getRegistration(int slotId);
+    void removeImsFeature(int slotId, int featureType, boolean changeSubId);
+    IImsConfig getConfig(int slotId, int subId);
+    IImsRegistration getRegistration(int slotId, int subId);
     ISipTransport getSipTransport(int slotId);
-    oneway void enableIms(int slotId);
-    oneway void disableIms(int slotId);
+    oneway void enableIms(int slotId, int subId);
+    oneway void disableIms(int slotId, int subId);
 }
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 9a3f592..ad2e9e1 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -40,16 +40,25 @@
 import android.telephony.ims.stub.ImsSmsImplBase;
 import android.telephony.ims.stub.ImsUtImplBase;
 import android.util.ArraySet;
+import android.util.Log;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsUt;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 
 /**
  * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
@@ -60,6 +69,7 @@
 public class MmTelFeature extends ImsFeature {
 
     private static final String LOG_TAG = "MmTelFeature";
+    private Executor mExecutor;
 
     /**
      * @hide
@@ -68,160 +78,261 @@
     public MmTelFeature() {
     }
 
+    /**
+     * Create a new MmTelFeature using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of MmTelFeature.
+     * @hide
+     */
+    @SystemApi
+    public MmTelFeature(@NonNull Executor executor) {
+        super();
+        mExecutor = executor;
+    }
+
     private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
 
         @Override
         public void setListener(IImsMmTelListener l) {
-            MmTelFeature.this.setListener(l);
+            executeMethodAsyncNoException(() -> MmTelFeature.this.setListener(l), "setListener");
         }
 
         @Override
         public int getFeatureState() throws RemoteException {
-            try {
-                return MmTelFeature.this.getFeatureState();
-            } catch (Exception e) {
-                throw new RemoteException(e.getMessage());
-            }
+            return executeMethodAsyncForResult(() -> MmTelFeature.this.getFeatureState(),
+                    "getFeatureState");
         }
 
-
         @Override
         public ImsCallProfile createCallProfile(int callSessionType, int callType)
                 throws RemoteException {
-            synchronized (mLock) {
-                try {
-                    return MmTelFeature.this.createCallProfile(callSessionType, callType);
-                } catch (Exception e) {
-                    throw new RemoteException(e.getMessage());
-                }
-            }
+            return executeMethodAsyncForResult(() -> MmTelFeature.this.createCallProfile(
+                    callSessionType, callType), "createCallProfile");
         }
 
         @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());
-                }
-            }
+            executeMethodAsync(() -> MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(
+                    new ArraySet<>(types)), "changeOfferedRtpHeaderExtensionTypes");
         }
 
         @Override
         public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
-            synchronized (mLock) {
-                return createCallSessionInterface(profile);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsCallSession result = executeMethodAsyncForResult(() -> {
+                try {
+                    return createCallSessionInterface(profile);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "createCallSession");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public int shouldProcessCall(String[] numbers) {
-            synchronized (mLock) {
-                return MmTelFeature.this.shouldProcessCall(numbers);
+            Integer result = executeMethodAsyncForResultNoException(() ->
+                    MmTelFeature.this.shouldProcessCall(numbers), "shouldProcessCall");
+            if (result != null) {
+                return result.intValue();
+            } else {
+                return PROCESS_CALL_CSFB;
             }
         }
 
         @Override
         public IImsUt getUtInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getUtInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsUt result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getUtInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getUtInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public IImsEcbm getEcbmInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getEcbmInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsEcbm result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getEcbmInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getEcbmInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
-            synchronized (mLock) {
-                try {
-                    MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
-                } catch (Exception e) {
-                    throw new RemoteException(e.getMessage());
-                }
-            }
+            executeMethodAsync(() -> MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage),
+                    "setUiTtyMode");
         }
 
         @Override
         public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getMultiEndpointInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsMultiEndpoint result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getMultiEndpointInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getMultiEndpointInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public int queryCapabilityStatus() {
-            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            Integer result = executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+                    .queryCapabilityStatus().mCapabilities, "queryCapabilityStatus");
+
+            if (result != null) {
+                return result.intValue();
+            } else {
+                return 0;
+            }
         }
 
         @Override
         public void addCapabilityCallback(IImsCapabilityCallback c) {
-            // no need to lock, structure already handles multithreading.
-            MmTelFeature.this.addCapabilityCallback(c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .addCapabilityCallback(c), "addCapabilityCallback");
         }
 
         @Override
         public void removeCapabilityCallback(IImsCapabilityCallback c) {
-            // no need to lock, structure already handles multithreading.
-            MmTelFeature.this.removeCapabilityCallback(c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .removeCapabilityCallback(c), "removeCapabilityCallback");
         }
 
         @Override
         public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
                 IImsCapabilityCallback c) {
-            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .requestChangeEnabledCapabilities(request, c),
+                    "changeCapabilitiesConfiguration");
         }
 
         @Override
         public void queryCapabilityConfiguration(int capability, int radioTech,
                 IImsCapabilityCallback c) {
-            queryCapabilityConfigurationInternal(capability, radioTech, c);
+            executeMethodAsyncNoException(() -> queryCapabilityConfigurationInternal(
+                    capability, radioTech, c), "queryCapabilityConfiguration");
         }
 
         @Override
         public void setSmsListener(IImsSmsListener l) {
-            MmTelFeature.this.setSmsListener(l);
+            executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l),
+                    "setSmsListener");
         }
 
         @Override
         public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
                 byte[] pdu) {
-            synchronized (mLock) {
-                MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms");
         }
 
         @Override
         public void acknowledgeSms(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSms(token, messageRef, result);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .acknowledgeSms(token, messageRef, result), "acknowledgeSms");
         }
 
         @Override
         public void acknowledgeSmsReport(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport");
         }
 
         @Override
         public String getSmsFormat() {
-            synchronized (mLock) {
-                return MmTelFeature.this.getSmsFormat();
-            }
+            return executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+                    .getSmsFormat(), "getSmsFormat");
         }
 
         @Override
         public void onSmsReady() {
-            synchronized (mLock) {
-                MmTelFeature.this.onSmsReady();
+            executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(),
+                    "onSmsReady");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResultNoException(Supplier<T> r,
+                String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
             }
         }
     };
@@ -283,6 +394,13 @@
         public @interface MmTelCapability {}
 
         /**
+         * Undefined capability type for initialization
+         * This is used to check the upper range of MmTel capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_NONE = 0;
+
+        /**
          * This MmTelFeature supports Voice calling (IR.92)
          */
         public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
@@ -308,6 +426,12 @@
         public static final int CAPABILITY_TYPE_CALL_COMPOSER = 1 << 4;
 
         /**
+         * This is used to check the upper range of MmTel capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_CALL_COMPOSER + 1;
+
+        /**
          * @hide
          */
         @Override
@@ -672,7 +796,12 @@
     public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
             throws RemoteException {
         ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
-        return s != null ? s.getServiceImpl() : null;
+        if (s != null) {
+            s.setDefaultExecutor(mExecutor);
+            return s.getServiceImpl();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -713,7 +842,12 @@
      */
     protected IImsUt getUtInterface() throws RemoteException {
         ImsUtImplBase utImpl = getUt();
-        return utImpl != null ? utImpl.getInterface() : null;
+        if (utImpl != null) {
+            utImpl.setDefaultExecutor(mExecutor);
+            return utImpl.getInterface();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -721,7 +855,12 @@
      */
     protected IImsEcbm getEcbmInterface() throws RemoteException {
         ImsEcbmImplBase ecbmImpl = getEcbm();
-        return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
+        if (ecbmImpl != null) {
+            ecbmImpl.setDefaultExecutor(mExecutor);
+            return ecbmImpl.getImsEcbm();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -729,7 +868,12 @@
      */
     public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
         ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
-        return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
+        if (multiendpointImpl != null) {
+            multiendpointImpl.setDefaultExecutor(mExecutor);
+            return multiendpointImpl.getIImsMultiEndpoint();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -859,4 +1003,16 @@
     public final IImsMmTelFeature getBinder() {
         return mImsMMTelBinder;
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of MmTelFeature.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mExecutor == null) {
+            mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 18cc37d..70e4ef1 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -59,9 +59,7 @@
 /**
  * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
  * this class and provide implementations of the RcsFeature methods that they support.
- * @hide
  */
-@SystemApi
 public class RcsFeature extends ImsFeature {
 
     private static final String LOG_TAG = "RcsFeature";
@@ -70,7 +68,7 @@
         // Reference the outer class in order to have better test coverage metrics instead of
         // creating a inner class referencing the outer class directly.
         private final RcsFeature mReference;
-        private final Executor mExecutor;
+        private Executor mExecutor;
 
         RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) {
             mReference = classRef;
@@ -186,14 +184,14 @@
      * Contains the capabilities defined and supported by a {@link RcsFeature} in the
      * form of a bitmask. The capabilities that are used in the RcsFeature are
      * defined as:
-     * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
-     * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
+     * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
+     * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
      *
      * The enabled capabilities of this RcsFeature will be set by the framework
-     * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
+     * using {#changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
      * After the capabilities have been set, the RcsFeature may then perform the necessary bring up
      * of the capability and notify the capability status as true using
-     * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
+     * {#notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
      * framework that the capability is available for usage.
      */
     public static class RcsImsCapabilities extends Capabilities {
@@ -227,10 +225,18 @@
         public static final int CAPABILITY_TYPE_PRESENCE_UCE =  1 << 1;
 
         /**
+         * This is used to check the upper range of RCS capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1;
+
+        /**
          * Create a new {@link RcsImsCapabilities} instance with the provided capabilities.
          * @param capabilities The capabilities that are supported for RCS in the form of a
          * bitfield.
+         * @hide
          */
+        @SystemApi
         public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super(capabilities);
         }
@@ -243,23 +249,35 @@
             super(capabilities.getMask());
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super.addCapabilities(capabilities);
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super.removeCapabilities(capabilities);
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             return super.isCapable(capabilities);
         }
     }
 
-    private final Executor mExecutor;
+    private Executor mExecutor;
     private final RcsFeatureBinder mImsRcsBinder;
     private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
     private CapabilityExchangeEventListener mCapExchangeEventListener;
@@ -270,13 +288,11 @@
      * Method stubs called from the framework will be called asynchronously. To specify the
      * {@link Executor} that the methods stubs will be called, use
      * {@link RcsFeature#RcsFeature(Executor)} instead.
-     *
-     * @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature.
+     * @hide
      */
-    @Deprecated
+    @SystemApi
     public RcsFeature() {
         super();
-        mExecutor = Runnable::run;
         // Run on the Binder threads that call them.
         mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
     }
@@ -286,7 +302,9 @@
      * framework.
      * @param executor The executor for the framework to use when executing the methods overridden
      * by the implementation of RcsFeature.
+     * @hide
      */
+    @SystemApi
     public RcsFeature(@NonNull Executor executor) {
         super();
         if (executor == null) {
@@ -305,7 +323,7 @@
      * @hide
      */
     @Override
-    public void initialize(Context context, int slotId) {
+    public void initialize(@NonNull Context context, @NonNull int slotId) {
         super.initialize(context, slotId);
         // Notify that the RcsFeature is ready.
         mExecutor.execute(() -> onFeatureReady());
@@ -317,8 +335,10 @@
      * requests. To change the status of the capabilities
      * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
      * @return A copy of the current RcsFeature capability status.
+     * @hide
      */
     @Override
+    @SystemApi
     public @NonNull final RcsImsCapabilities queryCapabilityStatus() {
         return new RcsImsCapabilities(super.queryCapabilityStatus());
     }
@@ -328,7 +348,9 @@
      * this signals to the framework that the capability has been initialized and is ready.
      * Call {@link #queryCapabilityStatus()} to return the current capability status.
      * @param capabilities The current capability status of the RcsFeature.
+     * @hide
      */
+    @SystemApi
     public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) {
         if (capabilities == null) {
             throw new IllegalArgumentException("RcsImsCapabilities must be non-null!");
@@ -345,7 +367,9 @@
      * @param capability The capability that we are querying the configuration for.
      * @param radioTech The radio technology type that we are querying.
      * @return true if the capability is enabled, false otherwise.
+     * @hide
      */
+    @SystemApi
     public boolean queryCapabilityConfiguration(
             @RcsUceAdapter.RcsImsCapabilityFlag int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
@@ -368,8 +392,10 @@
      * be called for each capability change that resulted in an error.
      * @param request The request to change the capability.
      * @param callback To notify the framework that the result of the capability changes.
+     * @hide
      */
     @Override
+    @SystemApi
     public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
             @NonNull CapabilityCallbackProxy callback) {
         // Base Implementation - Override to provide functionality
@@ -389,7 +415,9 @@
      * event to the framework.
      * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
      * exchange if it is supported by the device.
+     * @hide
      */
+    @SystemApi
     public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
             @NonNull CapabilityExchangeEventListener listener) {
         // Base Implementation, override to implement functionality
@@ -399,20 +427,28 @@
     /**
      * Remove the given CapabilityExchangeImplBase instance.
      * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed.
+     * @hide
      */
+    @SystemApi
     public void destroyCapabilityExchangeImpl(
             @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
         // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance.
     }
 
-    /**{@inheritDoc}*/
+    /**{@inheritDoc}
+     * @hide
+     */
     @Override
+    @SystemApi
     public void onFeatureRemoved() {
 
     }
 
-    /**{@inheritDoc}*/
+    /**{@inheritDoc}
+     * @hide
+     */
     @Override
+    @SystemApi
     public void onFeatureReady() {
 
     }
@@ -477,4 +513,17 @@
             return mCapabilityExchangeImpl;
         }
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of RcsFeature.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mImsRcsBinder.mExecutor == null) {
+            mExecutor = executor;
+            mImsRcsBinder.mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index a3a6cb8..e810095 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -30,12 +30,20 @@
 import android.telephony.ims.RtpHeaderExtensionType;
 import android.telephony.ims.aidl.IImsCallSessionListener;
 import android.util.ArraySet;
+import android.util.Log;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Base implementation of IImsCallSession, which implements stub versions of the methods available.
@@ -48,6 +56,8 @@
 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
 // will break other implementations of ImsCallSession maintained by other ImsServices.
 public class ImsCallSessionImplBase implements AutoCloseable {
+
+    private static final String LOG_TAG = "ImsCallSessionImplBase";
     /**
      * Notify USSD Mode.
      */
@@ -110,185 +120,235 @@
         }
     }
 
+    private Executor mExecutor = Runnable::run;
+
     // Non-final for injection by tests
     private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
         @Override
         public void close() {
-            ImsCallSessionImplBase.this.close();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close");
         }
 
         @Override
         public String getCallId() {
-            return ImsCallSessionImplBase.this.getCallId();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(),
+                    "getCallId");
         }
 
         @Override
         public ImsCallProfile getCallProfile() {
-            return ImsCallSessionImplBase.this.getCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(),
+                    "getCallProfile");
         }
 
         @Override
         public ImsCallProfile getLocalCallProfile() {
-            return ImsCallSessionImplBase.this.getLocalCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getLocalCallProfile(), "getLocalCallProfile");
         }
 
         @Override
         public ImsCallProfile getRemoteCallProfile() {
-            return ImsCallSessionImplBase.this.getRemoteCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getRemoteCallProfile(), "getRemoteCallProfile");
         }
 
         @Override
         public String getProperty(String name) {
-            return ImsCallSessionImplBase.this.getProperty(name);
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name),
+                    "getProperty");
         }
 
         @Override
         public int getState() {
-            return ImsCallSessionImplBase.this.getState();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(),
+                    "getState");
         }
 
         @Override
         public boolean isInCall() {
-            return ImsCallSessionImplBase.this.isInCall();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(),
+                    "isInCall");
         }
 
         @Override
         public void setListener(IImsCallSessionListener listener) {
-            ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
+                    new ImsCallSessionListener(listener)), "setListener");
         }
 
         @Override
         public void setMute(boolean muted) {
-            ImsCallSessionImplBase.this.setMute(muted);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute");
         }
 
         @Override
         public void start(String callee, ImsCallProfile profile) {
-            ImsCallSessionImplBase.this.start(callee, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start");
         }
 
         @Override
         public void startConference(String[] participants, ImsCallProfile profile) throws
                 RemoteException {
-            ImsCallSessionImplBase.this.startConference(participants, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants,
+                    profile), "startConference");
         }
 
         @Override
         public void accept(int callType, ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.accept(callType, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile),
+                    "accept");
         }
 
         @Override
         public void deflect(String deflectNumber) {
-            ImsCallSessionImplBase.this.deflect(deflectNumber);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber),
+                    "deflect");
         }
 
         @Override
         public void reject(int reason) {
-            ImsCallSessionImplBase.this.reject(reason);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject");
         }
 
         @Override
         public void transfer(@NonNull String number, boolean isConfirmationRequired) {
-            ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number,
+                    isConfirmationRequired), "transfer");
         }
 
         @Override
         public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
-            ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
-            otherSession.setServiceImpl(transferToSession);
-            ImsCallSessionImplBase.this.transfer(otherSession);
+            executeMethodAsync(() -> {
+                ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
+                otherSession.setServiceImpl(transferToSession);
+                ImsCallSessionImplBase.this.transfer(otherSession);
+            }, "consultativeTransfer");
         }
 
         @Override
         public void terminate(int reason) {
-            ImsCallSessionImplBase.this.terminate(reason);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate");
         }
 
         @Override
         public void hold(ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.hold(profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold");
         }
 
         @Override
         public void resume(ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.resume(profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume");
         }
 
         @Override
         public void merge() {
-            ImsCallSessionImplBase.this.merge();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge");
         }
 
         @Override
         public void update(int callType, ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.update(callType, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile),
+                    "update");
         }
 
         @Override
         public void extendToConference(String[] participants) {
-            ImsCallSessionImplBase.this.extendToConference(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants),
+                    "extendToConference");
         }
 
         @Override
         public void inviteParticipants(String[] participants) {
-            ImsCallSessionImplBase.this.inviteParticipants(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants),
+                    "inviteParticipants");
         }
 
         @Override
         public void removeParticipants(String[] participants) {
-            ImsCallSessionImplBase.this.removeParticipants(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants),
+                    "removeParticipants");
         }
 
         @Override
         public void sendDtmf(char c, Message result) {
-            ImsCallSessionImplBase.this.sendDtmf(c, result);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf");
         }
 
         @Override
         public void startDtmf(char c) {
-            ImsCallSessionImplBase.this.startDtmf(c);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf");
         }
 
         @Override
         public void stopDtmf() {
-            ImsCallSessionImplBase.this.stopDtmf();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf");
         }
 
         @Override
         public void sendUssd(String ussdMessage) {
-            ImsCallSessionImplBase.this.sendUssd(ussdMessage);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd");
         }
 
         @Override
         public IImsVideoCallProvider getVideoCallProvider() {
-            return ImsCallSessionImplBase.this.getVideoCallProvider();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getVideoCallProvider(), "getVideoCallProvider");
         }
 
         @Override
         public boolean isMultiparty() {
-            return ImsCallSessionImplBase.this.isMultiparty();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(),
+                    "isMultiparty");
         }
 
         @Override
         public void sendRttModifyRequest(ImsCallProfile toProfile) {
-            ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile),
+                    "sendRttModifyRequest");
         }
 
         @Override
         public void sendRttModifyResponse(boolean status) {
-            ImsCallSessionImplBase.this.sendRttModifyResponse(status);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status),
+                    "sendRttModifyResponse");
         }
 
         @Override
         public void sendRttMessage(String rttMessage) {
-            ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage),
+                    "sendRttMessage");
         }
 
         @Override
         public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) {
-            ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
-                    new ArraySet<RtpHeaderExtension>(extensions));
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
+                    new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
+            }
         }
     };
 
@@ -674,4 +734,14 @@
     public void setServiceImpl(IImsCallSession serviceImpl) {
         mServiceImpl = serviceImpl;
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsCallSession.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index d75da90..11fc328 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -33,12 +33,21 @@
 import com.android.ims.ImsConfig;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
 
 /**
  * Controls the modification of IMS specific configurations. For more information on the supported
@@ -81,21 +90,48 @@
         WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
         private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
         private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+        private final Object mLock = new Object();
+        private Executor mExecutor;
 
         @VisibleForTesting
-        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
+        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) {
+            mExecutor = executor;
             mImsConfigImplBaseWeakReference =
                     new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
         }
 
         @Override
         public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().addImsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().addImsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addImsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().removeImsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().removeImsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "removeImsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         /**
@@ -108,16 +144,34 @@
          * unavailable.
          */
         @Override
-        public synchronized int getConfigInt(int item) throws RemoteException {
-            if (mProvisionedIntValue.containsKey(item)) {
-                return mProvisionedIntValue.get(item);
-            } else {
-                int retVal = getImsConfigImpl().getConfigInt(item);
-                if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
-                    updateCachedValue(item, retVal, false);
+        public int getConfigInt(int item) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                synchronized (mLock) {
+                    if (mProvisionedIntValue.containsKey(item)) {
+                        return mProvisionedIntValue.get(item);
+                    } else {
+                        try {
+                            returnVal = getImsConfigImpl().getConfigInt(item);
+                            if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+                                mProvisionedIntValue.put(item, returnVal);
+                            }
+                        } catch (RemoteException e) {
+                            exceptionRef.set(e);
+                            return returnVal;
+                        }
+                    }
                 }
-                return retVal;
+                return returnVal;
+            }, "getConfigInt");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+                throw exceptionRef.get();
             }
+
+            return retVal;
         }
 
         /**
@@ -129,16 +183,34 @@
          * @return value in String format.
          */
         @Override
-        public synchronized String getConfigString(int item) throws RemoteException {
-            if (mProvisionedStringValue.containsKey(item)) {
-                return mProvisionedStringValue.get(item);
-            } else {
-                String retVal = getImsConfigImpl().getConfigString(item);
-                if (retVal != null) {
-                    updateCachedValue(item, retVal, false);
+        public String getConfigString(int item) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            String retVal = executeMethodAsyncForResult(()-> {
+                String returnVal = null;
+                synchronized (mLock) {
+                    if (mProvisionedStringValue.containsKey(item)) {
+                        returnVal = mProvisionedStringValue.get(item);
+                    } else {
+                        try {
+                            returnVal = getImsConfigImpl().getConfigString(item);
+                            if (returnVal != null) {
+                                mProvisionedStringValue.put(item, returnVal);
+                            }
+                        } catch (RemoteException e) {
+                            exceptionRef.set(e);
+                            return returnVal;
+                        }
+                    }
                 }
-                return retVal;
+                return returnVal;
+            }, "getConfigString");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+                throw exceptionRef.get();
             }
+
+            return retVal;
         }
 
         /**
@@ -153,14 +225,32 @@
          * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
          */
         @Override
-        public synchronized int setConfigInt(int item, int value) throws RemoteException {
-            mProvisionedIntValue.remove(item);
-            int retVal = getImsConfigImpl().setConfig(item, value);
-            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
-                updateCachedValue(item, value, true);
-            } else {
-                Log.d(TAG, "Set provision value of " + item +
-                        " to " + value + " failed with error code " + retVal);
+        public int setConfigInt(int item, int value) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                try {
+                    synchronized (mLock) {
+                        mProvisionedIntValue.remove(item);
+                        returnVal = getImsConfigImpl().setConfig(item, value);
+                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                            mProvisionedIntValue.put(item, value);
+                        } else {
+                            Log.d(TAG, "Set provision value of " + item
+                                    + " to " + value + " failed with error code " + returnVal);
+                        }
+                    }
+                    notifyImsConfigChanged(item, value);
+                    return returnVal;
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return returnVal;
+                }
+            }, "setConfigInt");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+                throw exceptionRef.get();
             }
 
             return retVal;
@@ -178,12 +268,30 @@
          * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
          */
         @Override
-        public synchronized int setConfigString(int item, String value)
+        public int setConfigString(int item, String value)
                 throws RemoteException {
-            mProvisionedStringValue.remove(item);
-            int retVal = getImsConfigImpl().setConfig(item, value);
-            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
-                updateCachedValue(item, value, true);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                try {
+                    synchronized (mLock) {
+                        mProvisionedStringValue.remove(item);
+                        returnVal = getImsConfigImpl().setConfig(item, value);
+                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                            mProvisionedStringValue.put(item, value);
+                        }
+                    }
+                    notifyImsConfigChanged(item, value);
+                    return returnVal;
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return returnVal;
+                }
+            }, "setConfigString");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+                throw exceptionRef.get();
             }
 
             return retVal;
@@ -191,7 +299,19 @@
 
         @Override
         public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
-            getImsConfigImpl().updateImsCarrierConfigs(bundle);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().updateImsCarrierConfigs(bundle);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "updateImsCarrierConfigs");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs");
+                throw exceptionRef.get();
+            }
         }
 
         private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
@@ -206,13 +326,37 @@
         @Override
         public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
                 throws RemoteException {
-            getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyRcsAutoConfigurationReceived");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyRcsAutoConfigurationRemoved()
                 throws RemoteException {
-            getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyRcsAutoConfigurationRemoved");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved");
+                throw exceptionRef.get();
+            }
         }
 
         private void notifyImsConfigChanged(int item, int value) throws RemoteException {
@@ -223,50 +367,144 @@
             getImsConfigImpl().notifyConfigChanged(item, value);
         }
 
-        protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
-        throws RemoteException {
-            mProvisionedIntValue.put(item, value);
-            if (notifyChange) {
-                notifyImsConfigChanged(item, value);
+        protected void updateCachedValue(int item, int value) {
+            synchronized (mLock) {
+                mProvisionedIntValue.put(item, value);
             }
         }
 
-        protected synchronized void updateCachedValue(int item, String value,
-                boolean notifyChange) throws RemoteException {
-            mProvisionedStringValue.put(item, value);
-            if (notifyChange) {
-                notifyImsConfigChanged(item, value);
+        protected void updateCachedValue(int item, String value) {
+            synchronized (mLock) {
+                mProvisionedStringValue.put(item, value);
             }
         }
 
         @Override
         public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().addRcsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().addRcsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addRcsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().removeRcsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().removeRcsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "removeRcsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void triggerRcsReconfiguration() throws RemoteException {
-            getImsConfigImpl().triggerAutoConfiguration();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().triggerAutoConfiguration();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "triggerRcsReconfiguration");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
-            getImsConfigImpl().setRcsClientConfiguration(rcc);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().setRcsClientConfiguration(rcc);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "setRcsClientConfiguration");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
-            notifyImsConfigChanged(item, value);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    notifyImsConfigChanged(item, value);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyIntImsConfigChanged");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
-            notifyImsConfigChanged(item, value);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    notifyImsConfigChanged(item, value);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyStringImsConfigChanged");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged");
+                throw exceptionRef.get();
+            }
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     }
 
@@ -303,15 +541,24 @@
     ImsConfigStub mImsConfigStub;
 
     /**
-     * Used for compatibility between older versions of the ImsService.
+     * Create a ImsConfig using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of ImsConfig.
+     */
+    public ImsConfigImplBase(@NonNull Executor executor) {
+        mImsConfigStub = new ImsConfigStub(this, executor);
+    }
+
+    /**
      * @hide
      */
-    public ImsConfigImplBase(Context context) {
-        mImsConfigStub = new ImsConfigStub(this);
+    public ImsConfigImplBase(@NonNull Context context) {
+        mImsConfigStub = new ImsConfigStub(this, null);
     }
 
     public ImsConfigImplBase() {
-        mImsConfigStub = new ImsConfigStub(this);
+        mImsConfigStub = new ImsConfigStub(this, null);
     }
 
     /**
@@ -427,8 +674,10 @@
      * @param value in Integer format.
      */
     public final void notifyProvisionedValueChanged(int item, int value) {
+        mImsConfigStub.updateCachedValue(item, value);
+
         try {
-            mImsConfigStub.updateCachedValue(item, value, true);
+            mImsConfigStub.notifyImsConfigChanged(item, value);
         } catch (RemoteException e) {
             Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
         }
@@ -443,8 +692,10 @@
      * @param value in String format.
      */
     public final void notifyProvisionedValueChanged(int item, String value) {
+        mImsConfigStub.updateCachedValue(item, value);
+
         try {
-        mImsConfigStub.updateCachedValue(item, value, true);
+            mImsConfigStub.notifyImsConfigChanged(item, value);
         } catch (RemoteException e) {
             Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
         }
@@ -582,4 +833,16 @@
             }
         });
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsConfig.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mImsConfigStub.mExecutor == null) {
+            mImsConfigStub.mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 8ad40ed..84b2253 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -16,14 +16,21 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsEcbmListener;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
+
 
 /**
  * Base implementation of ImsEcbm, which implements stub versions of the methods
@@ -40,10 +47,12 @@
 
     private final Object mLock = new Object();
     private IImsEcbmListener mListener;
+    private Executor mExecutor = Runnable::run;
+
     private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
         @Override
         public void setListener(IImsEcbmListener listener) {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mListener != null && !mListener.asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
                     mListener = null;
@@ -62,12 +71,25 @@
                             + "listener");
                     mListener = listener;
                 }
-            }
+            }, "setListener");
         }
 
         @Override
         public void exitEmergencyCallbackMode() {
-            ImsEcbmImplBase.this.exitEmergencyCallbackMode();
+            executeMethodAsync(() -> ImsEcbmImplBase.this.exitEmergencyCallbackMode(),
+                    "exitEmergencyCallbackMode");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsEcbmImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
         }
     };
 
@@ -123,4 +145,14 @@
             }
         }
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsEcbm.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index ec1c7b3..a723cd8b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.ims.ImsExternalCallState;
@@ -23,9 +24,14 @@
 
 import com.android.ims.internal.IImsExternalCallStateListener;
 import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
 
 /**
  * Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
@@ -43,11 +49,13 @@
 
     private IImsExternalCallStateListener mListener;
     private final Object mLock = new Object();
+    private Executor mExecutor = Runnable::run;
+
     private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
 
         @Override
         public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mListener != null && !mListener.asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
                     mListener = null;
@@ -67,12 +75,25 @@
                             + "listener");
                     mListener = listener;
                 }
-            }
+            }, "setListener");
         }
 
         @Override
         public void requestImsExternalCallStateInfo() throws RemoteException {
-            ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
+            executeMethodAsync(() -> ImsMultiEndpointImplBase.this
+                    .requestImsExternalCallStateInfo(), "requestImsExternalCallStateInfo");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsMultiEndpointImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
         }
     };
 
@@ -108,4 +129,14 @@
     public void requestImsExternalCallStateInfo() {
         Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsMultiEndpoint.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 02bcdec..ac5565b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -31,10 +31,18 @@
 import android.util.Log;
 
 import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.ArrayUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 
 /**
  * Controls IMS registration for this ImsService and notifies the framework when the IMS
@@ -42,9 +50,7 @@
  * <p>
  * Note: There is no guarantee on the thread that the calls from the framework will be called on. It
  * is the implementors responsibility to handle moving the calls to a working thread if required.
- * @hide
  */
-@SystemApi
 public class ImsRegistrationImplBase {
 
     private static final String LOG_TAG = "ImsRegistrationImplBase";
@@ -85,6 +91,12 @@
      */
     public static final int REGISTRATION_TECH_NR = 3;
 
+    /**
+     * This is used to check the upper range of registration tech
+     * {@hide}
+     */
+    public static final int REGISTRATION_TECH_MAX = REGISTRATION_TECH_NR + 1;
+
     // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current
     // state.
     // The unknown state is set as the initialization state. This is so that we do not call back
@@ -92,39 +104,118 @@
     // yet.
     private static final int REGISTRATION_STATE_UNKNOWN = -1;
 
+    private Executor mExecutor;
+
+    /**
+     * Create a new ImsRegistration.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. To specify the
+     * {@link Executor} that the methods stubs will be called, use
+     * {@link ImsRegistrationImplBase#ImsRegistrationImplBase(Executor)} instead.
+     * @hide This API is not part of the Android public SDK API
+     */
+    @SystemApi
+    public ImsRegistrationImplBase() {
+        super();
+    }
+
+    /**
+     * Create a ImsRegistration using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of ImsRegistration.
+     * @hide This API is not part of the Android public SDK API
+     */
+    @SystemApi
+    public ImsRegistrationImplBase(@NonNull Executor executor) {
+        super();
+        mExecutor = executor;
+    }
+
     private final IImsRegistration mBinder = new IImsRegistration.Stub() {
 
         @Override
         public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
-            synchronized (mLock) {
-                return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE
-                        : mRegistrationAttributes.getRegistrationTechnology();
-            }
+            return executeMethodAsyncForResult(() -> (mRegistrationAttributes == null)
+                    ? REGISTRATION_TECH_NONE : mRegistrationAttributes.getRegistrationTechnology(),
+                    "getRegistrationTechnology");
         }
 
         @Override
         public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
-            ImsRegistrationImplBase.this.addRegistrationCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(() -> {
+                try {
+                    ImsRegistrationImplBase.this.addRegistrationCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addRegistrationCallback");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
-            ImsRegistrationImplBase.this.removeRegistrationCallback(c);
+            executeMethodAsync(() -> ImsRegistrationImplBase.this.removeRegistrationCallback(c),
+                    "removeRegistrationCallback");
         }
 
         @Override
         public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
-            ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .triggerFullNetworkRegistration(sipCode, sipReason),
+                    "triggerFullNetworkRegistration");
         }
 
         @Override
         public void triggerUpdateSipDelegateRegistration() {
-            ImsRegistrationImplBase.this.updateSipDelegateRegistration();
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .updateSipDelegateRegistration(), "triggerUpdateSipDelegateRegistration");
         }
 
         @Override
         public void triggerSipDelegateDeregistration() {
-            ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .triggerSipDelegateDeregistration(), "triggerSipDelegateDeregistration");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     };
 
@@ -166,7 +257,9 @@
      * 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 This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void updateSipDelegateRegistration() {
         // Stub implementation, ImsService should implement this
     }
@@ -182,7 +275,9 @@
      * <p>
      * This should not affect the registration of features managed by the ImsService itself, such as
      * feature tags related to MMTEL registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void triggerSipDelegateDeregistration() {
         // Stub implementation, ImsService should implement this
     }
@@ -200,7 +295,9 @@
      *    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 This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode,
             @Nullable String sipReason) {
         // Stub implementation, ImsService should implement this
@@ -211,7 +308,9 @@
      * Notify the framework that the device is connected to the IMS network.
      *
      * @param imsRadioTech the radio access technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
         onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
     }
@@ -220,7 +319,9 @@
      * Notify the framework that the device is connected to the IMS network.
      *
      * @param attributes The attributes associated with the IMS registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
         updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED);
         mCallbacks.broadcastAction((c) -> {
@@ -236,7 +337,9 @@
      * Notify the framework that the device is trying to connect the IMS network.
      *
      * @param imsRadioTech the radio access technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
         onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
     }
@@ -245,7 +348,9 @@
      * Notify the framework that the device is trying to connect the IMS network.
      *
      * @param attributes The attributes associated with the IMS registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) {
         updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING);
         mCallbacks.broadcastAction((c) -> {
@@ -272,7 +377,9 @@
      * result.
      *
      * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onDeregistered(ImsReasonInfo info) {
         updateToDisconnectedState(info);
         // ImsReasonInfo should never be null.
@@ -293,7 +400,9 @@
      * {@link #REGISTRATION_TECH_LTE}, {@link #REGISTRATION_TECH_IWLAN} and
      * {@link #REGISTRATION_TECH_CROSS_SIM}.
      * @param info The {@link ImsReasonInfo} for the failure to change technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
             ImsReasonInfo info) {
         final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo();
@@ -312,7 +421,9 @@
      *
      * The {@link Uri}s are not guaranteed to be different between subsequent calls.
      * @param uris changed uris
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
         synchronized (mLock) {
             mUris = ArrayUtils.cloneOrNull(uris);
@@ -394,4 +505,16 @@
             onSubscriberAssociatedUriChanged(c, uris);
         }
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of Registration.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mExecutor == null) {
+            mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index eb3e8ed..11cdeed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -27,10 +27,17 @@
 
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Base implementation of IMS UT interface, which implements stubs. Override these methods to
@@ -119,96 +126,108 @@
      */
     public static final int INVALID_RESULT = -1;
 
+    private Executor mExecutor = Runnable::run;
+
     private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
         private final Object mLock = new Object();
         private ImsUtListener mUtListener;
 
         @Override
         public void close() throws RemoteException {
-            ImsUtImplBase.this.close();
+            executeMethodAsync(() ->ImsUtImplBase.this.close(), "close");
         }
 
         @Override
         public int queryCallBarring(int cbType) throws RemoteException {
-            return ImsUtImplBase.this.queryCallBarring(cbType);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType),
+                    "queryCallBarring");
         }
 
         @Override
         public int queryCallForward(int condition, String number) throws RemoteException {
-            return ImsUtImplBase.this.queryCallForward(condition, number);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward(
+                    condition, number), "queryCallForward");
         }
 
         @Override
         public int queryCallWaiting() throws RemoteException {
-            return ImsUtImplBase.this.queryCallWaiting();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(),
+                    "queryCallWaiting");
         }
 
         @Override
         public int queryCLIR() throws RemoteException {
-            return ImsUtImplBase.this.queryCLIR();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR");
         }
 
         @Override
         public int queryCLIP() throws RemoteException {
-            return ImsUtImplBase.this.queryCLIP();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP");
         }
 
         @Override
         public int queryCOLR() throws RemoteException {
-            return ImsUtImplBase.this.queryCOLR();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR");
         }
 
         @Override
         public int queryCOLP() throws RemoteException {
-            return ImsUtImplBase.this.queryCOLP();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP");
         }
 
         @Override
         public int transact(Bundle ssInfo) throws RemoteException {
-            return ImsUtImplBase.this.transact(ssInfo);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo),
+                    "transact");
         }
 
         @Override
         public int updateCallBarring(int cbType, int action, String[] barrList) throws
                 RemoteException {
-            return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring(
+                    cbType, action, barrList), "updateCallBarring");
         }
 
         @Override
         public int updateCallForward(int action, int condition, String number, int serviceClass,
                 int timeSeconds) throws RemoteException {
-            return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
-                    timeSeconds);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward(
+                    action, condition, number, serviceClass, timeSeconds), "updateCallForward");
         }
 
         @Override
         public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
-            return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting(
+                    enable, serviceClass), "updateCallWaiting");
         }
 
         @Override
         public int updateCLIR(int clirMode) throws RemoteException {
-            return ImsUtImplBase.this.updateCLIR(clirMode);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode),
+                    "updateCLIR");
         }
 
         @Override
         public int updateCLIP(boolean enable) throws RemoteException {
-            return ImsUtImplBase.this.updateCLIP(enable);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable),
+                    "updateCLIP");
         }
 
         @Override
         public int updateCOLR(int presentation) throws RemoteException {
-            return ImsUtImplBase.this.updateCOLR(presentation);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation),
+                    "updateCOLR");
         }
 
         @Override
         public int updateCOLP(boolean enable) throws RemoteException {
-            return ImsUtImplBase.this.updateCOLP(enable);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable),
+                    "updateCOLP");
         }
 
         @Override
         public void setListener(IImsUtListener listener) throws RemoteException {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mUtListener != null
                         && !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
@@ -229,29 +248,59 @@
                             + "listener");
                     mUtListener = new ImsUtListener(listener);
                 }
-            }
 
-            ImsUtImplBase.this.setListener(mUtListener);
+                ImsUtImplBase.this.setListener(mUtListener);
+            }, "setListener");
         }
 
         @Override
         public int queryCallBarringForServiceClass(int cbType, int serviceClass)
                 throws RemoteException {
-            return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .queryCallBarringForServiceClass(cbType, serviceClass),
+                    "queryCallBarringForServiceClass");
         }
 
         @Override
         public int updateCallBarringForServiceClass(int cbType, int action,
                 String[] barrList, int serviceClass) throws RemoteException {
-            return ImsUtImplBase.this.updateCallBarringForServiceClass(
-                    cbType, action, barrList, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .updateCallBarringForServiceClass(cbType, action, barrList, serviceClass),
+                    "updateCallBarringForServiceClass");
         }
 
         @Override
         public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
                 int serviceClass, String password) throws RemoteException {
-            return ImsUtImplBase.this.updateCallBarringWithPassword(
-                    cbType, action, barrList, serviceClass, password);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .updateCallBarringWithPassword(cbType, action, barrList, serviceClass,
+                    password), "updateCallBarringWithPassword");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     };
 
@@ -470,4 +519,14 @@
     public IImsUt getInterface() {
         return mServiceImpl;
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsUT.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 13ea9973..52538cb 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -86,10 +86,21 @@
         }
     };
 
-    private final Executor mBinderExecutor;
+    private Executor mBinderExecutor;
     private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
 
     /**
+     * Create a new SipTransport.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. To specify the
+     * {@link Executor} that the methods stubs will be called, use
+     * {@link SipTransportImplBase#SipTransportImplBase(Executor)} instead.
+     */
+    public SipTransportImplBase() {
+        super();
+    }
+
+    /**
      * Create an implementation of SipTransportImplBase.
      *
      * @param executor The executor that remote calls from the framework will be called on. This
@@ -212,4 +223,16 @@
     public ISipTransport getBinder() {
         return mSipTransportImpl;
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of SipTransport.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mBinderExecutor == null) {
+            mBinderExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
index f5f67bd..416096b 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -23,11 +23,11 @@
  * {@hide}
  */
 oneway interface IImsServiceFeatureCallback {
-    void imsFeatureCreated(in ImsFeatureContainer feature);
+    void imsFeatureCreated(in ImsFeatureContainer feature, int subId);
     // Reason defined in FeatureConnector.UnavailableReason
     void imsFeatureRemoved(int reason);
     // Status defined in ImsFeature.ImsState.
-    void imsStatusChanged(int status);
+    void imsStatusChanged(int status, int subId);
     //Capabilities defined in ImsService.ImsServiceCapability
     void updateCapabilities(long capabilities);
 }
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 167aa07f..0ac7cf9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -55,6 +55,7 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.RcsClientConfiguration;
 import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
@@ -2027,6 +2028,18 @@
     void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
 
     /**
+     * Register an IMS provisioning change callback with Telephony.
+     */
+    void registerFeatureProvisioningChangedCallback(int subId,
+            IFeatureProvisioningCallback callback);
+
+    /**
+     * unregister an existing IMS provisioning change callback.
+     */
+    void unregisterFeatureProvisioningChangedCallback(int subId,
+            IFeatureProvisioningCallback callback);
+
+    /**
      * Set the provisioning status for the IMS MmTel capability using the specified subscription.
      */
     void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
@@ -2040,19 +2053,12 @@
     /**
      * Get the provisioning status for the IMS Rcs capability specified.
      */
-    boolean getRcsProvisioningStatusForCapability(int subId, int capability);
+    boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech);
 
     /**
      * Set the provisioning status for the IMS Rcs capability using the specified subscription.
      */
-    void setRcsProvisioningStatusForCapability(int subId, int capability,
-            boolean isProvisioned);
-
-    /** Is the capability and tech flagged as provisioned in the cache */
-    boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech);
-
-    /** Set the provisioning for the capability and tech in the cache */
-    void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
+    void setRcsProvisioningStatusForCapability(int subId, int capability, int tech,
             boolean isProvisioned);
 
     /**
@@ -2555,4 +2561,18 @@
      * @return the service name of the modem service which bind to.
      */
     String getModemService();
+
+    /**
+     * Is Provisioning required for capability
+     * @return true if provisioning is required for the MMTEL capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    boolean isProvisioningRequiredForCapability(int subId, int capability, int tech);
+
+    /**
+     * Is RCS Provisioning required for capability
+     * @return true if provisioning is required for the RCS capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech);
 }
diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp
deleted file mode 100644
index f87ca2e..0000000
--- a/tests/benchmarks/Android.bp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2015 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.
-
-// build framework base core benchmarks
-// ============================================================
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library {
-    name: "networkStatsFactory-benchmarks",
-    installable: true,
-
-    srcs: ["src/**/*.java"],
-
-    libs: [
-        "caliper-api-target",
-        "services.core",
-    ],
-
-}
diff --git a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java b/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
deleted file mode 100644
index ef014f0..0000000
--- a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.server.net;
-
-import android.net.NetworkStats;
-import android.os.SystemClock;
-import com.android.server.net.NetworkStatsFactory;
-import com.google.caliper.AfterExperiment;
-import com.google.caliper.BeforeExperiment;
-import java.io.File;
-
-public class NetworkStatsFactoryBenchmark {
-    private File mStats;
-
-    // TODO: consider staging stats file with different number of rows
-
-    @BeforeExperiment
-    protected void setUp() {
-        mStats = new File("/proc/net/xt_qtaguid/stats");
-    }
-
-    @AfterExperiment
-    protected void tearDown() {
-        mStats = null;
-    }
-
-    public void timeReadNetworkStatsDetailJava(int reps) throws Exception {
-        for (int i = 0; i < reps; i++) {
-            NetworkStatsFactory.javaReadNetworkStatsDetail(mStats, NetworkStats.UID_ALL,
-                    // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
-                    // Fixed compilation problem but needs addressing properly.
-                    new String[0], 999);
-        }
-    }
-
-    public void timeReadNetworkStatsDetailNative(int reps) {
-        for (int i = 0; i < reps; i++) {
-            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-            NetworkStatsFactory.nativeReadNetworkStatsDetail(
-                    stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL,
-                    // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
-                    // Fixed compilation problem but needs addressing properly.
-                    new String[0], 999, false);
-        }
-    }
-}
diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS
deleted file mode 100644
index aa87958..0000000
--- a/tests/benchmarks/src/com/android/server/net/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
index 41f73cd..228520e 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -18,6 +18,7 @@
         "java/**/*.kt",
     ],
     platform_apis: true,
+    defaults: ["framework-connectivity-test-defaults"],
     test_suites: ["device-tests"],
     certificate: "platform",
     static_libs: [
@@ -28,6 +29,7 @@
         "net-tests-utils",
         "platform-test-annotations",
         "services.core",
+        "service-connectivity-tiramisu-pre-jarjar",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/vcn/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml
index 2ad9aac..a8f657c 100644
--- a/tests/vcn/AndroidManifest.xml
+++ b/tests/vcn/AndroidManifest.xml
@@ -16,7 +16,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.tests.vcn">
-
+    <uses-sdk android:minSdkVersion="33"
+        android:targetSdkVersion="33"/>
     <application>
         <uses-library android:name="android.test.runner" />
     </application>