Merge "Cleaning up flag NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE" into main
diff --git a/Android.bp b/Android.bp
index 9cb3067..48f0928 100644
--- a/Android.bp
+++ b/Android.bp
@@ -399,6 +399,7 @@
         "com.android.sysprop.foldlockbehavior",
         "com.android.sysprop.view",
         "framework-internal-utils",
+        "dynamic_instrumentation_manager_aidl-java",
         // If MimeMap ever becomes its own APEX, then this dependency would need to be removed
         // in favor of an API stubs dependency in java_library "framework" below.
         "mimemap",
diff --git a/core/api/current.txt b/core/api/current.txt
index 664b3dd..80928bf 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -44280,6 +44280,8 @@
     field public static final String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
     field public static final int CARRIER_NR_AVAILABILITY_NSA = 1; // 0x1
     field public static final int CARRIER_NR_AVAILABILITY_SA = 2; // 0x2
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC = 0; // 0x0
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int CARRIER_ROAMING_NTN_CONNECT_MANUAL = 1; // 0x1
     field public static final int CROSS_SIM_SPN_FORMAT_CARRIER_NAME_ONLY = 0; // 0x0
     field public static final int CROSS_SIM_SPN_FORMAT_CARRIER_NAME_WITH_BRANDING = 1; // 0x1
     field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
@@ -44350,11 +44352,14 @@
     field public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY = "carrier_nr_availabilities_int_array";
     field public static final String KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL = "carrier_provisions_wifi_merged_networks_bool";
     field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT = "carrier_roaming_ntn_connect_type_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT = "carrier_roaming_ntn_emergency_call_to_satellite_handover_type_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY = "carrier_roaming_satellite_default_services_int_array";
     field public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
     field public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY = "carrier_service_number_array";
     field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT = "carrier_supported_satellite_notification_hysteresis_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE = "carrier_supported_satellite_services_per_provider_bundle";
     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";
@@ -44405,6 +44410,7 @@
     field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
     field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL = "disable_charge_indication_bool";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL = "disable_dun_apn_while_roaming_with_preset_apn_bool";
     field public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL = "disable_supplementary_services_in_airplane_mode_bool";
     field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
     field public static final String KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL = "display_call_strength_indicator_bool";
@@ -44417,6 +44423,8 @@
     field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
     field public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
     field public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL = "editable_wfc_roaming_mode_bool";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT = "emergency_call_to_satellite_t911_handover_timeout_millis_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL = "emergency_messaging_supported_bool";
     field public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = "emergency_notification_delay_int";
     field public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY = "emergency_number_prefix_string_array";
     field public static final String KEY_ENABLE_CROSS_SIM_CALLING_ON_OPPORTUNISTIC_DATA_BOOL = "enable_cross_sim_calling_on_opportunistic_data_bool";
@@ -44463,6 +44471,7 @@
     field public static final String KEY_MMS_MAX_IMAGE_HEIGHT_INT = "maxImageHeight";
     field public static final String KEY_MMS_MAX_IMAGE_WIDTH_INT = "maxImageWidth";
     field public static final String KEY_MMS_MAX_MESSAGE_SIZE_INT = "maxMessageSize";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_MMS_MAX_NTN_PAYLOAD_SIZE_BYTES_INT = "mms_max_ntn_payload_size_bytes_int";
     field public static final String KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT = "maxMessageTextSize";
     field public static final String KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL = "enableMMSDeliveryReports";
     field public static final String KEY_MMS_MMS_ENABLED_BOOL = "enabledMMS";
@@ -44501,6 +44510,7 @@
     field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG = "opportunistic_network_max_backoff_time_long";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG = "opportunistic_network_ping_pong_time_long";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_OVERRIDE_WFC_ROAMING_MODE_WHILE_USING_NTN_BOOL = "override_wfc_roaming_mode_while_using_ntn_bool";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT = "parameters_used_for_ntn_lte_signal_bar_int";
     field public static final String KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL = "ping_test_before_data_switch_bool";
     field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
@@ -44519,6 +44529,7 @@
     field public static final String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
     field public static final String KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY = "read_only_apn_fields_string_array";
     field public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY = "read_only_apn_types_string_array";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL = "remove_satellite_plmn_in_manual_network_scan_bool";
     field public static final String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field @Deprecated public static final String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
     field public static final String KEY_RTT_AUTO_UPGRADE_BOOL = "rtt_auto_upgrade_bool";
@@ -44530,13 +44541,18 @@
     field public static final String KEY_RTT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_VT_CALL_BOOL = "rtt_upgrade_supported_for_downgraded_vt_call";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ATTACH_SUPPORTED_BOOL = "satellite_attach_supported_bool";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_DATA_SUPPORT_MODE_INT = "satellite_data_support_mode_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING = "satellite_entitlement_app_name_string";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING = "satellite_information_redirect_url_string";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_NIDD_APN_NAME_STRING = "satellite_nidd_apn_name_string";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_esos_inactivity_timeout_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL = "satellite_roaming_p2p_sms_supported_bool";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_screen_off_inactivity_timeout_sec_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL = "satellite_roaming_turn_off_session_for_emergency_call_bool";
     field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
     field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
     field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
@@ -44606,6 +44622,9 @@
     field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
     field public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000";
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_DATA_SUPPORT_ALL = 2; // 0x2
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED = 1; // 0x1
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED = 0; // 0x0
     field public static final int SERVICE_CLASS_NONE = 0; // 0x0
     field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
     field public static final int USSD_OVER_CS_ONLY = 2; // 0x2
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 30fe244..8954f8e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -138,6 +138,7 @@
     field public static final String DISABLE_SYSTEM_SOUND_EFFECTS = "android.permission.DISABLE_SYSTEM_SOUND_EFFECTS";
     field public static final String DISPATCH_PROVISIONING_MESSAGE = "android.permission.DISPATCH_PROVISIONING_MESSAGE";
     field public static final String DOMAIN_VERIFICATION_AGENT = "android.permission.DOMAIN_VERIFICATION_AGENT";
+    field @FlaggedApi("com.android.art.flags.executable_method_file_offsets") public static final String DYNAMIC_INSTRUMENTATION = "android.permission.DYNAMIC_INSTRUMENTATION";
     field @FlaggedApi("com.android.window.flags.untrusted_embedding_any_app_permission") public static final String EMBED_ANY_APP_IN_UNTRUSTED_MODE = "android.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE";
     field @FlaggedApi("android.content.pm.emergency_install_permission") public static final String EMERGENCY_INSTALL_PACKAGES = "android.permission.EMERGENCY_INSTALL_PACKAGES";
     field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED";
@@ -18332,7 +18333,12 @@
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForModemStateChanged(@NonNull android.telephony.satellite.SatelliteModemStateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForNtnSignalStrengthChanged(@NonNull android.telephony.satellite.NtnSignalStrengthCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForProvisionStateChanged(@NonNull android.telephony.satellite.SatelliteProvisionStateCallback);
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS = 7; // 0x7
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3; // 0x3
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5; // 0x5
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP = 4; // 0x4
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2; // 0x2
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_SMS = 6; // 0x6
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DATAGRAM_TYPE_SOS_MESSAGE = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DATAGRAM_TYPE_UNKNOWN = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DEVICE_HOLD_POSITION_LANDSCAPE_LEFT = 2; // 0x2
@@ -18352,6 +18358,7 @@
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; // 0x2
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; // 0x1
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7; // 0x7
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6; // 0x6
@@ -18365,6 +18372,8 @@
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_CONNECTED = 7; // 0x7
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3; // 0x3
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2; // 0x2
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9; // 0x9
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8; // 0x8
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_IDLE = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_LISTENING = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_NOT_CONNECTED = 6; // 0x6
@@ -18372,11 +18381,16 @@
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5; // 0x5
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1; // 0xffffffff
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_ACCESS_BARRED = 16; // 0x10
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28; // 0x1c
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS = 27; // 0x1b
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_RESULT_ENABLE_IN_PROGRESS = 29; // 0x1d
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_ERROR = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_ILLEGAL_STATE = 23; // 0x17
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_INVALID_ARGUMENTS = 8; // 0x8
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_INVALID_MODEM_STATE = 7; // 0x7
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_INVALID_TELEPHONY_STATE = 6; // 0x6
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_RESULT_LOCATION_DISABLED = 25; // 0x19
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_RESULT_LOCATION_NOT_AVAILABLE = 26; // 0x1a
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_MODEM_BUSY = 22; // 0x16
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_MODEM_ERROR = 4; // 0x4
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int SATELLITE_RESULT_MODEM_TIMEOUT = 24; // 0x18
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 71623c5..cf5ebbaa3 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -28,6 +28,7 @@
     exclude_srcs: [
         "android/os/*MessageQueue/**/*.java",
         "android/ranging/**/*.java",
+        ":dynamic_instrumentation_manager_aidl_sources",
     ],
     visibility: ["//frameworks/base"],
 }
@@ -120,6 +121,17 @@
 }
 
 filegroup {
+    name: "dynamic_instrumentation_manager_aidl_sources",
+    srcs: ["android/os/instrumentation/*.aidl"],
+}
+
+aidl_interface {
+    name: "dynamic_instrumentation_manager_aidl",
+    srcs: [":dynamic_instrumentation_manager_aidl_sources"],
+    unstable: true,
+}
+
+filegroup {
     name: "framework-internal-display-sources",
     srcs: ["com/android/internal/display/BrightnessSynchronizer.java"],
     visibility: ["//frameworks/base/services/tests/mockingservicestests"],
@@ -685,16 +697,31 @@
 // Generates com.android.internal.pm.RoSystemFeatures, optionally compiling in
 // details about fixed system features defined by build flags. When disabled,
 // the APIs are simply passthrough stubs with no meaningful side effects.
+// TODO(b/203143243): Implement the `--feature=` aggregation  directly with a native soong module.
 genrule {
     name: "systemfeatures-gen-srcs",
     cmd: "$(location systemfeatures-gen-tool) com.android.internal.pm.RoSystemFeatures " +
         // --readonly=false (default) makes the codegen an effective no-op passthrough API.
         " --readonly=" + gen_readonly_feature_apis +
-        // For now, only export "android.hardware.type.*" system features APIs.
-        // TODO(b/203143243): Use an intermediate soong var that aggregates all declared
-        // RELEASE_SYSTEM_FEATURE_* declarations into a single arg.
-        " --feature-apis=AUTOMOTIVE,WATCH,TELEVISION,EMBEDDED,PC" +
-        " > $(out)",
+        " --feature=AUTOMOTIVE:" + select(release_flag("RELEASE_SYSTEM_FEATURE_AUTOMOTIVE"), {
+            any @ value: value,
+            default: "",
+        }) + " --feature=EMBEDDED:" + select(release_flag("RELEASE_SYSTEM_FEATURE_EMBEDDED"), {
+            any @ value: value,
+            default: "",
+        }) + " --feature=LEANBACK:" + select(release_flag("RELEASE_SYSTEM_FEATURE_LEANBACK"), {
+            any @ value: value,
+            default: "",
+        }) + " --feature=PC:" + select(release_flag("RELEASE_SYSTEM_FEATURE_PC"), {
+            any @ value: value,
+            default: "",
+        }) + " --feature=TELEVISION:" + select(release_flag("RELEASE_SYSTEM_FEATURE_TELEVISION"), {
+            any @ value: value,
+            default: "",
+        }) + " --feature=WATCH:" + select(release_flag("RELEASE_SYSTEM_FEATURE_WATCH"), {
+            any @ value: value,
+            default: "",
+        }) + " > $(out)",
     out: [
         "RoSystemFeatures.java",
     ],
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 186f7b3..6086f24 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6802,6 +6802,12 @@
     public static final String MEDIA_QUALITY_SERVICE = "media_quality";
 
     /**
+     * Service to perform operations needed for dynamic instrumentation.
+     * @hide
+     */
+    public static final String DYNAMIC_INSTRUMENTATION_SERVICE = "dynamic_instrumentation";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index ef59e0a..93ef5c3 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -45,7 +45,7 @@
  * </p>
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("CursorWindow_host")
+@RavenwoodRedirectionClass("CursorWindow_ravenwood")
 public class CursorWindow extends SQLiteClosable implements Parcelable {
     private static final String STATS_TAG = "CursorWindowStats";
 
diff --git a/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java b/core/java/android/database/CursorWindow_ravenwood.java
similarity index 89%
rename from ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
rename to core/java/android/database/CursorWindow_ravenwood.java
index e21a9cd..990ec5e 100644
--- a/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
+++ b/core/java/android/database/CursorWindow_ravenwood.java
@@ -17,6 +17,7 @@
 
 import android.database.sqlite.SQLiteException;
 import android.os.Parcel;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
 import android.util.Base64;
 
 import java.text.DecimalFormat;
@@ -26,9 +27,10 @@
 import java.util.HashMap;
 import java.util.List;
 
-public class CursorWindow_host {
+@RavenwoodKeepWholeClass
+class CursorWindow_ravenwood {
 
-    private static final HashMap<Long, CursorWindow_host> sInstances = new HashMap<>();
+    private static final HashMap<Long, CursorWindow_ravenwood> sInstances = new HashMap<>();
     private static long sNextId = 1;
 
     private String mName;
@@ -41,7 +43,7 @@
     private final List<Row> mRows = new ArrayList<>();
 
     public static long nativeCreate(String name, int cursorWindowSize) {
-        CursorWindow_host instance = new CursorWindow_host();
+        CursorWindow_ravenwood instance = new CursorWindow_ravenwood();
         instance.mName = name;
         long instanceId = sNextId++;
         sInstances.put(instanceId, instance);
@@ -66,7 +68,7 @@
     }
 
     public static boolean nativeAllocRow(long windowPtr) {
-        CursorWindow_host instance = sInstances.get(windowPtr);
+        CursorWindow_ravenwood instance = sInstances.get(windowPtr);
         Row row = new Row();
         row.mFields = new String[instance.mColumnNum];
         row.mTypes = new int[instance.mColumnNum];
@@ -76,7 +78,7 @@
     }
 
     private static boolean put(long windowPtr, String value, int type, int row, int column) {
-        CursorWindow_host instance = sInstances.get(windowPtr);
+        CursorWindow_ravenwood instance = sInstances.get(windowPtr);
         if (row >= instance.mRows.size() || column >= instance.mColumnNum) {
             return false;
         }
@@ -87,7 +89,7 @@
     }
 
     public static int nativeGetType(long windowPtr, int row, int column) {
-        CursorWindow_host instance = sInstances.get(windowPtr);
+        CursorWindow_ravenwood instance = sInstances.get(windowPtr);
         if (row >= instance.mRows.size() || column >= instance.mColumnNum) {
             return Cursor.FIELD_TYPE_NULL;
         }
@@ -101,7 +103,7 @@
     }
 
     public static String nativeGetString(long windowPtr, int row, int column) {
-        CursorWindow_host instance = sInstances.get(windowPtr);
+        CursorWindow_ravenwood instance = sInstances.get(windowPtr);
         if (row >= instance.mRows.size() || column >= instance.mColumnNum) {
             return null;
         }
@@ -164,7 +166,7 @@
     }
 
     public static void nativeWriteToParcel(long windowPtr, Parcel parcel) {
-        CursorWindow_host window = sInstances.get(windowPtr);
+        CursorWindow_ravenwood window = sInstances.get(windowPtr);
         parcel.writeString(window.mName);
         parcel.writeInt(window.mColumnNum);
         parcel.writeInt(window.mRows.size());
@@ -176,7 +178,7 @@
 
     public static long nativeCreateFromParcel(Parcel parcel) {
         long windowPtr = nativeCreate(null, 0);
-        CursorWindow_host window = sInstances.get(windowPtr);
+        CursorWindow_ravenwood window = sInstances.get(windowPtr);
         window.mName = parcel.readString();
         window.mColumnNum = parcel.readInt();
         int rowCount = parcel.readInt();
diff --git a/core/java/android/os/CombinedMessageQueue/MessageQueue.java b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
index acda0c5..69bd668 100644
--- a/core/java/android/os/CombinedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/CombinedMessageQueue/MessageQueue.java
@@ -55,7 +55,7 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
 public final class MessageQueue {
     private static final String TAG_L = "LegacyMessageQueue";
     private static final String TAG_C = "ConcurrentMessageQueue";
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index 9db88d1..c2a47d7 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -54,7 +54,7 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
 public final class MessageQueue {
     private static final String TAG = "ConcurrentMessageQueue";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index 9f7b0b7..cae82d0 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -45,7 +45,7 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
 public final class MessageQueue {
     private static final String TAG = "MessageQueue";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
index f3eec13..2401f3d 100644
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -48,7 +48,7 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
 public final class MessageQueue {
     private static final String TAG = "LockedMessageQueue";
     private static final boolean DEBUG = false;
diff --git a/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java b/core/java/android/os/MessageQueue_ravenwood.java
similarity index 87%
rename from ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
rename to core/java/android/os/MessageQueue_ravenwood.java
index 1b63adc..4033707 100644
--- a/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
+++ b/core/java/android/os/MessageQueue_ravenwood.java
@@ -16,13 +16,16 @@
 
 package android.os;
 
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
-public class MessageQueue_host {
+@RavenwoodKeepWholeClass
+class MessageQueue_ravenwood {
     private static final AtomicLong sNextId = new AtomicLong(1);
-    private static final Map<Long, MessageQueue_host> sInstances = new ConcurrentHashMap<>();
+    private static final Map<Long, MessageQueue_ravenwood> sInstances = new ConcurrentHashMap<>();
 
     private boolean mDeleted = false;
 
@@ -37,8 +40,8 @@
         }
     }
 
-    private static MessageQueue_host getInstance(long id) {
-        MessageQueue_host q = sInstances.get(id);
+    private static MessageQueue_ravenwood getInstance(long id) {
+        MessageQueue_ravenwood q = sInstances.get(id);
         if (q == null) {
             throw new RuntimeException("MessageQueue doesn't exist with id=" + id);
         }
@@ -48,7 +51,7 @@
 
     public static long nativeInit() {
         final long id = sNextId.getAndIncrement();
-        final MessageQueue_host q = new MessageQueue_host();
+        final MessageQueue_ravenwood q = new MessageQueue_ravenwood();
         sInstances.put(id, q);
         return id;
     }
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index db323dc..435c34f 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -52,7 +52,7 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("MessageQueue_host")
+@RavenwoodRedirectionClass("MessageQueue_ravenwood")
 public final class MessageQueue {
     private static final String TAG = "SemiConcurrentMessageQueue";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/os/instrumentation/ExecutableMethodFileOffsets.aidl b/core/java/android/os/instrumentation/ExecutableMethodFileOffsets.aidl
new file mode 100644
index 0000000..dbe5489
--- /dev/null
+++ b/core/java/android/os/instrumentation/ExecutableMethodFileOffsets.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+/**
+ * Represents the location of the code for a compiled method within a process'
+ * memory.
+ * {@hide}
+ */
+@JavaDerive(toString=true)
+parcelable ExecutableMethodFileOffsets {
+  /**
+   * The OS path of the containing file (could be virtual).
+   */
+  @utf8InCpp String containerPath;
+  /**
+   * The offset of the containing file within the process' memory.
+   */
+  long containerOffset;
+  /**
+   * The offset of the method within the containing file.
+   */
+  long methodOffset;
+}
diff --git a/core/java/android/os/instrumentation/IDynamicInstrumentationManager.aidl b/core/java/android/os/instrumentation/IDynamicInstrumentationManager.aidl
new file mode 100644
index 0000000..c45c51d
--- /dev/null
+++ b/core/java/android/os/instrumentation/IDynamicInstrumentationManager.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+import android.os.instrumentation.ExecutableMethodFileOffsets;
+import android.os.instrumentation.MethodDescriptor;
+import android.os.instrumentation.TargetProcess;
+
+/**
+ * System private API for managing the dynamic attachment of instrumentation.
+ *
+ * {@hide}
+ */
+interface IDynamicInstrumentationManager {
+    /** Provides ART metadata about the described compiled method within the target process */
+    @PermissionManuallyEnforced
+    @nullable ExecutableMethodFileOffsets getExecutableMethodFileOffsets(
+            in TargetProcess targetProcess, in MethodDescriptor methodDescriptor);
+}
diff --git a/core/java/android/os/instrumentation/MethodDescriptor.aidl b/core/java/android/os/instrumentation/MethodDescriptor.aidl
new file mode 100644
index 0000000..055d0ec
--- /dev/null
+++ b/core/java/android/os/instrumentation/MethodDescriptor.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+/**
+ * Represents a JVM method, where class fields that make up its signature.
+ * {@hide}
+ */
+@JavaDerive(toString=true)
+parcelable MethodDescriptor {
+  /**
+    * Fully qualified class in reverse.domain.Naming
+    */
+  @utf8InCpp String fullyQualifiedClassName;
+  /**
+    * Name of the method.
+    */
+  @utf8InCpp String methodName;
+  /**
+    * Fully qualified types of method parameters, or string representations if primitive e.g. "int".
+    */
+  @utf8InCpp String[] fullyQualifiedParameters;
+}
diff --git a/core/java/android/os/instrumentation/TargetProcess.aidl b/core/java/android/os/instrumentation/TargetProcess.aidl
new file mode 100644
index 0000000..e90780d
--- /dev/null
+++ b/core/java/android/os/instrumentation/TargetProcess.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+/**
+ * Addresses a process that would run on the device.
+ * Helps disambiguate targeted processes in cases of pid re-use.
+ * {@hide}
+ */
+@JavaDerive(toString=true)
+parcelable TargetProcess {
+  int uid;
+  int pid;
+  @utf8InCpp String processName;
+}
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index b3480ab..2931bd2 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -56,7 +56,7 @@
  * @hide
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("LongArrayMultiStateCounter_host")
+@RavenwoodRedirectionClass("LongArrayMultiStateCounter_ravenwood")
 public final class LongArrayMultiStateCounter implements Parcelable {
     private static volatile NativeAllocationRegistry sRegistry;
     private final int mStateCount;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
similarity index 98%
rename from ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
rename to core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
index 90608f6..7030d8e 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter_ravenwood.java
@@ -18,6 +18,7 @@
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -25,7 +26,8 @@
 /**
  * Native implementation substitutions for the LongArrayMultiStateCounter class.
  */
-public class LongArrayMultiStateCounter_host {
+@RavenwoodKeepWholeClass
+class LongArrayMultiStateCounter_ravenwood {
 
     /**
      * A reimplementation of {@link LongArrayMultiStateCounter}, only in
diff --git a/core/java/com/android/internal/os/LongMultiStateCounter.java b/core/java/com/android/internal/os/LongMultiStateCounter.java
index c386a86..ee855d5 100644
--- a/core/java/com/android/internal/os/LongMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongMultiStateCounter.java
@@ -60,7 +60,7 @@
  * @hide
  */
 @RavenwoodKeepWholeClass
-@RavenwoodRedirectionClass("LongMultiStateCounter_host")
+@RavenwoodRedirectionClass("LongMultiStateCounter_ravenwood")
 public final class LongMultiStateCounter implements Parcelable {
 
     private static NativeAllocationRegistry sRegistry;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java b/core/java/com/android/internal/os/LongMultiStateCounter_ravenwood.java
similarity index 97%
rename from ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
rename to core/java/com/android/internal/os/LongMultiStateCounter_ravenwood.java
index 1d95aa1..42db37f 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
+++ b/core/java/com/android/internal/os/LongMultiStateCounter_ravenwood.java
@@ -18,13 +18,15 @@
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
 
 import java.util.HashMap;
 
 /**
  * Native implementation substitutions for the LongMultiStateCounter class.
  */
-public class LongMultiStateCounter_host {
+@RavenwoodKeepWholeClass
+class LongMultiStateCounter_ravenwood {
 
     /**
      * A reimplementation of {@link com.android.internal.os.LongMultiStateCounter}, only in
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 73776f0..0e4e22b 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -172,6 +172,7 @@
         "android.security.flags-aconfig",
         "com.android.hardware.input.input-aconfig",
         "aconfig_trade_in_mode_flags",
+        "art-aconfig-flags",
         "ranging_aconfig_flags",
         "aconfig_settingslib_flags",
     ],
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0e4eb94..d09802a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8524,6 +8524,16 @@
                 android:protectionLevel="signature|privileged"
                 android:featureFlag="com.android.tradeinmode.flags.enable_trade_in_mode" />
 
+    <!-- @SystemApi
+        @FlaggedApi(com.android.art.flags.Flags.FLAG_EXECUTABLE_METHOD_FILE_OFFSETS)
+        Ability to read program metadata and attach dynamic instrumentation.
+        <p>Protection level: signature
+        @hide
+    -->
+    <permission android:name="android.permission.DYNAMIC_INSTRUMENTATION"
+                android:protectionLevel="signature"
+                android:featureFlag="com.android.art.flags.executable_method_file_offsets" />
+
     <!--
         @TestApi
         Signature permission reserved for testing. This should never be used to
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 7b96699..857df10 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -213,6 +213,8 @@
     <assign-permission name="android.permission.REGISTER_STATS_PULL_ATOM" uid="gpu_service" />
     <assign-permission name="android.permission.REGISTER_STATS_PULL_ATOM" uid="keystore" />
 
+    <assign-permission name="android.permission.DYNAMIC_INSTRUMENTATION" uid="uprobestats" />
+
     <split-permission name="android.permission.ACCESS_FINE_LOCATION">
         <new-permission name="android.permission.ACCESS_COARSE_LOCATION" />
     </split-permission>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
index 501bedd..c2755ef 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml
@@ -19,6 +19,7 @@
     android:layout_height="wrap_content"
     android:layout_width="wrap_content"
     android:orientation="vertical"
+    android:clipChildren="false"
     android:id="@+id/bubble_expanded_view">
 
     <com.android.wm.shell.bubbles.bar.BubbleBarHandleView
diff --git a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
index f1ecde4..7aca921 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_bar_menu_view.xml
@@ -14,20 +14,18 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.wm.shell.bubbles.bar.BubbleBarMenuView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<com.android.wm.shell.bubbles.bar.BubbleBarMenuView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
+    android:clipToPadding="false"
     android:minWidth="@dimen/bubble_bar_manage_menu_min_width"
     android:orientation="vertical"
-    android:elevation="@dimen/bubble_manage_menu_elevation"
-    android:paddingTop="@dimen/bubble_bar_manage_menu_padding_top"
-    android:paddingHorizontal="@dimen/bubble_bar_manage_menu_padding"
-    android:paddingBottom="@dimen/bubble_bar_manage_menu_padding"
-    android:clipToPadding="false">
+    android:visibility="invisible"
+    tools:visibility="visible">
 
     <LinearLayout
         android:id="@+id/bubble_bar_manage_menu_bubble_section"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index 2a50e4d0..272dfec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -222,7 +222,7 @@
 
             mHandleView.setAccessibilityDelegate(new HandleViewAccessibilityDelegate());
         }
-        mMenuViewController = new BubbleBarMenuViewController(mContext, this);
+        mMenuViewController = new BubbleBarMenuViewController(mContext, mHandleView, this);
         mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() {
             @Override
             public void onMenuVisibilityChanged(boolean visible) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
index e781c07..712e41b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
@@ -17,17 +17,18 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.graphics.Outline;
-import android.graphics.Path;
-import android.graphics.RectF;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewOutlineProvider;
 
 import androidx.annotation.ColorInt;
+import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.IntProperty;
 import androidx.core.content.ContextCompat;
 
 import com.android.wm.shell.R;
@@ -37,14 +38,33 @@
  */
 public class BubbleBarHandleView extends View {
     private static final long COLOR_CHANGE_DURATION = 120;
-    // Path used to draw the dots
-    private final Path mPath = new Path();
 
+    /** Custom property to set handle color. */
+    private static final IntProperty<BubbleBarHandleView> HANDLE_COLOR = new IntProperty<>(
+            "handleColor") {
+        @Override
+        public void setValue(BubbleBarHandleView bubbleBarHandleView, int color) {
+            bubbleBarHandleView.setHandleColor(color);
+        }
+
+        @Override
+        public Integer get(BubbleBarHandleView bubbleBarHandleView) {
+            return bubbleBarHandleView.getHandleColor();
+        }
+    };
+
+    @VisibleForTesting
+    final Paint mHandlePaint = new Paint();
     private final @ColorInt int mHandleLightColor;
     private final @ColorInt int mHandleDarkColor;
-    private @ColorInt int mCurrentColor;
+    private final ArgbEvaluator mArgbEvaluator = ArgbEvaluator.getInstance();
+    private final float mHandleHeight;
+    private final float mHandleWidth;
+    private float mCurrentHandleHeight;
+    private float mCurrentHandleWidth;
     @Nullable
     private ObjectAnimator mColorChangeAnim;
+    private @ColorInt int mRegionSamplerColor;
 
     public BubbleBarHandleView(Context context) {
         this(context, null /* attrs */);
@@ -61,30 +81,52 @@
     public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        final int handleHeight = getResources().getDimensionPixelSize(
+        mHandlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+        mHandlePaint.setStyle(Paint.Style.FILL);
+        mHandlePaint.setColor(0);
+        mHandleHeight = getResources().getDimensionPixelSize(
                 R.dimen.bubble_bar_expanded_view_handle_height);
+        mHandleWidth = getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_caption_width);
         mHandleLightColor = ContextCompat.getColor(getContext(),
                 R.color.bubble_bar_expanded_view_handle_light);
         mHandleDarkColor = ContextCompat.getColor(getContext(),
                 R.color.bubble_bar_expanded_view_handle_dark);
-
-        setClipToOutline(true);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                final int handleCenterY = view.getHeight() / 2;
-                final int handleTop = handleCenterY - handleHeight / 2;
-                final int handleBottom = handleTop + handleHeight;
-                final int radius = handleHeight / 2;
-                RectF handle = new RectF(/* left = */ 0, handleTop, view.getWidth(), handleBottom);
-                mPath.reset();
-                mPath.addRoundRect(handle, radius, radius, Path.Direction.CW);
-                outline.setPath(mPath);
-            }
-        });
+        mCurrentHandleHeight = mHandleHeight;
+        mCurrentHandleWidth = mHandleWidth;
         setContentDescription(getResources().getString(R.string.handle_text));
     }
 
+    private void setHandleColor(int color) {
+        mHandlePaint.setColor(color);
+        invalidate();
+    }
+
+    private int getHandleColor() {
+        return mHandlePaint.getColor();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        float handleLeft = (getWidth() - mCurrentHandleWidth) / 2;
+        float handleRight = handleLeft + mCurrentHandleWidth;
+        float handleCenterY = (float) getHeight() / 2;
+        float handleTop = (int) (handleCenterY - mCurrentHandleHeight / 2);
+        float handleBottom = handleTop + mCurrentHandleHeight;
+        float cornerRadius = mCurrentHandleHeight / 2;
+        canvas.drawRoundRect(handleLeft, handleTop, handleRight, handleBottom, cornerRadius,
+                cornerRadius, mHandlePaint);
+    }
+
+    /** Sets handle width, height and color. Does not change the layout properties */
+    private void setHandleProperties(float width, float height, int color) {
+        mCurrentHandleHeight = height;
+        mCurrentHandleWidth = width;
+        mHandlePaint.setColor(color);
+        invalidate();
+    }
+
     /**
      * Updates the handle color.
      *
@@ -94,15 +136,15 @@
      */
     public void updateHandleColor(boolean isRegionDark, boolean animated) {
         int newColor = isRegionDark ? mHandleLightColor : mHandleDarkColor;
-        if (newColor == mCurrentColor) {
+        if (newColor == mRegionSamplerColor) {
             return;
         }
+        mRegionSamplerColor = newColor;
         if (mColorChangeAnim != null) {
             mColorChangeAnim.cancel();
         }
-        mCurrentColor = newColor;
         if (animated) {
-            mColorChangeAnim = ObjectAnimator.ofArgb(this, "backgroundColor", newColor);
+            mColorChangeAnim = ObjectAnimator.ofArgb(this, HANDLE_COLOR, newColor);
             mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
@@ -112,7 +154,39 @@
             mColorChangeAnim.setDuration(COLOR_CHANGE_DURATION);
             mColorChangeAnim.start();
         } else {
-            setBackgroundColor(newColor);
+            setHandleColor(newColor);
         }
     }
+
+    /** Returns handle padding top. */
+    public int getHandlePaddingTop() {
+        return (getHeight() - getResources().getDimensionPixelSize(
+                R.dimen.bubble_bar_expanded_view_handle_height)) / 2;
+    }
+
+    /** Animates handle for the bubble menu. */
+    public void animateHandleForMenu(float progress, float widthDelta, float heightDelta,
+            int menuColor) {
+        float currentWidth = mHandleWidth + widthDelta * progress;
+        float currentHeight = mHandleHeight + heightDelta * progress;
+        int color = (int) mArgbEvaluator.evaluate(progress, mRegionSamplerColor, menuColor);
+        setHandleProperties(currentWidth, currentHeight, color);
+        setTranslationY(heightDelta * progress / 2);
+    }
+
+    /** Restores all the properties that were animated to the default values. */
+    public void restoreAnimationDefaults() {
+        setHandleProperties(mHandleWidth, mHandleHeight, mRegionSamplerColor);
+        setTranslationY(0);
+    }
+
+    /** Returns the handle height. */
+    public int getHandleHeight() {
+        return (int) mHandleHeight;
+    }
+
+    /** Returns the handle width. */
+    public int getHandleWidth() {
+        return (int) mHandleWidth;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
index 0ee20ef..99e2009 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuView.java
@@ -47,6 +47,10 @@
     private ImageView mBubbleIconView;
     private ImageView mBubbleDismissIconView;
     private TextView mBubbleTitleView;
+    // The animation has three stages. Each stage transition lasts until the animation ends. In
+    // stage 1, the title item content fades in. In stage 2, the background of the option items
+    // fades in. In stage 3, the option item content fades in.
+    private static final int SHOW_MENU_STAGES_COUNT = 3;
 
     public BubbleBarMenuView(Context context) {
         this(context, null /* attrs */);
@@ -97,6 +101,35 @@
         }
     }
 
+    /** Animates the menu from the specified start scale. */
+    public void animateFromStartScale(float currentScale, float progress) {
+        int menuItemElevation = getResources().getDimensionPixelSize(
+                R.dimen.bubble_manage_menu_elevation);
+        setScaleX(currentScale);
+        setScaleY(currentScale);
+        setAlphaForTitleViews(progress);
+        mBubbleSectionView.setElevation(menuItemElevation * progress);
+        float actionsBackgroundAlpha = Math.max(0,
+                (progress - (float) 1 / SHOW_MENU_STAGES_COUNT) * (SHOW_MENU_STAGES_COUNT - 1));
+        float actionItemsAlpha = Math.max(0,
+                (progress - (float) 2 / SHOW_MENU_STAGES_COUNT) * SHOW_MENU_STAGES_COUNT);
+        mActionsSectionView.setAlpha(actionsBackgroundAlpha);
+        mActionsSectionView.setElevation(menuItemElevation * actionsBackgroundAlpha);
+        setMenuItemViewsAlpha(actionItemsAlpha);
+    }
+
+    private void setAlphaForTitleViews(float alpha) {
+        mBubbleIconView.setAlpha(alpha);
+        mBubbleTitleView.setAlpha(alpha);
+        mBubbleDismissIconView.setAlpha(alpha);
+    }
+
+    private void setMenuItemViewsAlpha(float alpha) {
+        for (int i = mActionsSectionView.getChildCount() - 1; i >= 0; i--) {
+            mActionsSectionView.getChildAt(i).setAlpha(alpha);
+        }
+    }
+
     /** Update menu details with bubble info */
     void updateInfo(Bubble bubble) {
         if (bubble.getIcon() != null) {
@@ -153,6 +186,11 @@
         return mBubbleSectionView.getAlpha();
     }
 
+    /** Return title menu item height. */
+    public float getTitleItemHeight() {
+        return mBubbleSectionView.getHeight();
+    }
+
     /**
      * Menu action details used to create menu items
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
index 5148107..9dd0cae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarMenuViewController.java
@@ -15,6 +15,9 @@
  */
 package com.android.wm.shell.bubbles.bar;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -26,13 +29,10 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
-
+import com.android.app.animation.Interpolators;
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.R;
 import com.android.wm.shell.bubbles.Bubble;
-import com.android.wm.shell.shared.animation.PhysicsAnimator;
 
 import java.util.ArrayList;
 
@@ -40,22 +40,26 @@
  * Manages bubble bar expanded view menu presentation and animations
  */
 class BubbleBarMenuViewController {
-    private static final float MENU_INITIAL_SCALE = 0.5f;
+
+    private static final float WIDTH_SWAP_FRACTION = 0.4F;
+    private static final long MENU_ANIMATION_DURATION = 600;
+
     private final Context mContext;
     private final ViewGroup mRootView;
+    private final BubbleBarHandleView mHandleView;
     private @Nullable Listener mListener;
     private @Nullable Bubble mBubble;
     private @Nullable BubbleBarMenuView mMenuView;
     /** A transparent view used to intercept touches to collapse menu when presented */
     private @Nullable View mScrimView;
-    private @Nullable PhysicsAnimator<BubbleBarMenuView> mMenuAnimator;
-    private PhysicsAnimator.SpringConfig mMenuSpringConfig;
+    private @Nullable ValueAnimator mMenuAnimator;
 
-    BubbleBarMenuViewController(Context context, ViewGroup rootView) {
+
+    BubbleBarMenuViewController(Context context, BubbleBarHandleView handleView,
+            ViewGroup rootView) {
         mContext = context;
         mRootView = rootView;
-        mMenuSpringConfig = new PhysicsAnimator.SpringConfig(
-                SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+        mHandleView = handleView;
     }
 
     /** Tells if the menu is visible or being animated */
@@ -81,20 +85,21 @@
         if (mMenuView == null || mScrimView == null) {
             setupMenu();
         }
-        cancelAnimations();
-        mMenuView.setVisibility(View.VISIBLE);
-        mScrimView.setVisibility(View.VISIBLE);
-        Runnable endActions = () -> {
-            mMenuView.getChildAt(0).requestAccessibilityFocus();
-            if (mListener != null) {
-                mListener.onMenuVisibilityChanged(true /* isShown */);
+        runOnMenuIsMeasured(() -> {
+            mMenuView.setVisibility(View.VISIBLE);
+            mScrimView.setVisibility(View.VISIBLE);
+            Runnable endActions = () -> {
+                mMenuView.getChildAt(0).requestAccessibilityFocus();
+                if (mListener != null) {
+                    mListener.onMenuVisibilityChanged(true /* isShown */);
+                }
+            };
+            if (animated) {
+                animateTransition(true /* show */, endActions);
+            } else {
+                endActions.run();
             }
-        };
-        if (animated) {
-            animateTransition(true /* show */, endActions);
-        } else {
-            endActions.run();
-        }
+        });
     }
 
     /**
@@ -103,18 +108,30 @@
      */
     void hideMenu(boolean animated) {
         if (mMenuView == null || mScrimView == null) return;
-        cancelAnimations();
-        Runnable endActions = () -> {
-            mMenuView.setVisibility(View.GONE);
-            mScrimView.setVisibility(View.GONE);
-            if (mListener != null) {
-                mListener.onMenuVisibilityChanged(false /* isShown */);
+        runOnMenuIsMeasured(() -> {
+            Runnable endActions = () -> {
+                mHandleView.restoreAnimationDefaults();
+                mMenuView.setVisibility(View.GONE);
+                mScrimView.setVisibility(View.GONE);
+                mHandleView.setVisibility(View.VISIBLE);
+                if (mListener != null) {
+                    mListener.onMenuVisibilityChanged(false /* isShown */);
+                }
+            };
+            if (animated) {
+                animateTransition(false /* show */, endActions);
+            } else {
+                endActions.run();
             }
-        };
-        if (animated) {
-            animateTransition(false /* show */, endActions);
+        });
+    }
+
+    private void runOnMenuIsMeasured(Runnable action) {
+        if (mMenuView.getWidth() == 0 || mMenuView.getHeight() == 0) {
+            // the menu view is not yet measured, postpone showing the animation
+            mMenuView.post(() -> runOnMenuIsMeasured(action));
         } else {
-            endActions.run();
+            action.run();
         }
     }
 
@@ -125,24 +142,63 @@
      */
     private void animateTransition(boolean show, Runnable endActions) {
         if (mMenuView == null) return;
-        mMenuAnimator = PhysicsAnimator.getInstance(mMenuView);
-        mMenuAnimator.setDefaultSpringConfig(mMenuSpringConfig);
-        mMenuAnimator
-                .spring(DynamicAnimation.ALPHA, show ? 1f : 0f)
-                .spring(DynamicAnimation.SCALE_Y, show ? 1f : MENU_INITIAL_SCALE)
-                .withEndActions(() -> {
-                    mMenuAnimator = null;
-                    endActions.run();
-                })
-                .start();
+        float startValue = show ? 0 : 1;
+        if (mMenuAnimator != null && mMenuAnimator.isRunning()) {
+            startValue = (float) mMenuAnimator.getAnimatedValue();
+            mMenuAnimator.cancel();
+        }
+        ValueAnimator showMenuAnimation = ValueAnimator.ofFloat(startValue, show ? 1 : 0);
+        showMenuAnimation.setDuration(MENU_ANIMATION_DURATION);
+        showMenuAnimation.setInterpolator(Interpolators.EMPHASIZED);
+        showMenuAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mMenuAnimator = null;
+                endActions.run();
+            }
+        });
+        mMenuAnimator = showMenuAnimation;
+        setupAnimatorListener(showMenuAnimation);
+        showMenuAnimation.start();
     }
 
-    /** Cancel running animations */
-    private void cancelAnimations() {
-        if (mMenuAnimator != null) {
-            mMenuAnimator.cancel();
-            mMenuAnimator = null;
+    /** Setup listener that orchestrates the animation. */
+    private void setupAnimatorListener(ValueAnimator showMenuAnimation) {
+        // Getting views properties start values
+        int widthDiff = mMenuView.getWidth() - mHandleView.getHandleWidth();
+        int handleHeight = mHandleView.getHandleHeight();
+        float targetWidth = mHandleView.getHandleWidth() + widthDiff * WIDTH_SWAP_FRACTION;
+        float targetHeight = targetWidth * mMenuView.getTitleItemHeight() / mMenuView.getWidth();
+        int menuColor;
+        try (TypedArray ta = mContext.obtainStyledAttributes(new int[]{
+                com.android.internal.R.attr.materialColorSurfaceBright,
+        })) {
+            menuColor = ta.getColor(0, Color.WHITE);
         }
+        // Calculating deltas
+        float swapScale = targetWidth / mMenuView.getWidth();
+        float handleWidthDelta = targetWidth - mHandleView.getHandleWidth();
+        float handleHeightDelta = targetHeight - handleHeight;
+        // Setting update listener that will orchestrate the animation
+        showMenuAnimation.addUpdateListener(animator -> {
+            float animationProgress = (float) animator.getAnimatedValue();
+            boolean showHandle = animationProgress <= WIDTH_SWAP_FRACTION;
+            mHandleView.setVisibility(showHandle ? View.VISIBLE : View.GONE);
+            mMenuView.setVisibility(showHandle ? View.GONE : View.VISIBLE);
+            if (showHandle) {
+                float handleAnimationProgress = animationProgress / WIDTH_SWAP_FRACTION;
+                mHandleView.animateHandleForMenu(handleAnimationProgress, handleWidthDelta,
+                        handleHeightDelta, menuColor);
+            } else {
+                mMenuView.setTranslationY(mHandleView.getHandlePaddingTop());
+                mMenuView.setPivotY(0);
+                mMenuView.setPivotX((float) mMenuView.getWidth() / 2);
+                float menuAnimationProgress =
+                        (animationProgress - WIDTH_SWAP_FRACTION) / (1 - WIDTH_SWAP_FRACTION);
+                float currentMenuScale = swapScale + (1 - swapScale) * menuAnimationProgress;
+                mMenuView.animateFromStartScale(currentMenuScale, menuAnimationProgress);
+            }
+        });
     }
 
     /** Sets up and inflate menu views */
@@ -150,9 +206,6 @@
         // Menu view setup
         mMenuView = (BubbleBarMenuView) LayoutInflater.from(mContext).inflate(
                 R.layout.bubble_bar_menu_view, mRootView, false);
-        mMenuView.setAlpha(0f);
-        mMenuView.setPivotY(0f);
-        mMenuView.setScaleY(MENU_INITIAL_SCALE);
         mMenuView.setOnCloseListener(() -> hideMenu(true  /* animated */));
         if (mBubble != null) {
             mMenuView.updateInfo(mBubble);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index b27c428..0154d04 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -45,12 +45,17 @@
     }
 
     /**
-     * Set the callback when {@link PipTaskOrganizer#isInPip()} state is changed.
+     * Set the callback when isInPip state is changed.
      *
-     * @param callback The callback accepts the result of {@link PipTaskOrganizer#isInPip()}
-     *                 when it's changed.
+     * @param callback The callback accepts the state of isInPip when it's changed.
      */
-    default void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {}
+    default void addOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {}
+
+    /**
+     * Remove the callback when isInPip state is changed.
+     * @param callback The callback accepts the state of isInPip when it's changed.
+     */
+    default void removeOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {}
 
     /**
      * Called when showing Pip menu.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 7f61186..588b887 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -104,6 +104,7 @@
 import com.android.wm.shell.transition.Transitions;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
@@ -215,7 +216,7 @@
 
     private boolean mIsKeyguardShowingOrAnimating;
 
-    private Consumer<Boolean> mOnIsInPipStateChangedListener;
+    private final List<Consumer<Boolean>> mOnIsInPipStateChangedListeners = new ArrayList<>();
 
     @VisibleForTesting
     interface PipAnimationListener {
@@ -501,11 +502,11 @@
                     false /* saveRestoreSnapFraction */);
         });
         mPipTransitionState.addOnPipTransitionStateChangedListener((oldState, newState) -> {
-            if (mOnIsInPipStateChangedListener != null) {
-                final boolean wasInPip = PipTransitionState.isInPip(oldState);
-                final boolean nowInPip = PipTransitionState.isInPip(newState);
-                if (nowInPip != wasInPip) {
-                    mOnIsInPipStateChangedListener.accept(nowInPip);
+            final boolean wasInPip = PipTransitionState.isInPip(oldState);
+            final boolean nowInPip = PipTransitionState.isInPip(newState);
+            if (nowInPip != wasInPip) {
+                for (Consumer<Boolean> listener : mOnIsInPipStateChangedListeners) {
+                    listener.accept(nowInPip);
                 }
             }
         });
@@ -960,13 +961,19 @@
         mPipBoundsState.getLauncherState().setAppIconSizePx(iconSizePx);
     }
 
-    private void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
-        mOnIsInPipStateChangedListener = callback;
-        if (mOnIsInPipStateChangedListener != null) {
+    private void addOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+        if (callback != null) {
+            mOnIsInPipStateChangedListeners.add(callback);
             callback.accept(mPipTransitionState.isInPip());
         }
     }
 
+    private void removeOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+        if (callback != null) {
+            mOnIsInPipStateChangedListeners.remove(callback);
+        }
+    }
+
     private void setShelfHeightLocked(boolean visible, int height) {
         final int shelfHeight = visible ? height : 0;
         mPipBoundsState.setShelfVisibility(visible, shelfHeight);
@@ -1222,9 +1229,16 @@
         }
 
         @Override
-        public void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
+        public void addOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
             mMainExecutor.execute(() -> {
-                PipController.this.setOnIsInPipStateChangedListener(callback);
+                PipController.this.addOnIsInPipStateChangedListener(callback);
+            });
+        }
+
+        @Override
+        public void removeOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+            mMainExecutor.execute(() -> {
+                PipController.this.removeOnIsInPipStateChangedListener(callback);
             });
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index d3f537b..bc09183 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -21,6 +21,7 @@
 
 import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_PIP;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
@@ -66,6 +67,8 @@
 import com.android.wm.shell.sysui.ShellInit;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Consumer;
 
 /**
@@ -94,7 +97,7 @@
     private final PipTouchHandler mPipTouchHandler;
     private final ShellExecutor mMainExecutor;
     private final PipImpl mImpl;
-    private Consumer<Boolean> mOnIsInPipStateChangedListener;
+    private final List<Consumer<Boolean>> mOnIsInPipStateChangedListeners = new ArrayList<>();
 
     // Wrapper for making Binder calls into PiP animation listener hosted in launcher's Recents.
     private PipAnimationListener mPipRecentsAnimationListener;
@@ -413,13 +416,13 @@
                 if (mPipTransitionState.isInSwipePipToHomeTransition()) {
                     mPipTransitionState.resetSwipePipToHomeState();
                 }
-                if (mOnIsInPipStateChangedListener != null) {
-                    mOnIsInPipStateChangedListener.accept(true /* inPip */);
+                for (Consumer<Boolean> listener : mOnIsInPipStateChangedListeners) {
+                    listener.accept(true /* inPip */);
                 }
                 break;
             case PipTransitionState.EXITED_PIP:
-                if (mOnIsInPipStateChangedListener != null) {
-                    mOnIsInPipStateChangedListener.accept(false /* inPip */);
+                for (Consumer<Boolean> listener : mOnIsInPipStateChangedListeners) {
+                    listener.accept(false /* inPip */);
                 }
                 break;
         }
@@ -451,13 +454,19 @@
         mPipTransitionState.dump(pw, innerPrefix);
     }
 
-    private void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
-        mOnIsInPipStateChangedListener = callback;
-        if (mOnIsInPipStateChangedListener != null) {
+    private void addOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+        if (callback != null) {
+            mOnIsInPipStateChangedListeners.add(callback);
             callback.accept(mPipTransitionState.isInPip());
         }
     }
 
+    private void removeOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+        if (callback != null) {
+            mOnIsInPipStateChangedListeners.remove(callback);
+        }
+    }
+
     private void setLauncherAppIconSize(int iconSizePx) {
         mPipBoundsState.getLauncherState().setAppIconSizePx(iconSizePx);
     }
@@ -473,9 +482,16 @@
         public void onSystemUiStateChanged(boolean isSysUiStateValid, long flag) {}
 
         @Override
-        public void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
+        public void addOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
             mMainExecutor.execute(() -> {
-                PipController.this.setOnIsInPipStateChangedListener(callback);
+                PipController.this.addOnIsInPipStateChangedListener(callback);
+            });
+        }
+
+        @Override
+        public void removeOnIsInPipStateChangedListener(@NonNull Consumer<Boolean> callback) {
+            mMainExecutor.execute(() -> {
+                PipController.this.removeOnIsInPipStateChangedListener(callback);
             });
         }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
index d38b848..329a109 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleViewTest.java
@@ -16,9 +16,8 @@
 package com.android.wm.shell.bubbles.bar;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
-import android.graphics.drawable.ColorDrawable;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -47,10 +46,9 @@
     public void testUpdateHandleColor_lightBg() {
         mHandleView.updateHandleColor(false /* isRegionDark */, false /* animated */);
 
-        assertTrue(mHandleView.getClipToOutline());
-        assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
-        ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
-        assertEquals(bgDrawable.getColor(),
+        assertFalse(mHandleView.getClipToOutline());
+        int handleColor = mHandleView.mHandlePaint.getColor();
+        assertEquals(handleColor,
                 ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_dark));
     }
 
@@ -58,10 +56,9 @@
     public void testUpdateHandleColor_darkBg() {
         mHandleView.updateHandleColor(true /* isRegionDark */, false /* animated */);
 
-        assertTrue(mHandleView.getClipToOutline());
-        assertTrue(mHandleView.getBackground() instanceof ColorDrawable);
-        ColorDrawable bgDrawable = (ColorDrawable) mHandleView.getBackground();
-        assertEquals(bgDrawable.getColor(),
+        assertFalse(mHandleView.getClipToOutline());
+        int handleColor = mHandleView.mHandlePaint.getColor();
+        assertEquals(handleColor,
                 ContextCompat.getColor(mContext, R.color.bubble_bar_expanded_view_handle_light));
     }
 }
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 3eb99c3..da29c49 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -55,6 +55,7 @@
         "surface_control_input_receiver.cpp",
         "choreographer.cpp",
         "configuration.cpp",
+        "dynamic_instrumentation_manager.cpp",
         "hardware_buffer_jni.cpp",
         "input.cpp",
         "input_transfer_token.cpp",
@@ -100,6 +101,7 @@
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
         "android.os.flags-aconfig-cc",
+        "dynamic_instrumentation_manager_aidl-cpp",
         "libnativedisplay",
         "libfmq",
     ],
diff --git a/native/android/dynamic_instrumentation_manager.cpp b/native/android/dynamic_instrumentation_manager.cpp
new file mode 100644
index 0000000..d9bacb1
--- /dev/null
+++ b/native/android/dynamic_instrumentation_manager.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ADynamicInstrumentationManager"
+#include <android/dynamic_instrumentation_manager.h>
+#include <android/os/instrumentation/ExecutableMethodFileOffsets.h>
+#include <android/os/instrumentation/IDynamicInstrumentationManager.h>
+#include <android/os/instrumentation/MethodDescriptor.h>
+#include <android/os/instrumentation/TargetProcess.h>
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <mutex>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace android::dynamicinstrumentationmanager {
+
+// Global instance of IDynamicInstrumentationManager, service is obtained only on first use.
+static std::mutex mLock;
+static sp<os::instrumentation::IDynamicInstrumentationManager> mService;
+
+sp<os::instrumentation::IDynamicInstrumentationManager> getService() {
+    std::lock_guard<std::mutex> scoped_lock(mLock);
+    if (mService == nullptr || !IInterface::asBinder(mService)->isBinderAlive()) {
+        sp<IBinder> binder =
+                defaultServiceManager()->waitForService(String16("dynamic_instrumentation"));
+        mService = interface_cast<os::instrumentation::IDynamicInstrumentationManager>(binder);
+    }
+    return mService;
+}
+
+} // namespace android::dynamicinstrumentationmanager
+
+using namespace android;
+using namespace dynamicinstrumentationmanager;
+
+struct ADynamicInstrumentationManager_TargetProcess {
+    uid_t uid;
+    uid_t pid;
+    std::string processName;
+
+    ADynamicInstrumentationManager_TargetProcess(uid_t uid, pid_t pid, const char* processName)
+          : uid(uid), pid(pid), processName(processName) {}
+};
+
+ADynamicInstrumentationManager_TargetProcess* ADynamicInstrumentationManager_TargetProcess_create(
+        uid_t uid, pid_t pid, const char* processName) {
+    return new ADynamicInstrumentationManager_TargetProcess(uid, pid, processName);
+}
+
+void ADynamicInstrumentationManager_TargetProcess_destroy(
+        ADynamicInstrumentationManager_TargetProcess* instance) {
+    delete instance;
+}
+
+struct ADynamicInstrumentationManager_MethodDescriptor {
+    std::string fqcn;
+    std::string methodName;
+    std::vector<std::string> fqParameters;
+
+    ADynamicInstrumentationManager_MethodDescriptor(const char* fqcn, const char* methodName,
+                                                    const char* fullyQualifiedParameters[],
+                                                    size_t numParameters)
+          : fqcn(fqcn), methodName(methodName) {
+        std::vector<std::string> fqParameters;
+        fqParameters.reserve(numParameters);
+        std::copy_n(fullyQualifiedParameters, numParameters, std::back_inserter(fqParameters));
+        this->fqParameters = std::move(fqParameters);
+    }
+};
+
+ADynamicInstrumentationManager_MethodDescriptor*
+ADynamicInstrumentationManager_MethodDescriptor_create(const char* fullyQualifiedClassName,
+                                                       const char* methodName,
+                                                       const char* fullyQualifiedParameters[],
+                                                       size_t numParameters) {
+    return new ADynamicInstrumentationManager_MethodDescriptor(fullyQualifiedClassName, methodName,
+                                                               fullyQualifiedParameters,
+                                                               numParameters);
+}
+
+void ADynamicInstrumentationManager_MethodDescriptor_destroy(
+        ADynamicInstrumentationManager_MethodDescriptor* instance) {
+    delete instance;
+}
+
+struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets {
+    std::string containerPath;
+    uint64_t containerOffset;
+    uint64_t methodOffset;
+};
+
+ADynamicInstrumentationManager_ExecutableMethodFileOffsets*
+ADynamicInstrumentationManager_ExecutableMethodFileOffsets_create() {
+    return new ADynamicInstrumentationManager_ExecutableMethodFileOffsets();
+}
+
+const char* ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
+    return instance->containerPath.c_str();
+}
+
+uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
+    return instance->containerOffset;
+}
+
+uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
+    return instance->methodOffset;
+}
+
+void ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* instance) {
+    delete instance;
+}
+
+int32_t ADynamicInstrumentationManager_getExecutableMethodFileOffsets(
+        const ADynamicInstrumentationManager_TargetProcess* targetProcess,
+        const ADynamicInstrumentationManager_MethodDescriptor* methodDescriptor,
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets** out) {
+    android::os::instrumentation::TargetProcess targetProcessParcel;
+    targetProcessParcel.uid = targetProcess->uid;
+    targetProcessParcel.pid = targetProcess->pid;
+    targetProcessParcel.processName = targetProcess->processName;
+
+    android::os::instrumentation::MethodDescriptor methodDescriptorParcel;
+    methodDescriptorParcel.fullyQualifiedClassName = methodDescriptor->fqcn;
+    methodDescriptorParcel.methodName = methodDescriptor->methodName;
+    methodDescriptorParcel.fullyQualifiedParameters = methodDescriptor->fqParameters;
+
+    sp<os::instrumentation::IDynamicInstrumentationManager> service = getService();
+    if (service == nullptr) {
+        return INVALID_OPERATION;
+    }
+
+    std::optional<android::os::instrumentation::ExecutableMethodFileOffsets> offsets;
+    binder_status_t result =
+            service->getExecutableMethodFileOffsets(targetProcessParcel, methodDescriptorParcel,
+                                                    &offsets)
+                    .exceptionCode();
+    if (result != OK) {
+        return result;
+    }
+
+    if (offsets != std::nullopt) {
+        auto* value = new ADynamicInstrumentationManager_ExecutableMethodFileOffsets();
+        value->containerPath = offsets->containerPath;
+        value->containerOffset = offsets->containerOffset;
+        value->methodOffset = offsets->methodOffset;
+        *out = value;
+    } else {
+        *out = nullptr;
+    }
+
+    return result;
+}
\ No newline at end of file
diff --git a/native/android/include_platform/android/dynamic_instrumentation_manager.h b/native/android/include_platform/android/dynamic_instrumentation_manager.h
new file mode 100644
index 0000000..6c46288
--- /dev/null
+++ b/native/android/include_platform/android/dynamic_instrumentation_manager.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef __ADYNAMICINSTRUMENTATIONMANAGER_H__
+#define __ADYNAMICINSTRUMENTATIONMANAGER_H__
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+struct ADynamicInstrumentationManager_MethodDescriptor;
+typedef struct ADynamicInstrumentationManager_MethodDescriptor
+        ADynamicInstrumentationManager_MethodDescriptor;
+
+struct ADynamicInstrumentationManager_TargetProcess;
+typedef struct ADynamicInstrumentationManager_TargetProcess
+        ADynamicInstrumentationManager_TargetProcess;
+
+struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets;
+typedef struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets;
+
+/**
+ * Initializes an ADynamicInstrumentationManager_TargetProcess. Caller must clean up when they are
+ * done with ADynamicInstrumentationManager_TargetProcess_destroy.
+ *
+ * @param uid of targeted process.
+ * @param pid of targeted process.
+ * @param processName to disambiguate from corner cases that may arise from pid reuse.
+ */
+ADynamicInstrumentationManager_TargetProcess* _Nonnull
+        ADynamicInstrumentationManager_TargetProcess_create(
+                uid_t uid, pid_t pid, const char* _Nonnull processName) __INTRODUCED_IN(36);
+/**
+ * Clean up an ADynamicInstrumentationManager_TargetProcess.
+ *
+ * @param instance returned from ADynamicInstrumentationManager_TargetProcess_create.
+ */
+void ADynamicInstrumentationManager_TargetProcess_destroy(
+        ADynamicInstrumentationManager_TargetProcess* _Nonnull instance) __INTRODUCED_IN(36);
+
+/**
+ * Initializes an ADynamicInstrumentationManager_MethodDescriptor. Caller must clean up when they
+ * are done with ADynamicInstrumentationManager_MethodDescriptor_Destroy.
+ *
+ * @param fullyQualifiedClassName fqcn of class containing the method.
+ * @param methodName
+ * @param fullyQualifiedParameters fqcn of parameters of the method's signature, or e.g. "int" for
+ *                                 primitives.
+ * @param numParameters length of `fullyQualifiedParameters` array.
+ */
+ADynamicInstrumentationManager_MethodDescriptor* _Nonnull
+        ADynamicInstrumentationManager_MethodDescriptor_create(
+                const char* _Nonnull fullyQualifiedClassName, const char* _Nonnull methodName,
+                const char* _Nonnull fullyQualifiedParameters[_Nonnull], size_t numParameters)
+                __INTRODUCED_IN(36);
+/**
+ * Clean up an ADynamicInstrumentationManager_MethodDescriptor.
+ *
+ * @param instance returned from ADynamicInstrumentationManager_MethodDescriptor_create.
+ */
+void ADynamicInstrumentationManager_MethodDescriptor_destroy(
+        ADynamicInstrumentationManager_MethodDescriptor* _Nonnull instance) __INTRODUCED_IN(36);
+
+/**
+ * Get the containerPath calculated by
+ * ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @param instance created with ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @return The OS path of the containing file.
+ */
+const char* _Nullable ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* _Nonnull instance)
+        __INTRODUCED_IN(36);
+/**
+ * Get the containerOffset calculated by
+ * ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @param instance created with ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @return The offset of the containing file within the process' memory.
+ */
+uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* _Nonnull instance)
+        __INTRODUCED_IN(36);
+/**
+ * Get the methodOffset calculated by ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @param instance created with ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ * @return The offset of the method within the containing file.
+ */
+uint64_t ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* _Nonnull instance)
+        __INTRODUCED_IN(36);
+/**
+ * Clean up an ADynamicInstrumentationManager_ExecutableMethodFileOffsets.
+ *
+ * @param instance returned from ADynamicInstrumentationManager_getExecutableMethodFileOffsets.
+ */
+void ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy(
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* _Nonnull instance)
+        __INTRODUCED_IN(36);
+/**
+ * Provides ART metadata about the described java method within the target process.
+ *
+ * @param targetProcess describes for which process the data is requested.
+ * @param methodDescriptor describes the targeted method.
+ * @param out will be populated with the data if successful. A nullptr combined
+ *        with an OK status means that the program method is defined, but the offset
+ *        info was unavailable because it is not AOT compiled.
+ * @return status indicating success or failure. The values correspond to the `binder_exception_t`
+ *         enum values from <android/binder_status.h>.
+ */
+int32_t ADynamicInstrumentationManager_getExecutableMethodFileOffsets(
+        const ADynamicInstrumentationManager_TargetProcess* _Nonnull targetProcess,
+        const ADynamicInstrumentationManager_MethodDescriptor* _Nonnull methodDescriptor,
+        ADynamicInstrumentationManager_ExecutableMethodFileOffsets* _Nonnull* _Nullable out)
+        __INTRODUCED_IN(36);
+
+__END_DECLS
+
+#endif // __ADYNAMICINSTRUMENTATIONMANAGER_H__
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index b025cb8..a046057 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -4,6 +4,15 @@
     AActivityManager_removeUidImportanceListener; # systemapi introduced=31
     AActivityManager_isUidActive; # systemapi introduced=31
     AActivityManager_getUidImportance; # systemapi introduced=31
+    ADynamicInstrumentationManager_TargetProcess_create; # systemapi
+    ADynamicInstrumentationManager_TargetProcess_destroy; # systemapi
+    ADynamicInstrumentationManager_MethodDescriptor_create; # systemapi
+    ADynamicInstrumentationManager_MethodDescriptor_destroy; # systemapi
+    ADynamicInstrumentationManager_getExecutableMethodFileOffsets; # systemapi
+    ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath; # systemapi
+    ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset; # systemapi
+    ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset; # systemapi
+    ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy; # systemapi
     AAssetDir_close;
     AAssetDir_getNextFileName;
     AAssetDir_rewind;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 24b91f9..0724410 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -959,6 +959,9 @@
     <!-- Permission required for CTS test - CtsTelephonyTestCases -->
     <uses-permission android:name="android.permission.READ_BASIC_PHONE_STATE" />
 
+    <!-- Permission required for ExecutableMethodFileOffsetsTest -->
+    <uses-permission android:name="android.permission.DYNAMIC_INSTRUMENTATION" />
+
     <application
         android:label="@string/app_label"
         android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index f49693a..80ac2fc 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -696,7 +696,8 @@
                 TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
                         mTaskStackListener);
                 DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
-                mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null));
+                mPipOptional.ifPresent(pip -> pip.removeOnIsInPipStateChangedListener(
+                        mOnIsInPipStateChangedListener));
 
                 try {
                     mWindowManagerService.unregisterSystemGestureExclusionListener(
@@ -720,7 +721,7 @@
                         mTaskStackListener);
                 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                         mUiThreadContext.getExecutor()::execute, mOnPropertiesChangedListener);
-                mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(
+                mPipOptional.ifPresent(pip -> pip.addOnIsInPipStateChangedListener(
                         mOnIsInPipStateChangedListener));
                 mDesktopModeOptional.ifPresent(
                         dm -> dm.addDesktopGestureExclusionRegionListener(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogComponent.kt
index 9440a93..fb15795 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogComponent.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.volume.dialog.dagger
 
+import com.android.systemui.volume.dialog.dagger.module.VolumeDialogModule
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
 import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderComponent
@@ -28,7 +29,7 @@
  * [com.android.systemui.volume.dialog.VolumeDialogPlugin] and lives alongside it.
  */
 @VolumeDialogScope
-@Subcomponent(modules = [])
+@Subcomponent(modules = [VolumeDialogModule::class])
 interface VolumeDialogComponent {
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/module/VolumeDialogModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/module/VolumeDialogModule.kt
new file mode 100644
index 0000000..025e269
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/module/VolumeDialogModule.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.dagger.module
+
+import com.android.systemui.volume.dialog.ringer.data.repository.VolumeDialogRingerFeedbackRepository
+import com.android.systemui.volume.dialog.ringer.data.repository.VolumeDialogRingerFeedbackRepositoryImpl
+import dagger.Binds
+import dagger.Module
+
+/** Dagger module for volume dialog code in the volume package */
+@Module
+interface VolumeDialogModule {
+
+    @Binds
+    fun bindVolumeDialogRingerFeedbackRepository(
+        ringerFeedbackRepository: VolumeDialogRingerFeedbackRepositoryImpl
+    ): VolumeDialogRingerFeedbackRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepository.kt
new file mode 100644
index 0000000..263972b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepository.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.data.repository
+
+import android.content.Context
+import com.android.systemui.Prefs
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+interface VolumeDialogRingerFeedbackRepository {
+
+    /** gets number of shown toasts */
+    suspend fun getToastCount(): Int
+
+    /** updates number of shown toasts */
+    suspend fun updateToastCount(toastCount: Int)
+}
+
+class VolumeDialogRingerFeedbackRepositoryImpl
+@Inject
+constructor(
+    @Application private val applicationContext: Context,
+    @Background val backgroundDispatcher: CoroutineDispatcher,
+) : VolumeDialogRingerFeedbackRepository {
+
+    override suspend fun getToastCount(): Int =
+        withContext(backgroundDispatcher) {
+            return@withContext Prefs.getInt(
+                applicationContext,
+                Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT,
+                0,
+            )
+        }
+
+    override suspend fun updateToastCount(toastCount: Int) {
+        withContext(backgroundDispatcher) {
+            Prefs.putInt(applicationContext, Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT, toastCount + 1)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt
index 281e57f..b83613b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.plugins.VolumeDialogController
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
 import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogStateInteractor
+import com.android.systemui.volume.dialog.ringer.data.repository.VolumeDialogRingerFeedbackRepository
 import com.android.systemui.volume.dialog.ringer.shared.model.VolumeDialogRingerModel
 import com.android.systemui.volume.dialog.shared.model.VolumeDialogStateModel
 import javax.inject.Inject
@@ -45,6 +46,7 @@
     volumeDialogStateInteractor: VolumeDialogStateInteractor,
     private val controller: VolumeDialogController,
     private val audioSystemRepository: AudioSystemRepository,
+    private val ringerFeedbackRepository: VolumeDialogRingerFeedbackRepository,
 ) {
 
     val ringerModel: Flow<VolumeDialogRingerModel> =
@@ -84,4 +86,12 @@
     fun scheduleTouchFeedback() {
         controller.scheduleTouchFeedback()
     }
+
+    suspend fun getToastCount(): Int {
+        return ringerFeedbackRepository.getToastCount()
+    }
+
+    suspend fun updateToastCount(toastCount: Int) {
+        ringerFeedbackRepository.updateToastCount(toastCount)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
index d4da226..e040638 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
@@ -16,17 +16,23 @@
 
 package com.android.systemui.volume.dialog.ringer.ui.viewmodel
 
+import android.content.Context
 import android.media.AudioAttributes
 import android.media.AudioManager.RINGER_MODE_NORMAL
 import android.media.AudioManager.RINGER_MODE_SILENT
 import android.media.AudioManager.RINGER_MODE_VIBRATE
 import android.os.VibrationEffect
+import android.widget.Toast
+import com.android.internal.R as internalR
+import com.android.settingslib.Utils
 import com.android.settingslib.volume.shared.model.RingerMode
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.volume.Events
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
+import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor
 import com.android.systemui.volume.dialog.ringer.domain.VolumeDialogRingerInteractor
 import com.android.systemui.volume.dialog.ringer.shared.model.VolumeDialogRingerModel
 import com.android.systemui.volume.dialog.shared.VolumeDialogLogger
@@ -40,26 +46,37 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+
+private const val SHOW_RINGER_TOAST_COUNT = 12
 
 class VolumeDialogRingerDrawerViewModel
 @AssistedInject
 constructor(
+    @Application private val applicationContext: Context,
     @VolumeDialog private val coroutineScope: CoroutineScope,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val interactor: VolumeDialogRingerInteractor,
     private val vibrator: VibratorHelper,
     private val volumeDialogLogger: VolumeDialogLogger,
+    private val visibilityInteractor: VolumeDialogVisibilityInteractor,
 ) {
 
     private val drawerState = MutableStateFlow<RingerDrawerState>(RingerDrawerState.Initial)
 
     val ringerViewModel: StateFlow<RingerViewModelState> =
         combine(interactor.ringerModel, drawerState) { ringerModel, state ->
+                level = ringerModel.level
+                levelMax = ringerModel.levelMax
                 ringerModel.toViewModel(state)
             }
             .flowOn(backgroundDispatcher)
             .stateIn(coroutineScope, SharingStarted.Eagerly, RingerViewModelState.Unavailable)
 
+    // Level and Maximum level of Ring Stream.
+    private var level = -1
+    private var levelMax = -1
+
     // Vibration attributes.
     private val sonificiationVibrationAttributes =
         AudioAttributes.Builder()
@@ -71,8 +88,10 @@
         if (drawerState.value is RingerDrawerState.Open) {
             Events.writeEvent(Events.EVENT_RINGER_TOGGLE, ringerMode.value)
             provideTouchFeedback(ringerMode)
+            maybeShowToast(ringerMode)
             interactor.setRingerMode(ringerMode)
         }
+        visibilityInteractor.resetDismissTimeout()
         drawerState.value =
             when (drawerState.value) {
                 is RingerDrawerState.Initial -> {
@@ -201,6 +220,46 @@
         }
     }
 
+    private fun maybeShowToast(ringerMode: RingerMode) {
+        coroutineScope.launch {
+            val seenToastCount = interactor.getToastCount()
+            if (seenToastCount > SHOW_RINGER_TOAST_COUNT) {
+                return@launch
+            }
+
+            val toastText =
+                when (ringerMode.value) {
+                    RINGER_MODE_NORMAL -> {
+                        if (level != -1 && levelMax != -1) {
+                            applicationContext.getString(
+                                R.string.volume_dialog_ringer_guidance_ring,
+                                Utils.formatPercentage(level.toLong(), levelMax.toLong()),
+                            )
+                        } else {
+                            null
+                        }
+                    }
+
+                    RINGER_MODE_SILENT ->
+                        applicationContext.getString(
+                            internalR.string.volume_dialog_ringer_guidance_silent
+                        )
+
+                    RINGER_MODE_VIBRATE ->
+                        applicationContext.getString(
+                            internalR.string.volume_dialog_ringer_guidance_vibrate
+                        )
+
+                    else ->
+                        applicationContext.getString(
+                            internalR.string.volume_dialog_ringer_guidance_vibrate
+                        )
+                }
+            toastText?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_SHORT).show() }
+            interactor.updateToastCount(seenToastCount)
+        }
+    }
+
     @AssistedFactory
     interface Factory {
         fun create(): VolumeDialogRingerDrawerViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 8039e00..073781e 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -271,6 +271,12 @@
                         // No op.
                     }
                 }, mSysUiMainExecutor);
+        pip.addOnIsInPipStateChangedListener((isInPip) -> {
+            if (!isInPip) {
+                mSysUiState.setFlag(SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING, false)
+                        .commitUpdate(mDisplayTracker.getDefaultDisplayId());
+            }
+        });
         mSysUiState.addCallback(sysUiStateFlag -> {
             mIsSysUiStateValid = (sysUiStateFlag & INVALID_SYSUI_STATE_MASK) == 0;
             pip.onSystemUiStateChanged(mIsSysUiStateValid, sysUiStateFlag);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/FakeVolumeDialogRingerFeedbackRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/FakeVolumeDialogRingerFeedbackRepository.kt
new file mode 100644
index 0000000..d42de1e
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/FakeVolumeDialogRingerFeedbackRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.data.repository
+
+class FakeVolumeDialogRingerFeedbackRepository : VolumeDialogRingerFeedbackRepository {
+
+    private var seenToastCount = 0
+
+    override suspend fun getToastCount(): Int {
+        return seenToastCount
+    }
+
+    override suspend fun updateToastCount(toastCount: Int) {
+        seenToastCount = toastCount
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepositoryKosmos.kt
new file mode 100644
index 0000000..44371b4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/data/repository/VolumeDialogRingerFeedbackRepositoryKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.fakeVolumeDialogRingerFeedbackRepository by
+    Kosmos.Fixture { FakeVolumeDialogRingerFeedbackRepository() }
+val Kosmos.volumeDialogRingerFeedbackRepository by
+    Kosmos.Fixture { fakeVolumeDialogRingerFeedbackRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt
index 1addd91..a494d04 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.plugins.volumeDialogController
 import com.android.systemui.volume.data.repository.audioSystemRepository
 import com.android.systemui.volume.dialog.domain.interactor.volumeDialogStateInteractor
+import com.android.systemui.volume.dialog.ringer.data.repository.fakeVolumeDialogRingerFeedbackRepository
 
 val Kosmos.volumeDialogRingerInteractor by
     Kosmos.Fixture {
@@ -29,5 +30,6 @@
             volumeDialogStateInteractor = volumeDialogStateInteractor,
             controller = volumeDialogController,
             audioSystemRepository = audioSystemRepository,
+            ringerFeedbackRepository = fakeVolumeDialogRingerFeedbackRepository,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
index db1c01a..c8ba551 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
@@ -16,20 +16,24 @@
 
 package com.android.systemui.volume.dialog.ringer.ui.viewmodel
 
+import android.content.applicationContext
 import com.android.systemui.haptics.vibratorHelper
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.volume.dialog.domain.interactor.volumeDialogVisibilityInteractor
 import com.android.systemui.volume.dialog.ringer.domain.volumeDialogRingerInteractor
 import com.android.systemui.volume.dialog.shared.volumeDialogLogger
 
 val Kosmos.volumeDialogRingerDrawerViewModel by
     Kosmos.Fixture {
         VolumeDialogRingerDrawerViewModel(
+            applicationContext = applicationContext,
             backgroundDispatcher = testDispatcher,
             coroutineScope = applicationCoroutineScope,
             interactor = volumeDialogRingerInteractor,
             vibrator = vibratorHelper,
             volumeDialogLogger = volumeDialogLogger,
+            visibilityInteractor = volumeDialogVisibilityInteractor,
         )
     }
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 82be2c0..c196a09 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -15,7 +15,9 @@
 com.android.internal.os.BatteryStatsHistoryIterator
 com.android.internal.os.Clock
 com.android.internal.os.LongArrayMultiStateCounter
+com.android.internal.os.LongArrayMultiStateCounter_ravenwood
 com.android.internal.os.LongMultiStateCounter
+com.android.internal.os.LongMultiStateCounter_ravenwood
 com.android.internal.os.MonotonicClock
 com.android.internal.os.PowerProfile
 com.android.internal.os.PowerStats
@@ -143,6 +145,7 @@
 android.os.Looper
 android.os.Message
 android.os.MessageQueue
+android.os.MessageQueue_ravenwood
 android.os.PackageTagsList
 android.os.Parcel
 android.os.ParcelFileDescriptor
@@ -235,6 +238,7 @@
 android.database.CursorIndexOutOfBoundsException
 android.database.CursorJoiner
 android.database.CursorWindow
+android.database.CursorWindow_ravenwood
 android.database.CursorWrapper
 android.database.DataSetObservable
 android.database.DataSetObserver
@@ -370,4 +374,3 @@
 com.android.server.compat.*
 com.android.internal.compat.*
 android.app.AppCompatCallbacks
-
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 974cba2..86d3ee6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -5071,6 +5071,11 @@
     @EnforcePermission(MANAGE_ACCESSIBILITY)
     public boolean isAccessibilityServiceWarningRequired(AccessibilityServiceInfo info) {
         isAccessibilityServiceWarningRequired_enforcePermission();
+        if (info == null) {
+            Log.e(LOG_TAG, "Called isAccessibilityServiceWarningRequired with null service info");
+            return true;
+        }
+
         final ComponentName componentName = info.getComponentName();
 
         // Warning is not required if the service is already enabled.
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 3ccad160..7f482ac 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -158,6 +158,7 @@
         "android.hardware.gnss-V2-java",
         "android.hardware.vibrator-V3-java",
         "app-compat-annotations",
+        "art_exported_aconfig_flags_lib",
         "framework-tethering.stubs.module_lib",
         "keepanno-annotations",
         "service-art.stubs.system_server",
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index f2e2f65..5b4c033 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -1001,7 +1001,7 @@
             try {
                 // Create an AIDL callback that can callback onHotplugEvent
                 mHdmiConnection.setCallback(new HdmiConnectionCallbackAidl(callback));
-            } catch (RemoteException e) {
+            } catch (RemoteException | NullPointerException e) {
                 HdmiLogger.error("Couldn't initialise tv.hdmi callback : ", e);
             }
         }
@@ -1134,7 +1134,7 @@
                     i++;
                 }
                 return hdmiPortInfo;
-            } catch (RemoteException e) {
+            } catch (RemoteException | NullPointerException e) {
                 HdmiLogger.error("Failed to get port information : ", e);
                 return null;
             }
@@ -1144,7 +1144,7 @@
         public boolean nativeIsConnected(int port) {
             try {
                 return mHdmiConnection.isConnected(port);
-            } catch (RemoteException e) {
+            } catch (RemoteException | NullPointerException e) {
                 HdmiLogger.error("Failed to get connection info : ", e);
                 return false;
             }
@@ -1158,7 +1158,7 @@
                 HdmiLogger.error(
                         "Could not set HPD signal type for portId " + portId + " to " + signal
                                 + ". Error: ", sse.errorCode);
-            } catch (RemoteException e) {
+            } catch (RemoteException | NullPointerException e) {
                 HdmiLogger.error(
                         "Could not set HPD signal type for portId " + portId + " to " + signal
                                 + ". Exception: ", e);
@@ -1169,7 +1169,7 @@
         public int nativeGetHpdSignalType(int portId) {
             try {
                 return mHdmiConnection.getHpdSignal(portId);
-            } catch (RemoteException e) {
+            } catch (RemoteException | NullPointerException e) {
                 HdmiLogger.error(
                         "Could not get HPD signal type for portId " + portId + ". Exception: ", e);
                 return Constants.HDMI_HPD_TYPE_PHYSICAL;
diff --git a/services/core/java/com/android/server/os/instrumentation/DynamicInstrumentationManagerService.java b/services/core/java/com/android/server/os/instrumentation/DynamicInstrumentationManagerService.java
new file mode 100644
index 0000000..8ec7160
--- /dev/null
+++ b/services/core/java/com/android/server/os/instrumentation/DynamicInstrumentationManagerService.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+import static android.Manifest.permission.DYNAMIC_INSTRUMENTATION;
+import static android.content.Context.DYNAMIC_INSTRUMENTATION_SERVICE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.PermissionManuallyEnforced;
+import android.content.Context;
+import android.os.instrumentation.ExecutableMethodFileOffsets;
+import android.os.instrumentation.IDynamicInstrumentationManager;
+import android.os.instrumentation.MethodDescriptor;
+import android.os.instrumentation.TargetProcess;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemService;
+
+import dalvik.system.VMDebug;
+
+import java.lang.reflect.Method;
+
+/**
+ * System private implementation of the {@link IDynamicInstrumentationManager interface}.
+ */
+public class DynamicInstrumentationManagerService extends SystemService {
+    public DynamicInstrumentationManagerService(@NonNull Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(DYNAMIC_INSTRUMENTATION_SERVICE, new BinderService());
+    }
+
+    private final class BinderService extends IDynamicInstrumentationManager.Stub {
+        @Override
+        @PermissionManuallyEnforced
+        public @Nullable ExecutableMethodFileOffsets getExecutableMethodFileOffsets(
+                @NonNull TargetProcess targetProcess, @NonNull MethodDescriptor methodDescriptor) {
+            if (!com.android.art.flags.Flags.executableMethodFileOffsets()) {
+                throw new UnsupportedOperationException();
+            }
+            getContext().enforceCallingOrSelfPermission(
+                    DYNAMIC_INSTRUMENTATION, "Caller must have DYNAMIC_INSTRUMENTATION permission");
+
+            if (targetProcess.processName == null
+                    || !targetProcess.processName.equals("system_server")) {
+                throw new UnsupportedOperationException(
+                        "system_server is the only supported target process");
+            }
+
+            Method method = parseMethodDescriptor(
+                    getClass().getClassLoader(), methodDescriptor);
+            VMDebug.ExecutableMethodFileOffsets location =
+                    VMDebug.getExecutableMethodFileOffsets(method);
+
+            if (location == null) {
+                return null;
+            }
+
+            ExecutableMethodFileOffsets ret = new ExecutableMethodFileOffsets();
+            ret.containerPath = location.getContainerPath();
+            ret.containerOffset = location.getContainerOffset();
+            ret.methodOffset = location.getMethodOffset();
+            return ret;
+        }
+    }
+
+    @VisibleForTesting
+    static Method parseMethodDescriptor(ClassLoader classLoader,
+            @NonNull MethodDescriptor descriptor) {
+        try {
+            Class<?> javaClass = classLoader.loadClass(descriptor.fullyQualifiedClassName);
+            Class<?>[] parameters = new Class[descriptor.fullyQualifiedParameters.length];
+            for (int i = 0; i < descriptor.fullyQualifiedParameters.length; i++) {
+                String typeName = descriptor.fullyQualifiedParameters[i];
+                boolean isArrayType = typeName.endsWith("[]");
+                if (isArrayType) {
+                    typeName = typeName.substring(0, typeName.length() - 2);
+                }
+                switch (typeName) {
+                    case "boolean":
+                        parameters[i] = isArrayType ? boolean.class.arrayType() : boolean.class;
+                        break;
+                    case "byte":
+                        parameters[i] = isArrayType ? byte.class.arrayType() : byte.class;
+                        break;
+                    case "char":
+                        parameters[i] = isArrayType ? char.class.arrayType() : char.class;
+                        break;
+                    case "short":
+                        parameters[i] = isArrayType ? short.class.arrayType() : short.class;
+                        break;
+                    case "int":
+                        parameters[i] = isArrayType ? int.class.arrayType() : int.class;
+                        break;
+                    case "long":
+                        parameters[i] = isArrayType ? long.class.arrayType() : long.class;
+                        break;
+                    case "float":
+                        parameters[i] = isArrayType ? float.class.arrayType() : float.class;
+                        break;
+                    case "double":
+                        parameters[i] = isArrayType ? double.class.arrayType() : double.class;
+                        break;
+                    default:
+                        parameters[i] = isArrayType ? classLoader.loadClass(typeName).arrayType()
+                                : classLoader.loadClass(typeName);
+                }
+            }
+
+            return javaClass.getDeclaredMethod(descriptor.methodName, parameters);
+        } catch (ClassNotFoundException | NoSuchMethodException e) {
+            throw new IllegalArgumentException(
+                    "The specified method cannot be found. Is this descriptor valid? "
+                            + descriptor, e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index af2bb17..d538bb8 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -265,6 +265,7 @@
 
         @Override
         public void handleMessage(Message msg) {
+            Slog.d(TAG, "Package event received: " + msg.what);
             switch (msg.what) {
                 case MSG_USAGE_EVENT_RECEIVED:
                     mService.handleUsageEvent(
@@ -326,6 +327,8 @@
             return;
         }
 
+        Slog.d(TAG, "handlePackageAdd: adding " + packageName + " from "
+            + userId + " and notifying callbacks");
         initBackgroundInstalledPackages();
         mBackgroundInstalledPackages.add(userId, packageName);
         mCallbackHelper.notifyAllCallbacks(userId, packageName, INSTALL_EVENT_TYPE_INSTALL);
@@ -364,7 +367,11 @@
     // ADB sets installerPackageName to null, this creates a loophole to bypass BIC which will be
     // addressed with b/265203007
     private boolean installedByAdb(String initiatingPackageName) {
-        return PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName);
+        if(PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName)) {
+            Slog.d(TAG, "handlePackageAdd: is installed by ADB, skipping");
+            return true;
+        }
+        return false;
     }
 
     private boolean wasForegroundInstallation(
@@ -407,6 +414,7 @@
         if (mBackgroundInstalledPackages.contains(userId, packageName)) {
             mCallbackHelper.notifyAllCallbacks(userId, packageName, INSTALL_EVENT_TYPE_UNINSTALL);
         }
+        Slog.d(TAG, "handlePackageRemove: removing " + packageName + " from " + userId);
         mBackgroundInstalledPackages.remove(userId, packageName);
         writeBackgroundInstalledPackagesToDisk();
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3805c02..221b848 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -205,6 +205,7 @@
 import com.android.server.os.DeviceIdentifiersPolicyService;
 import com.android.server.os.NativeTombstoneManagerService;
 import com.android.server.os.SchedulingPolicyService;
+import com.android.server.os.instrumentation.DynamicInstrumentationManagerService;
 import com.android.server.pdb.PersistentDataBlockService;
 import com.android.server.people.PeopleService;
 import com.android.server.permission.access.AccessCheckingService;
@@ -2890,6 +2891,13 @@
         mSystemServiceManager.startService(TracingServiceProxy.class);
         t.traceEnd();
 
+        // UprobeStats DynamicInstrumentationManager
+        if (com.android.art.flags.Flags.executableMethodFileOffsets()) {
+            t.traceBegin("StartDynamicInstrumentationManager");
+            mSystemServiceManager.startService(DynamicInstrumentationManagerService.class);
+            t.traceEnd();
+        }
+
         // It is now time to start up the app processes...
 
         t.traceBegin("MakeLockSettingsServiceReady");
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/Android.bp b/services/tests/DynamicInstrumentationManagerServiceTests/Android.bp
new file mode 100644
index 0000000..2c2e5fd
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2024 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 {
+    // 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"],
+    default_team: "trendy_team_system_performance",
+}
+
+android_test {
+    name: "DynamicInstrumentationManagerServiceTests",
+    srcs: ["src/**/*.java"],
+
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.runner",
+        "hamcrest-library",
+        "platform-test-annotations",
+        "services.core",
+        "testables",
+        "truth",
+    ],
+
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: [
+        "device-tests",
+    ],
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/AndroidManifest.xml b/services/tests/DynamicInstrumentationManagerServiceTests/AndroidManifest.xml
new file mode 100644
index 0000000..4913d70
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.os.instrumentation" >
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.server.os.instrumentation"
+        android:label="DynamicInstrumentationmanagerService Unit Tests"/>
+</manifest>
\ No newline at end of file
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/TEST_MAPPING b/services/tests/DynamicInstrumentationManagerServiceTests/TEST_MAPPING
new file mode 100644
index 0000000..33defed
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+      {
+          "name": "DynamicInstrumentationManagerServiceTests"
+      }
+  ]
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClass.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClass.java
new file mode 100644
index 0000000..04073fa
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClass.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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;
+
+public abstract class TestAbstractClass {
+    abstract void abstractMethod();
+
+    void concreteMethod() {
+    }
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClassImpl.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClassImpl.java
new file mode 100644
index 0000000..2c25e7a5
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestAbstractClassImpl.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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;
+
+public class TestAbstractClassImpl extends TestAbstractClass {
+    @Override
+    void abstractMethod() {
+    }
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestClass.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestClass.java
new file mode 100644
index 0000000..085f595
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestClass.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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;
+
+public class TestClass {
+    void primitiveParams(boolean a, boolean[] b, byte c, byte[] d, char e, char[] f, short g,
+            short[] h, int i, int[] j, long k, long[] l, float m, float[] n, double o, double[] p) {
+    }
+
+    void classParams(String a, String[] b) {
+    }
+
+    private void privateMethod() {
+    }
+
+    /**
+     * docs!
+     */
+    public void publicMethod() {
+    }
+
+    private static class InnerClass {
+        private void innerMethod(InnerClass arg, InnerClass[] argArray) {
+        }
+    }
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterface.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterface.java
new file mode 100644
index 0000000..7af4f25
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterface.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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;
+
+/**
+ * docs!
+ */
+public interface TestInterface {
+    /**
+     * docs!
+     */
+    void interfaceMethod();
+
+    /**
+     * docs!
+     */
+    default void defaultMethod() {
+    }
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterfaceImpl.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterfaceImpl.java
new file mode 100644
index 0000000..53aecbc
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/TestInterfaceImpl.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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;
+
+public class TestInterfaceImpl implements TestInterface {
+    @Override
+    public void interfaceMethod() {
+    }
+}
diff --git a/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/os/instrumentation/ParseMethodDescriptorTest.java b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/os/instrumentation/ParseMethodDescriptorTest.java
new file mode 100644
index 0000000..5492ba6
--- /dev/null
+++ b/services/tests/DynamicInstrumentationManagerServiceTests/src/com/android/server/os/instrumentation/ParseMethodDescriptorTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 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.os.instrumentation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import android.os.instrumentation.MethodDescriptor;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.TestAbstractClass;
+import com.android.server.TestAbstractClassImpl;
+import com.android.server.TestClass;
+import com.android.server.TestInterface;
+import com.android.server.TestInterfaceImpl;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+
+/**
+ * Test class for
+ * {@link DynamicInstrumentationManagerService#parseMethodDescriptor(ClassLoader,
+ * MethodDescriptor)}.
+ * <p>
+ * Build/Install/Run:
+ * atest FrameworksMockingServicesTests:ParseMethodDescriptorTest
+ */
+@Presubmit
+@SmallTest
+public class ParseMethodDescriptorTest {
+    private static final String[] PRIMITIVE_PARAMS = new String[]{
+            "boolean", "boolean[]", "byte", "byte[]", "char", "char[]", "short", "short[]", "int",
+            "int[]", "long", "long[]", "float", "float[]", "double", "double[]"};
+    private static final String[] CLASS_PARAMS =
+            new String[]{"java.lang.String", "java.lang.String[]"};
+
+    @Test
+    public void primitiveParams() {
+        assertNotNull(parseMethodDescriptor(TestClass.class.getName(), "primitiveParams",
+                PRIMITIVE_PARAMS));
+    }
+
+    @Test
+    public void classParams() {
+        assertNotNull(
+                parseMethodDescriptor(TestClass.class.getName(), "classParams", CLASS_PARAMS));
+    }
+
+    @Test
+    public void publicMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestClass.class.getName(), "publicMethod"));
+    }
+
+    @Test
+    public void privateMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestClass.class.getName(), "privateMethod"));
+    }
+
+    @Test
+    public void innerClass() {
+        assertNotNull(
+                parseMethodDescriptor(TestClass.class.getName() + "$InnerClass", "innerMethod",
+                        new String[]{TestClass.class.getName() + "$InnerClass",
+                                TestClass.class.getName() + "$InnerClass[]"}));
+    }
+
+    @Test
+    public void interface_concreteMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestInterfaceImpl.class.getName(), "interfaceMethod"));
+    }
+
+    @Test
+    public void interface_defaultMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestInterface.class.getName(), "defaultMethod"));
+    }
+
+    @Test
+    public void abstractClassImpl_abstractMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestAbstractClassImpl.class.getName(), "abstractMethod"));
+    }
+
+    @Test
+    public void abstractClass_concreteMethod() {
+        assertNotNull(
+                parseMethodDescriptor(TestAbstractClass.class.getName(), "concreteMethod"));
+    }
+
+    @Test
+    public void notFound_illegalArgumentException() {
+        assertThrows(IllegalArgumentException.class, () -> parseMethodDescriptor("foo", "bar"));
+        assertThrows(IllegalArgumentException.class,
+                () -> parseMethodDescriptor(TestClass.class.getName(), "bar"));
+        assertThrows(IllegalArgumentException.class,
+                () -> parseMethodDescriptor(TestClass.class.getName(), "primitiveParams",
+                        new String[]{"int"}));
+    }
+
+    private Method parseMethodDescriptor(String fqcn, String methodName) {
+        return DynamicInstrumentationManagerService.parseMethodDescriptor(
+                getClass().getClassLoader(),
+                getMethodDescriptor(fqcn, methodName, new String[]{}));
+    }
+
+    private Method parseMethodDescriptor(String fqcn, String methodName, String[] fqParameters) {
+        return DynamicInstrumentationManagerService.parseMethodDescriptor(
+                getClass().getClassLoader(),
+                getMethodDescriptor(fqcn, methodName, fqParameters));
+    }
+
+    private MethodDescriptor getMethodDescriptor(String fqcn, String methodName,
+            String[] fqParameters) {
+        MethodDescriptor methodDescriptor = new MethodDescriptor();
+        methodDescriptor.fullyQualifiedClassName = fqcn;
+        methodDescriptor.methodName = methodName;
+        methodDescriptor.fullyQualifiedParameters = fqParameters;
+        return methodDescriptor;
+    }
+
+
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2a06c3d..6490cbe 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2183,8 +2183,8 @@
      * Maximum size in bytes of the PDU to send or download when connected to a non-terrestrial
      * network. MmsService will return a result code of MMS_ERROR_TOO_LARGE_FOR_TRANSPORT if
      * the PDU exceeds this limit when connected to a non-terrestrial network.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_MMS_MAX_NTN_PAYLOAD_SIZE_BYTES_INT =
             "mms_max_ntn_payload_size_bytes_int";
 
@@ -9850,9 +9850,8 @@
      * manually scanning available cellular network.
      * If key is {@code true}, satellite plmn should not be exposed to user and should be
      * automatically set, {@code false} otherwise. Default value is {@code true}.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL =
             "remove_satellite_plmn_in_manual_network_scan_bool";
 
@@ -9877,18 +9876,18 @@
 
     /**
      * Doesn't support unrestricted traffic on satellite network.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED = 0;
     /**
      * Support unrestricted but bandwidth_constrained traffic on satellite network.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED = 1;
     /**
      * Support unrestricted satellite network that serves all traffic.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_DATA_SUPPORT_ALL = 2;
     /**
      * Indicates what kind of traffic an {@link NetworkCapabilities#NET_CAPABILITY_NOT_RESTRICTED}
@@ -9898,8 +9897,8 @@
      * {@link ApnSetting#INFRASTRUCTURE_SATELLITE} from APN infrastructure_bitmask, and this
      * configuration is ignored.
      * By default it only supports restricted data.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_SATELLITE_DATA_SUPPORT_MODE_INT =
             "satellite_data_support_mode_int";
 
@@ -9911,8 +9910,8 @@
      *                 {@link com.android.ims.ImsConfig.WfcModeFeatureValueConstants#WIFI_PREFERRED}
      * {@code false} - roaming preference can be changed by user independently and is not
      *                 overridden when device is connected to non-terrestrial network.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_OVERRIDE_WFC_ROAMING_MODE_WHILE_USING_NTN_BOOL =
             "override_wfc_roaming_mode_while_using_ntn_bool";
 
@@ -9945,8 +9944,8 @@
      * Reference: GSMA TS.43-v11, 2.8.5 Fast Authentication and Token Management.
      * `app_name` is an optional attribute in the request and may vary depending on the carrier
      * requirement.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING =
             "satellite_entitlement_app_name_string";
 
@@ -9954,9 +9953,8 @@
      * URL to redirect user to get more information about the carrier support for satellite.
      *
      * The default value is empty string.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING =
             "satellite_information_redirect_url_string";
     /**
@@ -9966,9 +9964,8 @@
      * This will need agreement with carriers before enabling this flag.
      *
      * The default value is false.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL =
             "emergency_messaging_supported_bool";
 
@@ -9983,9 +9980,8 @@
      * prompt user to switch to using satellite emergency messaging.
      *
      * The default value is 30 seconds.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT =
             "emergency_call_to_satellite_t911_handover_timeout_millis_int";
 
@@ -9998,9 +9994,8 @@
      * The default capabilities are
      * {@link NetworkRegistrationInfo#SERVICE_TYPE_SMS}, and
      * {@link NetworkRegistrationInfo#SERVICE_TYPE_MMS}
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY =
             "carrier_roaming_satellite_default_services_int_array";
 
@@ -10031,9 +10026,8 @@
      * Defines the NIDD (Non-IP Data Delivery) APN to be used for carrier roaming to satellite
      * attachment. For more on NIDD, see 3GPP TS 29.542.
      * Note this config is the only source of truth regarding the definition of the APN.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_SATELLITE_NIDD_APN_NAME_STRING =
             "satellite_nidd_apn_name_string";
 
@@ -10044,9 +10038,8 @@
      *
      * If {@code false}, the emergency call is always blocked if device is in emergency satellite
      * mode. Note if device is NOT in emergency satellite mode, emergency call is always allowed.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL =
             "satellite_roaming_turn_off_session_for_emergency_call_bool";
 
@@ -10059,14 +10052,14 @@
 
     /**
      * Device can connect to carrier roaming non-terrestrial network automatically.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC = 0;
     /**
      * Device can connect to carrier roaming non-terrestrial network only if user manually triggers
      * satellite connection.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int CARRIER_ROAMING_NTN_CONNECT_MANUAL = 1;
     /**
      * Indicates carrier roaming non-terrestrial network connect type that the device can use to
@@ -10074,8 +10067,8 @@
      * If this key is set to CARRIER_ROAMING_NTN_CONNECT_MANUAL then connect button will be
      * displayed to user when the device is eligible to use carrier roaming
      * non-terrestrial network.
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT =
             "carrier_roaming_ntn_connect_type_int";
 
@@ -10088,7 +10081,6 @@
      * will be made to T911.
      *
      * The default value is {@link SatelliteManager#EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911}.
-     *
      */
     @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
     public static final String
@@ -10105,9 +10097,8 @@
      * After the timer is expired, device is marked as eligible for satellite communication.
      *
      * The default value is 180 seconds.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT =
             "carrier_supported_satellite_notification_hysteresis_sec_int";
 
@@ -10153,7 +10144,9 @@
             "satellite_roaming_esos_inactivity_timeout_sec_int";
 
     /**
-     * A string array containing the list of messaging package names that support satellite.
+     * A string array containing the list of messaging apps that support satellite.
+     *
+     * The default value contains only "com.google.android.apps.messaging"
      *
      * @hide
      */
@@ -10166,9 +10159,8 @@
      * the default APN (i.e. internet) will be used for tethering.
      *
      * This config is only available when using Preset APN(not user edited) as Preferred APN.
-     *
-     * @hide
      */
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL =
             "disable_dun_apn_while_roaming_with_preset_apn_bool";
 
@@ -11313,6 +11305,8 @@
                         NetworkRegistrationInfo.SERVICE_TYPE_SMS,
                         NetworkRegistrationInfo.SERVICE_TYPE_MMS
                 });
+        sDefaults.putStringArray(KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY, new String[]{
+                "com.google.android.apps.messaging"});
         sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
         sDefaults.putBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, false);
         sDefaults.putInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 7be3f33..88dddcf 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -483,43 +483,43 @@
     /**
      * Telephony framework needs to access the current location of the device to perform the
      * request. However, location in the settings is disabled by users.
-     *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_RESULT_LOCATION_DISABLED = 25;
 
     /**
      * Telephony framework needs to access the current location of the device to perform the
      * request. However, Telephony fails to fetch the current location from location service.
-     *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_RESULT_LOCATION_NOT_AVAILABLE = 26;
 
     /**
      * Emergency call is in progress.
-     *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS = 27;
 
     /**
      * Disabling satellite is in progress.
-     *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28;
 
     /**
      * Enabling satellite is in progress.
-     *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_RESULT_ENABLE_IN_PROGRESS = 29;
 
     /** @hide */
@@ -715,7 +715,7 @@
     public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2;
 
     /**
-     * This intent will be broadcasted if there are any change to list of subscriber informations.
+     * This intent will be broadcasted if there are any change to list of subscriber information.
      * This intent will be sent only to the app with component defined in
      * config_satellite_carrier_roaming_esos_provisioned_class and package defined in
      * config_satellite_gateway_service_package
@@ -1349,12 +1349,16 @@
      * The satellite modem is being powered on.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8;
 
     /**
      * The satellite modem is being powered off.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_MODEM_STATE_DISABLING_SATELLITE = 9;
 
     /**
@@ -1414,6 +1418,8 @@
      * there is any incoming message.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int DATAGRAM_TYPE_KEEP_ALIVE = 3;
 
     /**
@@ -1421,6 +1427,8 @@
      * is the last message to emergency service provider indicating still needs help.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP = 4;
 
     /**
@@ -1428,12 +1436,16 @@
      * is the last message to emergency service provider indicating no more help is needed.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED = 5;
 
     /**
      * Datagram type indicating that the message to be sent or received is of type SMS.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int DATAGRAM_TYPE_SMS = 6;
 
     /**
@@ -1441,6 +1453,8 @@
      * for pending incoming SMS.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS = 7;
 
     /** @hide */
@@ -1461,6 +1475,8 @@
      * Satellite communication restricted by user.
      * @hide
      */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0;
 
     /**
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
index 1abe77f..f260e27 100644
--- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesGenerator.kt
@@ -188,7 +188,7 @@
                         ?: throw IllegalArgumentException(
                             "Invalid feature version input for $name: ${featureArgs[1]}"
                         )
-                FeatureInfo(name, featureArgs[1].toInt(), readonly = true)
+                FeatureInfo(name, featureVersion, readonly = true)
             }
         }
     }